/**
  * Builds an index of all items inside the bundle
  * and checks if all of these items are exported to plentymarkets
  *
  * @throws PlentymarketsExportEntityException
  */
 protected function index()
 {
     /** @var Shopware\CustomModels\Bundle\Article $bundleArticle */
     foreach ($this->SHOPWARE_bundle->getArticles() as $bundleArticle) {
         try {
             // Variant
             $sku = PlentymarketsMappingController::getItemVariantByShopwareID($bundleArticle->getArticleDetail()->getId());
         } catch (PlentymarketsMappingExceptionNotExistant $E) {
             try {
                 // Base item
                 $bundleItemId = PlentymarketsMappingController::getItemByShopwareID($bundleArticle->getArticleDetail()->getArticle()->getId());
                 $sku = sprintf('%d-0', $bundleItemId);
             } catch (PlentymarketsMappingExceptionNotExistant $E) {
                 throw new PlentymarketsExportEntityException('The item bundle with the number »' . $this->SHOPWARE_bundle->getNumber() . '« can not be exported because not all of the items are available in plentymarkets.', 2220);
             }
         }
         $quantity = $bundleArticle->getQuantity();
         if (isset($this->PLENTY_bundleSkuList[$sku])) {
             $this->PLENTY_bundleSkuList[$sku] += $quantity;
         } else {
             $this->PLENTY_bundleSkuList[$sku] = $quantity;
         }
     }
 }
 /**
  * Exports the item variants
  */
 protected function exportVariants()
 {
     // Verknüpfung mit den Attribut(-werten)
     $ConfiguratorSet = $this->SHOPWARE_Article->getConfiguratorSet();
     if (!$ConfiguratorSet instanceof Shopware\Models\Article\Configurator\Set) {
         return;
     }
     // Active the attribute values at the item --------------------------------------------------------------------
     $objectsActivateLinks = array();
     $Request_SetItemAttributeLinks = new PlentySoapRequest_SetItemAttributeLinks();
     $Request_SetItemAttributeLinks->ItemID = $this->PLENTY_itemID;
     // int
     $Request_SetItemAttributeLinks->AttributeLinks = array();
     /** @var Shopware\Models\Article\Configurator\Option $ConfiguratorOption */
     foreach ($ConfiguratorSet->getOptions() as $ConfiguratorOption) {
         $PLENTY_attributeID = PlentymarketsMappingController::getAttributeGroupByShopwareID($ConfiguratorOption->getGroup()->getId());
         $PLENTY_attributeValueID = PlentymarketsMappingController::getAttributeOptionByShopwareID($ConfiguratorOption->getId());
         $Object_AttributeLink = new PlentySoapObject_AttributeLink();
         $Object_AttributeLink->AttributeID = $PLENTY_attributeID;
         // int
         $Object_AttributeLink->AttributeValueID = $PLENTY_attributeValueID;
         // int
         $Object_AttributeLink->Activate = true;
         $objectsActivateLinks[] = $Object_AttributeLink;
     }
     // Run the calls
     foreach (array_chunk($objectsActivateLinks, 100) as $activateLinks) {
         $Request_SetItemAttributeLinks->AttributeLinks = $activateLinks;
         PlentymarketsSoapClient::getInstance()->SetItemAttributeLinks($Request_SetItemAttributeLinks);
     }
     // generate the attribute value sets --------------------------------------------------------------------------
     $objectsSetAttributeValueSets = array();
     $cacheAttributeValueSets = array();
     $Request_SetItemAttributeVariants = new PlentySoapRequest_SetItemAttributeVariants();
     $Request_SetItemAttributeVariants->ItemID = $this->PLENTY_itemID;
     // int
     $Request_SetItemAttributeVariants->SetAttributeValueSets = array();
     $Details = $this->SHOPWARE_Article->getDetails();
     /**
      * @var Shopware\Models\Article\Detail $ItemVariation
      * @var Shopware\Models\Article\Configurator\Option $ConfiguratorOption
      */
     foreach ($Details as $ItemVariation) {
         $cacheAttributeValueSets[$ItemVariation->getId()] = array();
         $Object_AttributeVariantList = new PlentySoapObject_AttributeVariantList();
         foreach ($ItemVariation->getConfiguratorOptions() as $ConfiguratorOption) {
             $PLENTY_attributeValueID = PlentymarketsMappingController::getAttributeOptionByShopwareID($ConfiguratorOption->getId());
             $cacheAttributeValueSets[$ItemVariation->getId()][] = $PLENTY_attributeValueID;
             $Object_Integer = new PlentySoapObject_Integer();
             $Object_Integer->intValue = $PLENTY_attributeValueID;
             $Object_AttributeVariantList->AttributeValueIDs[] = $Object_Integer;
         }
         $objectsSetAttributeValueSets[] = $Object_AttributeVariantList;
     }
     foreach (array_chunk($objectsSetAttributeValueSets, 100) as $setAttributeValueSets) {
         // Complete the request
         $Request_SetItemAttributeVariants->SetAttributeValueSets = $setAttributeValueSets;
         // and go for it
         $Response_SetItemAttributeVariants = PlentymarketsSoapClient::getInstance()->SetItemAttributeVariants($Request_SetItemAttributeVariants);
         // Matching der Varianten
         foreach ($Response_SetItemAttributeVariants->ResponseMessages->item as $ResponseMessage) {
             if ($ResponseMessage->IdentificationKey != 'AttributeValueIDs') {
                 continue;
             }
             // If there is an error message, go ahead
             if (!is_null($ResponseMessage->ErrorMessages)) {
                 continue;
             }
             $PLENTY_attributeValueIDs = array_map('intval', explode(';', $ResponseMessage->IdentificationValue));
             $PLENTY_variantID = (int) $ResponseMessage->SuccessMessages->item[0]->Value;
             foreach ($cacheAttributeValueSets as $SHOPWARE_variantID => $attributeValueIDs) {
                 if (PlentymarketsUtils::arraysAreEqual($attributeValueIDs, $PLENTY_attributeValueIDs)) {
                     PlentymarketsMappingController::addItemVariant($SHOPWARE_variantID, sprintf('%s-%s-%s', $this->PLENTY_itemID, $this->PLENTY_priceID, $PLENTY_variantID));
                     break;
                 }
             }
         }
     }
     // Set the variation details ----------------------------------------------------------------------------------
     $objectsAttributeValueSetsDetails = array();
     // start the request
     $Request_SetAttributeValueSetsDetails = new PlentySoapRequest_SetAttributeValueSetsDetails();
     $Request_SetAttributeValueSetsDetails->AttributeValueSetsDetails = array();
     /** @var Shopware\Models\Article\Detail $ItemVariation */
     foreach ($Details as $ItemVariation) {
         try {
             $sku = PlentymarketsMappingController::getItemVariantByShopwareID($ItemVariation->getId());
         } catch (PlentymarketsMappingExceptionNotExistant $E) {
             // Roll back the item
             $this->rollback();
             // and quit
             throw new PlentymarketsExportException('The item variation with the number »' . $ItemVariation->getNumber() . '« could not be created (corrupt data)', 2880);
         }
         $Object_SetAttributeValueSetsDetails = new PlentySoapObject_SetAttributeValueSetsDetails();
         $Object_SetAttributeValueSetsDetails->Availability = $ItemVariation->getActive();
         // int
         $Object_SetAttributeValueSetsDetails->EAN1 = $ItemVariation->getEan();
         // string
         $Object_SetAttributeValueSetsDetails->MaxStock = null;
         // float
         $Object_SetAttributeValueSetsDetails->PurchasePrice = null;
         // float
         $Object_SetAttributeValueSetsDetails->SKU = $sku;
         $Object_SetAttributeValueSetsDetails->Variantnumber = $ItemVariation->getNumber();
         // string
         $objectsAttributeValueSetsDetails[] = $Object_SetAttributeValueSetsDetails;
     }
     foreach (array_chunk($objectsAttributeValueSetsDetails, 50) as $attributeValueSetsDetails) {
         $Request_SetAttributeValueSetsDetails->AttributeValueSetsDetails = $attributeValueSetsDetails;
         PlentymarketsSoapClient::getInstance()->SetAttributeValueSetsDetails($Request_SetAttributeValueSetsDetails);
     }
 }
 /**
  * Export the order
  */
 protected function exportOrder()
 {
     $VariantResource = self::getVariantApi();
     // Build the Request
     $Request_AddOrders = new PlentySoapRequest_AddOrders();
     $Request_AddOrders->Orders = array();
     //
     $Object_Order = new PlentySoapObject_Order();
     //
     $methodOfPayment = $this->getMethodOfPaymentId();
     if ($methodOfPayment == MOP_AMAZON_PAYMENT) {
         $externalOrderID = sprintf('Swag/%d/%s/%s', $this->Order->getId(), $this->Order->getNumber(), $this->Order->getTransactionId());
     } else {
         $externalOrderID = sprintf('Swag/%d/%s', $this->Order->getId(), $this->Order->getNumber());
     }
     $isOrderNet = (bool) $this->Order->getNet() || (bool) $this->Order->getTaxFree();
     // Order head
     $Object_OrderHead = new PlentySoapObject_OrderHead();
     $Object_OrderHead->Currency = PlentymarketsMappingController::getCurrencyByShopwareID($this->Order->getCurrency());
     $Object_OrderHead->CustomerID = $this->PLENTY_customerID;
     $Object_OrderHead->DeliveryAddressID = $this->PLENTY_addressDispatchID;
     $Object_OrderHead->ExternalOrderID = $externalOrderID;
     $Object_OrderHead->IsNetto = $isOrderNet;
     $Object_OrderHead->Marking1ID = PlentymarketsConfig::getInstance()->getOrderMarking1(null);
     $Object_OrderHead->MethodOfPaymentID = $this->getMethodOfPaymentId();
     $Object_OrderHead->OrderTimestamp = $this->getOrderTimestamp();
     $Object_OrderHead->OrderType = 'order';
     $Object_OrderHead->ResponsibleID = PlentymarketsConfig::getInstance()->getOrderUserID(null);
     $Object_OrderHead->ShippingCosts = $this->getShippingCosts();
     $Object_OrderHead->ShippingProfileID = $this->getParcelServicePresetId();
     $Object_OrderHead->StoreID = $this->getShopId();
     $Object_OrderHead->ReferrerID = $this->getReferrerId();
     $Object_Order->OrderHead = $Object_OrderHead;
     // Order infos
     $Object_OrderHead->OrderInfos = array();
     if ($Object_OrderHead->MethodOfPaymentID == MOP_DEBIT) {
         $Customer = $this->Order->getCustomer();
         if ($Customer) {
             $Debit = $Customer->getDebit();
             if ($Debit && $Debit->getAccountHolder()) {
                 $info = 'Account holder: ' . $Debit->getAccountHolder() . chr(10);
                 $info .= 'Bank name: ' . $Debit->getBankName() . chr(10);
                 $info .= 'Bank code: ' . $Debit->getBankCode() . chr(10);
                 $info .= 'Account number: ' . $Debit->getAccount() . chr(10);
                 $Object_OrderInfo = new PlentySoapObject_OrderInfo();
                 $Object_OrderInfo->Info = $info;
                 $Object_OrderInfo->InfoCustomer = 0;
                 $Object_OrderInfo->InfoDate = $this->getOrderTimestamp();
                 $Object_OrderHead->OrderInfos[] = $Object_OrderInfo;
             }
             $PaymentInstances = $Customer->getPaymentInstances();
             if ($PaymentInstances) {
                 foreach ($PaymentInstances as $PaymentInstance) {
                     if ($this->Order->getId() === $PaymentInstance->getOrder()->getId()) {
                         $Object_BankData = new PlentySoapObject_BankData();
                         $Object_BankData->OwnerFirstname = $PaymentInstance->getFirstName();
                         $Object_BankData->OwnerLastname = $PaymentInstance->getLastName();
                         $Object_BankData->BankName = $PaymentInstance->getBankName();
                         $Object_BankData->IBAN = $PaymentInstance->getIban();
                         $Object_BankData->BIC = $PaymentInstance->getBic();
                         $Object_SetBankCreditCardData = new PlentySoapObject_SetBankCreditCardData();
                         $Object_SetBankCreditCardData->CustomerID = $this->PLENTY_customerID;
                         $Object_SetBankCreditCardData->BankData = $Object_BankData;
                         $Request_SetBankCreditCardData = new PlentySoapRequest_SetBankCreditCardData();
                         $Request_SetBankCreditCardData->CustomerData[] = $Object_SetBankCreditCardData;
                         $Response_SetBankCreditCardData = PlentymarketsSoapClient::getInstance()->SetBankCreditCardData($Request_SetBankCreditCardData);
                         if (!$Response_SetBankCreditCardData->Success) {
                             // Set the error end quit
                             $this->setError(self::CODE_ERROR_SOAP);
                             throw new PlentymarketsExportEntityException('The order with the number »' . $this->Order->getNumber() . '« could not be exported');
                         }
                     }
                 }
             }
         }
     }
     if ($this->Order->getInternalComment()) {
         $Object_OrderInfo = new PlentySoapObject_OrderInfo();
         $Object_OrderInfo->Info = $this->Order->getInternalComment();
         $Object_OrderInfo->InfoCustomer = 0;
         $Object_OrderInfo->InfoDate = $this->getOrderTimestamp();
         $Object_OrderHead->OrderInfos[] = $Object_OrderInfo;
     }
     if ($this->Order->getCustomerComment()) {
         $Object_OrderInfo = new PlentySoapObject_OrderInfo();
         $Object_OrderInfo->Info = $this->Order->getCustomerComment();
         $Object_OrderInfo->InfoCustomer = 1;
         $Object_OrderInfo->InfoDate = $this->getOrderTimestamp();
         $Object_OrderHead->OrderInfos[] = $Object_OrderInfo;
     }
     if ($this->Order->getComment()) {
         $Object_OrderInfo = new PlentySoapObject_OrderInfo();
         $Object_OrderInfo->Info = $this->Order->getComment();
         $Object_OrderInfo->InfoCustomer = 1;
         $Object_OrderInfo->InfoDate = $this->getOrderTimestamp();
         $Object_OrderHead->OrderInfos[] = $Object_OrderInfo;
     }
     $Object_Order->OrderItems = array();
     /** @var Shopware\Models\Order\Detail $Item */
     foreach ($this->Order->getDetails() as $Item) {
         $number = $Item->getArticleNumber();
         $itemText = '';
         // Variant
         try {
             $itemId = null;
             try {
                 // get the detail id by the order number
                 $articleDetailID = $VariantResource->getIdFromNumber($Item->getArticleNumber());
             } catch (Exception $E) {
                 $articleDetailID = -1;
             }
             // get the sku from the detail id
             $sku = PlentymarketsMappingController::getItemVariantByShopwareID($articleDetailID);
         } catch (PlentymarketsMappingExceptionNotExistant $E) {
             // Base item
             try {
                 $itemId = PlentymarketsMappingController::getItemByShopwareID($Item->getArticleId());
                 $sku = null;
             } catch (PlentymarketsMappingExceptionNotExistant $E) {
                 $itemId = -2;
                 $sku = null;
                 // Mandatory because there will be no mapping to any item
                 $itemText = $Item->getArticleName();
             }
         }
         //
         if ($itemId > 0 || !empty($sku)) {
             if (PlentymarketsConfig::getInstance()->getOrderItemTextSyncActionID(EXPORT_ORDER_ITEM_TEXT_SYNC) == EXPORT_ORDER_ITEM_TEXT_SYNC) {
                 $itemText = $Item->getArticleName();
             } else {
                 $itemText = null;
             }
         }
         // Coupon
         if ($Item->getMode() == 2) {
             $itemId = -1;
             $rowType = 'Coupon';
         }
         // Additional coupon identifiers für 3rd party plugins
         $couponIdentifiers = PyConf()->get('OrderAdditionalCouponIdentifiers', '');
         $couponIdentifiers = explode('|', $couponIdentifiers);
         if (in_array($number, $couponIdentifiers)) {
             $itemId = -1;
             $rowType = 'Coupon';
         } else {
             // PAYONE fix
             if ($number == 'SHIPPING' && !$Object_OrderHead->ShippingCosts) {
                 $Object_OrderHead->ShippingCosts = $Item->getPrice();
                 continue;
             }
             $discountNumber = Shopware()->Config()->get('discountnumber');
             $surchargeNumber = Shopware()->Config()->get('surchargenumber');
             $paymentSurchargeNumber = Shopware()->Config()->get('paymentsurchargenumber');
             $paymentSurchargeAbsoluteNumber = Shopware()->Config()->get('paymentSurchargeAbsoluteNumber');
             $shippingDiscountNumber = Shopware()->Config()->get('shippingdiscountnumber');
             switch ($number) {
                 case $paymentSurchargeNumber:
                 case $paymentSurchargeAbsoluteNumber:
                     $rowType = 'SurchargeForPaymentMethod';
                     break;
                 case $discountNumber:
                     $rowType = 'Discount';
                     break;
                 case $surchargeNumber:
                     $rowType = 'Surcharge';
                     break;
                 case $shippingDiscountNumber:
                     $rowType = 'SurchargeForShippingMethod';
                     break;
                 default:
                     $rowType = 'Default';
                     break;
             }
         }
         if ($isOrderNet) {
             // Calculate the gross amount (needed by plentymakets even though it is a net sales order)
             $itemPrice = $Item->getPrice() * ((100 + (double) $Item->getTaxRate()) / 100);
         } else {
             $itemPrice = $Item->getPrice();
         }
         $Object_OrderItem = new PlentySoapObject_OrderItem();
         $Object_OrderItem->ExternalOrderItemID = $number;
         $Object_OrderItem->ItemID = $itemId;
         $Object_OrderItem->ReferrerID = $Object_OrderHead->ReferrerID;
         $Object_OrderItem->ItemText = $itemText;
         $Object_OrderItem->Price = $itemPrice;
         $Object_OrderItem->Quantity = $Item->getQuantity();
         $Object_OrderItem->SKU = $sku;
         $Object_OrderItem->VAT = $Item->getTaxRate();
         $Object_OrderItem->RowType = $rowType;
         $Object_Order->OrderItems[] = $Object_OrderItem;
     }
     $Request_AddOrders->Orders[] = $Object_Order;
     // Do the request
     $Response_AddOrders = PlentymarketsSoapClient::getInstance()->AddOrders($Request_AddOrders);
     if (!$Response_AddOrders->Success) {
         // Set the error end quit
         $this->setError(self::CODE_ERROR_SOAP);
         throw new PlentymarketsExportEntityException('The order with the number »' . $this->Order->getNumber() . '« could not be exported', 4010);
     }
     //
     $plentyOrderID = null;
     $plentyOrderStatus = 0.0;
     foreach ($Response_AddOrders->ResponseMessages->item[0]->SuccessMessages->item as $SuccessMessage) {
         switch ($SuccessMessage->Key) {
             case 'OrderID':
                 $plentyOrderID = (int) $SuccessMessage->Value;
                 break;
             case 'Status':
                 $plentyOrderStatus = (double) $SuccessMessage->Value;
                 break;
         }
     }
     if ($plentyOrderID && $plentyOrderStatus) {
         $this->setSuccess($plentyOrderID, $plentyOrderStatus);
     } else {
         // Set the error end quit
         $this->setError(self::CODE_ERROR_SOAP);
         throw new PlentymarketsExportEntityException('The order with the number »' . $this->Order->getNumber() . '« could not be exported (no order id or order status respectively)', 4020);
     }
     $paymentStatusPaid = explode('|', PlentymarketsConfig::getInstance()->getOrderPaidStatusID(12));
     // Directly book the incoming payment
     if ($this->Order->getPaymentStatus() && in_array($this->Order->getPaymentStatus()->getId(), $paymentStatusPaid)) {
         // May throw an exception
         $IncomingPayment = new PlentymarketsExportEntityOrderIncomingPayment($this->Order->getId());
         $IncomingPayment->book();
     }
 }