Index: /changelog
===================================================================
--- /changelog	(revision 8006)
+++ /changelog	(revision 8007)
@@ -510,2 +510,3 @@
 - Feature: Abos kÃ¶nnen jetzt auf 10 Jahre in der Zukunft gesetzt werden
 - Feature: Positionssnummer aus ProduktÃŒbersicht bearbeitbar
+- Feature: 
Index: /controller/wpsg_AdminController.class.php
===================================================================
--- /controller/wpsg_AdminController.class.php	(revision 8006)
+++ /controller/wpsg_AdminController.class.php	(revision 8007)
@@ -1563,7 +1563,13 @@
  
 				check_admin_referer('wpsg-admin-kundendaten');
-				
-			    $this->shop->update_option('wpsg_customerpreset_shipping', $_REQUEST['wpsg_customerpreset_shipping'], false, false, WPSG_SANITIZE_VALUES, array_keys($this->shop->arShipping));
-			    $this->shop->update_option('wpsg_customerpreset_payment', $_REQUEST['wpsg_customerpreset_payment'], false, false, WPSG_SANITIZE_VALUES, array_keys($this->shop->arPayment));
+
+				$arShippingPossible = ['-1'];
+				$arShippingPossible = array_merge($arShippingPossible, array_keys($this->shop->arShipping??[]));
+				
+				$arPaymentPossible = ['-1'];
+				$arPaymentPossible = array_merge($arPaymentPossible, array_keys($this->shop->arPayment??[]));
+				
+			    $this->shop->update_option('wpsg_customerpreset_shipping', $_REQUEST['wpsg_customerpreset_shipping'], false, false, WPSG_SANITIZE_VALUES, $arShippingPossible);
+			    $this->shop->update_option('wpsg_customerpreset_payment', $_REQUEST['wpsg_customerpreset_payment'], false, false, WPSG_SANITIZE_VALUES, $arPaymentPossible);
 			    $this->shop->update_option('wpsg_defaultland', $_REQUEST['wpsg_defaultland'], false, false, WPSG_SANITIZE_INT);
 			    $this->shop->update_option('wpsg_customerpreset_title', $_REQUEST['wpsg_customerpreset_title'], false, false, WPSG_SANITIZE_INT);
Index: /controller/wpsg_BasketController.class.php
===================================================================
--- /controller/wpsg_BasketController.class.php	(revision 8006)
+++ /controller/wpsg_BasketController.class.php	(revision 8007)
@@ -56,26 +56,16 @@
 				
 			}
-
-            $this->shop->checkShippingAvailable();
-            $this->shop->checkPaymentAvailable();
-
-            $array_keys_shipping = array_keys($this->shop->arShipping);
-			if (sizeof($this->shop->arShipping) === 1 || !in_array($_SESSION['wpsg']['checkout']['shipping'], $array_keys_shipping)) {
-
-			    $_SESSION['wpsg']['checkout']['shipping'] = $array_keys_shipping[0];
-
-            }
-
-			$array_keys_payment = array_keys($this->shop->arPayment);
-			if (sizeof($this->shop->arPayment) === 1 || !in_array($_SESSION['wpsg']['checkout']['payment'], $array_keys_payment)) {
-
-			    $_SESSION['wpsg']['checkout']['payment'] = $array_keys_payment[0];
-
-            }
-
+			
 			// Basket aus Session zusammenbauen
-			$this->shop->basket->initFromSession();
+			$this->shop->basket->initFromSession(true);
 			$this->shop->basket->save(false);
-
+			
+			// Basket muss aufgebaut sein
+			$this->shop->checkShippingAvailable();
+			$this->shop->checkPaymentAvailable();            
+			$this->shop->checkCustomerPreset();
+			
+			\wpsg\wpsg_calculation::getSessionCalculation()->update();
+			
 			$this->shop->basket->oCalculation = null;
 			$this->shop->view['basket'] = $this->shop->basket->toArray(false, false);
@@ -83,29 +73,5 @@
 			$this->shop->view['error'] = array();
 			if (isset($_SESSION['wpsg']['errorFields']) && wpsg_checkInput($_SESSION['wpsg']['errorFields'], WPSG_SANITIZE_ARRAY_TEXTFIELD)) $this->shop->view['error'] = $_SESSION['wpsg']['errorFields'];
-
-			//Im Zoo ging es bei den Zusammengesetzten Versandarten nicht, deshalb verbinde ich es weiter oben schon
-			//$this->shop->checkShippingAvailable();
-			//$this->shop->checkPaymentAvailable();
-			
-			// Sollte es nur eine Versand/Zahlungsart geben, dann diese verwenden
-			if (sizeof($this->shop->arShipping) == 1 || sizeof($this->shop->arPayment) == 1) {
-				
-				$this->shop->basket->initFromSession(true);
-				$this->shop->view['basket'] = $this->shop->basket->toArray(false, false);
-				
-			}
-
-			// Zur Sicherheit ÃŒberprÃŒfe ich hier noch einmal die Zahlungsarten
-			// Es kann vorkommen, das eine Zahlungsart voreingestellt ist die nicht mehr verfÃŒgbar ist
-			// Ist nicht ganz schÃ¶n, da aber checkShippingAvailable von toArray() abhÃ€ngig ist
-			if (isset($_SESSION['wpsg']['checkout']['shipping']) && (is_array($this->shop->arShipping) && !array_key_exists($_SESSION['wpsg']['checkout']['shipping'], $this->shop->arShipping))) {
-				
-				unset($_SESSION['wpsg']['checkout']['shipping']);
-				unset($this->shop->basket->arCheckout['shipping']);
-				
-				$this->shop->view['basket'] = $this->shop->basket->toArray(false, false);
-				
-			}
-			
+ 			
 			$this->shop->view['arLander'] = $this->db->fetchAssocField("SELECT L.`id`, L.`name` FROM `".WPSG_TBL_LAND."` AS L ORDER BY L.`name` ", "id", "name");
 			
@@ -204,8 +170,5 @@
 				
 			}
-			
-			// Sollte die Session noch nicht mit Werten gefÃŒllt sein dann hier die Kundenvoreinstellungen laden
-			$this->shop->checkCustomerPreset();
-			
+			 			
 			if ($this->shop->hasMod('wpsg_mod_onepagecheckout')) {
 				
@@ -441,5 +404,5 @@
 				
 			}
-			
+			 
 			// Der Warenkorb wurde abgeschickt
 			if (isset($_REQUEST['wpsg_basket_submit'])) {
@@ -914,5 +877,5 @@
 				$this->redirect($this->shop->getURL(wpsg_ShopController::URL_BASKET));
 				
-			} else if (isset($_REQUEST['wpsg']['checkout']) && !isset($_REQUEST['wpsg_mod'])) {
+			} else if (wpsg_isSizedArray($_REQUEST['wpsg']['checkout']) && !isset($_REQUEST['wpsg_mod'])) {
 
 				// Der AusschluÃ von wpsg_mod ist nÃ¶tig, da PayPal PLUS die Versandart Ã€ndert
Index: /controller/wpsg_ProduktController.class.php
===================================================================
--- /controller/wpsg_ProduktController.class.php	(revision 8006)
+++ /controller/wpsg_ProduktController.class.php	(revision 8007)
@@ -1317,6 +1317,5 @@
 
 				// Artikelnummer = id, wenn nicht gesetzt
-				if (trim($data['anr']) == '')
-				{
+				if (trim($data['anr']) == '') {
 
 					$data = array('anr' => wpsg_q($edit_id));
Index: /controller/wpsg_ShopController.class.php
===================================================================
--- /controller/wpsg_ShopController.class.php	(revision 8006)
+++ /controller/wpsg_ShopController.class.php	(revision 8007)
@@ -1917,33 +1917,120 @@
 		 * Hier kann noch nicht nach vorhandensein der Zahlungsarten in this->arShipping geschaut werden!
 		 */
-		public function checkCustomerPreset()
-		{
-
-			if (!wpsg_isSizedString($_SESSION['wpsg']['checkout']['shipping']) && wpsg_isSizedString($this->get_option('wpsg_customerpreset_shipping')))
-			{
-
-				$_SESSION['wpsg']['checkout']['shipping'] = $this->get_option('wpsg_customerpreset_shipping');
-				if (isset($this->view['basket'])) $this->view['basket']['checkout']['shipping'] = $_SESSION['wpsg']['checkout']['shipping'];
-
-			}
-
-			if (!wpsg_isSizedString($_SESSION['wpsg']['checkout']['payment']) && wpsg_isSizedString($this->get_option('wpsg_customerpreset_payment')))
-			{
-
-				$_SESSION['wpsg']['checkout']['payment'] = $this->get_option('wpsg_customerpreset_payment');
-				if (isset($this->view['basket'])) $this->view['basket']['checkout']['payment'] = $_SESSION['wpsg']['checkout']['payment'];
-
-			}
-
-			if (!wpsg_isSizedString($_SESSION['wpsg']['checkout']['land']) && wpsg_isSizedString($this->get_option('wpsg_defaultland')))
-			{
+		public function checkCustomerPreset() {
+ 
+			if (!wpsg_isSizedString($_SESSION['wpsg']['checkout']['land']) && wpsg_isSizedString($this->get_option('wpsg_defaultland'))) {
 
 				$_SESSION['wpsg']['checkout']['land'] = $this->get_option('wpsg_defaultland');
+				
 				if (isset($this->view['basket'])) $this->view['basket']['checkout']['land'] = $_SESSION['wpsg']['checkout']['land'];
 
 			}
-
-			if (!wpsg_isSizedString($_SESSION['wpsg']['checkout']['title']) && wpsg_isSizedString($this->get_option('wpsg_customerpreset_title')))
-			{
+			
+			if (!wpsg_isSizedString($_SESSION['wpsg']['checkout']['shipping']) && wpsg_isSizedString($this->get_option('wpsg_customerpreset_shipping')) && sizeof($_SESSION['wpsg']['basket']??[]) > 0) {
+
+				$oCalculation = \wpsg\wpsg_calculation::getSessionCalculation();
+				
+				if ($this->get_option('wpsg_customerpreset_shipping') === '-1') {
+					 
+					$min_shipping_key = null; $min_shipping_cost = null;
+					
+					foreach ($this->arShipping as $shipping_key => $shipping_data) {
+						
+						$cost = $oCalculation->calculateCostKey($shipping_data['price']);
+					 
+						if ($cost < $min_shipping_cost || $min_shipping_cost === null) {
+							
+							$min_shipping_cost = $cost;
+							$min_shipping_key = $shipping_key;
+							
+						}
+						
+					}
+					
+					if ($min_shipping_key !== null) {
+						 
+						$_SESSION['wpsg']['checkout']['shipping'] = $min_shipping_key;
+						$oCalculation->update();
+						
+					}  
+					
+				} else if (isset($this->arShipping[$this->get_option('wpsg_customerpreset_shipping')])) {
+				
+					$_SESSION['wpsg']['checkout']['shipping'] = $this->get_option('wpsg_customerpreset_shipping');
+					$oCalculation->update();
+					
+				}
+								 
+			}
+		 
+			// GÃŒltigkeit checken
+			if (($_SESSION['wpsg']['checkout']['shipping']??'') !== '') { 
+			 
+				if (!array_key_exists($_SESSION['wpsg']['checkout']['shipping'], $this->arShipping) && sizeof($this->arShipping) > 0) {
+				 
+					$_SESSION['wpsg']['checkout']['shipping'] = array_keys($this->arShipping)[0];
+
+					$oCalculation = \wpsg\wpsg_calculation::getSessionCalculation();
+					$oCalculation->update();											
+					
+					
+				}
+				
+				$this->view['basket']['checkout']['shipping'] = $_SESSION['wpsg']['checkout']['shipping'];
+
+			}
+
+			if (!wpsg_isSizedString($_SESSION['wpsg']['checkout']['payment']) && wpsg_isSizedString($this->get_option('wpsg_customerpreset_payment')) && sizeof($_SESSION['wpsg']['basket']??[]) > 0) {
+
+				$oCalculation = \wpsg\wpsg_calculation::getSessionCalculation();
+
+				if ($this->get_option('wpsg_customerpreset_payment') === '-1') {
+					 
+					$min_payment_key = null; $min_payment_cost = null;
+					
+					foreach ($this->arPayment as $paymnet_key => $payment_data) {
+						
+						$cost = $oCalculation->calculateCostKey($payment_data['price']);
+					 
+						if ($cost < $min_payment_cost || $min_payment_cost === null) {
+							
+							$min_payment_cost = $cost;
+							$min_payment_key = $paymnet_key;
+							
+						}
+						
+					}
+					
+					if ($min_payment_key !== null) {
+						 
+						$_SESSION['wpsg']['checkout']['payment'] = $min_payment_key;
+						$oCalculation->update();
+						
+					}
+					
+				} else {
+				
+					$_SESSION['wpsg']['checkout']['payment'] = $this->get_option('wpsg_customerpreset_payment');					
+					$oCalculation->update();
+					
+				}
+								 
+			}
+			
+			// GÃŒltigkeit checken
+			if (($_SESSION['wpsg']['checkout']['payment']??'') !== '') { 
+									
+				if (!array_key_exists($_SESSION['wpsg']['checkout']['payment'], $this->arPayment) && sizeof($this->arPayment) > 0) {
+					
+					$_SESSION['wpsg']['checkout']['payment'] = array_keys($this->arPayment)[0];
+					$oCalculation->update();
+											
+				}
+				
+				$this->view['basket']['checkout']['payment'] = $_SESSION['wpsg']['checkout']['payment'];
+				
+			}
+
+			if (!wpsg_isSizedString($_SESSION['wpsg']['checkout']['title']) && wpsg_isSizedString($this->get_option('wpsg_customerpreset_title'))) {
 
 				$_SESSION['wpsg']['checkout']['title'] = $this->get_option('wpsg_customerpreset_title');
@@ -3303,10 +3390,8 @@
 				]
 			];
-
-            $this->checkCustomerPreset();
 			
 			$this->callMods('addShipping', array(&$this->arShipping));
 			$this->callMods('addPayment', array(&$this->arPayment));
-
+ 
 			$this->callMods('addShipping', array(&$this->arShippingAll, true));
 			            
@@ -3334,8 +3419,5 @@
 
 			if (!is_admin()) {
-
-				// Sollte die Session noch nicht mit Werten gefÃŒllt sein dann hier die Kundenvoreinstellungen laden
-				$this->checkCustomerPreset();
-
+ 
 				// Modulverarbeitung
 				$this->callMods('template_redirect');
@@ -4770,14 +4852,4 @@
 
 			$this->callMods('checkShippingAvailable', array(&$this->arShipping));
-
-			if (isset($_SESSION['wpsg']['checkout']['shipping'])) {
-								
-				if (!array_key_exists($_SESSION['wpsg']['checkout']['shipping'], $this->arShipping)) {
-						
-					$_SESSION['wpsg']['checkout']['shipping'] = array_keys($this->arShipping)[0];
-						
-				}
-												
-			}
 			
 		} // public function checkShippingAvailable()
Index: /lib/functions.inc.php
===================================================================
--- /lib/functions.inc.php	(revision 8006)
+++ /lib/functions.inc.php	(revision 8007)
@@ -537,4 +537,11 @@
 				break;
 			
+			case WPSG_SANITIZE_DATE_EN:
+				
+				if (preg_match('/^\d{4}\-\d{2}\-\d{2}$/', $val)) $bReturn = true;
+				else $bReturn = false;
+				
+				break;
+				
 			case WPSG_SANITIZE_DATE:
 				
Index: /lib/wpsg_basket.class.php
===================================================================
--- /lib/wpsg_basket.class.php	(revision 8006)
+++ /lib/wpsg_basket.class.php	(revision 8007)
@@ -217,4 +217,5 @@
 			
 			unset($_SESSION['wpsg']['basket'][$produkt_index]);
+			\wpsg\wpsg_calculation::getSessionCalculation()->update();;
 			
 			$this->shop->callMods('basket_removeProduktFromSession', [$produkt_index]);			
@@ -1587,5 +1588,5 @@
 						if (wpsg_isSizedInt($arReturn['checkout']['shipping']) && !@array_key_exists($arReturn['checkout']['shipping'], $this->shop->arShipping))
 						{
-							
+						
 							unset($arReturn['checkout']['shipping']);
 							
@@ -1608,5 +1609,5 @@
 						
 						// 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
+						// Sonst ist die Grundlage fÃŒr die Berechnung nicht gleich
 						$arBasketPreShipping = $arReturn;
 						
@@ -1729,5 +1730,5 @@
 				} else {
 
-					$this->oCalculation->fromSession();
+					$this->oCalculation = \wpsg\wpsg_calculation::getSessionCalculation(); // ->fromSession();
 
 				}
Index: /lib/wpsg_calculation.class.php
===================================================================
--- /lib/wpsg_calculation.class.php	(revision 8006)
+++ /lib/wpsg_calculation.class.php	(revision 8007)
@@ -1369,4 +1369,6 @@
         public function calculateCostKey($set) {
 
+			if (strval($set) === '0' || strval($set) === '0,00' || strval($set) === '0.00') return 0;
+			
 			list($typ, $set) = explode('-', $set);
 
@@ -1377,5 +1379,9 @@
 			else if ($typ === 's') $value = $this->arCalculation['sum']['amount']; // Menge
 			else if ($typ === 'g') $value = $this->dWeight; // Gewicht
-			else throw new \Exception(wpsg_translate(__('Typ (#1#) fÃŒr KostenschlÃŒssel nicht definiert.', 'wpsg'), $typ));
+			else { 
+				
+				throw new \Exception(wpsg_translate(__('Typ (#1#) fÃŒr KostenschlÃŒssel nicht definiert.', 'wpsg'), $typ)); 
+			
+			}
 
 			foreach ($arKosten as $k) {
@@ -1599,4 +1605,58 @@
 		}
 
+		public function update() {
+			
+			unset(self::$functionscache['getSessionCalculation']);
+			
+		}
+		
+		public function getShippingName() {
+			
+			$arName = [];
+			
+			foreach ($this->arCalculationRow as $k_cr => $cr) {
+				
+				if ($cr['type'] === 'shipping') {
+					
+					if (strpos($cr['data']['shipping_key'], '-') !== false) {
+						
+						$arSubName = [];
+						
+						foreach (explode('-', $cr['data']['shipping_key']) as $shipping_key) {
+				
+							$arSubName[] = $this->shop->arShippingAll[$shipping_key]['name']??'';	
+							
+						}				
+						
+						$arName[] = implode(' + ', $arSubName);	
+						
+					} else {
+					
+						$arName[] = $this->shop->arShippingAll[$cr['data']['shipping_key']]['name']??'';
+						
+					}
+					
+				}
+				
+			}
+			
+			return implode(' / ', $arName);
+			
+		}
+		
+		public function getPaymentName() {
+			
+			$arName = [];
+			
+			foreach ($this->arCalculationRow as $k_cr => $cr) {
+				
+				if ($cr['type'] === 'payment') $arName[] = $this->shop->arPayment[$cr['data']['payment_key']]['name']??'';
+				
+			}
+			
+			return implode(' / ', $arName);
+			
+		}
+		
         /**
          * Gibt die Anzahl an Produkten zurÃŒck
@@ -1617,4 +1677,13 @@
         }
 
+		public function getShippingSum($bruttonetto = WPSG_NETTO) {
+		
+			$arCalculation = $this->getCalculationArray();
+			
+			if ($bruttonetto === WPSG_BRUTTO) return $arCalculation['sum']['shipping_brutto'];
+			else return $arCalculation['sum']['shipping_netto'];
+						
+		}
+		
 		public function getSum($bruttonetto = WPSG_NETTO) {
 
@@ -1706,6 +1775,6 @@
 			
 			$cache_key = __FUNCTION__.implode('|', \func_get_args());
-			
-			if (!isset(self::$functionscache[$cache_key]) || $no_cache) {
+			 
+			if (!isset(self::$functionscache[$cache_key]) || self::$functionscache[$cache_key] === null || $no_cache) {
 			
 				$oCalculation = new wpsg_calculation();
Index: /model/wpsg_model.class.php
===================================================================
--- /model/wpsg_model.class.php	(revision 8006)
+++ /model/wpsg_model.class.php	(revision 8007)
@@ -194,4 +194,6 @@
 
                 }
+				
+				if ($this->arMeta !== null) $this->arMeta[$meta_key] = $meta_value;
 
             }
Index: /model/wpsg_order_product.class.php
===================================================================
--- /model/wpsg_order_product.class.php	(revision 8006)
+++ /model/wpsg_order_product.class.php	(revision 8007)
@@ -87,4 +87,10 @@
 		} // public function getCount()
 		 
+		public function getDescription() {
+			
+			return $this->data['beschreibung'];
+			
+		}
+		
 		public function getProductIndex()
 		{
Index: /mods/mod_rechnungen/wpsg_invoice.php
===================================================================
--- /mods/mod_rechnungen/wpsg_invoice.php	(revision 8007)
+++ /mods/mod_rechnungen/wpsg_invoice.php	(revision 8007)
@@ -0,0 +1,78 @@
+<?php
+
+    declare(strict_types=1);
+    
+    /**
+     * @author: Daniel Schmitzer (daschmi@daschmi.de)
+     * @date: 09.06.22
+     * @time: 10:17
+     */
+     
+    namespace wpsg;
+	
+	class wpsg_invoice extends \wpsg_model {
+		
+		 static $_tableName = 'WPSG_TBL_RECHNUNGEN';
+		
+		 /**
+		 * LÃ€dt die Daten  
+		 */
+		public function load($invoice_id) {
+		
+			parent::load($invoice_id);
+				
+			$this->data = $this->db->fetchRow("SELECT I.* FROM `".WPSG_TBL_RECHNUNGEN."` AS I WHERE I.`id` = '".wpsg_q($invoice_id)."' ");
+			
+			if ($this->data === null || $this->data['id'] != $invoice_id) throw new \wpsg\Exception(
+				wpsg_translate(__('Die Daten einer Rechnung konnten nicht geladen werden', 'wpsg'), $invoice_id)
+			);
+			
+		}
+		 
+		public function isInvoice() {
+			
+			return $this->__get('rnr') !== '';
+			
+		}
+		
+		public function isStorno() {
+			
+			return $this->__get('gnr') !== '';
+			
+		}
+
+		/**
+		 * @return \wpsg_order 
+		 */
+		public function getOrder() {
+
+			return \wpsg_order::getInstance(intval($this->__get('o_id')));
+			
+		}
+		
+		public function getNr($bLink = false) {
+			
+			$strReturn = '';
+			
+			if ($bLink) {
+				
+				$strReturn .= '<a class="link_invoice '.(($this->isStorno())?'bg_storno':'').' '.(($this->isInvoice())?'bg_invoice':'').'" href="';
+				$strReturn .= wp_nonce_url(WPSG_URL_WP.'wp-admin/admin.php?page=wpsg-Order&action=ajax&noheader=1&mod=wpsg_mod_rechnungen&do=getRechnung&edit_id='.$this->getOrder()->getId().'&r_id='.$this->getId(), 'wpsg-mod_invoice-order_ajax-getRechnung-'.$this->getId());
+				$strReturn .= '" target="_blank">';
+				
+			}
+			
+			if ($this->isInvoice()) $strReturn .= 'R '.$this->__get('rnr');
+			else if ($this->isStorno()) $strReturn .= 'RK '.$this->__get('gnr');
+			
+			if ($bLink) {
+				
+				$strReturn .= '</a>';
+				
+			}
+			
+			return $strReturn;
+			
+		}
+		
+	}
Index: /mods/wpsg_mod_basic.class.php
===================================================================
--- /mods/wpsg_mod_basic.class.php	(revision 8006)
+++ /mods/wpsg_mod_basic.class.php	(revision 8007)
@@ -375,4 +375,6 @@
 		public function order_view_afterpayment(&$order_id) { }
 		
+		public function order_view_orderdata_after($order_id) { }
+		
 		/**
 		 * Wird bei der Ãnderung des Bestellstatus aufgerufen
Index: /mods/wpsg_mod_deliverytime.class.php
===================================================================
--- /mods/wpsg_mod_deliverytime.class.php	(revision 8006)
+++ /mods/wpsg_mod_deliverytime.class.php	(revision 8007)
@@ -66,11 +66,9 @@
 		} // public function install()
 
-		public function product_addedit_content(&$product_content, &$product_data)
-		{
+		public function product_addedit_content(&$product_content, &$product_data) {
 
 			if (isset($_REQUEST['wpsg_lang'])) return;
 
-			if ($this->shop->get_option('wpsg_mod_deliverytime_mode') == self::MODE_SELECT)
-			{
+			if ($this->shop->get_option('wpsg_mod_deliverytime_mode') == self::MODE_SELECT) {
 
 				$this->shop->view['wpsg_mod_deliverytime']['arSelection'] = $this->getPossibleSelection();
@@ -86,7 +84,8 @@
 			);
 			
-			foreach ($pages as $k => $v)
-			{
+			foreach ($pages as $k => $v) {
+				
 				$arPages[$v->ID] = $v->post_title.' (ID:'.$v->ID.')';
+				
 			}
 			
@@ -109,6 +108,6 @@
 
 			$product_content['general']['content'] .= $this->shop->render(WPSG_PATH_VIEW.'/mods/mod_deliverytime/produkt_addedit_allgemein.phtml', false);
+			
 		}
-
 
 		public function settings_edit()
@@ -134,6 +133,5 @@
 		} // public function settings_edit()
 
-		public function settings_save()
-		{
+		public function settings_save() {
 
 		    $this->shop->update_option('wpsg_mod_deliverytime_mode', $_REQUEST['wpsg_mod_deliverytime_mode'], false, false, WPSG_SANITIZE_INT);
@@ -164,10 +162,8 @@
 			$this->shop->addTranslationString('wpsg_mod_deliverytime_mode_select_values', wpsg_sinput(WPSG_SANITIZE_TEXTFIELD, $_REQUEST['wpsg_mod_deliverytime_mode_select_values']));
 			$this->shop->addTranslationString('wpsg_mod_deliverytime_mode_select_default', wpsg_sinput(WPSG_SANITIZE_INT, $_REQUEST['wpsg_mod_deliverytime_mode_select_default']));
-						
-
+			
 		} // public function settings_save()
 
-		public function produkt_save_before(&$produkt_data)
-		{
+		public function produkt_save_before(&$produkt_data) {
  
 		    $produkt_data['wpsg_mod_deliverytime_deliverytime'] = wpsg_q(wpsg_sinput(WPSG_SANITIZE_FLOAT, $_REQUEST['wpsg_mod_deliverytime']['wpsg_mod_deliverytime_deliverytime']));
@@ -207,4 +203,53 @@
 		} // public function produkt_save_before(&$produkt_data)
 
+		public function product_bottom(&$product_id, $template_index) {
+			
+			$oProduct = wpsg_product::getInstance($product_id);
+			
+			$set_available = $oProduct->getMeta('wpsg_mod_deliverytime_set_available', false, '0');
+			
+			if ($set_available === '1') {
+			
+				$this->shop->view['wpsg_mod_deliverytime']['set_available'] = $set_available;
+				$this->shop->view['wpsg_mod_deliverytime']['available_date'] = $oProduct->getMeta('wpsg_mod_deliverytime_available_date', false, date('Y-m-d'));
+
+				$this->shop->render(WPSG_PATH_VIEW.'/mods/mod_deliverytime/product_bottom.phtml');
+				
+			}
+				
+		}
+		
+		public function produkt_edit(&$product_data) {
+			
+			if (isset($product_data['id'])) {
+				
+				$oProduct = wpsg_product::getInstance(intval($product_data['id']));
+				
+				$this->shop->view['wpsg_mod_deliverytime']['set_available'] = $oProduct->getMeta('wpsg_mod_deliverytime_set_available', false, '0');
+				$this->shop->view['wpsg_mod_deliverytime']['available_date'] = $oProduct->getMeta('wpsg_mod_deliverytime_available_date', false, date('Y-m-d'));
+				
+			}
+			
+		}
+		
+		public function produkt_save(&$product_id) {
+			
+			$oProduct = wpsg_product::getInstance($product_id);
+			
+			if (wpsg_checkInput($_REQUEST['wpsg_mod_deliverytime']['set_available'], WPSG_SANITIZE_CHECKBOX)) {
+				
+				$oProduct->setMeta('wpsg_mod_deliverytime_set_available', $_REQUEST['wpsg_mod_deliverytime']['set_available']);	
+				
+			}
+			 
+			if (wpsg_checkInput($_REQUEST['wpsg_mod_deliverytime']['available_date'], WPSG_SANITIZE_DATE_EN)) {
+				
+				$oProduct->setMeta('wpsg_mod_deliverytime_available_date', $_REQUEST['wpsg_mod_deliverytime']['available_date']);	
+				
+			}
+			
+			
+		}
+		
 		public function mail_row($index, $produkt)
 		{
Index: /mods/wpsg_mod_onepagecheckout.class.php
===================================================================
--- /mods/wpsg_mod_onepagecheckout.class.php	(revision 8006)
+++ /mods/wpsg_mod_onepagecheckout.class.php	(revision 8007)
@@ -119,4 +119,5 @@
 			$this->shop->checkShippingAvailable();
 			$this->shop->checkPaymentAvailable();
+			$this->shop->checkCustomerPreset();
 			
 			$this->shop->view['arShipping'] = $this->shop->arShipping;
Index: /mods/wpsg_mod_rechnungen.class.php
===================================================================
--- /mods/wpsg_mod_rechnungen.class.php	(revision 8006)
+++ /mods/wpsg_mod_rechnungen.class.php	(revision 8007)
@@ -4,6 +4,5 @@
 	 * Modul welches das Schreiben von Rechnungen ermÃ¶glicht
 	 */
-	class wpsg_mod_rechnungen extends wpsg_mod_basic
-	{
+	class wpsg_mod_rechnungen extends wpsg_mod_basic {
 		
 		var $lizenz = 1;
@@ -18,6 +17,5 @@
 		 * Costructor
 		 */
-		public function __construct()
-		{
+		public function __construct() {
 			
 			parent::__construct();
@@ -48,5 +46,7 @@
 				'user5' => __('Benutzer 5', 'wpsg')	
 			);
-						
+			
+			require_once dirname(__FILE__).DIRECTORY_SEPARATOR.'mod_rechnungen'.DIRECTORY_SEPARATOR.'wpsg_invoice.php';
+			
 		} // public function __construct()
 		 
@@ -385,4 +385,28 @@
 			
 		} // public function order_view_content($order_id) { }
+		
+		public function order_view_row(&$p, $i) { 
+
+			$this->shop->view['wpsg_mod_rechnungen']['product'] = $p;
+			$this->shop->view['wpsg_mod_rechnungen']['i'] = $i;
+		
+			$this->shop->view['wpsg_mod_rechnungen']['oOrderProduct'] = wpsg_order_product::getInstance($p['order_product_id']);
+			$this->shop->view['wpsg_mod_rechnungen']['storno_amount'] = $this->getAmountToStorno($this->shop->view['wpsg_mod_rechnungen']['oOrderProduct']);
+			$this->shop->view['wpsg_mod_rechnungen']['invoice_amount'] = $this->getAmountToInvoice($this->shop->view['wpsg_mod_rechnungen']['oOrderProduct']);
+			
+			$this->shop->render(WPSG_PATH_VIEW.'/mods/mod_rechnungen/order_view_row.phtml');
+			
+		} // public function order_view_row(&$p, $i)
+		
+		public function order_view_orderdata_after($order_id) { 
+			
+			$oOrder = wpsg_order::getInstance($order_id);
+			
+			$this->shop->view['oOrder'] = $oOrder;
+			$this->shop->view['oCustomer'] = $oOrder->getCustomer();
+			
+			$this->shop->render(WPSG_PATH_VIEW.'/mods/mod_rechnungen/order_view_orderdata_after.phtml');
+			
+		}
 		
 		public function order_ajax() {
@@ -727,7 +751,8 @@
 		} // public function basket_save_done(&$order_id, &$kunde_id, &$oBasket)
 		
-		private function writeGutschrift($order_id, $gnr_id, $storno_fee, $bPreview)
-		{
-					
+		private function _writeGutschrift($order_id, $gnr_id, $storno_fee, $bPreview) {
+					
+			die(wpsg_debug($_REQUEST));
+			
 			$this->shop->view['invoice'] = $this->db->fetchRow("SELECT * FROM `".WPSG_TBL_RECHNUNGEN."` WHERE `id` = '".wpsg_q($gnr_id)."' ");
 			
@@ -914,22 +939,174 @@
 						
 		} // private function writeGutschrift($order_id)
-		 
+		
+		private function writeGutschrift($order_id, $gnr_id, $storno_fee, $bPreview) {
+				
+			if (!$bPreview) {
+			
+				$this->shop->view['invoice'] = $this->db->fetchRow("SELECT * FROM `".WPSG_TBL_RECHNUNGEN."` WHERE `id` = '".wpsg_q($gnr_id)."' ");
+				$this->shop->view['rnr'] = $this->shop->view['invoice']['gnr'];
+				
+			} else {
+				
+				$this->shop->view['rnr'] = __('Vorschau', 'wpsg');
+				
+			}
+			
+			$this->shop->view['data'] = $this->db->fetchRow("
+				SELECT
+					O.*
+				FROM
+					`".WPSG_TBL_ORDER."` AS O
+				WHERE
+					O.`id` = '".wpsg_q($order_id)."'
+			");			
+
+			if (trim($this->shop->view['data']['language']) != '') $this->shop->setTempLocale($this->shop->view['data']['language']);
+			
+			$this->getAdresse($this->shop->view['data']['k_id']);
+						 
+			$this->shop->view['fussText'] = false;
+						
+			$oCalculation = new \wpsg\wpsg_calculation();
+			
+			$oOrder = wpsg_order::getInstance($order_id);
+			$this->shop->view['oOrder'] = $oOrder;
+			
+			$this->shop->view['preview'] = $bPreview;
+			$this->shop->view['rDatum'] = date('d.m.Y');
+			
+			$oDefaultCountry = $oOrder->getInvoiceCountry();	
+			$oCalculation->addCountry($oDefaultCountry->id, $oDefaultCountry->mwst, $oDefaultCountry->mwst_a,$oDefaultCountry->mwst_b, $oDefaultCountry->mwst_c, $oDefaultCountry->mwst_d, true);
+			
+		    if (($_REQUEST['storno_shippay']??'0') === '1') {
+				 
+				$oCalculation->addShipping(
+					$oOrder->__get('shipping_set'), 
+					$oOrder->__get('shipping_bruttonetto'),
+					$oOrder->__get('shipping_tax_key'),
+					$oOrder->__get('shipping_key')
+				);
+				
+				$oCalculation->addPayment(
+					$oOrder->__get('payment_set'), 
+					$oOrder->__get('payment_bruttonetto'),
+					$oOrder->__get('payment_tax_key'),
+					$oOrder->__get('payment_key')
+				);
+				
+			}
+			
+			$arProduct = [];
+			
+			$tax_view = WPSG_BRUTTO;
+			
+			foreach ($_REQUEST['storno_products'] as $order_product_id => $order_product_info) {
+				
+				if ($order_product_info['set'] === '1') {
+					 
+					$oOrderProduct = wpsg_order_product::getInstance($order_product_id);
+				
+					if (!$bPreview) {
+						
+						$invoice_data = json_decode($oOrderProduct->getMeta('wpsg_mod_rechnungen_data', false, 'null'), true);
+						if (!is_array($invoice_data)) $invoice_data = [];
+						
+						$invoice_data[] = [						
+							'amount' => $order_product_info['amount'],
+							'invoice_id' => $gnr_id						
+						];
+						
+						$oOrderProduct->setMeta('wpsg_mod_rechnungen_data', json_encode($invoice_data));
+						
+					}
+					
+					$oCalculation->addProduct(
+						$oOrderProduct->getPrice($tax_view),
+						$tax_view,
+						$oOrderProduct->getProduct()->__get('mwst_key'),
+						$order_product_info['amount'],
+						$oOrderProduct->getProductKey()
+					); 
+					
+					$p = [
+						'oOrderProduct' => $oOrderProduct,
+						'id' => $oOrderProduct->getProductKey(),
+						'product_index' => $oOrderProduct->getProductIndex(),
+						'productkey' => $oOrderProduct->getProductKey(),
+						'menge' => $order_product_info['amount'],
+						'price' => $oOrderProduct->getPrice($tax_view),
+						'anr' => $oOrderProduct->getProduct()->getNr(), 
+						'mwst_value' => 0,
+						'preis_netto' => $oOrderProduct->getPrice(WPSG_NETTO),
+						'preis_brutto' => $oOrderProduct->getPrice(WPSG_BRUTTO),
+						'name' => $oOrderProduct->getProduct()->getProductName(false),
+						'detailname' => $oOrderProduct->getProduct()->getProductName(true),
+						'beschreibung' => $oOrderProduct->getDescription()						
+					];
+					
+					// Ãbersetzung
+					if ($this->shop->isOtherLang()) {
+					
+						$produkt_trans = $this->db->fetchRow("SELECT * FROM `".WPSG_TBL_PRODUCTS."` WHERE `lang_parent` = '".wpsg_q($oOrderProduct->getProduct()->getId())."' AND `lang_code` = '".wpsg_q($this->shop->getCurrentLanguageCode())."'");
+					
+						if ($produkt_trans['id'] > 0) {
+								
+							$p['name'] = $produkt_trans['name'];
+							$p['beschreibung'] = $produkt_trans['beschreibung'];
+							$p['detailname'] = $produkt_trans['detailname'];
+					
+						}
+					
+					}
+					
+					$arProduct[] = $p;
+					
+				}
+				
+			}
+			
+			$this->shop->view['basket'] = [
+				'arCalculation' => $oCalculation->getCalculationArray(),
+				'produkte' => $arProduct,
+				'sum' => [
+					'preis_gesamt_netto' => $oCalculation->getSum(WPSG_NETTO),
+					'preis_gesamt_brutto' => $oCalculation->getSum(WPSG_BRUTTO),					
+				]
+			];
+			
+			if ($storno_fee !== '') {
+				
+				if (strpos($storno_fee, '%') !== false) {
+					
+					$storno_proz = str_replace('%', '', $storno_fee);					
+					$storno_fee_value = $this->shop->view['basket']['sum']['preis_gesamt_brutto'] - ($this->shop->view['basket']['sum']['preis_gesamt_brutto'] / 100 * $storno_proz);
+					
+				} else $storno_fee_value = wpsg_tf($storno_fee);
+				
+				$this->shop->view['storno_fee_value'] = $storno_fee_value;
+				
+				$this->shop->view['basket']['sum']['preis_gesamt_brutto'] -= $storno_fee_value;
+				$this->shop->view['basket']['sum']['preis_gesamt_netto'] -= wpsg_calculatePreis($storno_fee_value, WPSG_NETTO, 19);
+				
+			}
+			
+			if (($_REQUEST['storno_shippay']??'0') === '1') {
+				
+				$this->shop->view['basket']['sum']['preis_shipping'] = $oCalculation->getShippingSum(WPSG_BRUTTO);
+				
+			}
+			
+			$this->shop->view['filename'] = $gnr_id;
+			$this->shop->view['filename_out'] = $this->shop->view['invoice']['gnr'].'.pdf';
+			
+			$this->shop->render(WPSG_PATH_VIEW.'/mods/mod_rechnungen/accounting_pdf.phtml');
+			
+			$this->shop->restoreTempLocale();
+						
+		} // private function writeGutschrift($order_id)
+		
 		public function writeRechnung($order_id, $preview, $bOutput = true) {
-
-			// PrÃŒfen ob schon eine Rechnung zu dieser Bestellung existiert und eventuell Fehler werfen
-			if (!$preview) {
-			
-				$lastEntry = $this->db->fetchRow("SELECT * FROM `".WPSG_TBL_RECHNUNGEN."` WHERE `o_id` = '".wpsg_q($order_id)."' AND `rnr` != '' ORDER BY `id` DESC LIMIT 1");
-				 
-				if (strtotime($lastEntry['datum']) > 0 && strtotime($lastEntry['storno']) === false) {
-					
-					throw new \Exception(wpsg_translate(__('Rechnung konnte nicht geschrieben werden, da fÃŒr diese Bestellung (ID:#1#) bereits eine Rechnung (NR:#2#) geschrieben wurde.'), $order_id, $lastEntry['rnr']));
-					
-				} 
-				
-			}
-            
+			
 			$this->shop->view['output'] = $bOutput;
-
 			$this->shop->view['data'] = $this->db->fetchRow("
 				SELECT
@@ -940,26 +1117,20 @@
 					O.`id` = '".wpsg_q($order_id)."'
 			");
-
+			
 			// Wurde die Bestellung in einer anderen Sprache gemacht
 			if (trim($this->shop->view['data']['language']) != '') $this->shop->setTempLocale($this->shop->view['data']['language']);
-
+			
 			$this->getAdresse($this->shop->view['data']['k_id']);
-
+			 
+			$oOrder = wpsg_order::getInstance($order_id);
+						
 			$custom_data = @unserialize($this->shop->view['data']['custom_data']);
-			$this->shop->view['basket'] = $custom_data['basket'];
-			
-			////if (!is_array($custom_data['basket']))
-			{
-                
-				$basket = new wpsg_basket();
-				$basket->initFromDB($order_id, true);
-				$this->shop->view['basket'] = $basket->toArray(true);
-                	
-			}
-            			
+		
 			$this->shop->view['kunde']['land'] = $this->db->fetchRow("SELECT L.* FROM `".WPSG_TBL_LAND."` AS L WHERE L.`id` = '".wpsg_q($this->shop->view['kunde']['land'])."'");
 			$this->shop->view['data']['shipping_land'] = $this->db->fetchRow("SELECT L.* FROM `".WPSG_TBL_LAND."` AS L WHERE L.`id` = '".wpsg_q(wpsg_getStr($this->shop->view['data']['shipping_land']))."'");
-			$this->shop->view['rDatum'] = wpsg_sinput("key", @$_REQUEST['wpsg_rechnungen_datum']);
-			            
+			
+			if (wpsg_checkInput($_REQUEST['wpsg_rechnungen_datum'], WPSG_SANITIZE_DATE_EN)) $this->shop->view['rDatum'] = date('d.m.Y', strtotime($_REQUEST['wpsg_rechnungen_datum']));
+			else throw \wpsg\Exception::getSanitizeException();
+		
 			if ($this->shop->hasMod('wpsg_mod_shippingadress') && $this->shop->callMod('wpsg_mod_shippingadress', 'check_different_shippingadress', array('k_id' => @$this->shop->view['data']['k_id'], 'o_id' => @$this->shop->view['data']['id']))) {
 				
@@ -980,9 +1151,11 @@
 				$this->shop->view['data']['shipping_plz'] = $temp['plz'];
 				$this->shop->view['data']['shipping_ort'] = $temp['ort'];
+				
 				$t = $this->db->fetchRow("SELECT L.* FROM `".WPSG_TBL_LAND."` AS L WHERE L.`id` = '".wpsg_q($temp['land'])."'");
-				//$this->shop->view['data']['shipping_land'] = $t['kuerzel'];
+				
 				$this->shop->view['data']['shipping_land'] = array();
 				$this->shop->view['data']['shipping_land']['name'] = $t['kuerzel'];
-			}			
+				
+			}	
 			
 			$this->shop->view['payment'] = $this->shop->getPaymentName(@$this->shop->view['data']['type_payment'], $order_id);
@@ -991,39 +1164,100 @@
 			if ($_REQUEST['wpsg_rechnungen_faelligkeit'] == '1') {
 			    
-				$this->shop->view['faelligkeitdatum'] = wpsg_sinput("key", $_REQUEST['wpsg_rechnungen_faelligkeitsdatum']);
-				
-			}
-            				
-			// Beschreibung dazuladen
-			foreach ($this->shop->view['basket']['produkte'] as $k => $v) {
-				
-				$produkt_id = $this->shop->getProduktID($v['id']);
-				
-				$this->shop->view['basket']['produkte'][$k]['beschreibung'] = $this->db->fetchOne("
-					SELECT
-						P.`beschreibung`
-					FROM
-						`".WPSG_TBL_PRODUCTS."` AS P
-					WHERE
-						P.`id` = '".wpsg_q($produkt_id)."'
-				");
-				
-				// Ãbersetzung
-				if ($this->shop->isOtherLang())
-				{
-				
-					$produkt_trans = $this->db->fetchRow("SELECT * FROM `".WPSG_TBL_PRODUCTS."` WHERE `lang_parent` = '".wpsg_q($produkt_id)."' AND `lang_code` = '".wpsg_q($this->shop->getCurrentLanguageCode())."'");
-				
-					if ($produkt_trans['id'] > 0)
-					{
-							
-						$this->shop->view['basket']['produkte'][$k]['name'] = $produkt_trans['name'];
-						$this->shop->view['basket']['produkte'][$k]['beschreibung'] = $produkt_trans['beschreibung'];
-						$this->shop->view['basket']['produkte'][$k]['detailname'] = $produkt_trans['detailname'];
-				
+				if (wpsg_checkInput($_REQUEST['wpsg_rechnungen_faelligkeitsdatum'], WPSG_SANITIZE_DATE_EN)) $this->shop->view['faelligkeitdatum'] = date('d.m.Y', strtotime($_REQUEST['wpsg_rechnungen_faelligkeitsdatum']));
+				else throw \wpsg\Exception::getSanitizeException();
+				
+			}
+			
+			$oCalculation = new \wpsg\wpsg_calculation();
+			
+			$oDefaultCountry = $oOrder->getInvoiceCountry();			
+			$oCalculation->addCountry($oDefaultCountry->id, $oDefaultCountry->mwst, $oDefaultCountry->mwst_a,$oDefaultCountry->mwst_b, $oDefaultCountry->mwst_c, $oDefaultCountry->mwst_d, true);
+					
+			if (($_REQUEST['wpsg_rechnungen_shippay']??'0') === '1') {
+				
+				$oCalculation->addShipping(
+					$oOrder->__get('shipping_set'), 
+					$oOrder->__get('shipping_bruttonetto'),
+					$oOrder->__get('shipping_tax_key'),
+					$oOrder->__get('shipping_key')
+				);
+				
+				$oCalculation->addPayment(
+					$oOrder->__get('payment_set'), 
+					$oOrder->__get('payment_bruttonetto'),
+					$oOrder->__get('payment_tax_key'),
+					$oOrder->__get('payment_key')
+				);
+				
+			}
+			
+			$arProduct = [];
+			
+			$tax_view = WPSG_BRUTTO;
+			
+			foreach ($_REQUEST['invoice_products'] as $order_product_id => $order_product_info) {
+				
+				if ($order_product_info['set'] === '1') {
+					
+					$oOrderProduct = wpsg_order_product::getInstance($order_product_id);
+					
+					$oCalculation->addProduct(
+						$oOrderProduct->getPrice($tax_view),
+						$tax_view,
+						$oOrderProduct->getProduct()->__get('mwst_key'),
+						$order_product_info['amount'],
+						$oOrderProduct->getProductKey()
+					); 
+					
+					$p = [
+						'oOrderProduct' => $oOrderProduct,
+						'id' => $oOrderProduct->getProductKey(),
+						'product_index' => $oOrderProduct->getProductIndex(),
+						'productkey' => $oOrderProduct->getProductKey(),
+						'menge' => $order_product_info['amount'],
+						'price' => $oOrderProduct->getPrice($tax_view),
+						'anr' => $oOrderProduct->getProduct()->getNr(), 
+						'mwst_value' => 0,
+						'preis_netto' => $oOrderProduct->getPrice(WPSG_NETTO),
+						'preis_brutto' => $oOrderProduct->getPrice(WPSG_BRUTTO),
+						'name' => $oOrderProduct->getProduct()->getProductName(false),
+						'detailname' => $oOrderProduct->getProduct()->getProductName(true),
+						'beschreibung' => $oOrderProduct->getDescription()						
+					];
+					
+					// Ãbersetzung
+					if ($this->shop->isOtherLang()) {
+					
+						$produkt_trans = $this->db->fetchRow("SELECT * FROM `".WPSG_TBL_PRODUCTS."` WHERE `lang_parent` = '".wpsg_q($oOrderProduct->getProduct()->getId())."' AND `lang_code` = '".wpsg_q($this->shop->getCurrentLanguageCode())."'");
+					
+						if ($produkt_trans['id'] > 0) {
+								
+							$p['name'] = $produkt_trans['name'];
+							$p['beschreibung'] = $produkt_trans['beschreibung'];
+							$p['detailname'] = $produkt_trans['detailname'];
+					
+						}
+					
 					}
-				
-				}
-								
+					
+					$arProduct[] = $p;
+					
+				}
+				
+			}
+			
+			$this->shop->view['basket'] = [
+				'arCalculation' => $oCalculation->getCalculationArray(),
+				'produkte' => $arProduct,
+				'sum' => [
+					'preis_gesamt_netto' => $oCalculation->getSum(WPSG_NETTO),
+					'preis_gesamt_brutto' => $oCalculation->getSum(WPSG_BRUTTO)
+				]
+			];
+			
+			if (($_REQUEST['wpsg_rechnungen_shippay']??'0') === '1') {
+				
+				$this->shop->view['basket']['sum']['preis_shipping'] = $oCalculation->getShippingSum(WPSG_BRUTTO);
+				
 			}
 			
@@ -1043,7 +1277,7 @@
 							
 			$rnr = $this->shop->replaceUniversalPlatzhalter($rnr, $order_id);
-            
-			if ($preview)
-			{
+			$oInvoice = null;
+			
+			if ($preview) {
 				
 				$this->shop->view['preview'] = true;
@@ -1051,7 +1285,5 @@
 				$r_id = "Vorschau";
 												
-			}
-			else
-			{
+			} else {
 				 
 				$this->shop->view['preview'] = false;
@@ -1061,6 +1293,5 @@
 				
 				// Status Ã€ndern
-				if ($_REQUEST['wpsg_rechnungen_status'] == "1")
-				{
+				if ($_REQUEST['wpsg_rechnungen_status'] == "1") {
 						
 					$this->shop->setOrderStatus($order_id, wpsg_sinput("key", $_REQUEST['wpsg_rechnungen_status_neu']), false);
@@ -1077,4 +1308,13 @@
 				);
 				
+				$oInvoice = \wpsg\wpsg_invoice::getInstance($r_id);
+				$oInvoice->setMeta('basket_data', json_encode($this->shop->view['basket']));
+				
+				if (($_REQUEST['wpsg_rechnungen_shippay']??'0') === '1') {
+				
+					$oInvoice->setMeta('include_shipping', '1');
+									
+				}
+				
 			}
 			
@@ -1088,9 +1328,24 @@
 			$this->shop->render(WPSG_PATH_VIEW.'/mods/mod_rechnungen/invoice_pdf.phtml');	
  
-			if (!$preview)
-			{
+			if (!$preview) {
 				 
-				if (@$_REQUEST['wpsg_rechnungen_sendmail'] == "1")
-				{
+				foreach ($this->shop->view['basket']['produkte'] as $p) {
+					
+					/** @var wpsg_order_product $oOrderProduct */
+					$oOrderProduct = $p['oOrderProduct'];
+					
+					$invoice_data = json_decode($oOrderProduct->getMeta('wpsg_mod_rechnungen_data', false, 'null'), true);
+					if (!is_array($invoice_data)) $invoice_data = [];
+					
+					$invoice_data[] = [						
+						'amount' => $p['menge'],
+						'invoice_id' => $r_id						
+					];
+					
+					$oOrderProduct->setMeta('wpsg_mod_rechnungen_data', json_encode($invoice_data));
+					
+				}
+				
+				if (@$_REQUEST['wpsg_rechnungen_sendmail'] == "1") {
 					
 					//Mail versenden
@@ -1099,28 +1354,8 @@
 					 * Damit alte Rechnungen noch versÃ€ndet werden
 					 */
-					if (file_exists($this->getFilePath($order_id).$r_id.'.pdf'))
-					{
-					
-						$file = $this->getFilePath($order_id).$r_id.'.pdf';
-					
-					}
-					else if (file_exists($this->getFilePath($order_id).$rnr.'.pdf'))
-					{
-						
-						$file = $this->getFilePath($order_id).$rnr.'.pdf';				
-						
-					}
-					else if (file_exists($this->getFilePath($order_id).'R'.$r_id.'.pdf'))
-					{
-						
-						$file = $this->getFilePath($order_id).'R'.$r_id.'.pdf';
-						
-					}
-					else
-					{
-						
-						$file = $this->getFilePath($order_id).'R'.$rnr.'.pdf'; 
-						
-					}  
+					if (file_exists($this->getFilePath($order_id).$r_id.'.pdf')) { $file = $this->getFilePath($order_id).$r_id.'.pdf'; }
+					else if (file_exists($this->getFilePath($order_id).$rnr.'.pdf')) { $file = $this->getFilePath($order_id).$rnr.'.pdf'; }
+					else if (file_exists($this->getFilePath($order_id).'R'.$r_id.'.pdf')) { $file = $this->getFilePath($order_id).'R'.$r_id.'.pdf'; }
+					else { $file = $this->getFilePath($order_id).'R'.$rnr.'.pdf'; }  
  
 					$file = $this->copyTemp($file, $rnr);
@@ -1128,16 +1363,6 @@
 					$mail_text = $this->shop->render(WPSG_PATH_VIEW."/mods/mod_rechnungen/invoicemail.phtml", false);
 
-					if ($this->shop->get_option('wpsg_htmlmail') === '1')
-					{
-						
-						$mail_html = $this->shop->render(WPSG_PATH_VIEW.'/mods/mod_rechnungen/invoicemail_html.phtml', false);
-						
-					}
-					else
-					{
-						
-						$mail_html = false;
-						
-					}
+					if ($this->shop->get_option('wpsg_htmlmail') === '1') { $mail_html = $this->shop->render(WPSG_PATH_VIEW.'/mods/mod_rechnungen/invoicemail_html.phtml', false); }
+					else { $mail_html = false; }
 					
 					$empfaenger = $_REQUEST['wpsg_rechnungen_email']; 
@@ -1146,11 +1371,9 @@
 					$arFiles = array($file);
 	 
-					if ($this->shop->get_option('wpsg_widerrufsformular_invoice') === '1' && wpsg_isSizedString($this->shop->get_option('wpsg_revocationform')))
-					{
+					if ($this->shop->get_option('wpsg_widerrufsformular_invoice') === '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))
-						{
+						if (file_exists($revocationFile) && is_file($revocationFile)) {
 								
 							$arFiles[] = $revocationFile;
@@ -1178,6 +1401,5 @@
 								
 				// Url Benachrichtigung
-				if (wpsg_isSizedString($_REQUEST['wpsg_rechnungen_url'], '1'))
-				{
+				if (wpsg_isSizedString($_REQUEST['wpsg_rechnungen_url'], '1')) {
 					
 					$this->shop->notifyURL(
@@ -1195,19 +1417,9 @@
 			$this->shop->restoreTempLocale();
 			
-		} // private function writeRechnung($order_id)
-
-		public function setOrderStatus_after($order_id, $status_id, $inform)
-		{
-			
-			if ($this->shop->get_option('wpsg_mod_rechnungen_auto') != '2' || $status_id != 100) return;
-			
-			$this->writeAutoRechnung($order_id);
-			
-		} // public function setOrderStatus($order_id, $status_id, $inform)
-		
+		}
+
 		public function stornoAction() {
-
+			
 			$order_id = intval($_REQUEST['edit_id']);
-
 			$order_data = $this->shop->cache->loadOrder($order_id);
 			
@@ -1218,128 +1430,87 @@
 			$this->shop->view['basket'] = $custom_data['basket'];
 			
-			// Rechnung laden die storniert werden soll
-			$rechnung = $this->db->fetchRow("SELECT * FROM `".WPSG_TBL_RECHNUNGEN."` WHERE `o_id` = '".wpsg_q($order_id)."' AND `storno` = '0000-00-00 00:00:00'");
-
-			// Letzte Rechnungsnummer
-			$last_rnr = $this->db->fetchOne("
-				SELECT
-					`rnr`
-				FROM
-					`".WPSG_TBL_RECHNUNGEN."`
-				WHERE
-					`storno` = '0000-00-00 00:00:00' AND 
-					`rnr` != '' AND
-					`o_id` = '".wpsg_q($order_id)."'
-			"); 
-						
-			if (isset($_REQUEST['form_submit_preview'])) $bPreview = true;
+			if (isset($_REQUEST['wpsg_storno_preview'])) $bPreview = true;
 			else $bPreview = false;
-			
+												
+			// Gutschriftnummer bilden
+			$gnr_format = $this->shop->get_option("wpsg_gutschrift_format");
+			if ($gnr_format == "") $gnr_format = "%nr%";
+				
+			// Neue Fortlaufende Nummer				
+			$gnr_nr = intval($this->shop->get_option("wpsg_gutschrift_start"));
+			if ($gnr_nr <= 0) $gnr_nr = 1;
+				
+			// StornierungsgebÃŒhr
+			if ($_REQUEST['storno_fee_set'] === '1') $storno_fee = $_REQUEST['storno_fee_value'];
+			else $storno_fee = '';
+			
+			$this->shop->view['storno_fee'] = $storno_fee;
+			
+			// Ersetzungen
+			$gnr = preg_replace("/\%nr\%/i", $gnr_nr, $gnr_format);
+			$gnr = preg_replace("/\%Jahr\%/i", date("Y"), $gnr);
+			$gnr = preg_replace("/\%Monat\%/i", date("m"), $gnr);
+			$gnr = preg_replace("/\%Tag\%/i", date("d"), $gnr);
+
+			$gnr = $this->shop->replaceUniversalPlatzhalter($gnr, $_REQUEST['edit_id']);
+				
 			if (!$bPreview) {
-
-				$this->db->UpdateQuery(
-					WPSG_TBL_RECHNUNGEN,
-					array(
-						"storno" => "NOW()"					
-					),
-					"`o_id` = '".wpsg_q($_REQUEST['edit_id'])."' AND `gnr` = ''"
-				);
-
-				$this->shop->setOrderStatus($order_id, wpsg_ShopController::STATUS_STORNIERT, false);
-
-				/*
-				if (isset($_REQUEST['wpsg_rechnungen_gutschrift']) && ($_REQUEST['wpsg_rechnungen_gutschrift'] == "0")) {
-				
-					// Status der Bestellung auf storniert Ã€ndern
-					$this->shop->setOrderStatus($_REQUEST['edit_id'], 500, false);
-					
-				}
-				*/
-
-				if (isset($_REQUEST['wpsg_mod_rechnungen_new_state'])) {
-
-					$this->shop->setOrderStatus(intval($_REQUEST['edit_id']), intval($_REQUEST['wpsg_mod_rechnungen_new_state']), false);
-
-				}
-				
-			}
-			
-			if (isset($_REQUEST['wpsg_rechnungen_gutschrift']) && ($_REQUEST['wpsg_rechnungen_gutschrift'] == "1" || $_REQUEST['wpsg_rechnungen_gutschrift'] == "2")) {
- 									
-				// Gutschriftnummer bilden
-				$gnr_format = $this->shop->get_option("wpsg_gutschrift_format");
-				if ($gnr_format == "") $gnr_format = "%nr%";
-					
-				// Neue Fortlaufende Nummer				
-				$gnr_nr = intval($this->shop->get_option("wpsg_gutschrift_start"));
-				if ($gnr_nr <= 0) $gnr_nr = 1;
-					
-				// StornierungsgebÃŒhr
-				$storno_fee = $_REQUEST['wpsg_mod_rechnungen_fee'];
-				
-				// Ersetzungen
-				$gnr = preg_replace("/\%nr\%/i", $gnr_nr, $gnr_format);
-				$gnr = preg_replace("/\%Jahr\%/i", date("Y"), $gnr);
-				$gnr = preg_replace("/\%Monat\%/i", date("m"), $gnr);
-				$gnr = preg_replace("/\%Tag\%/i", date("d"), $gnr);
-
-				$gnr = $this->shop->replaceUniversalPlatzhalter($gnr, $_REQUEST['edit_id']);
+				
+				$g_id = $this->db->ImportQuery(WPSG_TBL_RECHNUNGEN, array(
+					"o_id" => $_REQUEST['edit_id'],
+					"datum" => "NOW()",
+					"rnr" => "",
+					"gnr" => $gnr,
+					"storno_fee" => wpsg_q($storno_fee)
+				));
+				
+				$this->shop->update_option("wpsg_gutschrift_start", ($gnr_nr + 1));
+				
+			} else {
+								
+				$g_id = $gnr_nr;
+			
+			}
+ 			
+			$this->writeGutschrift($_REQUEST['edit_id'], $g_id, $storno_fee, $bPreview);
+				
+			if (isset($_REQUEST['storno_send'])) {
+											
+				// Mail an Kunden senden
+				//public function mail($e_mail, $subject, $message, $headers, $anhang = array())
+				//$this->shop->view['storno_fee'] = $storno_fee;
+				
+				$mail_text = $this->shop->render(WPSG_PATH_VIEW."/mods/mod_rechnungen/accountingmail.phtml", false);
+
+				if ($this->shop->get_option('wpsg_htmlmail') == '1') {
+					
+					$mail_html = $this->shop->render(WPSG_PATH_VIEW.'/mods/mod_rechnungen/accountingmail_html.phtml', false);
+					
+				} else {
+					
+					$mail_html = false;
+					
+				}
 				
 				if (!$bPreview) {
-				
-					$g_id = $this->db->ImportQuery(WPSG_TBL_RECHNUNGEN, array(
-						"o_id" => $_REQUEST['edit_id'],
-						"datum" => "NOW()",
-						"rnr" => "",
-						"gnr" => $gnr,
-						"storno_fee" => wpsg_q($storno_fee)
-					));
-					
-					$this->shop->update_option("wpsg_gutschrift_start", ($gnr_nr + 1));
-					
-				} else {
-									
-					$g_id = $gnr_nr;
-				
-				}
- 			
-				$this->writeGutschrift($_REQUEST['edit_id'], $g_id, $storno_fee, $bPreview);
-				
-				if ($_REQUEST['wpsg_rechnungen_gutschrift'] == "2") {
-												
-					// Mail an Kunden senden
-					//public function mail($e_mail, $subject, $message, $headers, $anhang = array())
-					$this->shop->view['storno_fee'] = $storno_fee;
-					
-					$mail_text = $this->shop->render(WPSG_PATH_VIEW."/mods/mod_rechnungen/accountingmail.phtml", false);
-
-					if ($this->shop->get_option('wpsg_htmlmail') == '1') {
-						
-						$mail_html = $this->shop->render(WPSG_PATH_VIEW.'/mods/mod_rechnungen/accountingmail_html.phtml', false);
-						
-					} else {
-						
-						$mail_html = false;
-						
-					}
-					
-					if (!$bPreview) {
-
-						$file = $this->getFilePath($_REQUEST['edit_id']).'/'.$g_id.'.pdf';						
-						$file = $this->copyTemp($file, $gnr);
-					
-						$arFiles = array($file);						
-						$this->shop->sendMail($mail_text, $this->shop->view['kunde']['email'], 'accountingmail', $arFiles, false, false, $mail_html);
-					
-						// TemporÃ€re Rechnung lÃ¶schen
-						@unlink($file);
-						
-					}
-					
-					$this->shop->restoreTempLocale();
-					
-					if ($bPreview) $subject = wpsg_translate(__('Rechnungskorrekturmail an #1# (Vorschau)', 'wpsg'), $this->shop->view['kunde']['email']);
-					else $subject = wpsg_translate(__('Rechnungskorrekturmail an #1#', 'wpsg'), $this->shop->view['kunde']['email']);
-										
+
+					$file = $this->getFilePath($_REQUEST['edit_id']).'/'.$g_id.'.pdf';						
+					$file = $this->copyTemp($file, $gnr);
+				
+					$arFiles = array($file);						
+					$this->shop->sendMail($mail_text, $this->shop->view['kunde']['email'], 'accountingmail', $arFiles, false, false, $mail_html);
+				
+					// TemporÃ€re Rechnung lÃ¶schen
+					@unlink($file);
+					
+				}
+				
+				$this->shop->restoreTempLocale();
+				
+				if ($bPreview) $subject = wpsg_translate(__('Rechnungskorrekturmail an #1# (Vorschau)', 'wpsg'), $this->shop->view['kunde']['email']);
+				else {
+					
+					$subject = wpsg_translate(__('Rechnungskorrekturmail an #1#', 'wpsg'), $this->shop->view['kunde']['email']);
+													
 					// In Bestelllog eintragen
 					$this->db->ImportQuery(WPSG_TBL_OL, array(
@@ -1349,19 +1520,150 @@
 						"mailtext" => $mail_text
 					));
-  
+
+				}
+
+			} 
+			
+			$this->shop->restoreTempLocale();
+			
+			exit;
+			
+		}
+		 
+		public function setOrderStatus_after($order_id, $status_id, $inform)
+		{
+			
+			if ($this->shop->get_option('wpsg_mod_rechnungen_auto') != '2' || $status_id != 100) return;
+			
+			$this->writeAutoRechnung($order_id);
+			
+		} // public function setOrderStatus($order_id, $status_id, $inform)
+		 
+		/**
+		 * @param wpsg_order_product $oOrderProduct
+		 */
+		private function getAmountToStorno($oOrderProduct) {
+			
+			$invoice_data = json_decode($oOrderProduct->getMeta('wpsg_mod_rechnungen_data', false, 'null'), true);
+			
+			if ($invoice_data !== null) {
+			
+				$amount_storno = 0;
+				
+				foreach ($invoice_data as $id) {
+					
+					try {
+					
+						$oInvoice = \wpsg\wpsg_invoice::getInstance($id['invoice_id']);
+						
+						if ($oInvoice->isInvoice()) {
+						
+							$amount_storno += $id['amount'];
+							
+						} else if ($oInvoice->isStorno()) {
+							
+							$amount_storno -= $id['amount'];
+							
+						}
+
+					} catch (\Exception $e) { }
+										
 				} 
-									
-				die();
-				
-			} // gutschrift 
-			
-			$this->shop->restoreTempLocale();
-			
-			$this->shop->addBackendMessage(__('Rechnung wurde erfolgreich storniert', 'wpsg'));
-						
-			$this->shop->redirect(
-				wpsg_admin_url('Order', 'view', ['edit_id' => $_REQUEST['edit_id']])
-			); 
-			
+				
+				return $amount_storno;
+				
+			} else {
+				
+				return $oOrderProduct->getAmount();
+				
+			}
+						
+		}
+
+		/**
+		 * @param int $order_id
+		 * @return \wpsg\wpsg_invoice[]
+		 */
+		public function getInvoiceToOrder($order_id) {
+			
+			$arReturn = [];
+			
+			$arInvoiceId = $this->db->fetchAssocField("SELECT `id` FROM `".WPSG_TBL_RECHNUNGEN."` WHERE `o_id` = '".wpsg_q($order_id)."' ");
+			
+			foreach ($arInvoiceId as $invoice_id) {
+				
+				try {
+					
+					$arReturn[] = \wpsg\wpsg_invoice::getInstance($invoice_id);
+
+				} catch (\Exception $e) { } 
+				
+			}
+			
+			return $arReturn;
+			
+		}
+		
+		/**
+		 * @param wpsg_order_product $oOrderProduct
+		 * @return \wpsg\wpsg_invoice[]
+		 */
+		public function getInvoiceToOrderProduct($oOrderProduct) {
+			
+			$arReturn = [];
+			
+			$invoice_data = json_decode($oOrderProduct->getMeta('wpsg_mod_rechnungen_data', false, 'null'), true);
+			
+			foreach ($invoice_data as $id) {
+					
+				try {
+				
+					$oInvoice = \wpsg\wpsg_invoice::getInstance($id['invoice_id']);
+
+					$arReturn[] = $oInvoice;
+					
+				} catch (\Exception $e) { }
+				
+			}
+			
+			return $arReturn;
+			
+		}
+		
+		/**
+		 * @param wpsg_order_product $oOrderProduct
+		 */
+		private function getAmountToInvoice($oOrderProduct) {
+			
+			$invoice_data = json_decode($oOrderProduct->getMeta('wpsg_mod_rechnungen_data', false, 'null'), true);
+			
+			if ($invoice_data !== null) {
+			
+				$amount_invoiced = 0;
+				
+				foreach ($invoice_data as $id) {
+					
+					try {
+					
+						$oInvoice = \wpsg\wpsg_invoice::getInstance($id['invoice_id']);
+					
+						if ($oInvoice->isInvoice()) {
+						
+							$amount_invoiced += $id['amount'];
+							
+						}
+
+					} catch (\Exception $e) { }
+										
+				} 
+				
+				return $oOrderProduct->getAmount() - $amount_invoiced;
+				
+			} else {
+				
+				return $oOrderProduct->getAmount();
+				
+			}
+						
 		}
 		
@@ -1528,4 +1830,5 @@
             header("Expires: Sat, 26 Jul 1997 05:00:00 GMT");
             header('Content-type: application/pdf');
+            header('Content-Disposition: inline');
 
             die(file_get_contents($file));
Index: /mods/wpsg_mod_versandarten.class.php
===================================================================
--- /mods/wpsg_mod_versandarten.class.php	(revision 8006)
+++ /mods/wpsg_mod_versandarten.class.php	(revision 8007)
@@ -269,5 +269,6 @@
 					$strQueryWHERE .= " AND (`vz` <= 0 OR `vz` = '".wpsg_q($vz)."') ";
 					
-				} else $strQueryWHERE .= " AND (`vz` <= 0) ";
+				} /* else $strQueryWHERE .= " AND (`vz` <= 0) "; */
+				// Am 07.06.2022 geÃ€ndert damit alle Versandarten drin sind wenn noch kein Land definiert
 								 				
 				$strQuery = "
Index: /views/admin/kundendaten_tab3.phtml
===================================================================
--- /views/admin/kundendaten_tab3.phtml	(revision 8006)
+++ /views/admin/kundendaten_tab3.phtml	(revision 8007)
@@ -7,6 +7,20 @@
 ?>
 
-<?php echo wpsg_drawForm_Select('wpsg_customerpreset_shipping', __('Standard Versandart', 'wpsg'), $this->view['arShipping'], $this->get_option('wpsg_customerpreset_shipping'), array('help' => 'wpsg_customerpreset_shipping')); ?>
-<?php echo wpsg_drawForm_Select('wpsg_customerpreset_payment', __('Standard Zahlungsart', 'wpsg'), $this->view['arPayment'], $this->get_option('wpsg_customerpreset_payment'), array('help' => 'wpsg_customerpreset_payment')); ?>
+<?php
+	
+	echo wpsg_drawForm_Select('wpsg_customerpreset_shipping', __('Standard Versandart', 'wpsg'), [
+		'-1' => __('gÃŒnstigste Versandart', 'wpsg')
+	] + $this->view['arShipping'], $this->get_option('wpsg_customerpreset_shipping'), array('help' => 'wpsg_customerpreset_shipping'));
+	
+?>
+	
+<?php 
+	
+	echo wpsg_drawForm_Select('wpsg_customerpreset_payment', __('Standard Zahlungsart', 'wpsg'), [
+		'-1' => __('gÃŒnstigste Zahlungsart', 'wpsg')
+	] + $this->view['arPayment'], $this->get_option('wpsg_customerpreset_payment'), array('help' => 'wpsg_customerpreset_payment')); 
+
+?>
+	
 <?php echo wpsg_drawForm_Select('wpsg_defaultland', __('Standardland', 'wpsg'), $this->view['arLander'], $this->get_option('wpsg_defaultland'), array('help' => 'wpsg_defaultland', 'hint' => 
 	'nohspc_'.wpsg_translate(__('Die LÃ€nder kÃ¶nnen in der <a href="#1#">LÃ€nderverwaltung</a> definiert werden.', 'wpsg'), WPSG_URL_WP.'wp-admin/admin.php?page=wpsg-Admin&subaction=laender')		
Index: /views/mods/mod_deliverytime/product_bottom.phtml
===================================================================
--- /views/mods/mod_deliverytime/product_bottom.phtml	(revision 8007)
+++ /views/mods/mod_deliverytime/product_bottom.phtml	(revision 8007)
@@ -0,0 +1,31 @@
+<?php
+
+    declare(strict_types=1);
+    
+    /**
+     * @author: Daniel Schmitzer (daschmi@daschmi.de)
+     * @date: 08.06.22
+     * @time: 13:43
+     */
+  
+	$available_date = $this->view['wpsg_mod_deliverytime']['available_date'];
+	$t_date = strtotime($available_date);
+		
+	$nowplusoneday = strtotime('+1 days');	
+	$days_between = ceil(($t_date - mktime(0, 0, 0)) / (24 * 60 * 60));
+	
+?>
+
+<?php if ($days_between <= 1) { ?>
+
+	<div class="wpsg_mod_deliverytime_product_bottom">
+		<?php echo __('sofort Lieferbar', 'wpsg') ;?>
+	</div>
+	
+<?php } else { ?>
+
+	<div class="wpsg_mod_deliverytime_product_bottom">
+		<?php echo wpsg_translate(__('Lieferbar in #1# Tagen', 'wpsg'), $days_between); ?> 
+	</div>
+
+<?php } ?>
Index: /views/mods/mod_deliverytime/produkt_addedit_allgemein.phtml
===================================================================
--- /views/mods/mod_deliverytime/produkt_addedit_allgemein.phtml	(revision 8006)
+++ /views/mods/mod_deliverytime/produkt_addedit_allgemein.phtml	(revision 8007)
@@ -18,4 +18,5 @@
 	<?php } ?>
 	</div>
+
 	<?php if (isset($this->view['wpsg_mod_deliverytime']['wpsg_mod_deliverytime_storeproduct'])) {?>
 		<?php echo wpsg_drawForm_Select('wpsg_mod_deliverytime[wpsg_mod_deliverytime_storeproduct]', __('Als Offlineprodukt anzeigen', 'wpsg'), array(0 => 'Moduleinstellungen', 1 => 'Offlineprodukt', 2 => 'Onlineprodukt'), $this->view['wpsg_mod_deliverytime']['wpsg_mod_deliverytime_storeproduct'], array('noIndex' => true, 'help' => 'wpsg_mod_deliverytime_store')); ?>
@@ -54,7 +55,33 @@
 		</div>
 	<?php } ?>
-	
+
+    <!-- Versanddatum -->
+    <?php echo wpsg_drawForm_Select('wpsg_mod_deliverytime[set_available]', __('VerfÃŒgbarkeit definieren', 'wpsg'), [
+        '0' => __('Nein', 'wpsg'),
+        '1' => __('Ja', 'wpsg')
+    ], $this->view['wpsg_mod_deliverytime']['set_available']??'0'); ?>    
+
+    <div class="wpsg_mod_deliverytime_set_available wpsg_mod_deliverytime_set_available_1" style="display:none;">
+        
+        <?php echo wpsg_drawForm_Input('wpsg_mod_deliverytime[available_date]', __('VerfÃŒgbar ab', 'wpsg'), $this->view['wpsg_mod_deliverytime']['available_date']??date('Y-m-d'), ['type' => 'date']); ?>
+        
+    </div>
+
+    <script>
+        
+        let el_set_available = document.getElementById('wpsg_mod_deliverytimeset_available');
+        
+        el_set_available.addEventListener('change', (event) => {
+			
+			for (let el of document.querySelectorAll('.wpsg_mod_deliverytime_set_available')) el.style.display = 'none';
+			for (let el of document.querySelectorAll('.wpsg_mod_deliverytime_set_available_' + event.target.value)) el.style.display = 'block';			
+				
+        });
+        
+		el_set_available.dispatchEvent(new Event('change'));
+		
+    </script>
+
 	<br />
-
 
 	<a href="<?php echo WPSG_URL_WP; ?>wp-admin/admin.php?page=wpsg-Admin&action=module&modul=wpsg_mod_deliverytime"><span class="wpsg-glyphicon glyphicon glyphicon-wrench"></span><?php echo __('Zur Konfiguration der Lieferzeit', 'wpsg'); ?></a>
Index: /views/mods/mod_rechnungen/accounting_pdf.phtml
===================================================================
--- /views/mods/mod_rechnungen/accounting_pdf.phtml	(revision 8006)
+++ /views/mods/mod_rechnungen/accounting_pdf.phtml	(revision 8007)
@@ -93,6 +93,6 @@
 			$pdf->Text($adress_left, $adress_top + 10, $shop->view['kunde']['strasse'].' '.wpsg_getStr($shop->view['kunde']['nr']));
 			$pdf->Text($adress_left, $adress_top + 15, $shop->view['kunde']['plz'].' '.$shop->view['kunde']['ort']);
-			if ($shop->get_option("wpsg_mod_rechnungen_hideCountry") == '0')
-				$pdf->Text($adress_left, $adress_top + 20, strtoupper($shop->view['oOrder']->getInvoiceCountryName()));			
+			
+			if ($shop->get_option("wpsg_mod_rechnungen_hideCountry") == '0') $pdf->Text($adress_left, $adress_top + 20, strtoupper($shop->view['oOrder']->getInvoiceCountryName()));			
 			
 			// Rechnungsdaten 
@@ -830,5 +830,5 @@
 	
 		$offset += 5;
-		$pdf->Text($prod_left + 100, $prod_top + $offset, __("SUMME", "wpsg"));
+		$pdf->Text($prod_left + 80, $prod_top + $offset, __("SUMME", "wpsg"));
 		$pdf->setXY($prod_left + 140, $prod_top + $offset - 5);
 	
@@ -969,19 +969,15 @@
     ob_end_clean();
 
-	if ($this->view['preview'])
-	{
+	if ($this->view['preview']) {
 	    
 		$pdf->Output($filename, 'I');
         
-	}
-	else
-	{
+	} else {
 		
 		$pdf->Output($this->callMod('wpsg_mod_rechnungen', 'getFilePath', array($this->view['data']['id'])).$filename, 'F');
 		
 		// Hier wird der Dateiname an FPD ÃŒbergeben. Er soll sich aus der Rechnungsnummer ergeben, auch wenn das Dokument ÃŒber die ID gespeichert ist.
-		if ($this->view['output'] === true) $pdf->Output($this->view['filename_out'], 'I');
+		$pdf->Output($this->view['filename_out'], 'I');
 			
 	} 
 	 
-?>
Index: /views/mods/mod_rechnungen/order_view_orderdata_after.phtml
===================================================================
--- /views/mods/mod_rechnungen/order_view_orderdata_after.phtml	(revision 8007)
+++ /views/mods/mod_rechnungen/order_view_orderdata_after.phtml	(revision 8007)
@@ -0,0 +1,243 @@
+<?php
+
+    declare(strict_types=1);
+    
+    /**
+     * @author: Daniel Schmitzer (daschmi@daschmi.de)
+     * @date: 09.06.22
+     * @time: 07:44
+     */
+     
+    namespace wpsg;
+
+    /** @var \wpsg_customer $oCustomer */
+    $oCustomer = $this->view['oCustomer']??null;
+    
+    /** @var \wpsg_order $oOrder */
+    $oOrder = $this->view['oOrder']??null;
+	
+    $wpsg_rechnungen_footer = $this->get_option("wpsg_rechnungen_footer");
+                        
+    if (!is_array($wpsg_rechnungen_footer)) $wpsg_rechnungen_footer = unserialize($this->get_option("wpsg_rechnungen_footer"));
+    if (!is_array($wpsg_rechnungen_footer)) $wpsg_rechnungen_footer = Array();
+
+    $default = $this->get_option('wpsg_rechnungen_foottext_standard');
+    
+?>
+
+
+<div id="wpsg_mod_invoice_tabs">
+    
+    <ul class="nav nav-tabs" role="tablist">
+        <li role="presentation" class="tab akttab active" id="tab1"><a href="#tab1" role="tab" data-toggle="tab" class="bg_invoice"><?php echo __('Rechnung erstellen', 'wpsg'); ?></a></li>
+        <li role="presentation" class="tab" id="tab2"><a href="#tab2" role="tab" data-toggle="tab" class="bg_storno"><?php echo __('Gutschrift/Rechnungskorrektur erstellen', 'wpsg'); ?></a></li>
+    </ul>
+ 
+	<div class="tab-content">
+		
+		<div role="tabpanel" class="tabcontent bg_invoice" id="tabcontent1">
+            
+            <form method="post" id="invoice_form" target="_blank" action="<?php 
+                
+                echo WPSG_URL_WP.'wp-admin/admin.php?page=wpsg-Order&action=ajax&mod=wpsg_mod_rechnungen&cmd=rechnung&noheader=1&edit_id='.$oOrder->getId(); 
+                
+            ?>" class="grid">
+                
+                <?php \wp_nonce_field('wpsg-mod_invoice-order_ajax-rechnung-'.$this->view['data']['id']); ?>
+                
+                <!-- Rechnung -->
+                
+                <input type="checkbox" name="wpsg_rechnungen_sendmail" value="1" id="invoice_sendmail" checked="checked" />
+                <label for="invoice_sendmail"><?php echo __('E-Mail an Kunden senden', 'wpsg'); ?></label>
+                <input type="email" name="wpsg_rechnungen_email" value="<?php echo $oCustomer->getEMail(); ?>" />
+                
+                <input type="checkbox" name="wpsg_rechnungen_faelligkeit" value="1" id="invoice_faelligkeit" checked="checked" />
+                <label for="invoice_faelligkeit"><?php echo __('FÃ€lligkeit anzeigen', 'wpsg'); ?></label>
+                <input type="date" name="wpsg_rechnungen_faelligkeitsdatum" value="<?php echo date('Y-m-d'); ?>" />
+                
+                <input type="checkbox" name="wpsg_rechnungen_status" value="1" id="invoice_state" checked="checked" />
+                <label for="invoice_state"><?php echo __('Neuer Status', 'wpsg'); ?></label>
+                <select name="wpsg_rechnungen_status_neu">
+                    <?php foreach ($this->arStatus as $status_key => $status_label) { ?>
+                    <option value="<?php echo $status_key; ?>"><?php echo $status_label; ?></option>
+                    <?php } ?>
+                </select>
+                
+                <input type="checkbox" name="wpsg_rechnungen_shippay" value="1" id="invoice_shippay" checked="checked" />
+                <label style="grid-column:2 / span 2;" for="invoice_shippay"><?php 
+                        
+                    echo __('Versand-/Zahlungskosten abrechnen', 'wpsg'); 
+                
+                    /** @var \wpsg\wpsg_invoice[] $arInvoice */
+                    $arInvoice = $this->callMod('wpsg_mod_rechnungen', 'getInvoiceToOrder', [$oOrder->getId()]);
+                    $arInvoiceLabel = [];
+                    
+                    foreach ($arInvoice as $oInvoice) {
+                        
+                        if ($oInvoice->getMeta('include_shipping', false, '0')) {
+                           
+                            $arInvoiceLabel[] = $oInvoice->getNr(true);    
+                            
+                        }
+                        
+                    }
+                    
+                    if (sizeof($arInvoiceLabel) > 0) {
+                        
+                        echo wpsg_translate(__(' (Enthalten in #1#)', 'wpsg'), implode(', ', $arInvoiceLabel));
+                        
+                    }
+                    
+                ?></label>
+                
+                <input type="checkbox" name="wpsg_rechnungen_url" value="1" id="invoice_url" />
+                <label  for="invoice_url" style="grid-column: 2 / span 2;"><?php echo __('URL Benachrichtigung', 'wpsg'); ?></label>
+                
+                <span></span>
+                <label for="invoice_date"><?php echo __('Rechnungsdatum', 'wpsg') ;?></label>
+                <input type="date" value="<?php echo date('Y-m-d'); ?>" name="wpsg_rechnungen_datum" id="invoice_date" />
+                
+                <span></span>
+                <label for="invoice_foottext_select"><?php echo __('FuÃtext', 'wpsg'); ?></label>
+                
+                <?php if (sizeof($wpsg_rechnungen_footer) > 0) { ?>
+                <select id="invoice_foottext_select">
+                    <?php foreach ($wpsg_rechnungen_footer as $k => $v) { ?>
+                    <option value="<?php echo wpsg_hspc($v[1]); ?>" <?php echo ((intval($default) === intval($k))?'selected="selected"':''); ?>><?php echo wpsg_hspc($v[0]); ?></option>
+                    <?php } ?>
+                </select>
+                <?php } else { ?>
+                <span></span>
+                <?php } ?>
+                
+                <span></span>
+                <input type="text" name="wpsg_rechnungen_fusstext" id="wpsg_rechnungen_fusstext" value="" style="grid-column: 2 / span 2;" />
+                                
+                <span style="grid-column:1 / span 3;"></span>
+                
+                <span style="display:flex; justify-content:flex-end; gap:0.5rem; grid-column:1/span 3;">
+                    
+                    <input class="button" style="" id="invoice_wpsg_rechnungen_preview" name="wpsg_rechnungen_preview" type="submit" value="Vorschau">
+                    <input class="button" style="" id="invoice_wpsg_rechnungen_submit" onclick="window.setTimeout(function() { location.href = '<?php 
+                    
+                        echo wpsg_admin_url('Order', 'view', ['edit_id' => $oOrder->getId()]);
+                    
+                    ?>'; }, 1000);" name="wpsg_rechnungen_write" type="submit" value="Rechnung schreiben">
+                    
+                </span>
+                
+                <script>
+                    
+                    let el_invoice_foottext_select = document.getElementById('invoice_foottext_select');
+					let el_invoice_form = document.getElementById('invoice_form');
+					
+					if (el_invoice_foottext_select) {
+						
+						el_invoice_foottext_select.addEventListener('change', (event) => {
+						
+							document.getElementById('wpsg_rechnungen_fusstext').value = event.target.value;
+							
+						});
+						
+						el_invoice_foottext_select.dispatchEvent(new Event('change'));
+						
+                    };
+					
+					let el_invoice_wpsg_rechnungen_preview = document.getElementById('invoice_wpsg_rechnungen_preview');
+					let el_invoice_wpsg_rechnungen_submit = document.getElementById('el_invoice_wpsg_rechnungen_submit');
+					 					                    
+                </script>
+                                
+            </form>
+            
+        </div>
+        
+        <div role="tabpanel" class="tabcontent bg_storno" id="tabcontent2">
+            
+            <form method="post" id="storno_form" target="_blank" action="<?php 
+                
+                echo WPSG_URL_WP.'wp-admin/admin.php?page=wpsg-Order&noheader=1&action=ajax&mod=wpsg_mod_rechnungen&edit_id='.$oOrder->getId().'&do=storno'; 
+                
+            ?>" class="grid">
+                
+                <?php \wp_nonce_field('wpsg-mod_invoice-order_ajax-storno-'.$this->view['data']['id']); ?>
+                
+                <input type="checkbox" name="storno_send" id="storno_send" value="1" />
+                <label for="storno_send"><?php echo __('E-Mail an Kunden senden', 'wpsg'); ?></label>
+                <input type="email" name="storno_mail" value="<?php echo $oCustomer->getEMail(); ?>" />
+                
+                <input type="checkbox" id="storno_shippay" name="storno_shippay" value="1" id="invoice_shippay" checked="checked" />
+                <label style="grid-column:2 / span 2;" for="storno_shippay"><?php echo __('Versand-/Zahlungskosten stornieren', 'wpsg'); ?></label>
+                
+                <input type="checkbox" name="storno_state" value="1" id="storno_state" checked="checked" />
+                <label for="storno_state"><?php echo __('Neuer Status', 'wpsg'); ?></label>
+                <select name="storno_state_new">
+                    <?php foreach ($this->arStatus as $status_key => $status_label) { ?>
+                    <option value="<?php echo $status_key; ?>"><?php echo $status_label; ?></option>
+                    <?php } ?>
+                </select>
+                
+                <input type="checkbox" name="storno_fee_set" id="storno_fee_set" value="1" id="storno_fee_set" />
+                <label for="storno_fee_set"><?php echo __('StornierungsgebÃŒhr in % oder EUR', 'wpsg'); ?></label>
+                <input type="text" value="" name="storno_fee_value" />
+                
+                <span style="grid-column:1 / span 3;"></span>
+                
+                <span style="display:flex; justify-content:flex-end; gap:0.5rem; grid-column:1/span 3;">
+                    
+                    <input class="button" style="" id="invoice_wpsg_storno_preview" name="wpsg_storno_preview" type="submit" value="Vorschau">
+                    <input class="button" style="" id="invoice_wpsg_storno_submit" onclick="window.setTimeout(function() { location.href = '<?php 
+                    
+                        echo wpsg_admin_url('Order', 'view', ['edit_id' => $oOrder->getId()]);
+                    
+                    ?>'; }, 1000);" name="wpsg_storno_write" type="submit" value="Rechnungskorrektur schreiben">
+                    
+                </span>
+                
+                <script>
+                     
+                    let el_storno_form = document.getElementById('storno_form');
+					
+					let el_invoice_wpsg_storno_preview = document.getElementById('invoice_wpsg_storno_preview');
+					let el_invoice_wpsg_storno_submit = document.getElementById('invoice_wpsg_storno_submit');
+					                     
+                </script>
+                
+            </form>
+            
+        </div>
+        
+    </div>
+    
+</div>
+
+<style>
+    
+    #wpsg_mod_invoice_tabs .grid { width:100%; padding:1rem; display:grid; row-gap:0.5rem; column-gap:0.5rem; grid-template-columns:25px 1fr 300px; align-items:center; grid-auto-rows:30px; padding-bottom:0.5rem; }
+    #wpsg_mod_invoice_tabs .grid input[type="checkbox"] { margin-top:0; }
+    #wpsg_mod_invoice_tabs .grid label { font-weight:normal; margin-bottom:0; } 
+    
+    .nav-tabs > li.active > a.bg_invoice,
+    .nav-tabs > li.active > a.bg_invoice:focus,
+    label.bg_invoice,
+    .link_invoice.bg_invoice,
+    .tabcontent.bg_invoice { background-color:lightgreen; color:black; }
+    
+    .nav-tabs > li.active > a.bg_storno,
+    .nav-tabs > li.active > a.bg_storno:focus,
+    label.bg_storno,
+    .link_invoice.bg_storno,
+    .tabcontent.bg_storno { background-color:lightpink; color:black; }
+    
+    .link_invoice { transform:translateX(-5px); padding:2px 5px; font-siz:12px; text-decoration:underline; }
+    label[for="invoice_shippay"] .link_invoice { padding:0; }
+    
+</style>
+
+<script>
+    
+    jQuery('#wpsg_mod_invoice_tabs').wpsg_tab( {
+    
+	} );
+  
+</script>
Index: /views/mods/mod_rechnungen/order_view_row.phtml
===================================================================
--- /views/mods/mod_rechnungen/order_view_row.phtml	(revision 8007)
+++ /views/mods/mod_rechnungen/order_view_row.phtml	(revision 8007)
@@ -0,0 +1,61 @@
+<?php
+
+	/**
+	 * Template fÃŒr die Produktauswahl innerhalb der Bestellansicht
+	 */
+
+    $storno_amount = $this->view['wpsg_mod_rechnungen']['storno_amount'];
+    $invoice_amount = $this->view['wpsg_mod_rechnungen']['invoice_amount'];
+  
+    /** @var wpsg_order_product $oOrderProduct */
+    $oOrderProduct = $this->view['wpsg_mod_rechnungen']['oOrderProduct'];
+    
+    $p = $this->view['wpsg_mod_rechnungen']['product'];
+    $product_index = $this->view['wpsg_mod_rechnungen']['product']['product_index'];
+  
+?>
+<tr class="wpsg_<?php echo (($this->view['wpsg_mod_rechnungen']['i'] == 0)?'odd':'even'); ?>">	
+	<td colspan="<?php echo ((sizeof($this->view['arCalculation']['tax']) > 1 || $this->get_option('wpsg_showMwstAlways') == '1')?'5':'4'); ?>">
+		<div style="display:flex; flex-direction:row; margin-bottom:0px; gap:2rem;">		
+            
+            <?php if ($invoice_amount > 0) { ?>
+             
+                <label style="display:flex; flex-direction:row; padding:5px; margin-left:-5px; gap:0.5rem; font-weight:normal; align-items:center;" class="bg_invoice">   
+                    
+                    <input form="invoice_form" type="hidden" name="invoice_products[<?php echo $p['order_product_id']; ?>][set]" value="0" />
+                    <input checked="checked" form="invoice_form" type="checkbox" class="wpsg_mod_deliverynote_product" name="invoice_products[<?php echo $p['order_product_id']; ?>][set]" value="1" style="margin:0;" />
+                    
+                    <input form="invoice_form" name="invoice_products[<?php echo $p['order_product_id']; ?>][amount]" type="number" max="<?php echo $invoice_amount; ?>" min="1" value="<?php echo min($invoice_amount, $p['amount']); ?>" style="padding:0; font-size:14px; line-height:22px; min-height:initial; height:22px; width:50px; text-indent:5px; border:1px solid black; margin:0;" />
+                    
+                    <span>&nbsp;<?php echo __('StÃŒck auf Rechnung', 'wpsg'); ?></span>
+                    
+                </label>
+            
+            <?php } ?>
+            
+            <?php if ($storno_amount > 0) { ?>
+            
+                <label style="display:flex; flex-direction:row; padding:5px; margin-left:-5px; gap:0.5rem; font-weight:normal; align-items:center;" class="bg_storno">   
+                    
+                    <input form="storno_form" type="hidden" name="storno_products[<?php echo $p['order_product_id']; ?>][set]" value="0" />
+                    <input form="storno_form" checked="checked" type="checkbox" class="wpsg_mod_deliverynote_product" name="storno_products[<?php echo $p['order_product_id']; ?>][set]" value="1" style="margin:0;" />
+                    
+                    <input form="storno_form" name="storno_products[<?php echo $p['order_product_id']; ?>][amount]" type="number" max="<?php echo $storno_amount; ?>" min="1" value="<?php echo min($storno_amount, $p['amount']); ?>" style="padding:0; font-size:14px; line-height:22px; min-height:initial; height:22px; width:50px; text-indent:5px; border:1px solid black; margin:0;" />
+                    
+                    <span>&nbsp;<?php echo __('StÃŒck auf Gutschrift', 'wpsg'); ?></span>
+                    
+                </label>
+            
+            <?php } ?>
+            
+		</div>
+        <?php /** @var \wpsg\wpsg_invoice[] $arInvoice */ $arInvoice = $this->callMod('wpsg_mod_rechnungen', 'getInvoiceToOrderProduct', [$oOrderProduct]); ?>
+        <?php if (sizeof($arInvoice) > 0) { ?>
+            <div style="display:flex; gap:0.5rem; justify-content:flex-start; flex-wrap:wrap;">
+            <?php foreach ($arInvoice as $oInvoice) { ?>
+                <?php echo $oInvoice->getNr(true); ?>
+            <?php } ?>
+            </div>
+        <?php } ?>
+	</td>
+</tr>
Index: /views/order/view_orderdata.phtml
===================================================================
--- /views/order/view_orderdata.phtml	(revision 8006)
+++ /views/order/view_orderdata.phtml	(revision 8007)
@@ -355,4 +355,6 @@
 	</script>
 	
+    <?php $this->callMods('order_view_orderdata_after', [intval($_REQUEST['edit_id'])]); ?>
+    
 	<?php wpsg_drawForm_AdminboxEnd(); ?>
 
Index: /views/produkttemplates/standard.phtml
===================================================================
--- /views/produkttemplates/standard.phtml	(revision 8006)
+++ /views/produkttemplates/standard.phtml	(revision 8007)
@@ -31,5 +31,5 @@
 
 	</div>
-
+ 
 	<?php $this->callMods('product_top', array(&$this->view['data']['id'], $this->getTemplateIndex())); ?>
 
Index: /wpshopgermany.php
===================================================================
--- /wpshopgermany.php	(revision 8006)
+++ /wpshopgermany.php	(revision 8007)
@@ -104,4 +104,5 @@
 	define('WPSG_SANITIZE_URL_LOCAL', 28);
 	define('WPSG_SANITIZE_PRODUCTKEY', 29);
+	define('WPSG_SANITIZE_DATE_EN', 30);
  	
 	// Ist in Multiblog manchma nicht definiert :? Sonst ist hier das Verzeichnis drin
