/**
  * convert cart positions in order positions
  *
  * @return void
  *
  * @author Sebastian Diel <*****@*****.**>,
  *         Sascha Koehler <*****@*****.**>
  * @since 15.11.2014
  */
 public function convertShoppingCartPositionsToOrderPositions()
 {
     if ($this->extend('updateConvertShoppingCartPositionsToOrderPositions')) {
         return true;
     }
     $member = SilvercartCustomer::currentUser();
     if ($member instanceof Member) {
         $silvercartShoppingCart = $member->getCart();
         $silvercartShoppingCart->setPaymentMethodID($this->SilvercartPaymentMethodID);
         $silvercartShoppingCart->setShippingMethodID($this->SilvercartShippingMethodID);
         $shoppingCartPositions = SilvercartShoppingCartPosition::get()->filter('SilvercartShoppingCartID', $member->SilvercartShoppingCartID);
         if ($shoppingCartPositions->exists()) {
             foreach ($shoppingCartPositions as $shoppingCartPosition) {
                 $product = $shoppingCartPosition->SilvercartProduct();
                 if ($product) {
                     $orderPosition = new SilvercartOrderPosition();
                     $orderPosition->objectCreated = true;
                     $orderPosition->Price->setAmount($shoppingCartPosition->getPrice(true)->getAmount());
                     $orderPosition->Price->setCurrency($shoppingCartPosition->getPrice(true)->getCurrency());
                     $orderPosition->PriceTotal->setAmount($shoppingCartPosition->getPrice()->getAmount());
                     $orderPosition->PriceTotal->setCurrency($shoppingCartPosition->getPrice()->getCurrency());
                     $orderPosition->Tax = $shoppingCartPosition->getTaxAmount(true);
                     $orderPosition->TaxTotal = $shoppingCartPosition->getTaxAmount();
                     $orderPosition->TaxRate = $product->getTaxRate();
                     $orderPosition->ProductDescription = $product->LongDescription;
                     $orderPosition->Quantity = $shoppingCartPosition->Quantity;
                     $orderPosition->numberOfDecimalPlaces = $product->SilvercartQuantityUnit()->numberOfDecimalPlaces;
                     $orderPosition->ProductNumber = $shoppingCartPosition->getProductNumberShop();
                     $orderPosition->Title = $product->Title;
                     $orderPosition->SilvercartOrderID = $this->ID;
                     $orderPosition->IsNonTaxable = $member->doesNotHaveToPayTaxes();
                     $orderPosition->SilvercartProductID = $product->ID;
                     $orderPosition->log = false;
                     $this->extend('onBeforeConvertSingleShoppingCartPositionToOrderPosition', $shoppingCartPosition, $orderPosition);
                     $orderPosition->write();
                     // Call hook method on product if available
                     if ($product->hasMethod('ShoppingCartConvert')) {
                         $product->ShoppingCartConvert($this, $orderPosition);
                     }
                     // decrement stock quantity of the product
                     if (SilvercartConfig::EnableStockManagement()) {
                         $product->decrementStockQuantity($shoppingCartPosition->Quantity);
                     }
                     $this->extend('onAfterConvertSingleShoppingCartPositionToOrderPosition', $shoppingCartPosition, $orderPosition);
                     $result = SilvercartPlugin::call($this, 'convertShoppingCartPositionToOrderPosition', array($shoppingCartPosition, $orderPosition), true, array());
                     if (!empty($result)) {
                         $orderPosition = $result[0];
                     }
                     $orderPosition->write();
                     unset($orderPosition);
                 }
             }
             // Get taxable positions from registered modules
             $registeredModules = $member->getCart()->callMethodOnRegisteredModules('ShoppingCartPositions', array($member->getCart(), $member, true));
             foreach ($registeredModules as $moduleName => $moduleOutput) {
                 foreach ($moduleOutput as $modulePosition) {
                     $orderPosition = new SilvercartOrderPosition();
                     if ($this->IsPriceTypeGross()) {
                         if ($modulePosition->Price instanceof Money) {
                             $price = $modulePosition->Price->getAmount();
                         } else {
                             $price = $modulePosition->Price;
                         }
                         $orderPosition->Price->setAmount($price);
                     } else {
                         if ($modulePosition->Price instanceof Money) {
                             $price = $modulePosition->PriceNet->getAmount();
                         } else {
                             $price = $modulePosition->PriceNet;
                         }
                         $orderPosition->Price->setAmount($price);
                     }
                     $orderPosition->Price->setCurrency($modulePosition->Currency);
                     if ($this->IsPriceTypeGross()) {
                         $orderPosition->PriceTotal->setAmount($modulePosition->PriceTotal);
                     } else {
                         $orderPosition->PriceTotal->setAmount($modulePosition->PriceNetTotal);
                     }
                     $orderPosition->PriceTotal->setCurrency($modulePosition->Currency);
                     $orderPosition->Tax = 0;
                     $orderPosition->TaxTotal = $modulePosition->TaxAmount;
                     $orderPosition->TaxRate = $modulePosition->TaxRate;
                     $orderPosition->ProductDescription = $modulePosition->LongDescription;
                     $orderPosition->Quantity = $modulePosition->Quantity;
                     $orderPosition->Title = $modulePosition->Name;
                     if ($modulePosition->isChargeOrDiscount) {
                         $orderPosition->isChargeOrDiscount = true;
                         $orderPosition->chargeOrDiscountModificationImpact = $modulePosition->chargeOrDiscountModificationImpact;
                     }
                     $orderPosition->SilvercartOrderID = $this->ID;
                     $orderPosition->write();
                     unset($orderPosition);
                 }
             }
             // Get charges and discounts for product values
             if ($silvercartShoppingCart->HasChargesAndDiscountsForProducts()) {
                 $chargesAndDiscountsForProducts = $silvercartShoppingCart->ChargesAndDiscountsForProducts();
                 foreach ($chargesAndDiscountsForProducts as $chargeAndDiscountForProduct) {
                     $orderPosition = new SilvercartOrderPosition();
                     $orderPosition->Price->setAmount($chargeAndDiscountForProduct->Price->getAmount());
                     $orderPosition->Price->setCurrency($chargeAndDiscountForProduct->Price->getCurrency());
                     $orderPosition->PriceTotal->setAmount($chargeAndDiscountForProduct->Price->getAmount());
                     $orderPosition->PriceTotal->setCurrency($chargeAndDiscountForProduct->Price->getCurrency());
                     $orderPosition->isChargeOrDiscount = true;
                     $orderPosition->chargeOrDiscountModificationImpact = $chargeAndDiscountForProduct->sumModificationImpact;
                     $orderPosition->Tax = $chargeAndDiscountForProduct->SilvercartTax->Title;
                     if ($this->IsPriceTypeGross()) {
                         $orderPosition->TaxTotal = $chargeAndDiscountForProduct->Price->getAmount() - $chargeAndDiscountForProduct->Price->getAmount() / (100 + $chargeAndDiscountForProduct->SilvercartTax->Rate) * 100;
                     } else {
                         $orderPosition->TaxTotal = $chargeAndDiscountForProduct->Price->getAmount() / 100 * (100 + $chargeAndDiscountForProduct->SilvercartTax->Rate) - $chargeAndDiscountForProduct->Price->getAmount();
                     }
                     $orderPosition->TaxRate = $chargeAndDiscountForProduct->SilvercartTax->Rate;
                     $orderPosition->ProductDescription = $chargeAndDiscountForProduct->Name;
                     $orderPosition->Quantity = 1;
                     $orderPosition->ProductNumber = $chargeAndDiscountForProduct->sumModificationProductNumber;
                     $orderPosition->Title = $chargeAndDiscountForProduct->Name;
                     $orderPosition->SilvercartOrderID = $this->ID;
                     $orderPosition->write();
                     unset($orderPosition);
                 }
             }
             // Get nontaxable positions from registered modules
             $registeredModulesNonTaxablePositions = $member->getCart()->callMethodOnRegisteredModules('ShoppingCartPositions', array($member->getCart(), $member, false));
             foreach ($registeredModulesNonTaxablePositions as $moduleName => $moduleOutput) {
                 foreach ($moduleOutput as $modulePosition) {
                     $orderPosition = new SilvercartOrderPosition();
                     if ($this->IsPriceTypeGross()) {
                         $orderPosition->Price->setAmount($modulePosition->Price);
                     } else {
                         $orderPosition->Price->setAmount($modulePosition->PriceNet);
                     }
                     $orderPosition->Price->setCurrency($modulePosition->Currency);
                     if ($this->IsPriceTypeGross()) {
                         $orderPosition->PriceTotal->setAmount($modulePosition->PriceTotal);
                     } else {
                         $orderPosition->PriceTotal->setAmount($modulePosition->PriceNetTotal);
                     }
                     $orderPosition->PriceTotal->setCurrency($modulePosition->Currency);
                     $orderPosition->Tax = 0;
                     $orderPosition->TaxTotal = $modulePosition->TaxAmount;
                     $orderPosition->TaxRate = $modulePosition->TaxRate;
                     $orderPosition->ProductDescription = $modulePosition->LongDescription;
                     $orderPosition->Quantity = $modulePosition->Quantity;
                     $orderPosition->Title = $modulePosition->Name;
                     $orderPosition->SilvercartOrderID = $this->ID;
                     $orderPosition->write();
                     unset($orderPosition);
                 }
             }
             // Get charges and discounts for shopping cart total
             if ($silvercartShoppingCart->HasChargesAndDiscountsForTotal()) {
                 $chargesAndDiscountsForTotal = $silvercartShoppingCart->ChargesAndDiscountsForTotal();
                 foreach ($chargesAndDiscountsForTotal as $chargeAndDiscountForTotal) {
                     $orderPosition = new SilvercartOrderPosition();
                     $orderPosition->Price->setAmount($chargeAndDiscountForTotal->Price->getAmount());
                     $orderPosition->Price->setCurrency($chargeAndDiscountForTotal->Price->getCurrency());
                     $orderPosition->PriceTotal->setAmount($chargeAndDiscountForTotal->Price->getAmount());
                     $orderPosition->PriceTotal->setCurrency($chargeAndDiscountForTotal->Price->getCurrency());
                     $orderPosition->isChargeOrDiscount = true;
                     $orderPosition->chargeOrDiscountModificationImpact = $chargeAndDiscountForTotal->sumModificationImpact;
                     $orderPosition->Tax = $chargeAndDiscountForTotal->SilvercartTax->Title;
                     if ($this->IsPriceTypeGross()) {
                         $orderPosition->TaxTotal = $chargeAndDiscountForTotal->Price->getAmount() - $chargeAndDiscountForTotal->Price->getAmount() / (100 + $chargeAndDiscountForTotal->SilvercartTax->Rate) * 100;
                     } else {
                         $orderPosition->TaxTotal = $chargeAndDiscountForTotal->Price->getAmount() / 100 * (100 + $chargeAndDiscountForTotal->SilvercartTax->Rate) - $chargeAndDiscountForTotal->Price->getAmount();
                     }
                     $orderPosition->TaxRate = $chargeAndDiscountForTotal->SilvercartTax->Rate;
                     $orderPosition->ProductDescription = $chargeAndDiscountForTotal->Name;
                     $orderPosition->Quantity = 1;
                     $orderPosition->ProductNumber = $chargeAndDiscountForTotal->sumModificationProductNumber;
                     $orderPosition->Title = $chargeAndDiscountForTotal->Name;
                     $orderPosition->SilvercartOrderID = $this->ID;
                     $orderPosition->write();
                     unset($orderPosition);
                 }
             }
             // Convert positions of registered modules
             $member->getCart()->callMethodOnRegisteredModules('ShoppingCartConvert', array(SilvercartCustomer::currentUser()->getCart(), SilvercartCustomer::currentUser(), $this));
             $this->extend('onAfterConvertShoppingCartPositionsToOrderPositions', $silvercartShoppingCart);
             // Delete the shoppingcart positions
             foreach ($shoppingCartPositions as $shoppingCartPosition) {
                 $shoppingCartPosition->delete();
             }
             $this->write();
         }
         SilvercartPlugin::call($this, 'convertShoppingCartPositionsToOrderPositions', array($this), true);
     }
 }
 /**
  * Is this product buyable with the given stock management settings?
  * If Stock management is deactivated true is returned.
  * If stock management is activated but the quantity is overbookable true is
  * returned.
  *
  * @return boolean Can this product be bought due to stock management
  *                 settings and the customers cart?
  *
  * @author Sebastian Diel <*****@*****.**>,
  *         Roland Lehmann <*****@*****.**>
  * @since 15.11.2014
  */
 public function isBuyableDueToStockManagementSettings()
 {
     //is the product already in the cart?
     $cartPositionQuantity = 0;
     if (SilvercartCustomer::currentUser() && SilvercartCustomer::currentUser()->getCart()) {
         $cartPositionQuantity = SilvercartCustomer::currentUser()->getCart()->getQuantity($this->ID);
     }
     if (SilvercartConfig::EnableStockManagement()) {
         if (!$this->isStockQuantityOverbookable() && $this->StockQuantity - $cartPositionQuantity <= 0) {
             return false;
         }
         if ($this->StockQuantityExpirationDate) {
             $curDate = new DateTime();
             $expirationDate = new DateTime(strftime($this->StockQuantityExpirationDate));
             if ($this->isStockQuantityOverbookable() && $this->StockQuantity - $cartPositionQuantity <= 0 && $expirationDate < $curDate) {
                 return false;
             }
         }
     }
     return true;
 }
 /**
  * Decrement the positions quantity if it is higher than the stock quantity.
  * If this position has a quantity of 5 but the products stock quantity is
  * only 3 the positions quantity would be set to 3.
  * This happens only if the product is not overbookable.
  * 
  * @return void
  * 
  * @author Roland Lehmann <*****@*****.**>, Sebastian Diel <*****@*****.**>
  * @since 26.11.2012
  */
 public function adjustQuantityToStockQuantity()
 {
     if (!SilvercartTools::isIsolatedEnvironment()) {
         if (SilvercartConfig::EnableStockManagement() && !$this->SilvercartProduct()->isStockQuantityOverbookable()) {
             if ($this->Quantity > $this->SilvercartProduct()->StockQuantity) {
                 $this->Quantity = $this->SilvercartProduct()->StockQuantity;
                 $this->write();
                 SilvercartShoppingCartPositionNotice::setNotice($this->ID, "adjusted");
             }
         }
     }
 }