<?php

	/**
	 * Diese Klasse kapselt die Produkte 
	 * @author Daschmi
	 */
	class wpsg_basket
	{
		
		/** Das Datenbankobjekt */
		var $db;
		
		/** Das Shop Objekt */
		var $shop;
		
		/** Array mit den Produkten */
		public $arProdukte;

		/** Gutscheinwert */
		public $gs_value = false;
		
		/** Gutscheinberechnungstyp */
		public $gs_calc = false;
		
		/** Gutscheincode */
		public $gs_code = false;
			
		/** Gutschein ID */
		public $gs_id = false;
		
		/** True wenn aus Session geladen */
		public $loadFromSession = false;
		
		/** Wenn der Warenkorb aus der DB kommt ist hier die BestellID drin */
		public $o_id = false;
		
		/** Enthält die ID der Bestellung wenn aus DB geladen */
		public $db_id = false;
		
		public $arCheckout;
		
		/**
		 * Konstruktor
		 */
		public function __construct()
		{
			
			$this->db = &$GLOBALS['wpsg_db'];
			$this->shop = &$GLOBALS['wpsg_sc'];
			
			$this->reset();
			
		} // public function __construct()
		
		public function reset()
		{
			
			$this->arProdukte = array();
			$this->arCheckout = array();
			$this->db_id = false;
			$this->o_id = false;
			$this->loadFromSession = false;
			$this->gs_id = false;
			$this->gs_code = false;
			$this->gs_calc = false;
			
		}
		
		/**
		 * Fügt ein Produkt in die Session ein
		 */
		public function addProduktToSession($produkt_key, $menge)
		{
			
			if (!wpsg_isSizedArray($_SESSION['wpsg']['basket'])) $_SESSION['wpsg']['basket'] = array();
			
			$product_data = $this->shop->cache->loadProduct($this->shop->getProduktId($produkt_key));
			
			if ($product_data['basket_multiple'] == 1)
			{
				
				// Nur einmal mit beliebiger Menge
				// Hier nichts machen, es wird weiter unten hinzugefügt
				
			}
			else if ($product_data['basket_multiple'] == 2)
			{

				// Mehrfach mit Menge 1
				if ($menge > 1)
				{
					
					$bOK = true;
					
					// Hier die Funktion mehrfach aufrufen (mit Menge 1) und dann abbrechen
					for ($i = 1; $i <= $menge; $i ++)
					{
						
						$bOK = $bOK && $this->addProduktToSession($produkt_key, 1);
						
					}
					
					return $bOK;
					
				}
				
			}
			else if ($product_data['basket_multiple'] == 4)
			{
				
				// Einmal mit Menge 1
				// Basket durchgehen und schauen ob es schon drin ist und dann abbrechen sonst mit 1 hinzufügen
				foreach ((array)$_SESSION['wpsg']['basket'] as $p_key => $p)
				{
						
					if ($p['id'] == $produkt_key)
					{
						
						// Produkt ist schon drin, ich breche hier mit -1 ab, damit zum Warenkorb geleitet wird und eine Meldung wird angezeigt
						$this->shop->addFrontendMessage(__('Das Produkt befindet sich bereits im Warenkorb, es kann nur einmal erworben werden.', 'wpsg'));						
						return -1;
						
					}
					
				} 
				
				$menge = 1;
				
			}
			else 
			{

				// Nur einmal mit beliebiger Menge
				// Basket durchgehen und schauen ob es schon drin ist und dann abbrechen sonst neu hinzufügen
				foreach ((array)$_SESSION['wpsg']['basket'] as $p_key => $p)
				{
					
					if ($p['id'] == $produkt_key)
					{
						 
						$bOK = $this->shop->callMods('basket_produkttosession', array($produkt_key, &$menge, &$_SESSION['wpsg']['basket'][$p_key]));
						if ($bOK === false) 
						{
							
							return false;
							
						}
						 	
						$_SESSION['wpsg']['basket'][$p_key]['menge'] += intval($menge);
						
						// Sollte die Menge auf 0 korrigiert werden dann Produkt entfernen
						if ($_SESSION['wpsg']['basket'][$p_key]['menge'] <= 0)
						{
								
							unset($_SESSION['wpsg']['basket'][$p_key]);
								
						}							
								
						return true;
											
					}
					
				}
				
			}
			
			$ses_data = array();
			
			$bOK = $this->shop->callMods('basket_produkttosession', array($produkt_key, &$menge, &$ses_data));
			if ($bOK === false) 
			{
				
				return false;
				
			}
			
			// War noch nicht drin => neu hinzufügen
			$ses_data = wpsg_array_merge($ses_data, array(
				'menge' => intval($menge),
				'id' => $produkt_key,
				'referer' => ''
			));
			
			if (isset($_REQUEST['myReferer'])) $ses_data['referer'] = $_REQUEST['myReferer'];
			
			//$_SESSION['wpsg']['basket'][] = wpsg_xss($ses_data);
			array_push($_SESSION['wpsg']['basket'], wpsg_xss($ses_data));
			
			return true;
					
		} // public function addProduktToBasket($produkt_id, $menge)

		/**
		 * Fügt einen Gutschein zum Warenkorb hinzu
		 * @param double $value Der Gutscheinwert
		 * @param string $mode w = Wertgutschein, p = Prozentual
		 */
		public function addGutscheinToSession($value, $calc, $code, $gs_id)
		{
			 
			$this->gs_value = $value;
			$this->gs_calc = $calc;
			$this->gs_code = $code;
			$this->gs_id = $gs_id;
			
			$_SESSION['wpsg']['gs'] = wpsg_xss(array(	
				'value' => $this->gs_value,
				'calc' => $this->gs_calc,
				'code' => $this->gs_code,
				'id' => $this->gs_id			
			));
			
		} // public function addGutscheinToSession($value, $calc, $code)
		
		/**
		 * Entfernt ein Produkt aus dem Warenkorb
		 */
		public function removeProduktFromSession($produkt_index)
		{
 
			unset($_SESSION['wpsg']['basket'][$produkt_index]);
			$this->shop->cache->clearShopBasketArray();
			
			return true;
			
		} // public function removeProduktFromSession($produkt_key)
		
		/**
		 * Aktualisiert den Warenkorb in der Session
		 */
		public function updateProduktFromSession($product_index, $produkt_menge)
		{
					
			if (intval($produkt_menge) <= 0)
			{
				
				$this->removeProduktFromSession($product_index);
				return true;
				
			} 
			
				 	 
			foreach ($_SESSION['wpsg']['basket'] as $k => $p)
			{
				
				if ($k == $product_index)
				{ 
					 
					$this->shop->callMods('basket_updateProduktFromSession', array(&$product_index, &$produkt_menge));
					$_SESSION['wpsg']['basket'][$k]['menge'] = intval($produkt_menge);
					
					if (!wpsg_isSizedInt($_SESSION['wpsg']['basket'][$k]['menge'])) unset($_SESSION['wpsg']['basket'][$k]);
					
				}
				
			}
			
			return true;
			
		} // public function updateProduktFromSession($produkt_key, $produkt_menge)
		
		/**
		 * Initiiert den Warenkorb aus der Session heraus
		 */
		public function initFromSession($rebuild = false)
		{
												
			if (!isset($_SESSION['wpsg']['basket'])) return;
			if ($this->loadFromSession === true && $rebuild === false) return;
			
			$this->arProdukte = array();
			
			foreach ((array)$_SESSION['wpsg']['basket'] as $produkt_key => $b)
			{
				
				$this->arProdukte[$produkt_key] = $b;
				
			}
			
			if (isset($_SESSION['wpsg']['gs']))
			{
				
				$this->gs_value = $_SESSION['wpsg']['gs']['value'];
				$this->gs_calc = $_SESSION['wpsg']['gs']['calc'];
				$this->gs_code = $_SESSION['wpsg']['gs']['code'];
				$this->gs_id = $_SESSION['wpsg']['gs']['id'];
				
			}
			
			$this->arCheckout = $_SESSION['wpsg']['checkout'];
			
			$this->loadFromSession = true;
			
		} // public function initFromSession()
		
		/**
		 * Gibt die ID eines Produktes in der Datenbank zurück
		 */
		public function getProduktDBID($produkt_key)
		{
			
			if (is_numeric($produkt_key)) return $produkt_key;
			else if (preg_match('/vp_\d(.*)/', $produkt_key))
			{
				
				// Varianten Produktschlüssel				
				$produkt_id = preg_replace('/(vp_)|(\/(.*))/', '', $produkt_key);

				return $produkt_id;
				
			}
			else return false;
			
		}
		
		/**
		 * Initiiert den Basket aus der Datenbank
		 */
		public function initFromDB($o_id, $backend = false)
		{
			
			$order = $this->db->fetchRow("SELECT * FROM `".WPSG_TBL_ORDER."` WHERE `id` = '".wpsg_q($o_id)."'");
			$kunde = $this->db->fetchRow("SELECT * FROM `".WPSG_TBL_KU."` WHERE `id` = '".wpsg_q($order['k_id'])."'");
			
			$this->arCheckout = array(
				'firma' => $kunde['firma'],
				'title' => $kunde['title'],
				'vname' => $kunde['vname'],
				'name' => $kunde['name'],
				'email' => $kunde['email'],
				'geb' => strtotime('d.m.Y', $kunde['geb']),
				'email2' => $kunde['email'],
				'tel' => $kunde['tel'],
				'strasse' => $kunde['strasse'],
				'fax' => $kunde['fax'],
				'plz' => $kunde['plz'],
				'ort' => $kunde['ort'],
				'land' => $kunde['land'],
				'ustidnr' => $kunde['ustidnr'],
				'shipping' => $order['type_shipping'],
				'payment' => $order['type_payment'],
				'comment' => $order['comment'],
				'onr' => $order['onr'],
				'knr' => $order['knr'],
				'datum' => strftime($order['cdate'])
			);
			 			
			// Produkte
			$arProdukte = $this->db->fetchAssoc("
				SELECT
					OP.`menge`, OP.`price` AS preis_brutto, 
					OP.`mwst_value` AS `mwst_value`,
					IF (OP.`productkey` != '', OP.`productkey`, P.`id`) AS `productkey`, 
					OP.`mod_vp_varkey`,
					OP.`id` AS `order_product_id`,					
					P.`id`, P.`anr`, P.`name`  
				FROM
					`".WPSG_TBL_ORDERPRODUCT."` AS OP
						LEFT JOIN `".WPSG_TBL_PRODUCTS."` AS P ON (OP.`p_id` = P.`id`)
				WHERE
					OP.`o_id` = '".wpsg_q($o_id)."'					
			"); 
			
			foreach ($arProdukte as $k => $v)
			{
				
				if ($v['mod_vp_varkey'] != '') $arProdukte[$k]['id'] = $v['mod_vp_varkey'];
				
				// Preis ist immer in Brutto in der WPSG_TBL_ORDERPRODUCTS
				$arProdukte[$k]['preis_netto'] = wpsg_calculatePreis($v['preis_brutto'], WPSG_NETTO, $v['mwst_value']);
				
				if ($backend)
				{
					
					if ($this->shop->get_option('wpsg_preisangaben') == WPSG_BRUTTO)
					{
						$arProdukte[$k]['preis'] = $arProdukte[$k]['preis_brutto'];
					}
					else
					{
						$arProdukte[$k]['preis'] = $arProdukte[$k]['preis_netto'];						
					}
					
				}
				else
				{
				
					if ($this->shop->getFrontendTaxview() == WPSG_BRUTTO)
					{
						$arProdukte[$k]['preis'] = $arProdukte[$k]['preis_brutto'];
					}
					else
					{
						$arProdukte[$k]['preis'] = $arProdukte[$k]['preis_netto'];
					}
					
				}
				
			}
			
			// Gutschein
			if ($order['gs_id'] > 0)
			{
				
				$gs = $this->db->fetchRow("SELECT * FROM `".WPSG_TBL_GUTSCHEIN."` WHERE `id` = '".wpsg_q($order['gs_id'])."'");
				
				$this->gs_value = $gs['value'];
				$this->gs_calc = $gs['calc_typ'];
				$this->gs_code = $gs['code'];
				$this->gs_id = $gs['id'];
				
			}
			
			$this->arProdukte = $arProdukte;
			
			$this->loadFromSession = false;
			$this->o_id = $o_id;
			 
		} // public function initFromDB($o_id)
		
		/**
		 * Löscht die Session
		 */
		public function clearSession()
		{
			
			if ($this->shop->get_option('wpsg_afterorder') == '1') unset($_SESSION['wpsg']);
			else
			{
			
				unset($_SESSION['wpsg']['basket']);
				unset($_SESSION['wpsg']['gs']);
			
				$this->shop->callMods('clearSession');
				
				if ($this->shop->hasMod('wpsg_mod_kundenverwaltung'))
				{
					
					$this->shop->callMod('wpsg_mod_kundenverwaltung', 'login', array($_SESSION['wpsg']['checkout']['id']));
					
				}
			
			}
			
		} // public function clearSession()
		
		/**
		 * Sendet die Mails beim Kauf an Admin und Kunden
		 * @param Integer $order_id
		 * @param Array $arBasket (Daten des Basket als Array)
		 */
		public function sendOrderSaveMails($order_id, $arBasket, $bCustomerMail = true, $bAdminMail = true, $bDebug = false)
		{
						
			$oOrder = wpsg_order::getInstance($order_id);
			
			$this->shop->view['oOrder'] = $oOrder;
			$this->shop->view['basket'] = $arBasket;
			
			$this->shop->view['o_id'] = $order_id;
			$this->shop->view['order'] = $this->shop->cache->loadOrder($order_id);
			$this->shop->view['customer'] = $this->shop->cache->loadKunden($this->shop->view['oOrder']->k_id);
			
			if ($bDebug === true)
			{
			
				$this->shop->view['basket']['checkout']['datum'] = time();
				$this->shop->view['basket']['checkout']['onr'] = $this->shop->view['oOrder']->onr;
				$this->shop->view['basket']['checkout']['knr'] = $this->shop->view['customer']['knr'];
				$this->shop->view['basket']['checkout']['comment'] = $oOrder->comment;
			
			}
			
			// Adminmail
			if ($bAdminMail === true)
			{
			
				$mail_text = $this->shop->render(WPSG_PATH_VIEW.'/mailtemplates/adminmail.phtml', false);
				
				if ($this->shop->get_option('wpsg_htmlmail') === '1') $mail_html = $this->shop->render(WPSG_PATH_VIEW.'/mailtemplates/html/adminmail.phtml', false);
				else $mail_html = false;
				
				$this->shop->sendMail($mail_text, $this->shop->get_option('wpsg_adminmail_empfaenger'), 'adminmail', array(), $order_id, $oOrder->k_id, $mail_html);
				
				if ($bDebug === false)
				{
					
					$this->db->ImportQuery(WPSG_TBL_OL, array(
						"o_id" => wpsg_q($order_id),
						"cdate" => "NOW()",
						"title" => wpsg_translate(__('Bestellmail (Admin) an:#1#', 'wpsg'), $this->shop->get_option('wpsg_adminmail_empfaenger')),
						"mailtext" => wpsg_q($mail_text)
					));
					
				}
					
				sleep(1);
				
			}
				
			// Kundenmail
			if ($bCustomerMail === true)
			{
			
				$mail_text = $this->shop->render(WPSG_PATH_VIEW.'/mailtemplates/kundenmail.phtml', false);
				
				if ($this->shop->get_option('wpsg_htmlmail') === '1') $mail_html = $this->shop->render(WPSG_PATH_VIEW.'/mailtemplates/html/kundenmail.phtml', false);
				else $mail_html = false;
					
				$arAttachments = array();
					
				if (wpsg_isSizedString($this->shop->get_option('wpsg_kundenmail_attachfile')) && file_exists(wpsg_getUploadDir('wpsg_mailconf').$this->shop->get_option('wpsg_kundenmail_attachfile')))
				{
				
					$arAttachments[] = wpsg_getUploadDir('wpsg_mailconf').$this->shop->get_option('wpsg_kundenmail_attachfile');
				
				}
				
				if ($this->shop->get_option('wpsg_widerrufsformular_kundenmail') === '1' && wpsg_isSizedString($this->shop->get_option('wpsg_revocationform')))
				{
				
					$revocationFile = WPSG_PATH_UPLOADS.'wpsg_revocation/'.$this->shop->get_option('wpsg_revocationform');
				
					if (file_exists($revocationFile) && is_file($revocationFile))
					{
							
						$arAttachments[] = $revocationFile;
							
					}
				
				}

				if ($bDebug === true) $empfaenger = $this->shop->get_option('wpsg_adminmail_empfaenger');
				else $empfaenger = $this->arCheckout['email'];
				
				$this->shop->sendMail($mail_text, $empfaenger, 'kundenmail', $arAttachments, $order_id, $oOrder->k_id, $mail_html);

				if ($bDebug === false)
				{
				
					$this->db->ImportQuery(WPSG_TBL_OL, array(
						"o_id" => wpsg_q($order_id),
						"cdate" => "NOW()",
						"title" => wpsg_translate(__('Bestellmail (Kunde) an:#1#', 'wpsg'), $this->arCheckout['email']),
						"mailtext" => wpsg_q($mail_text)
					));
					
				}
				
			}
			
		} // public function sendOrderSaveMails($order_id)
		 
		/**
		 * Speichert die Bestellung in die Datenbank
		 * Ist der Parameter $finish_order auf false so bleiben die Bestelldaten in der Session (Zur Vorspeicherung)
		 */
		public function save($finish_order = true)
		{
							
			// Berechnen
			$arBasket = $this->toArray();
		 
			// Keien Produkte nix speichern 
			// Sonst wurden schon beim Betreten des leeren Warenkorb (Bots) leere Bestellungen erzeugt 
			if (!wpsg_isSizedArray($arBasket['produkte'])) return;
			
			// Eintrag in Kundentabelle
			$data = array(
				'title' 	=> wpsg_q($this->arCheckout['title']),
				'name' 		=> wpsg_q($this->arCheckout['name']),
				'vname' 	=> wpsg_q($this->arCheckout['vname']),
				'email' 	=> wpsg_q($this->arCheckout['email']),
				'firma' 	=> wpsg_q($this->arCheckout['firma']),
				'fax' 		=> wpsg_q($this->arCheckout['fax']),
				'strasse' 	=> wpsg_q($this->arCheckout['strasse']),
				'plz' 		=> wpsg_q($this->arCheckout['plz']),
				'ort' 		=> wpsg_q($this->arCheckout['ort']),
				'land' 		=> wpsg_q($this->arCheckout['land']),
				'tel' 		=> wpsg_q($this->arCheckout['tel']),
				'geb' 		=> wpsg_q(wpsg_toDate($this->arCheckout['geb'])),
				'ustidnr' 	=> wpsg_q($this->arCheckout['ustidnr'])
			);	
						
			$this->shop->callMods('basket_save_kunde', array(&$data, &$this->arCheckout));
			
			$saved_order_db = array();
			
			if (wpsg_isSizedInt($_SESSION['wpsg']['order_id']))
			{
							
				$saved_order_db = $this->db->fetchRow("SELECT * FROM `".WPSG_TBL_ORDER."` WHERE `id` = '".wpsg_q($_SESSION['wpsg']['order_id'])."' ");
				
				if ($saved_order_db['id'] != $_SESSION['wpsg']['order_id'])
				{
					
					// Wenn die Bestellung aus der Session nicht in der Datenbank existiert lege ich sie neu an
					unset($_SESSION['wpsg']['order_id']); 
					
				}
				else
				{
				
					$k_id = $saved_order_db['k_id'];
					
				}
				
			}
			
			// Sollte die ID des eingeloggten Kunden nicht mit der ID in der Bestellung passen
			if (wpsg_isSizedInt($_SESSION['wpsg']['checkout']['id']))
			{
			
				if (wpsg_isSizedInt($k_id) && $k_id != $_SESSION['wpsg']['checkout']['id'])
				{
						
					$k_id = $_SESSION['wpsg']['checkout']['id'];
			
				}
			
			}			
			
			$data['custom'] = array();
			if (isset($this->arCheckout['custom']) && wpsg_isSizedArray($this->arCheckout)) $data['custom'] = $this->arCheckout['custom'];
					
			if ($k_id > 0)
			{
				
				// Kunde existiert bereits, hier muss aufgepasst werden dass nur abgefragte Kundenvariablen ersetzt werden
				$kunde_data = $this->shop->cache->loadKunden($k_id);					
				$custom_old = @unserialize($kunde_data['custom']);
				
				if (wpsg_isSizedArray($custom_old))
				{
					
					$data['custom'] = wpsg_array_merge($custom_old, (array)$this->arCheckout['custom']);
											
				}
				
			}
			 
			$data['custom'] = serialize($data['custom']);
			
			if ($k_id > 0)
			{
				
				$this->db->UpdateQuery(WPSG_TBL_KU, $data, "`id` = '".wpsg_q($k_id)."'");
				$knr = $this->db->fetchOne("SELECT `knr` FROM `".WPSG_TBL_KU."` WHERE `id` = '".wpsg_q($k_id)."'");
				
				$this->shop->callMods('customer_updatePwd', array(&$k_id, &$this->arCheckout['password']));
				$this->shop->callMods('customer_updated', array(&$k_id));
				
			}
			else
			{
				
				if ($this->shop->hasMod('wpsg_mod_customergroup'))
				{
				
					if (wpsg_isSizedInt($this->shop->get_option('wpsg_page_mod_kundenverwaltung_group_checkout'))) $data['group_id'] = $this->shop->get_option('wpsg_page_mod_kundenverwaltung_group_checkout');
					
				}

				$k_id = $this->db->ImportQuery(WPSG_TBL_KU, $data);
				$knr = $this->shop->buildKNR($k_id);
				
				$this->db->UpdateQuery(WPSG_TBL_KU, array(
					'knr' => wpsg_q($knr)
				), "`id` = '".wpsg_q($k_id)."'");
			 
				$this->shop->callMods('customer_created', array(&$k_id, &$this->arCheckout['password']));				
				
			}
			
			$arBasket['checkout']['k_id'] = $k_id;
			$arBasket['checkout']['knr'] = $knr;
						
			// Der Kunde ist ab 14.08.2015 nicht mehr angemeldet
			//$_SESSION['wpsg']['checkout']['id'] = wpsg_xss($k_id);
			 
			// Produkte letztmalig überprüfen			
			foreach ($arBasket['produkte'] as $p_id => &$p)
			{
			
				if ($this->shop->hasMod('wpsg_mod_stock'))
				{
			
					if (!$this->shop->callMod('wpsg_mod_stock', 'checkBestand', array($p['id'], $p['menge'])) && $this->shop->get_option('wpsg_mod_stock_allow') == '1')
					{
							
						$p['menge'] = $this->shop->callMod('wpsg_mod_stock', 'getBestand', array($p['id']));
			
					}
						
				}
				
			}
				 
			$data = array(
				'cdate' 			=> 'NOW()',
				'k_id' 				=> $k_id,
				'ip' 				=> wpsg_q($_SERVER['REMOTE_ADDR']),
				'useragent' 		=> wpsg_q($_SERVER['HTTP_USER_AGENT']),
				'comment' 			=> wpsg_q($this->arCheckout['comment']),
				'price_gesamt' 		=> wpsg_tf(round($arBasket['sum']['preis_gesamt_brutto'], 2)),
				'price_gesamt_netto' 		=> wpsg_tf(round($arBasket['sum']['preis_gesamt_netto'], 2)),
				'price_gesamt_brutto' 		=> wpsg_tf(round($arBasket['sum']['preis_gesamt_brutto'], 2)),
				'price_shipping' 	=> wpsg_tf($arBasket['sum']['preis_shipping']), // Sollte mal entfernt werden, wird aber an 1000 Stellen verwendet
				'price_shipping_netto' => wpsg_tf($arBasket['sum']['preis_shipping_netto']),
				'price_shipping_brutto'	=> wpsg_tf($arBasket['sum']['preis_shipping_brutto']),
				'price_payment' 	=> wpsg_tf($arBasket['sum']['preis_payment']), // Sollte mal entfernt wedren, wird aber an 1000 Stellen verwendet
				'price_payment_netto' 	=> wpsg_tf($arBasket['sum']['preis_payment_netto']),
				'price_payment_brutto' 	=> wpsg_tf($arBasket['sum']['preis_payment_brutto']),
				'price_rabatt' 		=> wpsg_tf($arBasket['sum']['preis_rabatt']),				
				'mwst_payment' 		=> wpsg_tf($arBasket['payment']['preis_payment_brutto'] - $arBasket['payment']['preis_payment_netto']),
				'mwst_shipping' 	=> wpsg_tf($arBasket['shipping']['preis_shipping_brutto'] - $arBasket['shipping']['preis_shipping_netto']),
				'type_shipping' 	=> wpsg_q($this->arCheckout['shipping']),
				'type_payment' 		=> wpsg_q($this->arCheckout['payment']),
				'custom_data' 		=> array(
					'basket' 				=> $arBasket,
					'preis_backend' 		=> $this->shop->get_option('wpsg_preisangaben'),
					'preis_frontend' 		=> $this->shop->getFrontendTaxview(),
					'wpsg_kleinunternehmer' => $this->shop->get_option('wpsg_kleinunternehmer'),
					'wpsg_kleinunternehmer_text' => $this->shop->get_option('wpsg_kleinunternehmer_text')
				)				
			);
			
			if ($finish_order === true) $data['status'] = wpsg_ShopController::STATUS_EINGEGANGEN; 
			else $data['status'] = wpsg_ShopController::STATUS_UNVOLLSTAENDIG;
			
			// Sprache des Nutzers speichern
			if ($this->shop->isOtherLang())
			{
				
				$data['language'] = wpsg_q($this->shop->getCurrentLanguage());
				
			}
			 
			/** Gutschein speichern */
			if ($this->gs_id !== false && $this->gs_id > 0)
			{
				
				$gs_db = $this->db->fetchRow("SELECT * FROM `".WPSG_TBL_GUTSCHEIN."` WHERE `id` = '".wpsg_q($this->gs_id)."'");
				
				if ($gs_db['id'] != $this->gs_id) die(__('Unerwarteter Fehler bei Gutscheinzuordnung.', 'wpsg'));
				
				$data['gs_id'] = wpsg_q($this->gs_id);
				$data['price_gs'] = wpsg_q($arBasket['sum']['gs']);
								
			}
			
			$this->shop->callMods('basket_save_order', array(&$data, &$this->arCheckout, &$arBasket, $finish_order));
			
			$data['custom_data'] = wpsg_q(serialize($data['custom_data']));
			
			if (wpsg_isSizedInt($_SESSION['wpsg']['order_id']))
			{
				
				$this->db->UpdateQuery(WPSG_TBL_ORDER, $data, " `id` = '".wpsg_q($_SESSION['wpsg']['order_id'])."' ");
				
				$o_id = $_SESSION['wpsg']['order_id'];
				$o_nr = $saved_order_db['onr'];
				
			}
			else 
			{
				
				$o_id = $this->db->ImportQuery(WPSG_TBL_ORDER, $data);
				$o_nr = $this->shop->buildONR($o_id, $k_id, $knr);
			
				// Bestellnummer speichern
				$this->db->UpdateQuery(WPSG_TBL_ORDER, array(
					'onr' => wpsg_q($o_nr)
				), "`id` = '".wpsg_q($o_id)."'");
								
			}
				
			$arBasket['checkout']['onr'] = $o_nr;			
			$arBasket['checkout']['o_id'] = $o_id;
			$arBasket['checkout']['datum'] = strtotime($this->db->fetchOne("SELECT `cdate` FROM `".WPSG_TBL_ORDER."` WHERE `id` = '".wpsg_q($o_id)."'")); 
			
			if ($finish_order === true)
			{
			
				/** Gutschein der Bestellung zuordnen */
				if ($this->gs_id !== false && $this->gs_id > 0)
				{
				
					if ($gs_db['multi'] != '1')
					{
							
						$this->db->UpdateQuery(WPSG_TBL_GUTSCHEIN, array('o_id' => $o_id), "`id` = '".wpsg_q($this->gs_id)."'");
							
					}
				
				}
				
				$this->shop->cache->clearOrderCache($o_id);
				$this->shop->cache->clearKundenCache($k_id);
				
			}
			
			// DB bereinigen und alte zur Bestellung gespeicherte Produkte löschen
			$this->db->Query("DELETE FROM `".WPSG_TBL_ORDERPRODUCT."` WHERE `o_id` = '".wpsg_q($o_id)."' ");
			 
			// Produkte eintragen
			foreach ($arBasket['produkte'] as $p_id => &$p)
			{
			 	 	 
				// Aufdröselung der Varianten damit in der DB die korrekt Produkt ID steht
				$produkt_id = $this->shop->getProduktID($p['id']);
				  
				$data = array(
					'o_id' => wpsg_q($o_id),
					'p_id' => wpsg_q($produkt_id),
					'productkey' => $p['id'],
					'product_index' => $p_id,
					'menge' => wpsg_q($p['menge']),
					'price' => wpsg_q($p['preis_brutto']),
					'price_netto' => wpsg_q(wpsg_tf($p['preis_netto'])),
					'price_brutto' => wpsg_q(wpsg_tf($p['preis_brutto'])),
					'mwst_key' => wpsg_q($p['mwst_key']),
					'mwst_value' => wpsg_q(wpsg_tf($p['preis_brutto'] - $p['preis_netto'])),
					'mod_vp_varkey' => wpsg_q($p['productkey']),
					'allowedpayments' => wpsg_q($p['allowedpayments']),
					'allowedshipping' => wpsg_q($p['allowedshipping'])
				);
				
				$this->shop->callMods('basket_save_product', array(&$data, &$p, $finish_order));
				
				$this->db->ImportQuery(WPSG_TBL_ORDERPRODUCT, $data);
				
				// Eventuelle URL Benachrichtigung bei Kauf
				if ($finish_order === true)
				{
				
					$produkt_db = $this->db->fetchRow("SELECT * FROM `".WPSG_TBL_PRODUCTS."` WHERE `id` = '".wpsg_q($produkt_id)."'");
				
					if ($produkt_db['posturl'] != '' && $produkt_db['posturl_verkauf'] == '1')
					{
						
						$this->shop->notifyURL($produkt_db['posturl'], $p['id'], $p['menge'], $o_id, 0, false, array(
							'product_index' => $p_id
						));
				
					}
					
				}
				
			}
			
			if ($finish_order === true)
			{
			
				$this->shop->callMods('basket_save_done', array(&$o_id, &$k_id, &$this));
				$this->shop->callMods('basket_save_done_array', array(&$o_id, &$k_id, &$arBasket));
	
				// Wenn CrefoPay aktiv, werden die Mails später versendet
				if (!$this->shop->hasMod('wpsg_mod_crefopay')) $this->sendOrderSaveMails($o_id, $arBasket);
				
				// Bestellung direkt auf "Zahlung akzeptiert setzen" wenn option aktiv ist
				if ($this->shop->get_option('wpsg_emptyorder_clear') == '1' && $arBasket['sum']['preis_gesamt_brutto'] == 0)
				{
					
					$this->shop->setOrderStatus($o_id, 100, true);
					
				}
				
				// Alte BestellID muss nach Abschluß entfernt werden
				unset($_SESSION['wpsg']['order_id']);
				unset($_SESSION['wpsg']['checkout']['payment_amount']);
				unset($_SESSION['wpsg']['checkout']['paymentId']);
				unset($_SESSION['wpsg']['checkout']['payer_id']);
				
				$this->clearSession();
				
			}
			else
			{
				
				$_SESSION['wpsg']['order_id'] = $o_id;
				
			}
			
			return $o_id;
						
		} // public function save()
		
		/**
		 * Wird als letzte Überprüfung der Bestellung aufgerufen und leitet zu overview.phtml wenn $error true wird
		 */
		public function checkFinaly(&$error) { }
		
		/**
		 * Überprüft die Korrektheit der Kunden- und Bestelldaten
		 */
		public function checkCheckout($state = true)
		{
			 
			$bError = false;
			$_SESSION['wpsg']['errorFields'] = array();
			
			$custom_config = $GLOBALS['wpsg_sc']->loadPflichtFeldDaten();

			$this->shop->callMods('checkCheckout', array(&$state, &$bError, &$this->arCheckout));
						
			if ($state == 1 || $state)
			{
			
				// Anrede überprüfen
				if ($custom_config['anrede'] != '1' && $this->arCheckout['title'] == '-1')
				{
					
					$this->shop->addFrontendError(__('Bitte im Feld "Anrede" eine Angabe machen!', 'wpsg'));
					$_SESSION['wpsg']['errorFields'][] = 'title';
					$bError = true;
					
				}
	
				// Firma 
				if ($custom_config['firma'] != '1' && trim($this->arCheckout['firma']) == '')
				{
					
					$this->shop->addFrontendError(__('Bitte im Feld "Firma" eine Angabe machen!', 'wpsg'));
					$_SESSION['wpsg']['errorFields'][] = 'firma';
					$bError = true;
					
				}
				
				// Vorname
				if ($custom_config['vname'] != '1' && trim($this->arCheckout['vname']) == '')
				{
					
					$this->shop->addFrontendError(__('Bitte im Feld "Vorname" eine Angabe machen!', 'wpsg'));
					$_SESSION['wpsg']['errorFields'][] = 'vname';
					$bError = true;
					
				}
				
				// Name
				if ($custom_config['name'] != '1' && trim($this->arCheckout['name']) == '')
				{
					
					$this->shop->addFrontendError(__('Bitte im Feld "Name" eine Angabe machen!', 'wpsg'));
					$_SESSION['wpsg']['errorFields'][] = 'name';
					$bError = true;
					
				}
				
				// Geburtsdatum
				if (
						$custom_config['geb'] == '0' && !wspg_isValidGeb($this->arCheckout['geb'])
						
						/*
						(wspg_isValidGeb($this->arCheckout['geb']) && wpsg_isSizedString($this->arCheckout['geb'])) || 
						$custom_config['geb'] == '0'
						 * */
					)
				{
					
					$this->shop->addFrontendError(__('Bitte die Eingabe im Feld "Geburtsdatum" überprüfen!', 'wpsg'));
					$_SESSION['wpsg']['errorFields'][] = 'geb';
					$bError = true;
					
				}
				
				// E-Mail Adresse
				if ($custom_config['email'] != '1' && !wpsg_isValidEMail($this->arCheckout['email']))
				{
					
					$this->shop->addFrontendError(__('Bitte die Eingabe der E-Mail Adresse überprüfen!', 'wpsg'));
					$_SESSION['wpsg']['errorFields'][] = 'email';
					$bError = true;
					
				}
	
				// E-Mail Eingabeüberprüfung
				if ($custom_config['emailconfirm'] == '1')
				{
					
					if ($this->arCheckout['email'] != $this->arCheckout['email2'])
					{
	
						$this->shop->addFrontendError(__('Bitte überprüfen Sie die Eingaben in der E-Mail Bestätigung!', 'wpsg'));
						$_SESSION['wpsg']['errorFields'][] = 'email'; 
						$bError = true;
						 
					}
					
				}
				
				// Telefonnummer validieren
				if ($custom_config['tel'] != '1' && $this->arCheckout['tel'] == '')
				{

					$this->shop->addFrontendError(__('Bitte die Eingabe im Feld "Telefonnummer" überprüfen!', 'wpsg'));
					$_SESSION['wpsg']['errorFields'][] = 'tel';
					$bError = true;
					
				}
				
				// Straße prüfen
				if ($custom_config['strasse'] != '1' && $this->arCheckout['strasse'] == '')
				{
					
					$this->shop->addFrontendError(__('Bitte die Eingaben im Feld "Straße" überprüfen!', 'wpsg'));
					$_SESSION['wpsg']['errorFields'][] = 'strasse';
					$bError = true;
					
				}
				
				// Fax prüfen
				if ($custom_config['fax'] != '1' && $this->arCheckout['fax'] == '')
				{
					
					$this->shop->addFrontendError(__('Bitte die Eingaben im Feld "Fax" überprüfen!', 'wpsg'));
					$_SESSION['wpsg']['errorFields'][] = 'fax';
					$bError = true;
					
				}
				
				// PLZ überprüfen
				if ($custom_config['plz'] != '1' && $this->arCheckout['plz'] == '')
				{
					
					$this->shop->addFrontendError(__('Bitte die Eingaben im Feld "PLZ" überprüfen!', 'wpsg'));
					$_SESSION['wpsg']['errorFields'][] = 'plz';
					$bError = true;
					
				}
				
				// Ort überprüfen
				if ($custom_config['ort'] != '1' && $this->arCheckout['ort'] == '')
				{
					
					$this->shop->addFrontendError(__('Bitte die Eingaben im Feld "Ort" überprüfen!', 'wpsg'));
					$_SESSION['wpsg']['errorFields'][] = 'ort';
					$bError = true;
					
				}
				
				// Land überprüfen
				if ($custom_config['land'] != '1' && $this->arCheckout['land'] <= 0)
				{
					
					$this->shop->addFrontendError(__('Bitte ein Land auswählen!', 'wpsg'));
					$_SESSION['wpsg']['errorFields'][] = 'land';
					$bError = true;
					
				}
				
				// UStIdNr prüfen
				if ($custom_config['ustidnr'] != '1' && !preg_match("/^[a-zA-Z]+\d+/", $this->arCheckout['ustidnr']))
				{
					
					$this->shop->addFrontendError(__('Bitte die Eingaben im Feld "UStIdNr." prüfen!', 'wpsg'));
					$_SESSION['wpsg']['errorFields'][] = 'ustidnr';
					$bError = true;
					
				}
				
				// Benutzerdefinierte Felder prüfen
				foreach ((array)$custom_config['custom'] as $c_id => $c)
				{
					
					// Wenn die Kundenvariable nicht im Request drin ist dann auch nichts machen
					// Problem war der Fall, dass eine Kundenvariable nicht angezeigt wurde 
					if (!isset($this->arCheckout['custom'][$c_id])) continue;
					
					if ($c['show'] == '0')
					{
						
						if ($c['typ'] == '2')
						{
							
							// Checkbox
							if ($this->arCheckout['custom'][$c_id] != '1')
							{
								
								$this->shop->addFrontendError(wpsg_translate(__('Bitte "#1#" akzeptieren!', 'wpsg'), __($c['name'], 'wpsg')));
								$_SESSION['wpsg']['errorFields'][] = 'custom_'.$c_id;
								$bError = true;
								
							}
							
						}
						else if ($c['typ'] == '1')
						{
							
							// Auswahl
							if ($this->arCheckout['custom'][$c_id] == '-1')
							{
								
								$this->shop->addFrontendError(wpsg_translate(__('Bitte eine Auswahl im Feld "#1#" treffen!', 'wpsg'), __($c['name'], 'wpsg')));
								$_SESSION['wpsg']['errorFields'][] = 'custom_'.$c_id;
								$bError = true;
								
							}
							
						}
						else if ($c['typ'] == '0')
						{
							
							// Texte
							if (trim($this->arCheckout['custom'][$c_id]) == '')
							{
								
								$this->shop->addFrontendError(wpsg_translate(__('Bitte machen Sie in Feld "#1#" eine Angabe!', 'wpsg'), __($c['name'], 'wpsg')));
								$_SESSION['wpsg']['errorFields'][] = 'custom_'.$c_id;
								$bError = true;
								
							}
							
						}
						
					}
					
				}
				
			}

			/**
			 * Versand- und Zahlungsarten nur Checken wenn State=2 oder alle State=true (Alles prüfen)
			 * Wenn Einseiten-Checkout aktiv, dann auch bei State=1 prüfen aber nicht(!) Wenn Profil oder Registrierung abgeschickt wird
			 */			
			if ($state == 2 || $state === true || 
				($this->shop->hasMod('wpsg_mod_onepagecheckout') && $state == 1 && !isset($_REQUEST['wpsg_mod_kundenverwaltung_save']) && !isset($_REQUEST['wpsg_mod_kundenverwaltung_register'])))
			{
							
				$this->shop->checkShippingAvailable(); 
 
				// Versandart prüfen
				if (!isset($this->arCheckout['shipping']) || !array_key_exists($this->arCheckout['shipping'], $this->shop->arShipping) || $this->arCheckout['shipping'] == '')
				{
				
					$this->shop->addFrontendError(__('Bitte eine gültige Versandart auswählen.', 'wpsg'));
					$_SESSION['wpsg']['errorFields'][] = 'shipping';
					$bError = true;
					
				}
 
				// Zahlungsart prüfen
				if (!$this->shop->hasMod('wpsg_mod_crefopay'))
				{
				
					if (!isset($this->arCheckout['payment']) || !array_key_exists($this->arCheckout['payment'], $this->shop->arPayment) || $this->arCheckout['payment'] == '')
					{
					
						$this->shop->addFrontendError(__('Bitte eine gültige Zahlungsart auswählen.', 'wpsg'));
						$_SESSION['wpsg']['errorFields'][] = 'payment';
						$bError = true;
						
					}
					
				}
			 
			}
			
			// prüft ob tatsächlich mind. ein Produkt im Warenkorb liegt
			if (count($_SESSION['wpsg']['basket']) < 1 && !is_numeric($state))
			{
				$this->shop->addFrontendError(__('Keine Produkte im Warenkorb.', 'wpsg'));
				$_SESSION['wpsg']['errorFields'][] = 'empty_basket';
				$bError = true;
			}
				
			return !$bError; 
			
		} // public function checkCheckout()

		/**
		 * Überprüft den Basket Array auf ein EU-Leistungsort Produkt und gibt true oder false zurück
		 */
		public function hasEULeistungsortProduct(&$arBasket)
		{
			
			foreach ($arBasket['produkte'] as $p)
			{
				
				if (wpsg_isSizedInt($p['euleistungsortregel'])) return true;
				
			}
			
			return false;
			
		} // public function hasEULeistungsortProduct(&$arBasket)
		
		/**
		 * Wandelt die in der Session gespeicherten Produkte in einen aufgewerteten Array
		 */
		public function toArray($backend = false, $clearVK = false)
		{
			
			if ($this->o_id > 0)
			{
				
				$order_data = $this->shop->cache->loadOrder($this->o_id);
				$custom_data = @unserialize($order_data['custom_data']);	
								
				if (is_array($custom_data['basket']))
				{
					
					$arBasket = $custom_data['basket'];
					
					// Ich vereinige die Checkoutdaten mit den Kundendaten aus der Datenbank
					// Damit sind hier die aktuellen Werte aus der Datenbank enthalten
					$arBasket['checkout'] = wpsg_array_merge($arBasket['checkout'], $this->shop->cache->loadKunden($arBasket['checkout']['k_id']));
										
					// Für das Backend eventuell Preise drehen
					if ($backend === true)
					{
						
						if ($this->shop->get_option('wpsg_preisangaben') == WPSG_NETTO)
						{
						 
							if (isset($arBasket['sum']['preis_payment_netto'])) $arBasket['sum']['preis_payment'] = $arBasket['sum']['preis_payment_netto'];
							if (isset($arBasket['sum']['preis_shipping_netto'])) $arBasket['sum']['preis_shipping'] = $arBasket['sum']['preis_shipping_netto']; 
							if (isset($arBasket['sum']['gs_netto'])) $arBasket['sum']['gs'] = $arBasket['sum']['gs_netto'];
							if (isset($arBasket['sum']['preis_rabatt_netto'])) $arBasket['sum']['preis_rabatt'] = $arBasket['sum']['preis_rabatt_netto'];
							if (isset($arBasket['sum']['preis_netto'])) $arBasket['sum']['preis'] = $arBasket['sum']['preis_netto'];
							if (isset($arBasket['sum']['preis_gesamt_netto'])) $arBasket['sum']['preis_gesamt'] = $arBasket['sum']['preis_gesamt_netto'];
											
						}
						else
						{
							
							if (isset($arBasket['sum']['preis_payment_brutto'])) $arBasket['sum']['preis_payment'] = $arBasket['sum']['preis_payment_brutto'];
							if (isset($arBasket['sum']['preis_shipping_brutto'])) $arBasket['sum']['preis_shipping'] = $arBasket['sum']['preis_shipping_brutto']; 
							if (isset($arBasket['sum']['gs_brutto'])) $arBasket['sum']['gs'] = $arBasket['sum']['gs_brutto'];
							if (isset($arBasket['sum']['preis_rabatt_brutto'])) $arBasket['sum']['preis_rabatt'] = $arBasket['sum']['preis_rabatt_brutto'];
							if (isset($arBasket['sum']['preis_brutto'])) $arBasket['sum']['preis'] = $arBasket['sum']['preis_brutto'];
							if (isset($arBasket['sum']['preis_gesamt_brutto'])) $arBasket['sum']['preis_gesamt'] = $arBasket['sum']['preis_gesamt_brutto'];
							
						}
						
						foreach ($arBasket['produkte'] as $k => $v)
						{
							
							if ($arBasket['noMwSt'] == '1')
							{
								
								$arBasket['produkte'][$k]['preis'] = $arBasket['produkte'][$k]['preis_netto'];
								
							}
							else
							{
							
								if ($this->shop->get_option('wpsg_preisangaben') == WPSG_NETTO)
								{
								
									$arBasket['produkte'][$k]['preis'] = $arBasket['produkte'][$k]['preis_netto'];
									
								}
								else
								{
									
									$arBasket['produkte'][$k]['preis'] = $arBasket['produkte'][$k]['preis_brutto'];
									
								}
								
							}
							
						}
						
					}
					
					return $arBasket;
					
				}
				
			}

			// MwSt. Im Frontend nicht anzeigen, weil z.B. UstIDnr angegeben wurde
			if (wpsg_isSizedInt($this->arCheckout['shipping_land'])) $land = $this->shop->db->fetchRow("SELECT * FROM `".WPSG_TBL_LAND."` WHERE `id` = '".wpsg_q($this->arCheckout['shipping_land'])."'");				
			else if (wpsg_isSizedInt($this->arCheckout['land'])) $land = $this->shop->db->fetchRow("SELECT * FROM `".WPSG_TBL_LAND."` WHERE `id` = '".wpsg_q($this->arCheckout['land'])."'");
			else $land = 0;

			$arReturn = array();
						
			$arReturn['land'] = $land;
			
			if (wpsg_isSizedInt($this->arCheckout['shipping_land']))
			{
				
				$arReturn['shipping_land'] = $this->shop->db->fetchRow("SELECT * FROM `".WPSG_TBL_LAND."` WHERE `id` = '".wpsg_q($this->arCheckout['shipping_land'])."'");
				
			}
			
			if ($land['mwst'] == '1' || $this->shop->get_option('wpsg_kleinunternehmer') == '1') $noMwSt = true;
			else if ($land['mwst'] == '2' && $this->arCheckout['ustidnr'] != '') $noMwSt = true;
			else $noMwSt = false;
			
			$arReturn['noMwSt'] = $noMwSt;
			$arReturn['produkte'] = array();
			$arReturn['mwst'] = array();
			$arReturn['sum'] = array(
				'preis' => 0,
				'preis_netto' => 0,
				'preis_brutto' => 0,
				'preis_gesamt_brutto' => 0,
				'preis_gesamt_netto' => 0,
				'preis_payment' => 0,
				'preis_shipping' => 0
			);
								
			foreach ($this->arProdukte as $product_index => &$b)
			{
								
				$produkt_id = $this->shop->getProduktID($b['id']);
				
				wpsg_addSet($arReturn['menge'], $b['menge']);

				$country = $this->shop->getDefaultCountry();
				
				if (is_numeric($produkt_id))
				{
										
					// Preis wird berechnet daher entfernen
					unset($b['preis']);
					unset($b['preis_netto']);
					unset($b['preis_brutto']);
					
					// in $b sind eventuell auch Moduldaten drin (Produktvariablen)
					$b = $this->shop->loadProduktArray($produkt_id, $b);
					
					if (wpsg_isSizedInt($b['euleistungsortregel']))
					{
						
						$this->shop->showEULayer = true;
						$country = $this->shop->getFrontendCountry();
						
					}
					
					$b['productkey'] = $b['id'];
  
				}
				
				$this->shop->callMods('basket_toArray', array(&$b, $backend, $noMwSt));
		 				 
				$this->checkMwSt($b['mwst_key'], $country, $arReturn);
								
				// Hier wird entschieden ob der gerundete oder der genaue Wert zum Gesamtpreis hinzuaddiert wird
				if ($this->shop->addRoundedValues === true) 
				{
					
					$price_sum_brutto = round($b['preis_brutto'], 2);
					$price_sum_netto = round($b['preis_netto'], 2);
					
				}
				else
				{
					
					$price_sum_brutto = $b['preis_brutto'];
					$price_sum_netto = $b['preis_netto'];
					
				}
				
				if ($noMwSt) $b['mwst_value'] = 0;
				else $b['mwst_value'] = $arReturn['mwst'][$b['mwst_key'].'_'.$country->id]['value'];
				
				if (!$noMwSt) wpsg_addSet($arReturn['sum']['mwst'], (($price_sum_brutto - $price_sum_netto) * $b['menge']));
				else $arReturn['sum']['mwst'] = 0;
				
				if ($noMwSt)
				{
				
					$arReturn['sum']['preis_brutto'] += $price_sum_netto * $b['menge'];
					$arReturn['sum']['preis_gesamt_brutto'] += $price_sum_netto * $b['menge'];
										
				}
				else
				{
									
					$arReturn['sum']['preis_brutto'] += $price_sum_brutto * $b['menge'];
					$arReturn['sum']['preis_gesamt_brutto'] += $price_sum_brutto * $b['menge'];
					
				}
									
				$arReturn['sum']['preis_netto'] += $price_sum_netto * $b['menge'];
				$arReturn['sum']['preis_gesamt_netto'] += $price_sum_netto * $b['menge'];
				
				// Preis Spalte auswählen
				if ($backend)
				{
					
					if ($this->shop->get_option('wpsg_preisangaben') == WPSG_NETTO || $noMwSt)
					{
						
						$b['preis'] = $price_sum_netto;
						$arReturn['sum']['preis'] += $price_sum_netto * $b['menge'];
						$arReturn['sum']['preis_gesamt'] += $price_sum_netto * $b['menge'];
						 
					}
					else 
					{
						
						$b['preis'] = $price_sum_brutto;
						$arReturn['sum']['preis'] += $price_sum_brutto * $b['menge'];
						$arReturn['sum']['preis_gesamt'] += $price_sum_brutto * $b['menge'];
						
					}
					
				}
				else
				{
					
					if ($this->shop->getFrontendTaxview() == WPSG_NETTO || $noMwSt)
					{ 
						
						$b['preis'] = $price_sum_netto;
						wpsg_addSet($arReturn['sum']['preis'], ($price_sum_netto * $b['menge']));
						wpsg_addSet($arReturn['sum']['preis_gesamt'], ($price_sum_netto * $b['menge']));
						
					}
					else 
					{
						
						$b['preis'] = $price_sum_brutto;
						wpsg_addSet($arReturn['sum']['preis'], ($price_sum_brutto * $b['menge']));						
						wpsg_addSet($arReturn['sum']['preis_gesamt'], ($price_sum_brutto * $b['menge']));
						
					}
					
				}
				
				// Steueranteil
				if (!$noMwSt)
				{
					
					wpsg_addSet($arReturn['mwst'][$b['mwst_key'].'_'.$country->id]['sum'], (($price_sum_brutto - $price_sum_netto) * $b['menge']));
					wpsg_addSet($arReturn['mwst'][$b['mwst_key'].'_'.$country->id]['base_value'], ($price_sum_brutto * $b['menge']));
					
				}

				$b['product_index'] = $product_index;
				$arReturn['produkte'][$product_index] = $b;
				
			} // foreach Produkte
			
			// Gutschein einberechnen
			$this->shop->callMod('wpsg_mod_gutschein', 'basket_toArray_gs', array(&$this, &$arReturn));

			// Staffelrabatt
			$this->shop->callMod('wpsg_mod_discount', 'basket_toArray_discount', arraY(&$this, &$arReturn));
			
			// Kundendaten einfügen
			$arReturn['checkout'] = $this->arCheckout;

			$this->shop->callMods('basket_toArray_preshippayment', array(&$this, &$arReturn));
			
			// Die Versandkosten für den Warenkorb berechnen berechnen
			// Dies darf im checkout2 nicht passieren, oder wenn der Parameter auf true
			if ($this->o_id > 0)
			{

				$order_data = $this->shop->cache->loadOrder($this->o_id);
				$price_shipping = $order_data['price_shipping'];
				$price_payment = $order_data['price_payment'];

				if ($this->shop->getFrontendTaxview() == WPSG_BRUTTO)
				{
				
					$arReturn['sum']['preis_payment_brutto'] = $price_payment;
					$arReturn['sum']['preis_payment_netto'] = wpsg_calculatePreis($price_payment, WPSG_NETTO, $order_data['mwst_payment']);
				
					$arReturn['sum']['preis_shipping_brutto'] = $price_shipping;
					$arReturn['sum']['preis_shipping_netto'] = wpsg_calculatePreis($price_shipping, WPSG_NETTO, $order_data['mwst_shipping']);
					
				}
				else
				{
					
					$arReturn['sum']['preis_payment_netto'] = $price_payment;
					$arReturn['sum']['preis_payment_brutto'] = wpsg_calculatePreis($price_payment, WPSG_BRUTTO, $order_data['mwst_payment']);
					
					$arReturn['sum']['preis_shipping_netto'] = $price_shipping;
					$arReturn['sum']['preis_shipping_brutto'] = wpsg_calculatePreis($price_shipping, WPSG_BRUTTO, $order_data['mwst_shipping']);
					
				}
				
			}
			else
			{
				
				// Bin mir nicht sicher warum die Versandkosten/Zahlungskosten im Checkout nicht berechnet wurde
				// Aufgrund von PayPal (PayPal Plus) brauch ich sie aber 
				//if (!isset($_REQUEST['wpsg_checkout2']) && !$clearVK)
				{
				
					if ($backend) $arReturn['backend'] = true;
					else $arReturn['backend'] = false;
					
					if (!$backend)
					{
						
						/*
						 * Prüfen ob die gesetzte Zahlungsart auch in den Verfügbaren ist
						 * Ist für die Auswahl der Länder, Zahlungsarten und Versandarten im Warenkorb nötig geworden
						 */
						if (wpsg_isSizedInt($arReturn['checkout']['shipping']) && !array_key_exists($arReturn['checkout']['shipping'], $this->shop->arShipping)) 
						{
							
							unset($arReturn['checkout']['shipping']);
							
						}
						
						if (wpsg_isSizedInt($arReturn['checkout']['payment']) && !array_key_exists($arReturn['checkout']['payment'], $this->shop->arPayment))
						{
							
							unset($arReturn['checkout']['payment']);
							
						}
												
					}
					
					// Versandarten können gruppiert sein, vorher trennen
					if (preg_match('/(.*)\-(.*)/', $arReturn['checkout']['shipping']))
					{
						
						$arShipping = explode('-', $arReturn['checkout']['shipping']);

						// Ich simuliere hier die Berechnung in einem Extra Array, da die Funktion leider so gebaut ist
						// Sonst ist die Grundlage für die Berechnung nicht die Selbe
						$arBasketPreShipping = $arReturn;
						
						foreach ($arShipping as $shipping)
						{
							
							$basket_calc = $arBasketPreShipping;
							
							$this->shop->callMods('calcShipping', array(&$basket_calc, $shipping));
							
							wpsg_addSet($arReturn['sum']['preis_shipping'], $basket_calc['sum']['preis_shipping']);
							wpsg_addSet($arReturn['sum']['preis_shipping_brutto'], $basket_calc['sum']['preis_shipping_brutto']);
							wpsg_addSet($arReturn['sum']['preis_shipping_netto'], $basket_calc['sum']['preis_shipping_netto']);
							
							wpsg_addSet($arReturn['shipping']['mwst'], $basket_calc['shipping']['mwst']);
							wpsg_addSet($arReturn['shipping']['preis_shipping_netto'], $basket_calc['shipping']['preis_shipping_netto']);
							wpsg_addSet($arReturn['shipping']['preis_shipping_brutto'], $basket_calc['shipping']['preis_shipping_brutto']);
 
							foreach ($basket_calc['mwst'] as $tax_key => $mwst)
							{
								
								$this->shop->basket->checkMwSt(substr($tax_key, 0, 1), $this->shop->getDefaultCountry(), $arReturn);
								
								if (!array_key_exists($tax_key, $arBasketPreShipping['mwst']))
								{
								
									// Satz war vorher noch nicht drin
									$arReturn['mwst'][$tax_key]['sum'] += $mwst['sum'];
									$arReturn['mwst'][$tax_key]['base_value'] += $mwst['base_value'];
									
								}
								else
								{
									
									$arReturn['mwst'][$tax_key]['sum'] += ($mwst['sum'] - $arBasketPreShipping['mwst'][$tax_key]['sum']); 
									$arReturn['mwst'][$tax_key]['base_value'] += ($mwst['base_value'] - $arBasketPreShipping['mwst'][$tax_key]['base_value']);
									
								}
								
							}
							
							if (wpsg_isSizedArray($arReturn['shipping']['methods'])) $arReturn['shipping']['methods'][] = $shipping;
							else $arReturn['shipping']['methods'] = array($shipping);
							
						}
						
						//wpsg_debug($arReturn);die();
						 
						// In den Produktdaten sind die für das Produkt zulässigen Versandarten gespeichert, hier entferne ich noch die die in dieser Bestellung nicht gewählt wurden
						foreach ($arReturn['produkte'] as &$p)
						{
							
							if (wpsg_isSizedString($p['allowedshipping']))
							{
								
								$arAllowedShipping = explode(',', $p['allowedshipping']);
								
								foreach ($arAllowedShipping as $shipping)
								{
									
									if (!in_array($shipping, $arReturn['shipping']['methods'])) unset($arReturn['shipping']['methods'][$shipping]);
									
								}
								
								$p['order_allowedshipping'] = $arAllowedShipping;
								
							}
							
						}
						
						// Anteilig und kein eindeutiger Satz, wenn zusammengesetzte Versandart
						unset($arReturn['shipping']['mwst']);
						$arReturn['shipping']['tax_rata'] = true;
						
					}
					else
					{
						
						$this->shop->callMods('calcShipping', array(&$arReturn, $arReturn['checkout']['shipping']));
						
					}
										
					$this->shop->callMods('calcPayment', array(&$arReturn));
										
				}
				
			}
			
			// Zahlungskosten der Summe hinzurechnen
			if (isset($arReturn['sum']['preis_payment_netto'])) $arReturn['sum']['preis_gesamt_netto'] += $arReturn['sum']['preis_payment_netto'];
			if (isset($arReturn['sum']['preis_payment_brutto'])) $arReturn['sum']['preis_gesamt_brutto'] += $arReturn['sum']['preis_payment_brutto'];

			// Versandkosten der Summe hinzurechnen
			if (isset($arReturn['sum']['preis_shipping_netto'])) $arReturn['sum']['preis_gesamt_netto'] += $arReturn['sum']['preis_shipping_netto'];
			if (isset($arReturn['sum']['preis_shipping_brutto'])) $arReturn['sum']['preis_gesamt_brutto'] += $arReturn['sum']['preis_shipping_brutto'];
			
			if ($backend)
			{
				
				// Preisangaben fürs Backend
				if ($this->shop->get_option('wpsg_preisangaben') == WPSG_NETTO)
				{
					
					$arReturn['sum']['preis_gesamt'] += $arReturn['sum']['preis_shipping_netto'];
					$arReturn['sum']['preis_shipping'] = $arReturn['sum']['preis_shipping_netto'];
					
					$arReturn['sum']['preis_gesamt'] += $arReturn['sum']['preis_payment_netto'];
					$arReturn['sum']['preis_payment'] = $arReturn['sum']['preis_payment_netto'];
					
				}
				else
				{
					
					$arReturn['sum']['preis_gesamt'] += $arReturn['sum']['preis_shipping_brutto'];
					$arReturn['sum']['preis_shipping'] = $arReturn['sum']['preis_shipping_brutto'];
					
					$arReturn['sum']['preis_gesamt'] += $arReturn['sum']['preis_payment_brutto'];
					$arReturn['sum']['preis_payment'] = $arReturn['sum']['preis_payment_brutto'];
					
				}
				
			}
			else 
			{
				
				// Preisangaben fürs Frontend 
				if ($this->shop->getFrontendTaxview() == WPSG_NETTO)
				{
					
					if (isset($arReturn['sum']['preis_shipping_brutto'])) $arReturn['sum']['preis_gesamt'] += $arReturn['sum']['preis_shipping_netto'];
					if (isset($arReturn['sum']['preis_payment_brutto'])) $arReturn['sum']['preis_gesamt'] += $arReturn['sum']['preis_payment_netto'];
					
					if (isset($arReturn['sum']['preis_shipping_brutto'])) $arReturn['sum']['preis_shipping'] = $arReturn['sum']['preis_shipping_netto'];
					if (isset($arReturn['sum']['preis_payment_brutto'])) $arReturn['sum']['preis_payment'] = $arReturn['sum']['preis_payment_netto'];
					
				}
				else
				{
					
					if (isset($arReturn['sum']['preis_shipping_brutto'])) $arReturn['sum']['preis_gesamt'] += $arReturn['sum']['preis_shipping_brutto'];
					if (isset($arReturn['sum']['preis_payment_brutto'])) $arReturn['sum']['preis_gesamt'] += $arReturn['sum']['preis_payment_brutto'];
					
					if (isset($arReturn['sum']['preis_shipping_brutto'])) $arReturn['sum']['preis_shipping'] = $arReturn['sum']['preis_shipping_brutto'];
					if (isset($arReturn['sum']['preis_payment_brutto'])) $arReturn['sum']['preis_payment'] = $arReturn['sum']['preis_payment_brutto'];
					 
				}
				
			}
			
			// Leere MwSt. Sätze entfernen
			foreach ((array)$arReturn['mwst'] as $k => $v)
			{
				if ($v['sum'] <= 0) unset($arReturn['mwst'][$k]);
			}
			 			
			// Negative Bestellungen Verhindern 
			if (isset($arReturn['sum']['preis_netto']) && $arReturn['sum']['preis_netto'] < 0) $arReturn['sum']['preis_netto'] = 0;
			if (isset($arReturn['sum']['preis_brutto']) && $arReturn['sum']['preis_brutto'] < 0) $arReturn['sum']['preis_brutto'] = 0;
			if (isset($arReturn['sum']['preis']) && $arReturn['sum']['preis'] < 0) $arReturn['sum']['preis'] = 0;
			if (isset($arReturn['sum']['preis_gesamt_netto']) && $arReturn['sum']['preis_gesamt_netto'] < 0) $arReturn['sum']['preis_gesamt_netto'] = 0;
			if (isset($arReturn['sum']['preis_gesamt_brutto']) && $arReturn['sum']['preis_gesamt_brutto'] < 0) $arReturn['sum']['preis_gesamt_brutto'] = 0;
			if (isset($arReturn['sum']['preis_gesamt']) && $arReturn['sum']['preis_gesamt'] < 0) $arReturn['sum']['preis_gesamt'] = 0; 
			
			$this->shop->callMods('basket_toArray_final', array(&$this, &$arReturn));
			
			return $arReturn;
			
		} // public function toArray()
		
		/**
		 * Gibt die Anzahl zurück, die im Warenkorb zu einem ProduktKEY enthalten ist
		 */
		public function getBasketAmount($product_key)
		{
			
			$nAmount = 0;
			
			if (!wpsg_isSizedArray($_SESSION['wpsg']['basket'])) return 0;
			
			foreach ($_SESSION['wpsg']['basket'] as $product_index => $product_data)
			{
				
				if ($product_data['id'] == $product_key)
				{
					
					$nAmount += $product_data['menge'];
					
				}
				
			}
			
			return $nAmount;
						
		} // public function getBasketAmount($product_key)
		
		/**
		 * Gibt die ProduktIDs der Produkte aus dem Warenkorb zurück
		 */
		public function getProductIDs()
		{
			
			$arReturn = array();
			
			foreach ($this->arProdukte as $p)
			{
				
				$product_id = $this->shop->getProduktID($p['id']);
				if (!in_array($product_id, $arReturn)) $arReturn[] = $product_id;
				
			}
			
			return $arReturn;
			
		} // public function getProductIDs()
				
		/**
		 * Verteilt den Wert $value auf die Steuerarten in $arReturn
		 */
		public function distributeMwSt($value, &$arReturn)
		{
			
			if ($arReturn['noMwSt'] == true) 
			{
				
				$arReturn['sum']['preis_brutto'] -= $value;
				$arReturn['sum']['preis_gesamt_brutto'] -= $value;				
				$arReturn['sum']['preis_netto'] -= $value;
				$arReturn['sum']['preis_gesamt_netto'] -= $value;
				$arReturn['sum']['preis'] -= $value;
				$arReturn['sum']['preis_gesamt'] -= $value;
				
			}
			
			// Da ich hier nicht weiß ob der Basket fürs Frontend/Backend berechnet werden soll schaue ich hier ob der NETTO oder BRUTTO Preis im Preisarray ist
			// Die unterschiedliche Speicherung in preis is ansich quatsch ... Bei Ausgabe sollte immer Brutto / Netto entsprechend verwendet werden
			if ($arReturn['sum']['preis'] == $arReturn['sum']['preis_netto'])
			{
				$brut_nett = WPSG_NETTO;
			}
			else
			{
				$brut_nett = WPSG_BRUTTO;
			}
			
			// Gesamt Brutto. vor der Verteilung
			$netto_gesamt = $arReturn['sum']['preis_netto'];
			
			foreach ($arReturn['mwst'] as $k => $v)
			{
				
				$proz = ($v['base_value'] - $v['sum']) * 100 / $netto_gesamt; // Anteil 
				$value_anteilig = $value / 100 * $proz; // Der Teil, der mit der Steuer besteuert werden soll 70% mit 19%, 30% mit 7% usw.
				
				if ($brut_nett == WPSG_BRUTTO) 
				{
					 
					$mwst_anteilig = wpsg_calculateSteuer($value_anteilig, WPSG_BRUTTO, $v['value']); // Der anteilige Steuerwert
					
					$arReturn['mwst'][$k]['sum'] -= $mwst_anteilig;
					$arReturn['sum']['mwst'] -= $mwst_anteilig;
					$arReturn['sum']['preis_brutto'] -= $mwst_anteilig;
					$arReturn['sum']['preis_gesamt_brutto'] -= $mwst_anteilig;				
					$arReturn['sum']['preis_netto'] -= $value_anteilig;
					$arReturn['sum']['preis_gesamt_netto'] -= $value_anteilig;
					$arReturn['sum']['preis'] -= $value_anteilig;
					$arReturn['sum']['preis_gesamt'] -= $value_anteilig;
					
				}
				else
				{
					
					$mwst_anteilig = wpsg_calculateSteuer($value_anteilig, WPSG_NETTO, $v['value']); // Der anteilige Steuerwert
					
					$arReturn['mwst'][$k]['sum'] -= $mwst_anteilig;
					$arReturn['sum']['mwst'] -= $mwst_anteilig;
					$arReturn['sum']['preis_brutto'] -= $mwst_anteilig;
					$arReturn['sum']['preis_gesamt_brutto'] -= $mwst_anteilig;				
					$arReturn['sum']['preis_netto'] -= $value_anteilig;
					$arReturn['sum']['preis_gesamt_netto'] -= $value_anteilig;
					$arReturn['sum']['preis'] -= $value_anteilig;
					$arReturn['sum']['preis_gesamt'] -= $value_anteilig;
					
				}
				
			} 
			
		} // public function distributeMwSt($value, &$arReturn)

		/**
		 * Hilfsfunktion
		 * Prüft ob die MwSt mit der id $mwst_key schon im Rückgabe Array ist, wenn nicht wird sie aus der DB geladen
		 */
		public function checkMwSt($tax_key, $country, &$arReturn)
		{
		
			if ($tax_key != null && !array_key_exists($tax_key.'_'.$country->id, (array)$arReturn['mwst']))
			{
		
				if (is_object($country)) $tax_value = $country->getTax($tax_key);
				else $tax_value = 0;
				
				$name = wpsg_ff($tax_value, '%');
				if ($country->id != $this->shop->getDefaultCountry(true)) $name .= ' / '.$country->name;
				
				$arReturn['mwst'][$tax_key.'_'.$country->id] = array(
					'country' => $country->id,
					'tax_key' => $tax_key,
					'sum' => '0',
					'name' => $name,
					'value' => $tax_value		
				); 
		
			}
				
		} // private function checkMwSt($mwst_id, $country, &$arReturn)
		
	} // class wpsg_basket

?>