<?php
/*
 *  This file is part of open3A.

 *  open3A is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 3 of the License, or
 *  (at your option) any later version.

 *  open3A is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.

 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 * 
 *  2007 - 2020, open3A GmbH - Support@open3A.de
 */
class Posten extends PersistentObject {
	public $parsers;
	public $recalcNetto = true;
	public $updateLagerOn = "R";
	public $updateLagerDoParent = true;
	public $updateLagerDoChildren = true;
	public $messageBestand = "";
	public $useAutoMwSt = true;
	
	public static $recalcBeleg = true;
	public static $ignoreLock = false;
	
	public function getA(){
		return $this->A;
	}
	
	function __construct($id, $parsers = true){
		parent::__construct($id);
		//für Interface
		$this->parsers = $parsers;
		if($parsers){
			$this->setParser("menge","Util::CLNumberParserZ");
			$this->setParser("menge2","Util::CLNumberParserZ");
			$this->setParser("preis","Util::CLNumberParserZ");
			$this->setParser("EK1","Util::CLNumberParserZ");
			$this->setParser("EK2","Util::CLNumberParserZ");
			$this->setParser("gewicht","Util::CLNumberParserZ");
		}
		/*$this->setParser("menge","mPosten::numberParser");
		$this->setParser("preis","mPosten::numberParser");
		$this->setParser("EK1","mPosten::numberParser");
		$this->setParser("EK2","mPosten::numberParser");
		$this->setParser("mwst","mPosten::numberParser");*/
		$this->customize();
	}
	
	public function prices(GRLBM $GRLBM){
		$netto = (float)$this->A("preis") * 1;
		
		$rabatt = 1;
		if($this->A("rabatt") !== null AND $this->A("rabatt") > 0)
			$rabatt = (100 - $this->A("rabatt")) / 100;
		
		$menge = $this->A("menge") * (($this->A("menge2") !== null AND $this->A("menge2") != 0 AND $this->A("menge2") != "") ? (float) $this->A("menge2") : 1);
		$netto = $netto * $rabatt;
		
		
		$brutto = $netto * (100 + (float)$this->A("mwst")) / 100;
		if($this->A("isBrutto") == "1")
			$brutto = $this->A("bruttopreis") * $rabatt;
		
		$nettoGesamt = $menge * $netto;
		$bruttoGesamt = $menge * $brutto;
		
		if($GRLBM->A("GRLBMCalcModePosten") == 1){
			$nettoGesamt = Util::kRound($nettoGesamt);
			$bruttoGesamt = Util::kRound($bruttoGesamt);
		}
		
		$r = array(
			"netto" => $netto,
			"nettoOhneRabatt" => (float)$this->A("preis") * 1, 
			"nettoGesamt" => $nettoGesamt,
			
			"brutto" => $brutto, 
			"bruttoGesamt" => $bruttoGesamt, 
			
			"mwstFaktor" => (1 + (float)$this->A("mwst") / 100), 
			"mwstBetragGesamt" => $bruttoGesamt - $nettoGesamt, 
			
			"rabattFaktor" => $rabatt, 
			"rabattBetrag" => (float)$this->A("preis") - ((float)$this->A("preis") * (float)$rabatt),
			
			"ek1Gesamt" => $menge * (float)$this->A("EK1"),
			"ek2Gesamt" => $menge * (float)$this->A("EK2"));
	
		return $r;
		#if(!isset($fpdf->gesamt_netto[$A->mwst]))
		#	$fpdf->gesamt_netto[$A->mwst] = 0;

		#$fpdf->gesamt_netto[$A->mwst] += $nettoSumme;
		#$fpdf->gesamt_brutto += $bruttoPreisGesamt;
		
		
		#$artikelsteuer = 0;
		#if(isset($A->steuer)){
		#	$artikelsteuer = $menge * $nettoPreis * ($A->steuer / 100);
			
		#	if(!isset($fpdf->artikelsteuern[$A->steuer]))
		#		$fpdf->artikelsteuern[$A->steuer] = 0;
			
		#	$fpdf->artikelsteuern[$A->steuer] += $artikelsteuer;
		#}
		

		#return array(
		#	"nettoPreis" => $nettoPreis, 
		#	"nettoGesamt" => $nettoSumme, 
		#	"bruttoPreis" => $bruttoPreis, 
		#	"nettoPreisOhneRabatt" => $nettoPreisOhneRabatt, 
		#	"bruttoPreisGesamt" => $bruttoPreisGesamt, 
		#	"mwstFaktor" => $mwstFaktor, 
		#	"mwstBetrag" => $mwstBetrag, 
		#	"rabattFaktor" => $rabatt, 
		#	"rabattBetrag" => $rabattBetrag);
	}
	
	public function newAttributes(GRLBM $GRLBM = null){
		$A = parent::newAttributes();

		if($this->customizer != null)
			$this->customizer->customizeNewAttributes($this->getClearClass(get_class($this)), $A);
			
		if($_SESSION["S"]->checkForPlugin("mBrutto"))
			$A->isBrutto = mUserdata::getUDValueS("DefaultValuePostenisBrutto", "1");

		#$AC = anyC::get("Kategorie", "type", "mwst");
		#$AC->addAssocV3("isDefault", "=", "1");
		#$M = $AC->getNextEntry();
		#if($M != null){
		#	$defaultMwst = Util::parseFloat("de_DE",str_replace("%","",$M->A("name")));
		#	$A->mwst = $this->hasParsers ? Util::CLNumberParserZ($defaultMwst) : $defaultMwst;
		#}
		
			
		if($GRLBM != null){
			$A->GRLBMID = $GRLBM->getID();
			
			$Auftrag = new Auftrag($GRLBM->A("AuftragID"));
			$Adresse = new Adresse($Auftrag->A("AdresseID"));
			$calc = self::calcMwst($Adresse, $Auftrag->A("UStIdNr"));
			
			$A->mwst = $this->hasParsers ? Util::CLNumberParserZ($calc) : $calc;
		} else
			$A->mwst = $this->hasParsers ? Util::CLNumberParserZ(self::calcMwst()) : self::calcMwst();

		return $A;
	}
	
	/*public function newFromProvision($ProvisionID,$GRLBMID){
		$this->A = $this->newAttributes();
		
		$prov = new Provision($ProvisionID);
		$prov->loadMe();
		$provA = $prov->getA();
		
		if($provA->GRLBMID != -1) {
			$R = new GRLBM($provA->GRLBMID);
			$R->loadMe();
		}
		$provA->provisionBetrag = str_replace(",",".",$provA->provisionBetrag);
		
		$this->A->GRLBMID = $GRLBMID;
		if($provA->GRLBMID != -1) $this->A->name = "Provision zu Rechnung ".$R->getA()->nummer;
		else $this->A->name = "Provision";
		$this->A->menge = 1;
		$this->A->bemerkung = "";
		$this->A->oldArtikelID = $ProvisionID;
		$skonto = 0;
		if($provA->GRLBMID != -1) $skonto = $provA->provisionBetrag * $R->getA()->payedWithSkonto / 100;
		$this->A->preis = number_format(round($provA->provisionBetrag - $skonto + 0.0000000000001,2),2,",","");
		$this->newMe();

		$provA->RechnungID = $GRLBMID;
		$prov->saveMe();
	}*/
	
	public $skipVariantTest = false;
	public $skipLieferantTest = false;
	public $skipLagerTest = false;
	public $skipStuecklisteTest = false;
	public $skipSeriennummernTest = false;
	public $skipChargenTest = false;
	public $increaseCount = false;
	public function newFromArtikel($ArtikelID, $GRLBMID, $menge = 1, $beschreibung = null, $kundennummer = null, $preis = null, $VarianteArtikelID = 0, $LieferantID = null, $ek1 = null, $ek2 = null, $options = array()){
		// <editor-fold defaultstate="collapsed" desc="Aspect:jP">
		try {
			$MArgs = func_get_args();
			return Aspect::joinPoint("around", $this, __METHOD__, $MArgs);
		} catch (AOPNoAdviceException $e) {}
		Aspect::joinPoint("before", $this, __METHOD__, $MArgs);
		// </editor-fold>
		
		if($this->increaseCount){
			$AC = anyC::get("Posten", "GRLBMID", $GRLBMID);
			$AC->addAssocV3("oldArtikelID", "=", $ArtikelID);
			$AC->addOrderV3("PostenID", "DESC");
			$AC->setLimitV3(1);
			$P = $AC->n();
			if($P){
				$P->recalcNetto = false;
				$P->resetParsers();
				$P->changeA("menge", $P->A("menge") + $menge);
				$P->saveMe();
				
				$this->messageBestand = $P->messageBestand;
				
				return $P->getID();
			}
		}
		$GRLBM = new GRLBM($GRLBMID);
		$Auftrag = new Auftrag($GRLBM->A("AuftragID"));
		
		$this->A = $this->newAttributes();
		$Artikel = new Artikel($ArtikelID);
		$keepPrice = false;
		
		if(!$this->skipStuecklisteTest AND Session::isPluginLoaded("mStueckliste") AND ($GRLBM->getMyPrefix() == "O" OR $GRLBM->getMyPrefix() == "P") AND Stueckliste::has($ArtikelID))
			Red::redirect(OnEvent::popup("Stückliste", "mStueckliste", "-1", "stuecklisteSelectionPopup", array("'$ArtikelID'", "'$GRLBMID'")));
		
		$showOptions = false;
		if(!$this->skipVariantTest AND Session::isPluginLoaded("mVariante") AND Variante::has($ArtikelID) AND !defined("PHYNX_VIA_INTERFACE"))
			$showOptions = true;
			#Red::redirect(OnEvent::popup("Variante hinzufügen", "mVariante", "-1", "variantSelectionPopup", array("'$ArtikelID'", "'addToBeleg'", "'$GRLBMID'")));
		
		if(!$this->skipSeriennummernTest AND Session::isPluginLoaded("mSeriennummer") AND Seriennummer::has($ArtikelID) AND Seriennummer::check($GRLBM->getMyPrefix()) AND !defined("PHYNX_VIA_INTERFACE"))
			$showOptions = true;
			#Red::redirect(OnEvent::popup("Variante hinzufügen", "mVariante", "-1", "variantSelectionPopup", array("'$ArtikelID'", "'addToBeleg'", "'$GRLBMID'")));
		
		if(!$this->skipChargenTest AND Session::isPluginLoaded("mLagerbestandWare") AND LagerbestandWare::has($ArtikelID) AND LagerbestandWare::check($GRLBM->getMyPrefix()) AND !defined("PHYNX_VIA_INTERFACE"))
			$showOptions = true;
			#Red::redirect(OnEvent::popup("Variante hinzufügen", "mVariante", "-1", "variantSelectionPopup", array("'$ArtikelID'", "'addToBeleg'", "'$GRLBMID'")));
		
		
		/*if(
			!$this->skipLagerTest 
			AND !defined("PHYNX_VIA_INTERFACE")
			AND Session::isPluginLoaded("mLager")
			AND Lager::check($GRLBM->getMyPrefix())
			AND Lagerbestand::has("LArtikel", $ArtikelID)){
			
			$AC = Lagerbestand::ofArtikel($ArtikelID);
			$AC->lCV3();
			if($AC->numLoaded() > 1)
				$showOptions = true;
				
			if($AC->numLoaded() == 1){
				$L = $AC->n();
				if($L != null)
					$LagerID = $L->A("LagerbestandLagerID");
			}
		}*/
		
		if(
			!$this->skipLieferantTest 
			AND !defined("PHYNX_VIA_INTERFACE")
			AND Session::isPluginLoaded("mLieferant")
			AND Lieferant::check($GRLBM->getMyPrefix())
			AND Lieferant::has($ArtikelID)){
			
			$AC = Lieferant::getLieferanten($ArtikelID);
			$AC->lCV3();
			if($AC->numLoaded() > 1)
				$showOptions = true;
				#Red::redirect(OnEvent::popup("Lieferant auswählen", "mLieferant", "-1", "lieferantSelectionPopup", array("'$ArtikelID'", "'$GRLBMID'")));
			
			if($AC->numLoaded() == 1){
				$L = $AC->n();
				if($L != null)
					$LieferantID = $L->A("LieferantID");
			}
		}
		
		$showOptions = Aspect::joinPoint("showPopup", $this, __METHOD__, array($ArtikelID), $showOptions);
		$keepName = false;
		
		if($showOptions)
			Red::redirect(OnEvent::popup("Postenoptionen", "Posten", "-1", "popupOptions", array("'$ArtikelID'", "'$GRLBMID'"), "", "{ignoreWidth: true}"));
		
		$this->recalcNetto = false;
		
		$aAttr = $Artikel->getA();
		if($aAttr == null)
			return false;
		$aArray = PMReflector::getAttributesArray($aAttr);
		$pArray = PMReflector::getAttributesArray($this->A);

		$inters = array_intersect($aArray, $pArray);
		
		foreach($inters AS $key => $value)
			$this->A->$value = $aAttr->$value;
	
		if($aAttr->bildDateiName != "" AND file_exists($aAttr->bildDateiName))
			$this->A->bild = DBImageGUI::stringifyS("image/jpg", $aAttr->bildDateiName, 400, 400, "jpg");
		
		$this->A->VarianteArtikelID = $VarianteArtikelID;
		$this->A->PostenLieferantID = $LieferantID === null ? 0 : $LieferantID;
		if(isset($options["PostenLeistungszeitraum"]))
			$this->A->PostenLeistungszeitraum = $options["PostenLeistungszeitraum"];
		
		#$_SESSION["BPS"]->setActualClass("mArtikelGUI");
		#$bps = $_SESSION["BPS"]->getAllProperties();

		if($kundennummer == null AND $Auftrag->A("kundennummer"))
			$kundennummer = $Auftrag->A("kundennummer");

		if($GRLBM->getMyPrefix() != "O" AND $GRLBM->getMyPrefix() != "P"){
			$this->A->EK1 = $Artikel->getGesamtEK1($LieferantID, true, $VarianteArtikelID);
			$this->A->preis = $Artikel->getGesamtNettoVK(true, $LieferantID);
			$this->A->bruttopreis = $Artikel->getGesamtBruttoVK(true, $LieferantID);
		} else {
			$this->A->EK1 = 0;
			$this->A->preis = $Artikel->getGesamtEK1($Auftrag->A("lieferantennummer") != "0" ? $Auftrag->A("lieferantennummer")  : null, true, $VarianteArtikelID);
			
			if($Auftrag->A("lieferantennummer") != "0"){
				$Lieferant = new Lieferant($Auftrag->A("lieferantennummer"));
				$this->A->mwst = $Lieferant->A("LieferantMwStSatz");
				
				$AC = anyC::get("LieferantPreis", "LieferantPreisArtikelID", $Artikel->getID());
				$AC->addAssocV3 ("LieferantPreisLieferantID", "=", $Auftrag->A("lieferantennummer"));
				$AC->addAssocV3("LieferantPreisVarianteArtikelID", "=", $VarianteArtikelID);
				$LP = $AC->n();
				
				if($LP != null){
					if($LP->A("LieferantPreisArtikelnummer") != "")
						$this->A->artikelnummer = $LP->A("LieferantPreisArtikelnummer");
					
					if($LP->A("LieferantPreisArtikelname") != ""){
						$this->A->name = $LP->A("LieferantPreisArtikelname");
						$keepName = true;
					}
				}
				
				if($LP === null AND $VarianteArtikelID != 0){
					$AC = anyC::get("LieferantPreis", "LieferantPreisArtikelID", $Artikel->getID());
					$AC->addAssocV3 ("LieferantPreisLieferantID", "=", $Auftrag->A("lieferantennummer"));
					$AC->addAssocV3("LieferantPreisVarianteArtikelID", "=", 0);
					$LP = $AC->n();

					if($LP != null){
						if($LP->A("LieferantPreisArtikelnummer") != "")
							$this->A->artikelnummer = $LP->A("LieferantPreisArtikelnummer");

						if($LP->A("LieferantPreisArtikelname") != ""){
							$this->A->name = $LP->A("LieferantPreisArtikelname");
						#	$keepName = true;
						}
					}
				}
				
			}
		}
		
		if($kundennummer != null){
			if(Session::isPluginLoaded("mPreisgruppe")){
				$Kappendix = Kappendix::getKappendixToKundennummer($kundennummer);
				if($Kappendix AND $Kappendix->A("KappendixPreisgruppe") != "0"){
					$PGPrice = Preisgruppe::getPrice("Artikel", $ArtikelID, $Kappendix->A("KappendixPreisgruppe"));
					
					if($VarianteArtikelID != 0){
						$PGPriceV = Preisgruppe::getPrice("VarianteArtikel", $VarianteArtikelID, $Kappendix->A("KappendixPreisgruppe"));
						
						if($PGPriceV !== false){
							$PGPrice = $PGPriceV;
							$keepPrice = true;
						}
					}
					
					if($PGPrice !== false){
						$this->A->preis = $PGPrice;
						if($this->A("isBrutto"))
							$this->A->bruttopreis = $PGPrice;
						
						$this->recalcNetto = true;
					}
				}
			}
			
			if(Session::isPluginLoaded("mArtikelRG")){
				$Kappendix = Kappendix::getKappendixToKundennummer($kundennummer);
				if($Kappendix AND $Kappendix->A("KappendixRabattgruppe") != "0"){
					$rabatt = ArtikelRG::getRG($ArtikelID);
					
					$this->A->rabatt = $rabatt[$Kappendix->A("KappendixRabattgruppe")];
				}
			}
			
			try {
				$Ks = anyC::get("Kundenpreis");
				$Ks->addAssocV3("t1.kundennummer", "=", $kundennummer);
				$Ks->addAssocV3("t1.ArtikelID", "=", $ArtikelID);
				$Ks->addAssocV3 ("KundenpreisVarianteArtikelID", "=", $VarianteArtikelID);
				if($this->hasParsers)
					$Ks->setParser("kundenPreis","Util::CLNumberParserZ");
				$K = $Ks->getNextEntry();

				if($K != null) {
					$this->A->preis = $K->A("kundenPreis");
					if($this->A->isBrutto == "1")
						$this->A->bruttopreis = $K->A("kundenPreis");
					
					$this->recalcNetto = true;
				}
			} catch(TableDoesNotExistException $e){
				
			} catch(ClassNotFoundException $e){
				
			}
		}
		
		if($preis !== null){
			$this->A->preis = $preis;
			if($this->A("isBrutto"))
				$this->A->bruttopreis = $preis;
			$this->recalcNetto = true;
		}
		
		if($ek1 !== null)
			$this->A->EK1 = $ek1;
		
		if($ek2 !== null)
			$this->A->EK2 = $ek2;
		
		$this->A->GRLBMID = $GRLBMID;
		$this->A->bemerkung = "";
		if($beschreibung != null)
			$this->A->beschreibung = $beschreibung;
		$this->A->menge = $menge;
		$this->A->oldArtikelID = $ArtikelID;
		
		if(Session::isPluginLoaded("mMultiLanguage") OR Session::isPluginLoaded("mStammdaten") OR isset($_SESSION["viaInterface"])){
			#$Auftrag = new Auftrag($GRLBM->A("AuftragID"));
			$Adresse = new Adresse($Auftrag->A("AdresseID"));
		}
		
		if(Session::isPluginLoaded("mMultiLanguage") OR isset($_SESSION["viaInterface"])){
					
			if($Adresse->A("AdresseSpracheID") != "0" AND $Adresse->A("AdresseSpracheID") != ""){
				
				try {
					//LEGACY AS OF 20150408
					$ML = new mMultiLanguageGUI();
					$ML->addAssocV3("MultiLanguageClass","=","Artikel");
					$ML->addAssocV3("MultiLanguageClassID","=",$ArtikelID);

					$ML->addAssocV3("MultiLanguageSpracheID","=",$Adresse->A("AdresseSpracheID"));

					while($T = $ML->getNextEntry())
						$this->changeA($T->A("MultiLanguageClassField"),$T->A("MultiLanguageValue"));
				
				
					//NEW
					$S = new Sprache($Adresse->A("AdresseSpracheID"));

					$ML = new mMultiLanguageGUI();
					$ML->addAssocV3("MultiLanguageClass","=","Artikel");
					$ML->addAssocV3("MultiLanguageClassID", "=", $ArtikelID);

					$ML->addAssocV3("MultiLanguageSpracheID", "=", "0");
					$ML->addAssocV3("MultiLanguageSprache", "=", $S->A("SpracheSprache"));

					while($T = $ML->getNextEntry())
						$this->changeA($T->A("MultiLanguageClassField"), $T->A("MultiLanguageValue"));
				} catch (ClassNotFoundException $e){}
			}
		}
		
		if(
			$GRLBM->getMyPrefix() != "O" 
			AND $GRLBM->getMyPrefix() != "P" 
			AND Session::isPluginLoaded("mStammdaten")
			AND (!Session::isPluginLoaded("mMwSt") OR $Artikel->A("mwStKategorieID") == -1)
		){
			
			$S = Stammdaten::getActiveStammdaten();
			$this->A->mwst = Kappendix::mwst($S, $Artikel, $Adresse, $Auftrag->A("UStIdNr"));
			
			if($this->A("isBrutto") == "1"){
				$this->A->preis = $this->A->bruttopreis / (1 + $this->A->mwst / 100);
				#$this->A->isBrutto = 0; //removed on 20161209 because it made no sense!
				$this->recalcNetto = false;
			}
		}
		
		
		if(
			$GRLBM->getMyPrefix() != "O" 
			AND $GRLBM->getMyPrefix() != "P" 
			AND Session::isPluginLoaded("mStammdaten") 
			AND Session::isPluginLoaded("mMwSt")
			AND $Artikel->A("mwStKategorieID") != -1){
			
			$this->A->mwst = 0;
			
			$MwSt = MwSt::find($Artikel, $Adresse, $Auftrag);
			if($MwSt != null){
				$this->A->mwst = $MwSt->A("MwStValue");
				$this->A->erloeskonto = $MwSt->A("MwStErloeskonto");
				
				if($this->A("isBrutto") == "1"){
					$this->A->preis = $this->A->bruttopreis;
					if($this->hasParsers)
						$this->A->preis = Util::CLNumberParserZ($this->A->bruttopreis);
					
					$this->recalcNetto = true;
				}
			}
		}
		
		
		if($this->A->differenzbesteuert == "1"){
			$this->A->differenzbesteuertMwSt = $this->A->mwst;
			$this->A->mwst = 0;
		}
		
		
		#if($GRLBM->getMyPrefix() == "O"
		#	OR $GRLBM->getMyPrefix() == "P"
		#	OR $GRLBM->getMyPrefix() == "S")
		#	$this->A->beschreibung = ""; //MOVED TO PDFBrief
		
		
		$this->A->PostenLohnkosten = $Artikel->getLohnNettoVK();
		$this->A->PostenLohnkostenMwSt = $this->A->mwst;
		
		Aspect::joinPoint("newPosten", $this, __METHOD__, array($GRLBM, $Auftrag, $Artikel, $VarianteArtikelID));
		
		$id = $this->newMe(true, false, true, $options);
		
		Aspect::joinPoint("after", $this, __METHOD__, array($GRLBM, $Auftrag, $Artikel, $id));
		
		
		if($VarianteArtikelID != 0){
			if($GRLBM->getMyPrefix() == "O" OR $GRLBM->getMyPrefix() == "P")
				$keepPrice = true;
			
			$V = new VarianteArtikel($VarianteArtikelID);
			$V->fixPosten($ArtikelID, $id, $keepPrice, $keepName);
		}
		
		if(Session::isPluginLoaded("mPostenKalkulation") AND PostenKalkulation::has($ArtikelID))
			PostenKalkulation::copy($ArtikelID, $id);
		
		
		if(Session::isPluginLoaded("mDArtikel")){
			try {
				$P = new Posten($id);
				DArtikel::execute($ArtikelID,  $P);
			} catch (ClassNotFoundException $e){
				
			}
		}
		
		return $id;
	}
	
	public static function calcMwst(Adresse $Adresse = null, $UStIdNr = null){
		$mwst = 0;
		
		$AC = anyC::get("Kategorie", "type", "mwst");
		$AC->addAssocV3("isDefault", "=", "1");
		$M = $AC->getNextEntry();
		if($M != null)
			$mwst = Util::parseFloat("de_DE",str_replace("%", "", $M->A("name")));
		
		if($Adresse == null)
			return $mwst;
		
		if(Session::isPluginLoaded("mStammdaten") AND !Session::isPluginLoaded("mMwSt")){
			$S = Stammdaten::getActiveStammdaten();
			if($Adresse->A("land") != ISO3166::getCountryToCode($S->A("land")) AND $Adresse->A("land") != "")
				$mwst = 0;
		}
		
		return $mwst;
	}
	
	protected function saveMultiEditField($field, $value){
		if($field != "preis")
			$this->recalcNetto = false;
		
		$G = new GRLBM($this->A("GRLBMID"));
		
		if($field == "menge" AND $this->A("oldArtikelID") != "0" AND Session::isPluginLoaded("mStaffelpreis") AND Staffelpreis::useWith($G->getMyPrefix()) AND Staffelpreis::has("Artikel", $this->A("oldArtikelID")) AND $this->A("rabatt") != null){
			$A = new Artikel($this->A("oldArtikelID"));
			$preis = $A->getGesamtNettoVK();
			
			$SP = Staffelpreis::get("Artikel", $this->A("oldArtikelID"), Util::CLNumberParserZ($value, "store"));
			
			if(Kundenpreis::has($this->A("oldArtikelID"))){
				$KP = Kundenpreis::get($this->A("oldArtikelID"));
				if($KP != null AND Staffelpreis::has("Kundenpreis", $KP->getID())){
					$preis = $KP->A("kundenPreis");
					$SP = Staffelpreis::get ("Kundenpreis", $KP->getID(), Util::CLNumberParserZ($value, "store"));
				}
			}
			
			
			$this->recalcNetto = true;
			$this->changeA("preis", $this->hasParsers ? Util::CLNumberParserZ($preis) : $preis);
			
			if($SP != null AND $SP->A("StaffelpreisModus") == 0)
				$this->changeA("rabatt", $this->hasParsers ? Util::CLNumberParserZ($SP->A("StaffelpreisPercent")) : $SP->A("StaffelpreisPercent"));
			elseif($SP != null AND $SP->A("StaffelpreisModus") == 1) {
				$this->changeA("rabatt", $this->hasParsers ? Util::CLNumberParserZ(0) : 0);
				$this->changeA("preis", $this->hasParsers ? Util::CLNumberParserZ($SP->A("StaffelpreisPercent")) : $SP->A("StaffelpreisPercent"));
				
			}
		}
		
		if($this->A == null) 
			$this->loadMe();
		
		$this->A->$field = $value;
		
		$this->saveMe();
	}

	private function createArtikel(){
		$a = new Artikel(-1);

		$aAttr = $a->newAttributes();
		$aArray = PMReflector::getAttributesArray($aAttr);
		$pArray = PMReflector::getAttributesArray($this->A);
		$pAArray = PMReflector::getAttributesArray($this->AA);

		$inters = array_intersect($aArray, $pArray);

		foreach($inters AS $key => $value)
			$aAttr->$value = $this->A->$value;
		
		$inters2 = array_intersect($aArray, $pAArray);

		foreach($inters2 AS $key => $value)
			$aAttr->$value = $this->AA->$value;

		$a->setA($aAttr);
		return $a->newMe();
	}

	public function newMe($checkuserdata = true, $output = false, $updateLagerbestand = true, $options = array()){
		if($this->A->createArtikel == "1"){
			$this->A->oldArtikelID = $this->createArtikel();
			$this->A->createArtikel = "0";
		}
		
		$preis = $this->A->preis;
		$mwst = $this->A->mwst;
		if($this->parsers){
			$preis = Util::CLNumberParserZ($this->A->preis,"store");
			
			if($this instanceof PostenGUI)
				$mwst = Util::CLNumberParserZ($this->A->mwst,"store"); //only if via PostenGUI
		}
		
		if($this->A->isBrutto == "0")
			$this->A->bruttopreis = $preis * ((100 + $mwst) / 100);
		
		if($this->A->isBrutto == "1" AND $this->recalcNetto){
			$this->A->bruttopreis = $preis;
			if($this->hasParsers)
				$this->setParser("preis","Util::nothingParser");
			$this->A->preis = $this->A->bruttopreis / (1 + $mwst / 100);
		}

		$G = new GRLBM($this->A->GRLBMID);
		$G->loadMe();
		
		if($G->isLocked())
			Red::alertD ("Es können keine Posten mehr hinzugefügt werden, der Beleg wurde gesperrt!");

		$this->A->PostenChanges = "";
		
		$old = new stdClass();
		$old->changeUserID = Session::currentUser() != null ? Session::currentUser()->getID() : "unbekannt";
		$old->changeReason = "Created";
		$old->changeTime = time();
		
		$changed = array();
		foreach($this->getA() AS $k => $v)
			$changed[$k] = $v;
		
		$old->changedData = $changed;
		
		$this->changeA("PostenChanges", json_encode(array($old), defined("JSON_UNESCAPED_UNICODE") ? JSON_UNESCAPED_UNICODE : 0));
		
		
		$newid = parent::newMe($checkuserdata, false);
		
		$P = new Posten($newid, false);
		
		$updateLagerbestand = Aspect::joinPoint("updateLagerbestand", $this, __METHOD__, array(), $updateLagerbestand);
		
		if($updateLagerbestand AND !$this->A("keinLagerbestand") AND Session::isPluginLoaded("mLager") AND $this->A("oldArtikelID") > 0){# AND $G->A("is".$this->updateLagerOn) == "1")
			$this->book($G, $P->A("menge") * -1, isset($options["charge"]) ? $options["charge"] : "", isset($options["lagerID"]) ? $options["lagerID"] : null);
			
			Aspect::joinPoint("alterLager", $this, __METHOD__, array($P, $G));
		}
		
		Aspect::joinPoint("after", $this, __METHOD__, array($P, $G));
		
		if(self::$recalcBeleg){
			$G = new GRLBM($this->A("GRLBMID"));
			$G->getSumOfPosten(false, true);
		}
		
		return $newid;
	}
	
	public function saveMe($checkuserdata = true, $output = false, $updateLagerbestand = true){
		if($this->A("GRLBMID") < 0) //deleted, skip everything!
			return parent::saveMe($checkuserdata, false);
		
		if($this->A->createArtikel == "1"){
			$this->A->oldArtikelID = $this->createArtikel();
			$this->A->createArtikel = "0";
		}

		$this->A->mwstCheck = 0;
		
		
		$preis = $this->A->preis;
		$mwst = $this->A->mwst;
		if($this->parsers){
			$preis = Util::CLNumberParserZ($this->A->preis, "store");
			$mwst = Util::CLNumberParserZ($this->A->mwst, "store");
		}
		
		if($this->recalcNetto) //required when set via saveMultiEditField() because the preis field is loaded from DB and not set from interface
			$this->A->bruttopreis = $preis * ((100 + $mwst) / 100);

		if($this->A->isBrutto == "1" AND $this->recalcNetto){
			$this->A->bruttopreis = $preis;
			if($this->hasParsers)
				$this->setParser("preis","Util::nothingParser");
			$this->A->preis = $this->A->bruttopreis / (1 + $mwst / 100);
		}
		
		if($this->AA("bildAction") == "delete")
			$this->changeA("bild", "");
		
		if(strpos($this->AA("bildAction"), "changeTo:") === 0){
			$path = str_replace("changeTo:", "", $this->AA("bildAction"));
			$this->changeA("bild", DBImageGUI::stringifyS("image/".Util::ext($path), $path, 400, 400));
		}
		if(strpos($this->AA("bildAction"), "changeToPool:") === 0){
			$path = str_replace("changeToPool:", "", $this->AA("bildAction"));
			$this->changeA("bild", DBImageGUI::stringifyS("image/".Util::ext($path), $path, 400, 400));
		}
		
		Aspect::joinPoint("changes", $this, __METHOD__, array());
		
		$G = new GRLBM($this->A->GRLBMID);
		#$G->loadMe();
		
		if(!self::$ignoreLock AND $G->isLocked())
			Red::alertD ("Es können keine Posten mehr bearbeitet werden, dieser Beleg wurde gesperrt!");
		
		#if($G->A("isPayed") == "1" AND ($G->A("isR") == "1" OR $G->A("isB") == "1" OR $G->A("isL") == "1"))
		#	die("alert:AuftraegeMessages.A005");

		
		$updateLagerbestand = Aspect::joinPoint("updateLagerbestand", $this, __METHOD__, array(), $updateLagerbestand);
		
		if($updateLagerbestand AND !$this->A("keinLagerbestand") AND Session::isPluginLoaded("mLager") AND $this->A("oldArtikelID") > 0){# AND $G->A("is".$this->updateLagerOn) == "1"){
			$PostenAlt = new Posten($this->getID(), false);
			$menge = (($this->hasParsers ? Util::CLNumberParserZ($this->A("menge"), "store") : $this->A("menge")) - $PostenAlt->A("menge")) * -1;
			if($menge != 0){
				try {
					$this->book($G, $menge, $this->A("PostenUsedCharge"));
				} catch (LagerException $e){
					Red::alertD($e->getMessage());
				}
			}
			Aspect::joinPoint("alterLager", $this, __METHOD__, array($PostenAlt, $G));
		}
		
		
		if($this->hasParsers)
			$VP = new PostenGUI($this->getID());
		else
			$VP = new Posten($this->getID());
		
		$data = json_decode($this->A("PostenChanges") == "" ? "[]" : $this->A("PostenChanges"));
		
		
		$old = new stdClass();
		$old->changeUserID = Session::currentUser() != null ? Session::currentUser()->getID() : "unbekannt";
		$old->changeReason = "";
		$old->changeTime = time();
		
		$changed = array();
		foreach($this->getA() AS $k => $v)
			if($VP->A($k) != $v)
				$changed[$k] = $VP->A($k);
		
		$old->changedData = $changed;
		
		
		if(count($changed) > 0){
			$data[] = $old;
			$this->changeA("PostenChanges", json_encode($data, defined("JSON_UNESCAPED_UNICODE") ? JSON_UNESCAPED_UNICODE : 0));
		}
		
		parent::saveMe($checkuserdata, false);
		
		if(self::$recalcBeleg){
			$G = new GRLBM($this->A("GRLBMID"));
			$G->getSumOfPosten(false, true);
		}
		#echo $message;
		if($output)
			Red::messageSaved();
	}
	
	public function deleteMe($forceDelete = false){
		if($this->A == null) $this->loadMe();
		
		$G = new GRLBM($this->A->GRLBMID);
		$G->loadMe();
		
		if(!self::$ignoreLock AND !$forceDelete AND $G->isLocked())#->A("isPayed") == "1" AND ($G->A("isR") == "1" OR $G->A("isB") == "1" OR $G->A("isL") == "1"))
			Red::alertD ("Dieser Posten kann nicht gelöscht werden, der Beleg wurde gesperrt!");
		
		$P = new Posten($this->getID(), false);
		
		$updateLagerbestand = Aspect::joinPoint("updateLagerbestand", $this, __METHOD__, array(), true);
		
		if($updateLagerbestand AND !$this->A("keinLagerbestand") AND Session::isPluginLoaded("mLager") AND $this->A("oldArtikelID") > 0){# AND $G->A("is".$this->updateLagerOn) == "1"){
			$this->book($G, $P->A("menge"), $this->A("PostenUsedCharge"));
			
			if($this->A("PostenUsedSerials") != "[]" AND $this->A("PostenUsedSerials") != ""){
				$serials = json_decode($this->A("PostenUsedSerials"));
				mSeriennummerGUI::doPutIn($serials, "Artikel", $this->A("oldArtikelID"), $this->A("GRLBMID"));
			}
			
			
			Aspect::joinPoint("alterLager", $this, __METHOD__, array($P, $G));
		}
		
		if(Session::isPluginLoaded("mStueckliste"))
			Stueckliste::unlog($this->getID());
		
		$this->changeA("GRLBMID", $this->A("GRLBMID") * -1);
		$this->changeA("bild", "");
		$this->saveMe(true, false);
		
		#parent::deleteMe();
		Aspect::joinPoint("after", $this, __METHOD__, array($P, $G));
		
		if(self::$recalcBeleg){
			$G = new GRLBM($G->getID());
			$G->getSumOfPosten(false, true);
		}
	}
	
	public function book(GRLBM $G, $menge, $charge = "", $lagerID = null){
		if($this->A("keinLagerbestand") OR $this->A("oldArtikelID") <= 0)
			return;
		
		if(!Session::isPluginLoaded("mStueckliste") OR (Session::isPluginLoaded("mStueckliste") AND !Stueckliste::has($this->A("oldArtikelID"))))
			$this->messageBestand = Lagerbestand::updateMain(
				$this->A("oldArtikelID"),
				$menge,
				"Beleg ".$G->A("prefix").$G->A("nummer"),
				$G->getMyPrefix(),
				$this->updateLagerOn,
				$this->A("VarianteArtikelID"),
				$this->A("EK1"),
				$charge,
				$lagerID);
		
		if(Session::isPluginLoaded("mStueckliste") AND Stueckliste::has($this->A("oldArtikelID"))){
			$doChildren = $this->updateLagerDoChildren;
			if($this->A("keepStuecklisteOnSale"))
				$doChildren = false;
			
			$this->messageBestand = Stueckliste::updateLagerMain(
				$this->A("oldArtikelID"), 
				$menge,
				"Beleg ".$G->A("prefix").$G->A("nummer"),
				$G->getMyPrefix(),
				$this->updateLagerOn,
				$this->A("VarianteArtikelID"),
				$this->updateLagerDoParent,
				null,
				true,
				$doChildren,
				$this->A("EK1"),
				$charge);
		}
	}
	
	private static $kundenpreise = array();
	public function cloneMe($updatePrices = false, $kundennummer = 0){
		$this->setParser("menge","Util::nothingParser");
		$this->setParser("preis","Util::nothingParser");
		#$this->setParser("bruttopreis","Util::nothingParser");
		$this->setParser("EK1","Util::nothingParser");
		$this->setParser("EK2","Util::nothingParser");
		
		#$this->forceReload();
		
		$_SESSION["BPS"]->setActualClass("clone".get_class($this));
		$bps = $_SESSION["BPS"]->getAllProperties();
		foreach($bps AS $key => $value)
			if(isset($this->A->$key))
				$this->A->$key = $value;
		
		$this->recalcNetto = false;
		
		if($updatePrices AND $this->A("oldArtikelID") != "0"){
			$A = new Artikel($this->A("oldArtikelID"));
			$this->changeA("preis", !$this->A("isBrutto") ? $A->getGesamtNettoVK() : $A->getGesamtBruttoVK());
			$this->recalcNetto = true;
			
			try {
				if(Session::isPluginLoaded("Kundenpreise") AND $kundennummer > 0){
					if(!isset(self::$kundenpreise[$kundennummer])){
						$Ks = anyC::get("Kundenpreis");
						$Ks->addAssocV3("kundennummer", "=", $kundennummer);
						$Ks->lCV3();
						self::$kundenpreise[$kundennummer] = $Ks;
					}
					
					
					while($K = self::$kundenpreise[$kundennummer]->n()){
						if($K->A("ArtikelID") != $this->A("oldArtikelID"))
							continue;
						
						$this->changeA("preis", $K->A("kundenPreis"));
						$this->recalcNetto = true;
					}
					
					self::$kundenpreise[$kundennummer]->resetPointer();

				}
			} catch(ClassNotFoundException $e){	}
		}
			
		return $this->newMe();
	}
}
?>
