/**
  * Imports the item bundle
  *
  * @throws Exception
  */
 protected function importBundle()
 {
     // Get the bundle head
     $Request_GetItemsBase = new PlentySoapRequest_GetItemsBase();
     $Request_GetItemsBase->GetAttributeValueSets = false;
     $Request_GetItemsBase->GetCategories = false;
     $Request_GetItemsBase->GetCategoryNames = false;
     $Request_GetItemsBase->GetItemAttributeMarkup = false;
     $Request_GetItemsBase->GetItemOthers = false;
     $Request_GetItemsBase->GetItemProperties = false;
     $Request_GetItemsBase->GetItemSuppliers = false;
     $Request_GetItemsBase->GetItemURL = 0;
     $Request_GetItemsBase->GetLongDescription = false;
     $Request_GetItemsBase->GetMetaDescription = false;
     $Request_GetItemsBase->GetShortDescription = false;
     $Request_GetItemsBase->GetTechnicalData = false;
     $Request_GetItemsBase->ItemID = $this->PLENTY_bundleHeadId;
     $Request_GetItemsBase->Page = 0;
     /** @var PlentySoapResponse_GetItemsBase $Response_GetItemsBase */
     $Response_GetItemsBase = PlentymarketsSoapClient::getInstance()->GetItemsBase($Request_GetItemsBase);
     if ($Response_GetItemsBase->Success == false || !isset($Response_GetItemsBase->ItemsBase->item[0])) {
         throw new PlentymarketsImportException('The item bundle with SKU »' . $this->PLENTY_bundle->SKU . '« can not be imported (SOAP call failed).', 3701);
     }
     /** @var PlentySoapObject_ItemBase $ItemBase */
     $ItemBase = $Response_GetItemsBase->ItemsBase->item[0];
     try {
         // Get the existing bundle
         $shopwareBundleId = PlentymarketsMappingController::getItemBundleByPlentyID($this->PLENTY_bundleHeadId);
         /** @var Shopware\CustomModels\Bundle\Bundle $Bundle */
         $Bundle = Shopware()->Models()->find('Shopware\\CustomModels\\Bundle\\Bundle', $shopwareBundleId);
         $currentShopwareBundleHeadItemDetailId = $Bundle->getArticle()->getMainDetail()->getId();
         if (!isset($this->SHOPWARE_bundleItemDetailList[$currentShopwareBundleHeadItemDetailId])) {
             // If the item which is the bundle head in shopware
             // has been removed in plentymarkets, the bundle has to get a new
             // head item. If this is not possible, the bundle will be delete.
             try {
                 $mainDetail = $this->getShopwareBundleItemDetail();
                 /** @var Shopware\Models\Article\Article $Article */
                 $Article = $mainDetail->getArticle();
                 PyLog()->message('Sync:Item:Bundle', 'The item »' . $Article->getName() . '« with the number »' . $mainDetail->getNumber() . '« is now the master item of the item bundle with the number »' . $Bundle->getNumber() . '«.');
                 $Bundle->setArticle($Article);
             } catch (PlentymarketsImportException $e) {
                 PlentymarketsMappingController::deleteItemBundleByShopwareID($Bundle->getId());
                 PyLog()->message('Sync:Item:Bundle', 'The item bundle with the number »' . $Bundle->getNumber() . '« will be deleted because no item can be identified as the master item. The previous master item with the number »' . $Bundle->getArticle()->getMainDetail()->getNumber() . '« is no longer part of the item bundle.');
                 // Delete the bundle
                 Shopware()->Models()->remove($Bundle);
                 Shopware()->Models()->flush();
                 throw $e;
             }
         }
         $action = 'update';
     } catch (PlentymarketsMappingExceptionNotExistant $E) {
         $action = 'create';
         // Create a new one
         $Bundle = new Shopware\CustomModels\Bundle\Bundle();
         $mainDetail = $this->getShopwareBundleItemDetail();
         /** @var Shopware\Models\Article\Article $Article */
         $Article = $mainDetail->getArticle();
         PyLog()->message('Sync:Item:Bundle', 'The item »' . $Article->getName() . '« with the number »' . $mainDetail->getNumber() . '« will be the master item of the item bundle with the number »' . $ItemBase->ItemNo . '«.');
         // Set the stuff which needs to be set just one
         $Bundle->setArticle($Article);
         $Bundle->setType(1);
         $Bundle->setDiscountType('abs');
         $Bundle->setQuantity(0);
         $Bundle->setCreated();
         $Bundle->setSells(0);
         if (method_exists($Bundle, 'setDisplayGlobal')) {
             $Bundle->setDisplayGlobal(true);
         }
     }
     //
     $Bundle->setName($ItemBase->Texts->Name);
     $Bundle->setShowName(0);
     $Bundle->setNumber($ItemBase->ItemNo);
     $isLimited = $ItemBase->Stock->Limitation == 1;
     $Bundle->setLimited($isLimited);
     $isActive = $ItemBase->Availability->Inactive == 0 && $ItemBase->Availability->Webshop == 1;
     $Bundle->setActive($isActive);
     /**@var Shopware\Models\Customer\Group $CG */
     $CG = $this->getCustomerGroup();
     $shopwareBundleHeadItemId = $Bundle->getArticle()->getId();
     $items = array();
     foreach ($Bundle->getArticles() as $item) {
         /** @var Shopware\CustomModels\Bundle\Article $item */
         $itemDetailId = $item->getArticleDetail()->getId();
         // Not in the bundle or already done
         if (!isset($this->SHOPWARE_bundleItemDetailList[$itemDetailId])) {
             continue;
         }
         $quantity = $this->SHOPWARE_bundleItemDetailList[$itemDetailId]['quantity'];
         // If it is also the main item, the quantity needs to be reduced by one
         if ($item->getArticleDetail()->getArticle()->getId() == $shopwareBundleHeadItemId) {
             // If there is just one, the item is skipped since it is the HEAD - it will not be added as an item
             if ($quantity == 1) {
                 unset($this->SHOPWARE_bundleItemDetailList[$itemDetailId]);
                 continue;
             }
             // If the amount is higher - reduce item - the item is the HEAD and inside the bundle
             // in plenty it is just inside the bundle
             $quantity -= 1;
         }
         // Unset the detail - the rest of this array will be added as new items to the bundle
         unset($this->SHOPWARE_bundleItemDetailList[$itemDetailId]);
         // Update the quantity if changed
         if ($item->getQuantity() != $quantity) {
             $item->setQuantity($quantity);
         }
         $items[] = $item;
     }
     // Add all items, which aren't yet in the bundle
     foreach ($this->SHOPWARE_bundleItemDetailList as $config) {
         /** @var Shopware\Models\Article\Detail $detail */
         $detail = $config['detail'];
         // If the head is inside the bundle too, the amount needs to be reduced
         if ($detail->getArticle()->getId() == $shopwareBundleHeadItemId) {
             if ($config['quantity'] > 1) {
                 $config['quantity'] -= 1;
             } else {
                 if ($config['quantity'] == 1) {
                     continue;
                 }
             }
         }
         $ArticleNew = new Shopware\CustomModels\Bundle\Article();
         $ItemDetail = $detail;
         $quantity = $config['quantity'];
         $ArticleNew->setArticleDetail($ItemDetail);
         $ArticleNew->setQuantity($quantity);
         $items[] = $ArticleNew;
     }
     // Set the bundle items
     $Bundle->setArticles($items);
     $newPrice = $ItemBase->PriceSet->Price;
     $newPrice /= (100 + $ItemBase->PriceSet->VAT) / 100;
     $isPriceFound = false;
     $prices = array();
     foreach ($Bundle->getPrices() as $price) {
         /** @var Shopware\CustomModels\Bundle\Price $price */
         if ($price->getCustomerGroup()->getKey() == $CG->getKey()) {
             $price->setPrice($newPrice);
             $isPriceFound = true;
         }
         $prices[] = $price;
     }
     if (!$isPriceFound) {
         $Price = new Shopware\CustomModels\Bundle\Price();
         $Price->setBundle($Bundle);
         $Price->setCustomerGroup($CG);
         $Price->setPrice($newPrice);
         $prices[] = $Price;
         $Bundle->setPrices($prices);
     }
     $Bundle->setCustomerGroups(array($CG));
     Shopware()->Models()->persist($Bundle);
     Shopware()->Models()->flush();
     if ($action == 'create') {
         PlentymarketsMappingController::addItemBundle($Bundle->getId(), $this->PLENTY_bundleHeadId);
         PyLog()->message('Sync:Item:Bundle', 'The item bundle »' . $ItemBase->Texts->Name . '« with the number »' . $ItemBase->ItemNo . '« has been created');
     } else {
         PyLog()->message('Sync:Item:Bundle', 'The item bundle »' . $ItemBase->Texts->Name . '« with the number »' . $ItemBase->ItemNo . '« has been updated');
     }
 }
 /**
  * Exports the item bundle head item
  *
  * @throws PlentymarketsExportException
  */
 protected function exportHead()
 {
     // The shopware item on which the bundle is based on
     $shopwareBundleHead = $this->SHOPWARE_bundle->getArticle();
     $shopwareBundleHeadIsVariant = !is_null($shopwareBundleHead->getConfiguratorSet());
     // If the bundle head is a variant, the bundle can't be exported
     // since that feature is not provided by plentymarkets
     if ($shopwareBundleHeadIsVariant) {
         throw new PlentymarketsExportException('The item bundle with the number »' . $this->SHOPWARE_bundle->getNumber() . '« can not be exported because the master item is a variant.', 2230);
     }
     if ($this->SHOPWARE_bundle->getDiscountType() != 'abs') {
         throw new PlentymarketsExportException('The item bundle with the number »' . $this->SHOPWARE_bundle->getNumber() . '« can not be exported because the discount type is not supported.', 2240);
     }
     if ($this->SHOPWARE_bundle->getType() != 1) {
         throw new PlentymarketsExportException('The item bundle with the number »' . $this->SHOPWARE_bundle->getNumber() . '« can not be exported because the bundle type is not supported.', 2250);
     }
     // The shopware bundle head needs to be added as a plenty-bundle-item
     // The bundle head in plentymarkets is a "special" item
     $bundleItemId = PlentymarketsMappingController::getItemByShopwareID($shopwareBundleHead->getId());
     $sku = sprintf('%d-0', $bundleItemId);
     // If this item is also a bundle item in shopware,
     // we need to increase the quantity of it
     if (isset($this->PLENTY_bundleSkuList[$sku])) {
         $this->PLENTY_bundleSkuList[$sku] += 1;
     } else {
         $this->PLENTY_bundleSkuList[$sku] = 1;
     }
     // Create the bundle head
     $Request_AddItemsBase = new PlentySoapRequest_AddItemsBase();
     $Request_AddItemsBase->BaseItems = array();
     $Object_AddItemsBaseItemBase = new PlentySoapObject_AddItemsBaseItemBase();
     $Object_ItemAvailability = new PlentySoapObject_ItemAvailability();
     $validTo = $this->SHOPWARE_bundle->getValidTo();
     if ($validTo instanceof DateTime) {
         $Object_ItemAvailability->AvailableUntil = $this->SHOPWARE_bundle->getValidTo()->getTimestamp();
     }
     $Object_ItemAvailability->WebAPI = 1;
     $Object_ItemAvailability->Inactive = (int) $this->SHOPWARE_bundle->getActive();
     $Object_ItemAvailability->Webshop = (int) $this->SHOPWARE_bundle->getActive();
     $Object_AddItemsBaseItemBase->Availability = $Object_ItemAvailability;
     $storeIds = array();
     $Object_AddItemsBaseItemBase->Categories = array();
     $Object_AddItemsBaseItemBase->StoreIDs = array();
     foreach ($shopwareBundleHead->getCategories() as $category) {
         /** @var Shopware\Models\Category\Category $category */
         try {
             $categoryPath = PlentymarketsMappingController::getCategoryByShopwareID($category->getId());
         } catch (PlentymarketsMappingExceptionNotExistant $E) {
             continue;
         }
         $Object_ItemCategory = new PlentySoapObject_ItemCategory();
         $Object_ItemCategory->ItemCategoryPath = $categoryPath;
         // string
         $Object_AddItemsBaseItemBase->Categories[] = $Object_ItemCategory;
         // Get the store for this category
         $rootId = PlentymarketsUtils::getRootIdByCategory($category);
         $shops = PlentymarketsUtils::getShopIdByCategoryRootId($rootId);
         foreach ($shops as $shopId) {
             try {
                 $storeId = PlentymarketsMappingController::getShopByShopwareID($shopId);
             } catch (PlentymarketsMappingExceptionNotExistant $E) {
                 continue;
             }
             if (!isset($storeIds[$storeId])) {
                 // Activate the item for this store
                 $Object_Integer = new PlentySoapObject_Integer();
                 $Object_Integer->intValue = $storeId;
                 $Object_AddItemsBaseItemBase->StoreIDs[] = $Object_Integer;
                 // Cache
                 $storeIds[$storeId] = true;
             }
         }
     }
     $Object_AddItemsBaseItemBase->ExternalItemID = 'Swag/Bundle/' . $this->SHOPWARE_bundle->getId();
     // string
     $Object_AddItemsBaseItemBase->ItemNo = $this->SHOPWARE_bundle->getNumber();
     // string
     $Object_ItemPriceSet = new PlentySoapObject_ItemPriceSet();
     $defaultCustomerGroupKey = PlentymarketsConfig::getInstance()->get('DefaultCustomerGroupKey');
     $price = null;
     $isPriceFound = false;
     foreach ($this->SHOPWARE_bundle->getPrices() as $price) {
         /** @var Shopware\CustomModels\Bundle\Price $price */
         if ($price->getCustomerGroup()->getKey() == $defaultCustomerGroupKey) {
             $isPriceFound = true;
             break;
         }
     }
     if ($isPriceFound && $price instanceof Shopware\CustomModels\Bundle\Price) {
         $tax = $this->SHOPWARE_bundle->getArticle()->getTax()->getTax();
         $priceNet = $price->getPrice();
         $price = $priceNet + $priceNet / 100 * $tax;
         $Object_ItemPriceSet->Price = $price;
         $Object_ItemPriceSet->VAT = $tax;
     } else {
         // If there is no price, we have to set one anyway.
         // Otherwise the re-import will crash
         $Object_ItemPriceSet->Price = 1;
     }
     $Object_AddItemsBaseItemBase->PriceSet = $Object_ItemPriceSet;
     $Object_AddItemsBaseItemBase->VATInternalID = PlentymarketsMappingController::getVatByShopwareID($this->SHOPWARE_bundle->getArticle()->getTax()->getId());
     $Object_AddItemsBaseItemBase->ProducerID = PlentymarketsMappingController::getProducerByShopwareID($shopwareBundleHead->getSupplier()->getId());
     // int
     $Object_AddItemsBaseItemBase->Published = null;
     // int
     $Object_ItemTexts = new PlentySoapObject_ItemTexts();
     $Object_ItemTexts->Name = $this->SHOPWARE_bundle->getName();
     // string
     $Object_AddItemsBaseItemBase->Texts = $Object_ItemTexts;
     $Request_AddItemsBase->BaseItems[] = $Object_AddItemsBaseItemBase;
     $Response_AddItemsBase = PlentymarketsSoapClient::getInstance()->AddItemsBase($Request_AddItemsBase);
     $ResponseMessage = $Response_AddItemsBase->ResponseMessages->item[0];
     if (!$Response_AddItemsBase->Success || $ResponseMessage->Code != 100) {
         throw new PlentymarketsExportException('The item bundle with the number »' . $this->SHOPWARE_bundle->getNumber() . '« could not be exported', 2210);
     }
     $PLENTY_priceID = null;
     foreach ($ResponseMessage->SuccessMessages->item as $SubMessage) {
         if ($SubMessage->Key == 'ItemID') {
             $this->PLENTY_bundleHeadId = (int) $SubMessage->Value;
         } else {
             if ($SubMessage->Key == 'PriceID') {
                 $PLENTY_priceID = (int) $SubMessage->Value;
             }
         }
     }
     if ($this->PLENTY_bundleHeadId && $PLENTY_priceID) {
         PlentymarketsLogger::getInstance()->message('Export:Initial:Item:Bundle', 'The item bundle with the number »' . $this->SHOPWARE_bundle->getNumber() . '« has been created with the id »' . $this->PLENTY_bundleHeadId . '«.');
         PlentymarketsMappingController::addItemBundle($this->SHOPWARE_bundle->getId(), $this->PLENTY_bundleHeadId);
     } else {
         throw new PlentymarketsExportException('The item bundle with the number »' . $this->SHOPWARE_bundle->getNumber() . '« could not be exported', 2210);
     }
 }