From b5926ee039cfb490c6393b7daa84325eef717f76 Mon Sep 17 00:00:00 2001
From: OpenXE <>
Date: Fri, 2 Dec 2022 12:19:42 +0000
Subject: [PATCH] Bugfix www/pages/shopimporter_shopware6.php
---
www/pages/shopimporter_shopware6.php | 7634 +++++++++++++-------------
1 file changed, 3817 insertions(+), 3817 deletions(-)
diff --git a/www/pages/shopimporter_shopware6.php b/www/pages/shopimporter_shopware6.php
index 3189b694..c6cfa630 100644
--- a/www/pages/shopimporter_shopware6.php
+++ b/www/pages/shopimporter_shopware6.php
@@ -1,3820 +1,3820 @@
-app = $app;
- $this->intern = true;
- if ($intern) {
- return;
- }
- $this->app->ActionHandlerInit($this);
-
- $this->app->ActionHandler('list', 'Shopimporter_Shopware6List');
- $this->app->ActionHandler('auth', 'ImportAuth');
- $this->app->ActionHandler('sendlistlager', 'ImportSendListLager');
- $this->app->ActionHandler('getauftraegeanzahl', 'ImportGetAuftraegeAnzahl');
- $this->app->ActionHandler('getauftrag', 'ImportGetAuftrag');
- $this->app->ActionHandler('deleteauftrag', 'ImportDeleteAuftrag');
- $this->app->ActionHandler('updateauftrag', 'ImportUpdateAuftrag');
- $this->app->ActionHandler('storniereauftrag','ImportStorniereAuftrag');
- $this->app->ActionHandler('getarticle','ImportGetArticle');
- $this->app->ActionHandler('getarticlelist','ImportGetArticleList');
- $this->app->ActionHandler("updatezahlungsstatus","ImportUpdateZahlungsstatus");
- $this->app->DefaultActionHandler('list');
-
- $this->app->ActionHandlerListen($app);
- }
-
- /**
- * @param string $productId
- *
- * @return mixed
- */
- public function addSyncCustomFieldToProduct(string $productId)
- {
- $customField = [
- 'customFields' => [
- 'wawision_shopimporter_syncstate' => 1
- ]
- ];
-
- return $this->shopwareRequest('PATCH', "product/{$productId}", $customField);
- }
-
- /**
- * @param string $orderId
- *
- * @return mixed
- */
- public function addCustomFieldToOrder(string $orderId)
- {
- $customField = [
- 'customFields' => [
- 'wawision_shopimporter_syncstate' => 1
- ]
- ];
-
- return $this->shopwareRequest('PATCH', "order/{$orderId}", $customField);
- }
-
- public function ImportGetArticleList()
- {
- $page = 1;
- $limit = 500;
-
- do {
- $productIdsToAdd = [];
- $searchdata = [
- 'limit' => $limit,
- 'page' => $page,
- 'filter' => [
- [
- 'field' => 'product.parentId',
- 'type' => 'equals',
- 'value' => null
- ]
- ]
- ];
-
- $productsInShop = $this->shopwareRequest('POST', 'search/product', $searchdata);
- if (!empty($productsInShop['data'])) {
- foreach ($productsInShop['data'] as $productInShop) {
- $productIdsToAdd[] = $productInShop['id'];
- }
- }
-
- foreach ($productIdsToAdd as $productId) {
- $this->app->DB->Insert("INSERT INTO shopexport_getarticles (shop, nummer) VALUES ('$this->shopid', '" . $this->app->DB->real_escape_string($productId) . "')");
- }
- $page++;
- } while (count($productsInShop['data']) === $limit);
-
-
- $anzahl = $this->app->DB->Select("SELECT COUNT(id) FROM shopexport_getarticles WHERE shop=$this->shopid");
- $this->app->erp->SetKonfigurationValue('artikelimportanzahl_' . $this->shopid, $anzahl);
-
- }
-
- /**
- * @param string $method
- * @param string $endpoint
- * @param string $data
- *
- * @param array $headerInformation
- * @return mixed
- */
- public function shopwareRequest($method, $endpoint, $data = '', $headerInformation = [])
- {
- $accessToken = $this->shopwareToken();
- $url = $this->ShopUrl;
- $url .= 'v2/' . $endpoint;
-
- $ch = curl_init();
- $headerInformation[] = 'Content-Type:application/json';
- $headerInformation[] = 'Authorization:Bearer ' . $accessToken['token'];
- curl_setopt($ch, CURLOPT_URL, $url);
- if (!empty($data)) {
- curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
- }
- curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
- curl_setopt($ch, CURLOPT_HTTPHEADER, $headerInformation);
- curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
- curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
- $response = curl_exec($ch);
- if (curl_error($ch)) {
- $this->error[] = curl_error($ch);
- }
- curl_close($ch);
-
- return json_decode($response, true);
- }
-
- /**
- * @return array
- */
- protected function shopwareToken()
- {
- $result = [];
-
- $result['success'] = true;
- $result['token'] = $this->accessToken;
- $result['message'] = 'Keine Antwort von API erhalten.';
-
- if (!empty($result['token'])) {
- return $result;
- }
-
- $result['success'] = false;
-
- $data = [
- 'username' => $this->UserName,
- 'password' => $this->Password,
- 'grant_type' => 'password',
- 'scopes' => 'write',
- 'client_id' => 'administration',
- ];
-
- $ch = curl_init($this->ShopUrl . 'oauth/token');
- curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
- curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
- curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
- curl_setopt($ch, CURLOPT_HTTPHEADER, [
- 'Accept: application/json',
- 'Content-Type: application/json',
- 'Cache-Control: no-cache',
- ]
- );
- $response = json_decode(curl_exec($ch), true);
-
- if (!empty((string)$response['title'])) {
- $result['message'] = $response['title'];
- }
-
- if (!empty($response['access_token'])) {
- $result['success'] = true;
- $this->accessToken = $response['access_token'];
- $result['token'] = $response['access_token'];
- }
-
- return $result;
- }
-
- public function ImportGetArticle()
- {
- $tmp = $this->CatchRemoteCommand('data');
-
- if (isset($tmp['nummerintern'])) {
- $nummer = $tmp['nummerintern'];
- $response = $this->shopwareRequest('GET', 'product/' . $nummer);
- if (empty($response['data'])) {
- $this->error[] = 'Artikel in der Shop Datenbank nicht gefunden!';
- return;
- }
- $nummer = $response['data']['attributes']['productNumber'];
- } else {
- $nummer = $tmp['nummer'];
- }
- $articleInfo = $this->shopwareRequest('GET', 'product?filter[product.productNumber]=' . $nummer .
- '&associations[manufacturer][]&associations[properties][]');
- if (empty($articleInfo['data'][0])) {
- $this->error[] = 'Artikel in der Shop Datenbank nicht gefunden!';
- return;
- }
- $articleIdInShop = $articleInfo['data'][0]['id'];
- if(empty($articleInfo['data'][0]['customFields'])
- || empty($articleInfo['data'][0]['customFields']['wawision_shopimporter_syncstate'])){
- $this->addSyncCustomFieldToProduct((string)$articleIdInShop);
- }
-
- $articleInfo = $this->shopwareRequest('GET', 'product?filter[product.productNumber]=' . $nummer .
- '&associations[manufacturer][]&associations[properties][]');
- $associatedInformation = [];
- $properties = [];
- foreach ($articleInfo['included'] as $includedInformation) {
- if ($includedInformation['type'] === 'property_group_option') {
- $properties[$includedInformation['id']] = $includedInformation['attributes'];
- } else {
- $associatedInformation[$includedInformation['id']] = $includedInformation['attributes'];
- }
- }
- $groups = [];
- if (!empty($properties)) {
- $groupsInShop = $this->shopwareRequest('GET', 'property-group');
- foreach ($groupsInShop['data'] as $groupInShop) {
- $groups[$groupInShop['id']] = $groupInShop['attributes']['name'];
- }
- }
- $media = $this->shopwareRequest('GET', 'product/' . $articleIdInShop . '/media');
- $imagesToAdd = [];
- if (!empty($media['included'])) {
- foreach ($media['included'] as $mediaInfo) {
- if ($mediaInfo['type'] === 'media') {
- $imagesToAdd[] = [
- 'content' => base64_encode(@file_get_contents($mediaInfo['attributes']['url'])),
- 'path' => $mediaInfo['attributes']['url'],
- 'id' => $mediaInfo['id']
- ];
- }
- }
- }
- $articleInfo = $articleInfo['data'][0]['attributes'];
-
- $data = [];
- $data['name'] = $articleInfo['name'];
- if (isset($tmp['nummerintern'])) {
- $data['nummer'] = $articleInfo['productNumber'];
- }
-
-
- $data['artikelnummerausshop'] = $articleInfo['productNumber'];
- $data['restmenge'] = $articleInfo['stock'];
- $data['uebersicht_de'] = $articleInfo['description'];
- $data['preis_netto'] = $articleInfo['price'][0]['net'];
- if (!empty($articleInfo['price'][0]['listPrice'])) {
- $data['pseudopreis'] = $articleInfo['price'][0]['listPrice'];
- }
- $data['aktiv'] = $articleInfo['active'];
- if (!empty($articleInfo['weight'])) {
- $data['gewicht'] = $articleInfo['weight'];
- }
- if (!empty($articleInfo['manufacturerNumber'])) {
- $data['herstellernummer'] = $articleInfo['manufacturerNumber'];
- }
- if (!empty($articleInfo['ean'])) {
- $data['ean'] = $articleInfo['ean'];
- }
- if (!empty($articleInfo['manufacturerId'])) {
- $data['hersteller'] = $associatedInformation[$articleInfo['manufacturerId']]['name'];
- }
- if (!empty($articleInfo['taxId'])) {
- $data['umsatzsteuer'] = $associatedInformation[$articleInfo['taxId']]['taxRate'];
- }
- if (!empty($properties)) {
- foreach ($properties as $property) {
- if ($this->propertyOption === 'toProperties') {
- $data['eigenschaften'][] = [
- 'name' => $groups[$property['groupId']],
- 'values' => $property['name'],
- ];
- }
- if ($this->propertyOption === 'toCustomFields') {
- $data['freifeld_' . $groups[$property['groupId']]] = $property['name'];
- }
- }
- }
- if (!empty($articleInfo['customFields'])) {
- foreach ($articleInfo['customFields'] as $customFieldName => $customFieldValue) {
- if ($this->freeFieldOption === 'toProperties') {
- $data['eigenschaften'][] = [
- 'name' => $customFieldName,
- 'values' => $customFieldValue
- ];
- }
- if ($this->freeFieldOption === 'toCustomFields') {
- $data['freifeld_' . $customFieldName] = $customFieldValue;
- }
- }
- }
- if (!empty($imagesToAdd)) {
- $data['bilder'] = $imagesToAdd;
- }
-
-
- if ($articleInfo['childCount'] > 0) {
- $data = [$data];
-
- $limit = 50;
- $page = 1;
- $optionInfo = [];
- $optionGroupInfo = [];
- do {
-
- $searchdata = [
- 'limit' => $limit,
- 'page' => $page,
- 'filter' => [
- [
- 'field' => 'product.parentId',
- 'type' => 'equals',
- 'value' => $articleIdInShop
- ]
- ],
- 'sort' => [
- [
- 'field' => 'product.options.groupId',
- 'naturalSorting' => false,
- 'order' => 'ASC'
- ],
- [
- 'field' => 'product.options.id',
- 'naturalSorting' => false,
- 'order' => 'ASC'
- ]
- ],
- 'associations' => [
- 'options' => [
- 'sort' => [
- [
- 'field' => 'groupId',
- 'naturalSorting' => false,
- 'order' => 'ASC'
- ],
- [
- 'field' => 'id',
- 'naturalSorting' => false,
- 'order' => 'ASC'
- ]
- ]
- ]
- ]
- ];
- $variantsInShop = $this->shopwareRequest('POST', 'search/product', $searchdata);
- foreach ($variantsInShop['included'] as $includedInfo) {
- if ($includedInfo['type'] === 'property_group_option') {
- $optionInfo[$includedInfo['id']] = $includedInfo['attributes'];
- if (empty($optionGroupInfo[$includedInfo['attributes']['groupId']])) {
- $optionGroupInfo[$includedInfo['attributes']['groupId']] = (!empty($optionGroupInfo)?count($optionGroupInfo):0) + 1;
- }
- }
- }
-
- foreach ($variantsInShop['data'] as $variantInShop) {
- $variantData = [];
- $variantName = $data[0]['name'];
- foreach ($variantInShop['attributes']['optionIds'] as $optionId) {
- $variantData['matrixprodukt_wert' . $optionGroupInfo[$optionInfo[$optionId]['groupId']]] =
- $optionInfo[$optionId]['name'];
- $variantName .= ' - ' . $optionInfo[$optionId]['name'];
- }
-
- $variantData['name'] = $variantName;
- $variantData['nummer'] = $variantInShop['attributes']['productNumber'];
- $variantData['artikelnummerausshop'] = $variantInShop['attributes']['productNumber'];
- $variantData['restmenge'] = $variantInShop['attributes']['stock'];
- $variantData['uebersicht_de'] = $variantInShop['attributes']['description'];
- if (empty($variantInShop['attributes']['price'][0]['net'])) {
- $variantData['preis_netto'] = $data[0]['preis_netto'];
- } else {
- $variantData['preis_netto'] = $variantInShop['attributes']['price'][0]['net'];
- }
- if (!empty($variantInShop['attributes']['price'][0]['listPrice'])) {
- $variantData['pseudopreis'] = $variantInShop['attributes']['price'][0]['listPrice'];
- }
- $variantData['aktiv'] = $variantInShop['attributes']['active'];
- if (!empty($variantInShop['attributes']['weight'])) {
- $variantData['gewicht'] = $variantInShop['attributes']['weight'];
- }
- if (!empty($variantInShop['attributes']['manufacturerNumber'])) {
- $variantData['herstellernummer'] = $variantInShop['attributes']['manufacturerNumber'];
- }
- if (!empty($variantInShop['attributes']['ean'])) {
- $variantData['ean'] = $variantInShop['attributes']['ean'];
- }
- if (!empty($data[0]['umsatzsteuer'])) {
- $variantData['umsatzsteuer'] = $data[0]['umsatzsteuer'];
- }
-
- $data[] = $variantData;
- }
-
- $page++;
- } while (count($variantsInShop['data']) > $limit);
-
- foreach ($optionGroupInfo as $groupId => $sorting) {
- $data[0]['matrixprodukt_gruppe' . $sorting] = $groups[$groupId];
- }
- foreach ($optionInfo as $optionData) {
- $data[0]['matrixprodukt_optionen' . $optionGroupInfo[$optionData['groupId']]][] = $optionData['name'];
- }
- }
-
- //TODO Staffelpreise
- //TODO Kategorien
- //TODO Freifelder
- //TODO Crossselling
-
- return $data;
- }
-
- /**
- * @param array $data
- *
- * @return array
- */
- public function checkApiApp($data)
- {
- foreach (['shopwareUserName', 'shopwarePassword', 'shopwareUrl'] as $field) {
- if (empty($data['data'][$field])) {
- return ['success' => false, 'error' => sprintf('%s is empty', $field)];
- }
- }
-
- $shops = $this->app->DB->SelectArr(
- sprintf(
- "SELECT `einstellungen_json`, `bezeichnung`,`id`
- FROM `shopexport`
- WHERE `modulename` = 'shopimporter_shopware6'
- AND `einstellungen_json` IS NOT NULL AND `einstellungen_json` <> ''"
- )
- );
- if (empty($shops)) {
- return [
- 'info' => [
- 'Shop' => 'Shopware',
- 'info' => 'Url ' . $data['data']['shopwareUrl'],
- ]
- ];
- }
- foreach ($shops as $shop) {
- if (empty($shop['einstellungen_json'])) {
- continue;
- }
- $json = @json_decode($shop['einstellungen_json'], true);
- if (empty($json['felder']) || empty($json['felder']['shopwareUrl'])) {
- continue;
- }
- if ($json['felder']['shopwareUrl'] === $data['data']['shopwareUrl']) {
- return [
- 'success' => false,
- 'error' => sprintf('Shop with url %s allready exists', $data['data']['shopwareUrl'])
- ];
- }
- }
-
- return [
- 'info' => [
- 'Shop' => 'Shopware',
- 'info' => 'Url ' . $data['data']['shopwareUrl'],
- ]
- ];
- }
-
- /**
- *
- */
- public function Shopimporter_Shopware6List()
- {
- $msg = $this->app->erp->base64_url_encode('
Sie können hier die Shops einstellen
');
- header('Location: index.php?module=onlineshops&action=list&msg=' . $msg);
- exit;
- }
-
- /**
- * @param $shopid
- * @param $data
- */
- public function getKonfig($shopid, $data)
- {
- $this->shopid = $shopid;
- $this->data = $data;
- $importerSettings = $this->app->DB->SelectArr("SELECT `einstellungen_json`, `kategorienuebertragen` FROM `shopexport` WHERE `id` = '$shopid' LIMIT 1");
- $importerSettings = reset($importerSettings);
-
- $this->exportCategories = (bool) $importerSettings['kategorienuebertragen'];
-
- $einstellungen = [];
- if (!empty($importerSettings['einstellungen_json'])) {
- $einstellungen = json_decode($importerSettings['einstellungen_json'], true);
- }
- $this->protocol = $einstellungen['felder']['protocol'];
- $this->UserName = $einstellungen['felder']['shopwareUserName'];
- $this->Password = $einstellungen['felder']['shopwarePassword'];
- $this->ShopUrl = rtrim($einstellungen['felder']['shopwareUrl'], '/') . '/';
- $this->createManufacturerAllowed = false;
- if ($einstellungen['felder']['shopwareAllowCreateManufacturer'] === '1') {
- $this->createManufacturerAllowed = true;
- }
- $this->defaultManufacturer = $einstellungen['felder']['shopwareDefaultManufacturer'];
- $this->defaultRuleName = $einstellungen['felder']['shopwareDefaultRuleName'];
- $this->statesToFetch = $einstellungen['felder']['statesToFetch'];
- $this->deliveryStatesToFetch = $einstellungen['felder']['deliveryStatesToFetch'];
- $this->transactionStatesToFetch = $einstellungen['felder']['transactionStatesToFetch'];
- $this->salesChannelToFetch = $einstellungen['felder']['salesChannelToFetch'];
- $this->orderSearchLimit = $einstellungen['felder']['orderSearchLimit'];
- $this->freeFieldOption = $einstellungen['felder']['shopwareFreeFieldOption'];
- $this->propertyOption = $einstellungen['felder']['shopwarePropertyOption'];
- $this->shopwareDefaultSalesChannel = $einstellungen['felder']['shopwareDefaultSalesChannel'];
- $this->shopwareMediaFolder = $einstellungen['felder']['shopwareMediaFolder'];
- $query = sprintf('SELECT `steuerfreilieferlandexport` FROM `shopexport` WHERE `id` = %d', $this->shopid);
- $this->taxationByDestinationCountry = !empty($this->app->DB->Select($query));
-
- $this->client = $this->app->Container->get('Shopware6Client');
- $this->client->setCredentials(
- $this->UserName,
- $this->Password,
- $this->ShopUrl
- );
- }
-
- /**
- * @return array
- */
- public function EinstellungenStruktur()
- {
- return
- [
- 'ausblenden' => ['abholmodus' => ['ab_nummer']],
- 'functions' => ['exportartikelbaum','getarticlelist','updatezahlungsstatus'],
- 'felder' => [
- 'protocol' => [
- 'typ' => 'checkbox',
- 'bezeichnung' => '{|Protokollierung im Logfile|}:',
- ],
- 'shopwareUserName' => [
- 'typ' => 'text',
- 'bezeichnung' => '{|Benutzername|}:',
- 'size' => 40,
- ],
- 'shopwarePassword' => [
- 'typ' => 'text',
- 'bezeichnung' => '{|Passwort|}:',
- 'size' => 40,
- ],
- 'shopwareUrl' => [
- 'typ' => 'text',
- 'bezeichnung' => '{|Shop API URL|}:',
- 'size' => 40,
- ],
- 'shopwareDefaultManufacturer' => [
- 'typ' => 'text',
- 'bezeichnung' => '{|Standard Hersteller|}:',
- 'size' => 40,
- 'default' => 'Keine Herstellerinformation',
- ],
- 'shopwareAllowCreateManufacturer' => [
- 'typ' => 'checkbox',
- 'bezeichnung' => '{|Bei Artikelexport Hersteller anlegen|}:',
- ],
- 'shopwareDefaultRuleName' => [
- 'typ' => 'text',
- 'bezeichnung' => '{|Name der Standardpreisgruppe|}:',
- 'size' => 40,
- 'default' => 'All customers',
- ],
- 'shopwarePropertyOption' => [
- 'heading' => '{|Eigenschaften / Freifeld Zuordnung|}',
- 'typ' => 'select',
- 'bezeichnung' => '{|Xentral Artikel Eigenschaften|}:',
- 'size' => 40,
- 'default' => 'toProperties',
- 'optionen' => ['toProperties' => '{|Shopware Eigenschaften|}', 'toCustomFields' => '{|Shopware Zusatzfelder|}', 'doNotExport' => '{|Nicht übertragen|}']
- ],
- 'shopwareFreeFieldOption' => [
- 'typ' => 'select',
- 'bezeichnung' => '{|Xentral Artikel Freifelder|}:',
- 'size' => 40,
- 'default' => 'toCustomFields',
- 'optionen' => ['toProperties' => '{|Shopware Eigenschaften|}', 'toCustomFields' => '{|Shopware Zusatzfelder|}', 'doNotExport' => '{|Nicht übertragen|}']
- ],
- 'shopwareDefaultSalesChannel' => [
- 'heading' => '{|Artikelexport Standardeinstellungen|}',
- 'typ' => 'text',
- 'bezeichnung' => '{|Standard Sichtbarkeit|}:',
- 'size' => 40
- ],
- 'shopwareMediaFolder' => [
- 'typ' => 'text',
- 'bezeichnung' => '{|Media Folder für Artikelbilder|}:',
- 'size' => 40,
- 'default' => 'Product Media'
- ],
- 'statesToFetch' => [
- 'typ' => 'text',
- 'bezeichnung' => '{|Abzuholender Bestellstatus|}:',
- 'size' => 40,
- 'default' => 'open',
- 'col' => 2,
- 'info' => '
Erlaubte Werte: open;in_progress;completed;cancelled'
- ],
- 'deliveryStatesToFetch' => [
- 'typ' => 'text',
- 'bezeichnung' => '{|Eingrenzen auf Lieferstatus|}:',
- 'size' => 40,
- 'default' => '',
- 'col' => 2,
- 'info' => '
Erlaubte Werte: open;shipped_partially;shipped;returned;returned_partially;cancelled'
- ],
- 'transactionStatesToFetch' => [
- 'typ' => 'text',
- 'bezeichnung' => '{|Eingrenzen auf Bezahlstatus|}:',
- 'size' => 40,
- 'default' => '',
- 'col' => 2,
- 'info' => '
Erlaubte Werte: open;paid;authorized;paid_partially;refunded;refunded_partially;reminded;cancelled'
- ],
- 'salesChannelToFetch' => [
- 'typ' => 'text',
- 'bezeichnung' => '{|Eingrenzen auf Sales Channel|}:',
- 'size' => 40,
- 'default' => '',
- 'col' => 2,
- 'info' => '
Klicke auf "Verbindung prüfen" um die verfügbaren Channels (bitte die Id verwenden) anzuzeigen.'
- ],
- 'orderSearchLimit' => [
- 'typ' => 'select',
- 'bezeichnung' => '{|Anzahl Aufträge abholen|}:',
- 'optionen' => [
- '25' => '25',
- '50' => '50',
- '75' => '75',
- '100' => '100',
- ],
- 'default' => '25',
- 'col' => 2
- ],
- ],
- ];
- }
-
- public function ImportUpdateZahlungsstatus()
- {
- $tmp = $this->CatchRemoteCommand('data');
- $auftrag = $tmp['auftrag'];
-
- $transactions = $this->shopwareRequest('GET', 'order/'.$auftrag.'/transactions');
- $transactionId = $transactions['data'][0]['id'];
-
- if(empty($transactionId)){
- return;
- }
-
- $response = $this->shopwareRequest('POST', '_action/order_transaction/'.$transactionId.'/state/paid');
- if (!empty($response['id'])) {
- return 'ok';
- }
- }
-
- public function ImportSendArtikelbaum(){
- $xentralCategoryTree = [];
- $this->app->erp->GetKategorienbaum($xentralCategoryTree, 0, 0, $this->shopid);
-
- $xentralCategoryIdToParentId = [];
- foreach ($xentralCategoryTree as $key => $value) {
- $xentralCategoryTree[$key]['erledigt'] = false;
- $xentralCategoryTree[$key]['shopid'] = '';
- $xentralCategoryTree[$key]['aktiv'] = false;
- $xentralCategoryIdToParentId[$value['id']] = $key;
- }
-
- $parentCategoryId = null;
- foreach ($xentralCategoryTree as $index => $categoryData) {
- $this->createCategoryTree($index, $xentralCategoryTree, $xentralCategoryIdToParentId, $parentCategoryId);
- }
- }
-
- protected function createCategoryTree($id, &$xentralCategoryTree, $xentralCategoryIdToParentId, $parentCategoryId)
- {
- $parentId = $parentCategoryId;
- if ($xentralCategoryTree[$id]['parent']) {
- $parentId = $xentralCategoryTree[$xentralCategoryIdToParentId[$xentralCategoryTree[$id]['parent']]]['shopid'];
- }
- if ($xentralCategoryTree[$id]['parent'] && !$xentralCategoryTree[$xentralCategoryIdToParentId[$xentralCategoryTree[$id]['parent']]]['erledigt']) {
- $this->createCategoryTree($xentralCategoryIdToParentId[$xentralCategoryTree[$id]['parent']], $xentralCategoryTree, $xentralCategoryIdToParentId, $parentCategoryId);
- }
- $xentralCategoryTree[$id]['erledigt'] = true;
-
- $categoryName = $xentralCategoryTree[$id]['bezeichnung'];
- $searchdata = [
- 'limit' => 25,
- 'filter' => [
- [
- 'field' => 'category.name',
- 'type' => 'equals',
- 'value' => $categoryName
- ],
- [
- 'field' => 'category.parentId',
- 'type' => 'equals',
- 'value' => $parentId
- ]
- ]
- ];
-
- $categoriesInShop = $this->shopwareRequest('POST', 'search/category', $searchdata);
-
- $categoryId = '';
- if (!empty($categoriesInShop['data'])) {
- $categoryId = $categoriesInShop['data'][0]['id'];
- }
-
- if (!$categoryId) {
- $categoryData = [
- 'parentId' => $parentId,
- 'name' => $categoryName
- ];
- $result = $this->shopwareRequest('POST', 'category?_response=true', $categoryData);
- if ($result['data']['id']) {
- $categoryId = $result['data']['id'];
- }
- }
-
- if ($categoryId) {
- $xentralCategoryTree[$id]['shopid'] = $categoryId;
- }
- }
-
- /**
- * @return int
- */
- public function ImportSendListLager()
- {
- $tmp = $this->CatchRemoteCommand('data');
-
- $count = 0;
- foreach ($tmp as $article) {
- $artikel = $article['artikel'];
- if ($artikel === 'ignore') {
- continue;
- }
- $nummer = $article['nummer'];
- $fremdnummer = $article['fremdnummer'];
- if (!empty($fremdnummer)) {
- $nummer = $fremdnummer;
- }
- $articleInfo = $this->shopwareRequest('GET', 'product?filter[product.productNumber]=' . $nummer);
-
- if (empty($articleInfo['data'][0]['id'])) {
- $this->Shopware6Log('Artikel wurde nicht im Shop gefunden: ' . $nummer, $articleInfo);
- continue;
- }
- if(empty($articleInfo['data'][0]['customFields'])
- || empty($articleInfo['data'][0]['customFields']['wawision_shopimporter_syncstate'])){
- $this->addSyncCustomFieldToProduct((string)$articleInfo['data'][0]['id']);
- }
-
- $active = true;
- if ($article['inaktiv']) {
- $active = false;
- }
-
- $stock = $article['anzahl_lager'];
- if (!empty($article['pseudolager'])) {
- $stock = $article['pseudolager'];
- }
- $stock = $this->getCorrectedStockFromAvailable($active, (int)$stock, $articleInfo);
- $data = [
- 'stock' => $stock,
- 'active' => $active,
- ];
- $response = $this->shopwareRequest('PATCH', 'product/' . $articleInfo['data'][0]['id'], $data);
- $this->Shopware6Log('Lagerbestand konnte nicht uebertragen werden fuer Artikel: ' . $nummer, $response);
- $count++;
- }
-
- return $count;
- }
-
- /**
- * @param bool $isStockActive
- * @param int $stock
- * @param array|null $articleInfo
- *
- * @return int
- */
- public function getCorrectedStockFromAvailable(bool $isStockActive, int $stock, ?array $articleInfo): int
- {
- if(!$isStockActive) {
- return $stock;
- }
- if(empty($articleInfo)) {
- return $stock;
- }
- if(!isset($articleInfo['data'][0]['attributes']['availableStock'])) {
- return $stock;
- }
- if(!isset($articleInfo['data'][0]['attributes']['availableStock'])) {
- return $stock;
- }
- $reserved = (int)$articleInfo['data'][0]['attributes']['stock']
- - (int)$articleInfo['data'][0]['attributes']['availableStock'];
- if($reserved <= 0) {
- return $stock;
- }
-
- return $stock + $reserved;
- }
-
- /**
- * @param string $message
- * @param mixed $dump
- */
- public function Shopware6Log($message, $dump = '')
- {
- if ($this->protocol) {
- $this->app->erp->Logfile($message, print_r($dump, true));
- }
- }
-
- /**
- * @return int
- */
- public function ImportSendList()
- {
- $articleList = $this->CatchRemoteCommand('data');
-
- $successCounter = 0;
- foreach ($articleList as $article) {
- $number = $article['nummer'];
- $articleInfo = $this->shopwareRequest(
- 'GET',
- sprintf('product?filter[product.productNumber]=%s', $number)
- );
- $articleIdShopware = '';
- if (!empty($articleInfo['data'][0]['id'])) {
- $articleIdShopware = $articleInfo['data'][0]['id'];
- }
-
- $quantity = $article['anzahl_lager'];
- if (!empty($article['pseudolager'])) {
- $quantity = $article['pseudolager'];
- }
- $inaktiv = $article['inaktiv'];
- $active = true;
- if (!empty($inaktiv)) {
- $active = false;
- }
- $quantity = $this->getCorrectedStockFromAvailable($active, (int)$quantity, $articleInfo);
- $taxRate = (float)$article['steuersatz'];
-
- $taxId = $this->getTaxIdByRate($taxRate);
-
- $mediaToAdd = $this->mediaToExport($article, $articleIdShopware);
-
- $categoriesToAdd = [];
- if($this->exportCategories){
- $categoriesToAdd = $this->categoriesToExport($article, $articleIdShopware);
- }
-
- $propertiesToAdd = $this->propertiesToExport($article, $articleIdShopware);
-
- $crosselingToAdd = $this->crosssellingToExport($article, $articleIdShopware);
-
- $systemFieldsToAdd = $this->systemFieldsToExport($article, $articleIdShopware);
-
- $deliveryTimeId = null;
- if(!empty($article['lieferzeitmanuell'])){
- $deliveryTimeId = $this->getDeliveryTimeId($article['lieferzeitmanuell']);
- }
-
- if (empty($systemFieldsToAdd['visibilities']) && !empty($this->shopwareDefaultSalesChannel)) {
- $systemFieldsToAdd['visibilities'] = $this->modifySalesChannel(explode(',', $this->shopwareDefaultSalesChannel), $articleIdShopware);
- }
-
- if(empty($systemFieldsToAdd['unitId']) && !empty($article['einheit']) ){
- $systemFieldsToAdd['unitId'] = $this->unitToAdd($article['einheit']);
- }
-
-
- //Hersteller in Shopware suchen bzw. Anlegen
- $manufacturerName = $article['hersteller'];
- $manufacturerId = $this->getManufacturerIdByName($manufacturerName);
-
- if ($manufacturerId === null && $this->createManufacturerAllowed === true) {
- $manufacturerId = $this->createManufacturer($manufacturerName);
- }
-
- if (empty($manufacturerId)) {
- return 'error: Für den Artikelexport ist die Herstellerinformation zwingend erforderlich';
- }
-
- $isCloseOut = false;
- if(!empty($article['restmenge'])){
- $isCloseOut = true;
- }
-
- $description = $this->prepareDescription($article['uebersicht_de']);
- $ean = $article['ean'];
- $metaTitle = $article['metatitle_de'];
- $metaDescription = $article['metadescription_de'];
- $metaKeywords = $article['metakeywords_de'];
-
- $manufacturerNumber = $article['herstellernummer'];
- if (empty($manufacturerNumber)) {
- $manufacturerNumber = '';
- }
-
- $weight = (float)$article['gewicht'];
- $length = (float)$article['laenge'] * 10;
- $height = (float)$article['hoehe'] * 10;
- $width = (float)$article['breite'] * 10;
-
- $purchasePrice = (float)$article['einkaufspreis'];
-
- $currencyId = $this->findCurrencyId($article['waehrung']);
- $price = [
- 'net' => $article['preis'],
- 'gross' => $article['bruttopreis'],
- 'currencyId' => $currencyId,
- 'linked' => true];
-
- if (!empty($article['pseudopreis'])) {
- $price['listPrice'] = [
- 'currencyId' => $currencyId,
- 'gross' => $article['pseudopreis'],
- 'linked' => true,
- 'net' => $article['pseudopreis']/(1+$taxRate/100)
- ];
- }
-
- $data = [
- 'name' => $article['name_de'],
- 'isCloseout' => $isCloseOut,
- 'productNumber' => $number,
- 'manufacturerId' => $manufacturerId,
- 'stock' => (int)$quantity,
- 'taxId' => $taxId,
- 'active' => $active,
- 'description' => $description,
- 'ean' => $ean,
- 'metaTitle' => $metaTitle,
- 'metaDescription' => $metaDescription,
- 'keywords' => $metaKeywords,
- 'manufacturerNumber' => $manufacturerNumber,
- 'length' => $length,
- 'width' => $width,
- 'height' => $height,
- 'weight' => $weight,
- 'purchasePrice' => $purchasePrice,
- 'price' => [$price],
- 'categories' => $categoriesToAdd,
- 'properties' => $propertiesToAdd,
- 'crossSellings' => $crosselingToAdd,
- 'media' => $mediaToAdd,
- 'deliveryTimeId' => $deliveryTimeId
- ];
-
- $data = array_merge($data, $systemFieldsToAdd);
- if(empty($data['customFields'])
- || empty($data['customFields']['wawision_shopimporter_syncstate'])){
- $data['customFields']['wawision_shopimporter_syncstate'] = 1;
- }
-
- if (empty($articleIdShopware)) {
- $result = $this->shopwareRequest('POST',
- 'product?_response=true', $data);
- if (!empty($result['data']['id'])) {
- $articleIdShopware = $result['data']['id'];
- $articleInfo['data'][0] = $result['data'];
- }
- } else {
- $headerInformation = [];
- $languageId = $this->getLanguageIdByCountryIso('DE');
- if (!empty($languageId)) {
- $headerInformation[] = 'sw-language-id: ' . $languageId;
- }
- $result = $this->shopwareRequest('PATCH',
- sprintf('product/%s?_response=true', $articleIdShopware), $data, $headerInformation);
- }
-
- if(!empty($articleIdShopware)){
- $this->exportTranslationsForArticle($article, $articleIdShopware);
- }
-
- $this->addCoverImage($article, $articleIdShopware);
-
- if (empty($result['data']) || is_array($result['errors'])) {
- $this->Shopware6Log('Artikelexport fehlgeschlagen', ['data:' => $data, 'response' => $result]);
- continue;
- }
-
- $this->exportSeoUrls($article, $articleIdShopware);
-
- $this->exportVariants($article, $articleIdShopware, $currencyId);
-
- if (empty($result['data']) || is_array($result['errors'])) {
- $this->Shopware6Log('Artikelexport bei Bildübertragung fehlgeschlagen', ['data:' => $data, 'response' => $result]);
- continue;
- }
-
- $defaultPrices = $this->getPricesFromArray($article['staffelpreise_standard'] ?? []);
- $groupPrices = $this->getPricesFromArray($article['staffelpreise_gruppen'] ?? []);
-
- if (!empty($defaultPrices) || !empty($groupPrices)) {
- $this->deleteOldBulkPrices($articleIdShopware);
- }
- if (!empty($defaultPrices)) {
- foreach ($defaultPrices as $priceData) {
- $this->exportBulkPriceForGroup($articleIdShopware, $this->defaultRuleName, $priceData);
- }
- }
- if (!empty($groupPrices)) {
- foreach ($groupPrices as $priceData) {
- $this->exportBulkPriceForGroup($articleIdShopware, $priceData->getGroupName(), $priceData);
- }
- }
-
- $successCounter++;
- }
-
- return $successCounter;
- }
-
- protected function exportBulkPriceForGroup(string $productId, string $groupName, PriceData $priceData): void
- {
- $currencyId = $this->findCurrencyId($priceData->getCurrency());
-
- $groupRuleId = $this->client->getGroupRuleId($groupName);
- if (empty($groupRuleId)) {
- $this->Shopware6Log("Fehler: Gruppe {$groupName} konnte im Shop nicht gefunden werden");
- return;
- }
-
- $result = $this->client->saveBulkPrice($productId, $groupRuleId, $currencyId, $priceData);
- if (empty($result['data'])) {
- $this->Shopware6Log("Fehler: Staffelpreis für Gruppe {$groupName} konnte nicht exportiert werden", $result);
- }
- }
-
- /**
- * @param string $deliveryTimeText
- *
- * @return string|null
- */
- protected function getDeliveryTimeId(string $deliveryTimeText): ?string
- {
- $searchCommand = [
- 'limit' => 5,
- 'filter' => [
- [
- 'field' => 'name',
- 'type' => 'equals',
- 'value' => $deliveryTimeText
- ]
- ]
- ];
- $result = $this->shopwareRequest('POST', 'search/delivery-time', $searchCommand);
-
- if (empty($result['data'][0]['id'])) {
- return null;
- }
-
- return $result['data'][0]['id'];
- }
-
- /**
- * @param string $description
- * @return string
- */
- protected function prepareDescription($description): string
- {
- $markupSubstitute = [
- '/"/' => '"',
- '/<([^&]+)>/' => '<\1>',
- '/\\/' => '',
- '/\\<\/strong>/' => '',
- '/\\/' => '',
- '/\\<\/em>/' => '',
- '/&/' => '&',
- ];
-
- return (string)preg_replace(array_keys($markupSubstitute), array_values($markupSubstitute), $description);
- }
-
- /**
- * @param array $article
- * @param string $articleIdShopware
- */
- protected function exportTranslationsForArticle(array $article, string $articleIdShopware): void
- {
- $customFieldsToAdd = $this->customFieldsToExport($article, $articleIdShopware);
-
- $preparedTranslations = [];
- $preparedTranslations['DE'] = [
- 'name' => $article['name_de'],
- 'description' => $this->prepareDescription($article['uebersicht_de']),
- 'metaTitle' => $article['metatitle_de'],
- 'metaDescription' => $article['metadescription_de'],
- 'keywords' => $article['metakeywords_de'],
- 'customFields' => []
- ];
- if(!empty($customFieldsToAdd['DE'])){
- $preparedTranslations['DE']['customFields'] = $customFieldsToAdd['DE'];
- }
- $preparedTranslations['GB'] = [
- 'name' => $article['name_en'],
- 'description' => $this->prepareDescription($article['uebersicht_en']),
- 'metaTitle' => $article['metatitle_en'],
- 'metaDescription' => $article['metadescription_en'],
- 'keywords' => $article['metakeywords_en'],
- 'customFields' => [],
- ];
- if(!empty($customFieldsToAdd['GB'])){
- $preparedTranslations['GB']['customFields'] = $customFieldsToAdd['GB'];
- }
- foreach ($article['texte'] as $translation) {
- if ($translation['sprache'] === 'EN') {
- $translation['sprache'] = 'GB';
- }
- $preparedTranslations[$translation['sprache']] = [
- 'name' => $translation['name'],
- 'description' => $this->prepareDescription($translation['beschreibung_online']),
- 'metaTitle' => $translation['meta_title'],
- 'metaDescription' => $translation['meta_description'],
- 'keywords' => $translation['meta_keywords'],
- ];
- if(!empty($customFieldsToAdd[$translation['sprache']])){
- $preparedTranslations[$translation['sprache']]['customFields'] = $customFieldsToAdd[$translation['sprache']];
- }
- }
-
- foreach ($preparedTranslations as $countryIsoCode => $translation) {
- $languageId = $this->getLanguageIdByCountryIso($countryIsoCode);
- if (empty($languageId)) {
- $this->Shopware6Log('Language Id not found for country: ' . $countryIsoCode);
- continue;
- }
-
- $headerInformation = ['sw-language-id: ' . $languageId];
- $this->shopwareRequest(
- 'PATCH',
- sprintf('product/%s', $articleIdShopware),
- $translation, $headerInformation
- );
- }
- }
-
- /**
- * @param string $countryIso
- *
- * @return string|null
- */
- protected function getLanguageIdByCountryIso(string $countryIso): ?string
- {
- if(array_key_exists($countryIso, $this->knownShopLanguageIds)){
- return $this->knownShopLanguageIds[$countryIso];
- }
-
- $searchCommand = [
- 'limit' => 5,
- 'filter' => [
- [
- 'field' => 'country.iso',
- 'type' => 'equals',
- 'value' => $countryIso
- ]
- ]
- ];
- $countryInformation = $this->shopwareRequest('POST', 'search/country', $searchCommand);
-
- foreach ($countryInformation['data'] as $country){
- $searchCommand = [
- 'limit' => 5,
- 'filter' => [
- [
- 'field' => 'locale.territory',
- 'type' => 'equals',
- 'value' => $country['attributes']['name']
- ]
- ]
- ];
- $localeInformation = $this->shopwareRequest('POST', 'search/locale', $searchCommand);
- foreach ($localeInformation['data'] as $locale) {
- $searchCommand = [
- 'limit' => 5,
- 'filter' => [
- [
- 'field' => 'language.localeId',
- 'type' => 'equals',
- 'value' => $locale['id']
- ]
- ]
- ];
- $languageInformation = $this->shopwareRequest('POST', 'search/language', $searchCommand);
- if (!empty($languageInformation['data'][0]['id'])) {
- $this->knownShopLanguageIds[$countryIso] = $languageInformation['data'][0]['id'];
- return $languageInformation['data'][0]['id'];
- }
- }
- }
- $this->knownShopLanguageIds[$countryIso] = null;
-
- return null;
- }
-
- /**
- * @param string $manufacturerName
- *
- * @return null|string
- */
- protected function createManufacturer(string $manufacturerName): ?string
- {
- $data = ['name' => $manufacturerName];
- $response = $this->shopwareRequest('POST', 'product-manufacturer?_response=true', $data);
-
- $manufacturerId = null;
- if(!empty($response['data']['id'])){
- $manufacturerId = $response['data']['id'];
- $this->knownManufacturerIds[$manufacturerName] = $manufacturerId;
- }
-
- return $manufacturerId;
- }
-
- /**
- * @param string $manufacturerName
- *
- * @return null|string
- */
- protected function getManufacturerIdByName(string $manufacturerName): ?string
- {
- if (!empty($this->knownManufacturerIds[$manufacturerName])) {
- return $this->knownManufacturerIds[$manufacturerName];
- }
-
- $manufacturerId = null;
- if (empty($manufacturerName)) {
- $manufacturerName = $this->defaultManufacturer;
- }
- $manufacturer = $this->shopwareRequest(
- 'GET',
- 'product-manufacturer?filter[product_manufacturer.name]=' . urlencode($manufacturerName)
- );
- $manufacturerId = $manufacturer['data'][0]['id'];
- $this->knownManufacturerIds[$manufacturerName] = $manufacturerId;
-
- return $manufacturerId;
- }
-
- /**
- * @param float $taxRate
- *
- * @return string
- */
- protected function getTaxIdByRate(float $taxRate): string{
- if(empty($this->taxesInShop)){
- $this->taxesInShop = $this->shopwareRequest('GET', 'tax');
- }
- foreach ($this->taxesInShop['data'] as $taxData) {
- if (abs(($taxData['attributes']['taxRate']-$taxRate)) < 0.0001 ) {
- return $taxData['id'];
- }
- }
-
- return $this->taxesInShop['data'][0]['id'];
- }
-
- /**
- * @param array $internalArticleData
- * @param string $articleIdShopware
- *
- * @return array
- */
- protected function mediaToExport($internalArticleData, $articleIdShopware)
- {
- $mediaToAdd = [
- ];
-
- if (empty($internalArticleData['Dateien'])) {
- return $mediaToAdd;
- }
- $internalMediaIds = [];
-
- $searchdata = [
- 'limit' => 1,
- 'filter' => [
- [
- 'field' => 'name',
- 'type' => 'equals',
- 'value' => $this->shopwareMediaFolder
- ]
- ]
- ];
- $mediaFolderData = $this->shopwareRequest('POST', 'search/media-folder', $searchdata);
- if(empty($mediaFolderData['data'][0]['id'])){
- $this->Shopware6ErrorLog('Kein Media Folder gefunden für: ', $this->shopwareMediaFolder);
- return [];
- }
-
- $mediaFolderId = $mediaFolderData['data'][0]['id'];
-
- foreach ($internalArticleData['Dateien'] as $internalFile) {
- $filename = explode('.', $internalFile['filename']);
- unset($filename[(!empty($filename)?count($filename):0) - 1]);
- $filename = $internalFile['id'].'_'.implode($filename);
- $extension = $internalFile['extension'];
- $imageTitle = (string)$internalFile['titel'];
- $imageAltText = (string)$internalFile['beschreibung'];
- $accessToken = $this->shopwareToken();
-
- $searchdata = [
- 'limit' => 5,
- 'filter' => [
- [
- 'field' => 'media.fileName',
- 'type' => 'equals',
- 'value' => $filename
- ]
- ]
- ];
- $mediaData = $this->shopwareRequest('POST', 'search/media', $searchdata);
- if (!empty($mediaData['data'][0]['id'])) {
- $internalMediaIds[] = $mediaData['data'][0]['id'];
- if($mediaData['data'][0]['attributes']['title'] !== $imageTitle
- || $mediaData['data'][0]['attributes']['alt'] !== $imageAltText){
- $this->setMediaTitleAndAltText($mediaData['data'][0]['id'], $imageTitle, $imageAltText);
- }
- continue;
- }
-
- $mediaData = $this->shopwareRequest('POST', 'media?_response=true', []);
- if(empty($mediaData['data']['id'])){
- $this->Shopware6Log('Error when creating media for sku: ' . $internalArticleData['nummer'],
- ['mediaData' => $mediaData, 'title' => $imageTitle, 'text' => $imageAltText]);
- continue;
- }
- $mediaId = $mediaData['data']['id'];
- $this->setMediaTitleAndAltText($mediaId, $imageTitle, $imageAltText);
-
- $mediaAssociationData = [
- [
- 'action' => 'upsert',
- 'entity' => 'media',
- 'payload' => [
- [
- 'id' => $mediaId,
- 'mediaFolderId' => $mediaFolderId
- ]
- ]
- ]
- ];
- $this->shopwareRequest('POST', '_action/sync?_response=true', $mediaAssociationData);
-
- $url = $this->ShopUrl . 'v2/_action/media/' . $mediaId . '/upload?extension=' . $extension . '&fileName=' . $filename;
- $ch = curl_init();
- $setHeaders = [
- 'Content-Type:image/' . $extension,
- 'Authorization:Bearer ' . $accessToken['token']
- ];
- curl_setopt($ch, CURLOPT_URL, $url);
- curl_setopt($ch, CURLOPT_POSTFIELDS, base64_decode($internalFile['datei']));
- curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
- curl_setopt($ch, CURLOPT_HTTPHEADER, $setHeaders);
- curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
- curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
- curl_exec($ch);
-
- $internalMediaIds[] = $mediaId;
- }
-
- $existingMediaConnection = [];
- if (!empty($articleIdShopware)) {
- $existingMediaConnection = $this->shopwareRequest('GET', 'product/' . $articleIdShopware . '/media?limit=100');
- foreach ($existingMediaConnection['data'] as $existingConnection) {
- if (!in_array($existingConnection['attributes']['mediaId'], $internalMediaIds, false)) {
- $this->shopwareRequest('DELETE', 'product/' . $articleIdShopware . '/media/' . $existingConnection['id']);
- }
- }
- }
-
- $alreadyAddedMediaIDs = [];
- if (!empty($existingMediaConnection)) {
- foreach ($existingMediaConnection['data'] as $existingConnection) {
- $alreadyAddedMediaIDs[$existingConnection['attributes']['mediaId']] = $existingConnection['id'];
- }
- }
- $position = 0;
- foreach ($internalMediaIds as $mediaId) {
- $mediaDataSet = [
- 'mediaId' => $mediaId,
- 'position' => $position
- ];
- if (array_key_exists($mediaId, $alreadyAddedMediaIDs)) {
- $mediaDataSet['id'] = $alreadyAddedMediaIDs[$mediaId];
- }
- $mediaToAdd[] = $mediaDataSet;
- $position++;
- }
-
- return $mediaToAdd;
- }
-
- /**
- * @param string $mediaId
- * @param string $title
- * @param string $altText
- */
- protected function setMediaTitleAndAltText(string $mediaId, string $title, string $altText): void
- {
- $this->shopwareRequest('PATCH', 'media/' . $mediaId,
- ['title' => $title,
- 'alt' => $altText
- ]
- );
- }
-
- /**
- * @param array $articleInXentral
- * @param string $articleIdShopware
- */
- protected function addCoverImage($articleInXentral, $articleIdShopware){
- if(empty($articleIdShopware)){
- return;
- }
- if(empty($articleInXentral['Dateien'])){
- return;
- }
- $existingMediaConnection = $this->shopwareRequest('GET', 'product/' . $articleIdShopware . '/media?limit=100');
- if(empty($existingMediaConnection['data'])){
- return;
- }
- foreach ($articleInXentral['Dateien'] as $xentralFile) {
- $filename = explode('.', $xentralFile['filename']);
- unset($filename[(!empty($filename)?count($filename):0) - 1]);
- $filename = $xentralFile['id'].'_'.implode($filename);
-
- $searchdata = [
- 'limit' => 5,
- 'filter' => [
- [
- 'field' => 'media.fileName',
- 'type' => 'equals',
- 'value' => $filename
- ]
- ]
- ];
- $mediaData = $this->shopwareRequest('POST', 'search/media', $searchdata);
- $mediaId = $mediaData['data'][0]['id'];
-
- foreach ($existingMediaConnection['data'] as $mediaConnection){
- if($mediaId === $mediaConnection['attributes']['mediaId']){
-
- $this->shopwareRequest('PATCH',
- sprintf('product/%s?_response=true', $articleIdShopware),['coverId' => $mediaConnection['id']]);
- return;
- }
- }
- }
- }
-
- /**
- * @param array $articleInXentral
- * @param string $articleIdShopware
- * @return array
- */
- protected function categoriesToExport($articleInXentral, $articleIdShopware)
- {
- $categoryName = $articleInXentral['kategoriename'];
- $categoryTree = $articleInXentral['kategorien'];
-
- $categoriesToAdd = [];
- if (empty($categoryName) && empty($categoryTree)) {
- return $categoriesToAdd;
- }
-
- $categoriesInXentral = [];
- if (!empty($categoryTree)) {
- $rootcategory = null;
- $categoryTreeid = [];
- foreach ($categoryTree as $categoryData) {
- $categoryData['shopwareparent'] = 0;
- if (!$categoryData['parent']) {
- $categoryData['shopwareid'] = $rootcategory;
- }
- $categoryTreeid[$categoryData['id']] = $categoryData;
- }
-
- foreach ($categoryTree as $categoryData) {
- $parentid = $rootcategory;
- if (!empty($categoryData['parent'])) {
- $parentid = $this->getCategoryParentId($categoryData, $categoryTreeid);
- }
-
- $searchdata = [
- 'limit' => 25,
- 'filter' => [
- [
- 'field' => 'category.name',
- 'type' => 'equals',
- 'value' => $categoryData['name']
- ]
- ]
- ];
- if (!empty($parentid)) {
- $searchdata['filter'][] = [
- 'field' => 'category.parentId',
- 'type' => 'equals',
- 'value' => $parentid
- ];
- }
- $result = $this->shopwareRequest('POST', 'search/category', $searchdata);
-
-
- if (!empty($result['data'][0]['id'])) {
- $categoryTreeid[$categoryData['id']]['shopwareid'] = $result['data'][0]['id'];
- $categoriesInXentral[] = $result['data'][0]['id'];
- }
- }
- } else if (!empty($categoryName)) {
- $searchdata = [
- 'limit' => 25,
- 'filter' => [
- [
- 'field' => 'category.name',
- 'type' => 'equals',
- 'value' => $categoryName
- ]
- ]
- ];
-
- $result = $this->shopwareRequest('POST', 'search/category', $searchdata);
-
- if (!empty($result['data'][0]['id'])) {
- $categoriesInXentral[] = $result['data'][0]['id'];
- }
- }
-
- if (!empty($articleIdShopware)) {
- $existingCategories = $this->shopwareRequest('GET', 'product/' . $articleIdShopware . '/categories?limit=50');
- foreach ($existingCategories['data'] as $existingCategory) {
- if (!in_array($existingCategory['id'], $categoriesInXentral, false)) {
- $this->shopwareRequest('DELETE', 'product/' . $articleIdShopware . '/categories/' . $existingCategory['id']);
- }
- }
- }
- foreach ($categoriesInXentral as $categoryId) {
- $categoriesToAdd[] = ['id' => $categoryId];
- }
-
-
- return $categoriesToAdd;
- }
-
- /**
- * @param $categoryData
- * @param $categoryTreeId
- * @return string|null
- */
- protected function getCategoryParentId($categoryData, &$categoryTreeId)
- {
- $parentId = $categoryTreeId[$categoryData['parent']]['shopwareid'];
- if (!empty($parentId)) {
- return $parentId;
- }
-
- $parentCategoryData = $this->app->DB->SelectRow("SELECT id,parent,bezeichnung AS name FROM artikelkategorien WHERE id<>'' AND id<>'0' AND id='" . $categoryData['parent'] . "' LIMIT 1");
- if (empty($parentCategoryData)) {
- return null;
- }
-
- $searchData = [
- 'limit' => 25,
- 'filter' => [
- [
- 'field' => 'category.name',
- 'type' => 'equals',
- 'value' => $parentCategoryData['name']
- ]
- ]
- ];
- $result = $this->shopwareRequest('POST', 'search/category', $searchData);
-
- if (count($result['data']) < 1) {
- return null;
- }
-
- if (count($result['data']) === 1) {
- $parentCategoryData['shopwareid'] = $result['data'][0]['id'];
- $categoryTreeId[$parentCategoryData['id']] = $parentCategoryData;
- return $result['data'][0]['id'];
- }
-
- $grandparentId = $this->getCategoryParentId($parentCategoryData, $categoryTreeId);
-
- $searchData = [
- 'limit' => 25,
- 'filter' => [
- [
- 'field' => 'category.name',
- 'type' => 'equals',
- 'value' => $parentCategoryData['name']
- ],
- [
- 'field' => 'category.parentId',
- 'type' => 'equals',
- 'value' => $grandparentId
- ]
- ]
- ];
- $result = $this->shopwareRequest('POST', 'search/category', $searchData);
-
-
- if (count($result['data']) === 1) {
- $parentCategoryData['shopwareid'] = $result['data'][0]['id'];
- $categoryTreeId[$parentCategoryData['id']] = $parentCategoryData;
- return $result['data'][0]['id'];
- }
- return null;
- }
-
- /**
- * @param string $propertyName
- *
- * @return string|null
- */
- protected function getPropertyGroupId($propertyName): ?string
- {
- if(array_key_exists($propertyName, $this->knownPropertyGroupIds)){
- return $this->knownPropertyGroupIds[$propertyName];
- }
-
- $searchData = [
- 'limit' => 25,
- 'filter' => [
- [
- 'field' => 'property_group.name',
- 'type' => 'equals',
- 'value' => $propertyName
- ]
- ]
- ];
-
- $germanLanguageId = $this->getLanguageIdByCountryIso('DE');
- $headerInformation = ['sw-language-id: ' . $germanLanguageId];
- $propertyData = $this->shopwareRequest(
- 'POST',
- 'search/property-group',
- $searchData,
- $headerInformation);
- if (empty($propertyData['data'][0]['id'])) {
- return null;
- }
-
- $this->knownPropertyGroupIds[$propertyName] = $propertyData['data'][0]['id'];
-
- return $propertyData['data'][0]['id'];
- }
-
- /**
- * @param string $propertyName
- * @return null|string
- */
- protected function createPropertyGroup($propertyName): ?string
- {
- $propertyGroupData = [
- 'displayType' => 'text',
- 'name' => $propertyName,
- 'sortingType' => 'alphanumeric'
- ];
- $propertyGroup = $this->shopwareRequest(
- 'POST',
- 'property-group?_response=true',
- $propertyGroupData);
-
- $this->knownPropertyGroupIds[$propertyName] = $propertyGroup['data']['id'];
-
- if (empty($propertyGroup['data']['id'])) {
- return null;
- }
-
- return $propertyGroup['data']['id'];
- }
-
- /**
- * @param string $propertyGroupId
- * @param string $propertyName
- * @param string $countryIsoCode
- */
- protected function createTranslationForPropertyGroup($propertyGroupId, $propertyName, $countryIsoCode): void
- {
- $languageId = $this->getLanguageIdByCountryIso($countryIsoCode);
- if (empty($languageId)) {
- return;
- }
-
- $headerInformation = ['sw-language-id: ' . $languageId];
-
- $translation = [
- 'name' => $propertyName,
- ];
-
- $this->shopwareRequest(
- 'PATCH',
- sprintf('property-group/%s', $propertyGroupId),
- $translation,
- $headerInformation);
- }
-
- /**
- * @param string $propertyGroupId
- * @param string $propertyOptionName
- * @param string $countryIsoCode
- * @return mixed|null
- */
- protected function getPropertyOptionId($propertyGroupId, $propertyOptionName, $countryIsoCode = 'DE'): ?string
- {
- $searchData = [
- 'limit' => 25,
- 'filter' => [
- [
- 'field' => 'property_group_option.name',
- 'type' => 'equals',
- 'value' => $propertyOptionName
- ]
- ]
- ];
- $languageId = $this->getLanguageIdByCountryIso($countryIsoCode);
- $headerInformation = ['sw-language-id: ' . $languageId];
- $optionData = $this->shopwareRequest(
- 'POST',
- 'search/property-group/' . $propertyGroupId . '/options',
- $searchData,
- $headerInformation);
-
- if (empty($optionData['data'][0]['id'])) {
- return null;
- }
-
- return $optionData['data'][0]['id'];
- }
-
- /**
- * @param string $propertyGroupId
- * @param string $propertyOptionName
- * @return null|string
- */
- protected function createPropertyOption($propertyGroupId, $propertyOptionName): ?string
- {
- $propertyOptionData = [
- 'id' => '',
- 'name' => $propertyOptionName
- ];
- $createdPropertyOption = $this->shopwareRequest(
- 'POST',
- 'property-group/' . $propertyGroupId . '/options?_response=true',
- $propertyOptionData);
-
- if (empty($createdPropertyOption['data']['id'])) {
- return null;
- }
-
- return $createdPropertyOption['data']['id'];
- }
-
- /**
- * @param string $optionId
- * @param string $optionName
- * @param string $countryIsoCode
- */
- protected function createTranslationForPropertyOption($optionId, $optionName, $countryIsoCode): void
- {
- $languageId = $this->getLanguageIdByCountryIso($countryIsoCode);
- if (empty($languageId)) {
- return;
- }
- $headerInformation = ['sw-language-id: ' . $languageId];
- $translation = [
- 'name' => $optionName,
- ];
-
- $this->shopwareRequest(
- 'PATCH',
- sprintf('property-group-option/%s', $optionId),
- $translation,
- $headerInformation);
- }
-
- /**
- * @param array $internalArticle
- * @param string $articleIdShopware
- * @return array
- */
- protected function propertiesToExport($internalArticle, $articleIdShopware): array
- {
- $propertiesToAdd = $this->getPropertiesFromArticle($internalArticle);
- if (empty($propertiesToAdd)) {
- return [];
- }
- $assignedProperties = [];
-
- foreach ($propertiesToAdd as $propertyDefaultName => $countryIsoToPropertyTranslation) {
- if (empty($countryIsoToPropertyTranslation['DE'])) {
- continue;
- }
- $propertyGroupId = '';
- if (array_key_exists($propertyDefaultName, $this->knownPropertyGroupIds)) {
- $propertyGroupId = $this->knownPropertyGroupIds[$propertyDefaultName];
- }
- if (empty($propertyGroupId)) {
- $propertyGroupId = $this->getPropertyGroupId($propertyDefaultName);
- }
- if (empty($propertyGroupId)) {
- $propertyGroupId = $this->createPropertyGroup($propertyDefaultName);
- }
- if (empty($propertyGroupId)) {
- $this->Shopware6Log('PropertyGroup kann nicht erstellt werden: ' . $propertyDefaultName);
- continue;
- }
-
- foreach ($countryIsoToPropertyTranslation as $countryIsoCode => $translation) {
- $this->createTranslationForPropertyGroup($propertyGroupId, $translation['name'], $countryIsoCode);
- }
-
-
- $optionId = $this->getPropertyOptionId($propertyGroupId, $countryIsoToPropertyTranslation['DE']['value'], 'DE');
- if (empty($optionId)) {
- $optionId = $this->createPropertyOption($propertyGroupId, $countryIsoToPropertyTranslation['DE']['value']);
- }
- if (empty($optionId)) {
- $this->Shopware6Log('Option kann nicht erstellt werden: ' . $countryIsoToPropertyTranslation['DE']['value']);
- continue;
- }
-
- $assignedProperties[] = $optionId;
-
- foreach ($countryIsoToPropertyTranslation as $countryIsoCode => $translation) {
- $this->createTranslationForPropertyOption($optionId, $translation['value'], $countryIsoCode);
- }
- }
-
- if (!empty($articleIdShopware)) {
- $existingProperties = $this->shopwareRequest('GET', 'product/' . $articleIdShopware . '/properties?limit=100');
- foreach ($existingProperties['data'] as $existingProperty) {
- if (!in_array($existingProperty['id'], $assignedProperties, false)) {
- $this->shopwareRequest('DELETE', 'product/' . $articleIdShopware . '/properties/' . $existingProperty['id']);
- }
- }
- }
-
- $propertiesToAdd = [];
- foreach ($assignedProperties as $propertyOptionId) {
- $propertiesToAdd[] = ['id' => $propertyOptionId];
- }
-
- return $propertiesToAdd;
- }
-
- /**
- * @param string $name
- * @param string $value
- * @return bool
- */
- protected function propertyMustBeIgnored(string $name, string $value): bool
- {
- return empty($value) ||
- strpos($name, 'customField_') === 0 ||
- stripos($name, 'shopware6_') !== false;
- }
-
- /**
- * @param array $internalArticleData
- * @return array
- */
- protected function getPropertiesFromArticle($internalArticleData): array
- {
- //'Farbe' => [['DE' => ['name' => 'Farbe, 'value' => 'Gelb']],
- // ['EN' => ['name' => 'Colour, 'value' => 'Yellow']]]
- $propertiesToAdd = [];
- if (!empty($internalArticleData['eigenschaften'])) {
- foreach ($internalArticleData['eigenschaften'] as $property) {
- if ($this->propertyMustBeIgnored($property['name'], $property['values'])) {
- continue;
- }
- if (strpos($property['name'], 'property_') === 0) {
- $propertyName = substr($property['name'], 9);
- $propertiesToAdd[$propertyName]['DE'] = [
- 'name' => $propertyName,
- 'value' => $property['values']];
- continue;
- }
- if ($this->propertyOption === 'toProperties') {
- $propertiesToAdd[$property['name']]['DE'] = [
- 'name' => $property['name'],
- 'value' => $property['values']];
- }
- }
- }
-
- if (!empty($internalArticleData['eigenschaftenuebersetzungen'])) {
- foreach ($internalArticleData['eigenschaftenuebersetzungen'] as $translatedProperty) {
- if ($translatedProperty['language_to'] === 'EN') {
- $translatedProperty['language_to'] = 'GB';
- }
- if ($this->propertyMustBeIgnored($translatedProperty['property_to'], $translatedProperty['property_value_to'])) {
- continue;
- }
- if (strpos($translatedProperty['property_to'], 'property_') === 0) {
- $propertiesToAdd[$translatedProperty['property_from']][$translatedProperty['language_to']] = [
- 'name' => substr($translatedProperty['property_to'], 9),
- 'value' => $translatedProperty['property_value_to']];
- continue;
- }
- if ($this->propertyOption === 'toProperties') {
- $propertiesToAdd[$translatedProperty['property_from']][$translatedProperty['language_to']] = [
- 'name' => $translatedProperty['property_to'],
- 'value' => $translatedProperty['property_value_to']];
- }
- }
- }
-
- if (!empty($internalArticleData['freifelder'])) {
- foreach ($internalArticleData['freifelder']['DE'] as $freeFieldKey => $freeFieldValue) {
- if ($this->propertyMustBeIgnored($freeFieldKey, $freeFieldValue)) {
- continue;
- }
- if (strpos($freeFieldKey, 'property_') === 0) {
- $propertyName = substr($freeFieldKey, 9);
- $propertiesToAdd[$propertyName]['DE'] = [
- 'name' => $propertyName,
- 'value' => $freeFieldValue
- ];
- continue;
- }
- if ($this->freeFieldOption === 'toProperties') {
- $propertiesToAdd[$freeFieldKey]['DE'] = [
- 'name' => $freeFieldKey,
- 'value' => $freeFieldValue
- ];
- }
- }
-
- foreach ($internalArticleData['freifelder'] as $languageIso => $freeFields) {
- if ($languageIso === 'DE') {
- continue;
- }
- if ($languageIso === 'EN') {
- $languageIso = 'GB';
- }
- foreach ($freeFields as $freeFieldData) {
- if ($this->propertyMustBeIgnored($freeFieldData['mapping'], $freeFieldData['wert'])) {
- continue;
- }
- if (strpos($freeFieldData['mapping'], 'property_') === 0) {
- $propertyName = substr($freeFieldData['mapping'], 9);
- $propertiesToAdd[$propertyName][$languageIso] = [
- 'name' => $propertyName,
- 'value' => $freeFieldData['wert']
- ];
- continue;
- }
- if ($this->freeFieldOption === 'toProperties') {
- $propertiesToAdd[$freeFieldData['mapping']][$languageIso] = [
- 'name' => $freeFieldData['mapping'],
- 'value' => $freeFieldData['wert']
- ];
- }
- }
- }
- }
-
- return $propertiesToAdd;
- }
-
- /**
- * @param array $articleInXentral
- * @param string $articleIdShopware
- *
- * @return array
- */
- protected function customFieldsToExport($articleInXentral, $articleIdShopware): array
- {
- $customFieldsToAdd = $this->getCustomFieldsFromArticle($articleInXentral);
- if (empty($customFieldsToAdd)) {
- return [];
- }
- $languageId = $this->getLanguageIdByCountryIso('DE');
- $headerInformation = ['sw-language-id: ' . $languageId];
-
- $customFields = [];
- if (!empty($articleIdShopware)) {
- $articleInfo = $this->shopwareRequest(
- 'GET', 'product/' . $articleIdShopware,
- [],
- $headerInformation);
- $customFields['DE'] = $articleInfo['data'][0]['attributes']['customFields'];
- if ($customFields === null) {
- $customFields = [];
- }
- }
-
- foreach ($customFieldsToAdd as $defaultFieldName => $countryIsoCodeToCustomFieldData) {
- $customFieldDefinition = $this->shopwareRequest(
- 'GET',
- sprintf('custom-field?filter[custom_field.name]=%s', $defaultFieldName),
- [],
- $headerInformation
- );
- if (empty($customFieldDefinition)) {
- $this->Shopware6Log('Freifeld entspricht keinem shopware Freifeld', $defaultFieldName);
- continue;
- }
-
- foreach ($countryIsoCodeToCustomFieldData as $countryIsoCode => $customFieldData) {
- $name = $customFieldData['name'];
- $value = $customFieldData['value'];
- if ($value === '') {
- continue;
- }
- if($countryIsoCode === 'EN'){
- $countryIsoCode = 'GB';
- }
- $fieldType = $customFieldDefinition['data'][0]['attributes']['type'];
- $controlType = $customFieldDefinition['data'][0]['attributes']['config']['componentName'];
-
- switch ($fieldType) {
- case 'text':
- case 'html':
- if ($controlType === 'sw-media-field') {
- $this->Shopware6Log(
- 'Warnung: Freifelder vom Type "medium" werden nicht unterstützt.'
- );
- } else {
- $customFields[$countryIsoCode][$name] = (string)$value;
- }
- break;
- case 'bool':
- $customFields[$countryIsoCode][$name] = filter_var($value, FILTER_VALIDATE_BOOLEAN);
- break;
- case 'int':
- $customFields[$countryIsoCode][$name] = (int)$value;
- break;
- case 'float':
- $customFields[$countryIsoCode][$name] = (float)$value;
- break;
- case 'select':
- $options = $customFieldDefinition['data'][0]['attributes']['config']['options'];
- $allowedValues = [];
- foreach ($options as $option) {
- $allowedValues[] = $option['value'];
- }
- if ($controlType === 'sw-single-select') {
- if (in_array($value, $allowedValues, true)) {
- $customFields[$countryIsoCode][$name] = $value;
- } else {
- $this->Shopware6Log(
- sprintf('Warnung: Freifeld "%s"="%s"; ungültiger Wert', $name, $value),
- ['allowed values' => $allowedValues]
- );
- }
- }
- if ($controlType === 'sw-multi-select') {
- $value = explode(',', $value);
- foreach ($value as &$item) {
- $item = trim($item);
- }
- unset($item);
- if (array_intersect($value, $allowedValues) === $value) {
- $customFields[$countryIsoCode][$name] = $value;
- } else {
- $this->Shopware6Log(
- sprintf('Warnung: Freifeld "%s"; ungültiger Wert', $name),
- ['values' => $value, 'allowed values' => $allowedValues]
- );
- }
- }
- break;
- default:
- $this->Shopware6Log(
- 'Warnung: Freifeld enthält falschen Typ.',
- ['freifeld' => $name, 'wert' => $value]
- );
- continue 2;
- }
- }
- }
-
-
- return $customFields;
- }
-
- /**
- * @param string $name
- * @param string $value
- * @return bool
- */
- protected function customFieldMustBeIgnored(string $name, string $value): bool
- {
- return empty($value) ||
- strpos($name, 'property_') === 0 ||
- stripos($name, 'shopware6_') !== false;
- }
-
- /**
- * @param array $articleInXentral
- * @return array
- */
- protected function getCustomFieldsFromArticle($articleInXentral): array
- {
- $customFieldsToAdd = [];
- if (!empty($articleInXentral['eigenschaften'])) {
- foreach ($articleInXentral['eigenschaften'] as $propertyInXentral) {
- if ($this->customFieldMustBeIgnored($propertyInXentral['name'], $propertyInXentral['values'])) {
- continue;
- }
- if (strpos($propertyInXentral['name'], 'customField_') === 0) {
- $customFieldName = substr($propertyInXentral['name'], 12);
- $customFieldsToAdd[$customFieldName]['DE'] = [
- 'name' => $customFieldName,
- 'value' => $propertyInXentral['values']
- ];
- continue;
- }
- if ($this->propertyOption === 'toCustomFields') {
- $customFieldsToAdd[$propertyInXentral['name']]['DE'] = [
- 'name' => $propertyInXentral['name'],
- 'value' => $propertyInXentral['values']
- ];
- }
- }
- }
- if (!empty($articleInXentral['eigenschaftenuebersetzungen'])) {
- foreach ($articleInXentral['eigenschaftenuebersetzungen'] as $translatedProperty) {
- if ($this->customFieldMustBeIgnored($translatedProperty['property_to'], $translatedProperty['property_value_to'])) {
- continue;
- }
- if (strpos($translatedProperty['property_to'], 'customField_') === 0) {
- $customFieldName = substr($translatedProperty['property_to'], 12);
- $customFieldsToAdd[$customFieldName][$translatedProperty['language_to']] = [
- 'name' => $customFieldName,
- 'value' => $translatedProperty['property_value_to']
- ];
- continue;
- }
- if ($this->propertyOption === 'toCustomFields') {
- $customFieldsToAdd[$translatedProperty['property_to']][$translatedProperty['language_to']] = [
- 'name' => $translatedProperty['property_to'],
- 'value' => $translatedProperty['property_value_to']
- ];
- }
- }
- }
-
- if (!empty($articleInXentral['freifelder'])) {
- foreach ($articleInXentral['freifelder']['DE'] as $freeFieldKey => $freeFieldValue) {
- if ($this->customFieldMustBeIgnored($freeFieldKey, $freeFieldValue)) {
- continue;
- }
- if (strpos($freeFieldKey, 'customField_') === 0) {
- $customFieldName = substr($freeFieldKey, 12);
- $customFieldsToAdd[$customFieldName]['DE'] = [
- 'name' => $customFieldName,
- 'value' => $freeFieldValue
- ];
- continue;
- }
- if ($this->freeFieldOption === 'toCustomFields') {
- $customFieldsToAdd[$freeFieldKey]['DE'] = [
- 'name' => $freeFieldKey,
- 'value' => $freeFieldValue
- ];
- }
- }
-
- foreach ($articleInXentral['freifelder'] as $countryIsoCode => $freeFieldTranslations) {
- if ($countryIsoCode === 'DE') {
- continue;
- }
- foreach ($freeFieldTranslations as $freeFieldTranslation){
- if ($this->customFieldMustBeIgnored($freeFieldTranslation['mapping'], $freeFieldTranslation['wert'])) {
- continue;
- }
- if ($countryIsoCode === 'EN') {
- $countryIsoCode = 'GB';
- }
- if (strpos($freeFieldTranslation['mapping'], 'customField_') === 0) {
- $customFieldName = substr($freeFieldTranslation['mapping'], 12);
- $customFieldsToAdd[$customFieldName][$countryIsoCode] = [
- 'name' => $customFieldName,
- 'value' => $freeFieldTranslation['wert']
- ];
- continue;
- }
- if ($this->freeFieldOption === 'toCustomFields') {
- $customFieldsToAdd[$freeFieldTranslation['mapping']][$countryIsoCode] = [
- 'name' => $freeFieldTranslation['mapping'],
- 'value' => $freeFieldTranslation['wert']
- ];
- }
- }
- }
- }
-
- return $customFieldsToAdd;
- }
-
- /**
- * @param array $articleInXentral
- * @param int $articleIdShopware
- *
- * @return array
- */
- protected function crosssellingToExport($articleInXentral, $articleIdShopware){
- if (empty($articleInXentral['crosssellingartikel'])) {
- return [];
- }
-
- $crosssellingArticles = [];
- foreach ($articleInXentral['crosssellingartikel'] as $crosssellingArticle){
- $type = 'Ähnlich';
- if($crosssellingArticle['art'] == 2){
- $type = 'Zubehör';
- }
- $crosssellingArticles[$type][] = $crosssellingArticle['nummer'];
- }
- $crossselingInformation = [];
- foreach ($crosssellingArticles as $type => $articles){
- if(!empty($articleIdShopware)){
- $existingCrossSellings = $this->shopwareRequest('GET', sprintf('product/%s/cross-sellings/',
- $articleIdShopware));
- if(!empty($existingCrossSellings['data'])){
- foreach ($existingCrossSellings['data'] as $existingCrossSelling){
- if($existingCrossSelling['attributes']['name'] === $type){
- $this->shopwareRequest('DELETE', sprintf('product/%s/cross-sellings/%s/',
- $articleIdShopware, $existingCrossSelling['id']));
- }
- }
- }
- }
-
- $crosselingToAdd = [];
- foreach ($articles as $articleNumber) {
- $articleInfo = $this->shopwareRequest(
- 'GET',
- sprintf('product?filter[product.productNumber]=%s', $articleNumber)
- );
-
- if(empty($articleInfo['data'][0]['id'])){
- continue;
- }
- $crosselingToAdd[] = $articleInfo['data'][0]['id'];
- }
- if(empty($crosselingToAdd)){
- continue;
- }
- $crossselingInformationForType = [
- 'active' => true,
- 'name' => $type,
- 'assignedProducts' => [],
- 'type' => 'productList',
- 'sortBy' => 'name',
- 'limit' => 24,
- 'position' => 1
- ];
- $position = 1;
- foreach ($crosselingToAdd as $articleId){
- $crossselingInformationForType['assignedProducts'][] = [
- 'productId' => $articleId,
- 'position' => $position,
- ];
- $position++;
- }
- $crossselingInformation[] = $crossselingInformationForType;
- }
-
-
- return $crossselingInformation;
- }
-
- /**
- * @param string $unitShortCode
- *
- * @return string
- */
- protected function unitToAdd(string $unitShortCode): string{
- $searchData = [
- 'limit' => 25,
- 'source' => [
- 'id'
- ],
- 'filter' => [
- [
- 'field' => 'unit.shortCode',
- 'type' => 'equals',
- 'value' => $unitShortCode
- ]
- ]
- ];
- $unitInShopware = $this->shopwareRequest(
- 'POST',
- 'search/unit',
- $searchData);
-
- if(!empty($unitInShopware['data'][0]['id'])){
- return $unitInShopware['data'][0]['id'];
- }
-
- $query = sprintf("SELECT `internebemerkung` FROM `artikeleinheit` WHERE `einheit_de` = '%s' LIMIT 1",
- $unitShortCode);
- $unitName = $this->app->DB->Select($query);
- if(empty($unitName)){
- $unitName = $unitShortCode;
- }
-
- $unitInformation = [
- 'name' => $unitName,
- 'shortCode' => $unitShortCode
- ];
- $result = $this->shopwareRequest('POST', 'unit?_response=true', $unitInformation);
-
- if(empty($result['data']['id'])){
- return '';
- }
-
- return $result['data']['id'];
- }
-
- /**
- * @param array $internArticle
- * @param int $articleIdShopware
- *
- * @return array
- */
- protected function systemFieldsToExport($internArticle, $articleIdShopware): array
- {
- $internalSpecialFields = [];
- foreach ($internArticle['freifelder']['DE'] as $freeFieldName => $freeFieldValue) {
- if (stripos($freeFieldName, 'shopware6_') !== false) {
- $internalSpecialFields[$freeFieldName] = $freeFieldValue;
- }
- }
- foreach ($internArticle['eigenschaften'] as $property) {
- if (stripos($property['name'], 'shopware6_') !== false) {
- $internalSpecialFields[$property['name']] = $property['values'];
- }
- }
-
- $systemFields = [];
- foreach ($internalSpecialFields as $fieldName => $fieldValue) {
- switch (strtolower($fieldName)) {
- case 'shopware6_sales_channel':
- $systemFields['visibilities'] = $this->modifySalesChannel(explode(',', $fieldValue), $articleIdShopware);
- break;
- case 'shopware6_purchase_unit':
- $systemFields['purchaseUnit'] = (float)str_replace(',', '.', $fieldValue);
- break;
- case 'shopware6_reference_unit':
- $systemFields['referenceUnit'] = (float)str_replace(',', '.', $fieldValue);
- break;
- case 'shopware6_unit':
- $systemFields['unitId'] = $this->unitToAdd($fieldValue);
- break;
- case 'shopware6_pack_unit':
- $systemFields['packUnit'] = (string)$fieldValue;
- break;
- case 'shopware6_restock_time':
- $systemFields['restockTime'] = (int)$fieldValue;
- break;
- case 'shopware6_pack_unit_plural':
- $systemFields['packUnitPlural'] = (string)$fieldValue;
- break;
- }
- }
-
- return $systemFields;
- }
-
- /**
- * @param array $salesChannelNames
- * @param string $articleIdInShopware
- *
- * @return array
- */
- protected function modifySalesChannel($salesChannelNames, $articleIdInShopware)
- {
- $salesChannelInXentralIds = [];
- foreach ($salesChannelNames as $salesChannelName) {
- $salesChannelInfo = $this->shopwareRequest('GET',
- sprintf('sales-channel?filter[sales_channel.name]=%s', urlencode(trim($salesChannelName)))
- );
- if (!empty($salesChannelInfo['data'][0]['id'])) {
- $salesChannelInXentralIds[] = $salesChannelInfo['data'][0]['id'];
- }
- }
-
- $existingVisibilities = $this->shopwareRequest(
- 'GET',
- sprintf('product/%s/visibilities', $articleIdInShopware)
- );
-
- $existingSalesChannelIds = [];
- if (!empty($existingVisibilities['data'])) {
- foreach ($existingVisibilities['data'] as $visibility) {
- $existingSalesChannelIds[$visibility['id']] = $visibility['attributes']['salesChannelId'];
- }
- }
-
- foreach ($existingSalesChannelIds as $associationId => $existingSalesChannelId){
- if (!in_array($existingSalesChannelId, $salesChannelInXentralIds,true)) {
- $this->shopwareRequest('DELETE', sprintf('product/%s/visibilities/%s/',
- $articleIdInShopware, $associationId));
- }
- }
-
- $salesChannelsToAdd = [];
- foreach ($salesChannelInXentralIds as $salesChannelInXentralId){
- if (!in_array($salesChannelInXentralId, $existingSalesChannelIds,true)) {
- $salesChannelsToAdd[] = $salesChannelInXentralId;
- }
- }
-
- $visibilities = [];
- foreach ($salesChannelsToAdd as $salesChannelIdToAdd) {
- $visibilities[] = [
- 'salesChannelId' => $salesChannelIdToAdd,
- 'visibility' => 30
- ];
- }
-
- return $visibilities;
- }
-
- /**
- * @param string $isoCode
- *
- * @return string
- */
- protected function findCurrencyId($isoCode)
- {
-
- $this->requestCurrencyMappingLazy();
- if (isset($this->currencyMapping[strtoupper($isoCode)])) {
- return $this->currencyMapping[strtoupper($isoCode)];
- }
- $this->Shopware6Log(
- sprintf('Warnung: Kein Mapping für Waehrung "%s" gefunden.', $isoCode),
- $this->currencyMapping
- );
-
- return null;
- }
-
- /**
- * request currency mapping only once
- */
- protected function requestCurrencyMappingLazy()
- {
-
- if ($this->currencyMapping !== null) {
- return;
- }
- $currencies = $this->shopwareRequest('GET', 'currency');
- if (!isset($currencies['data'])) {
- $this->Shopware6Log('Kann Währungsmapping nicht abrufen', $currencies);
- }
- foreach ($currencies['data'] as $currency) {
- $isoCode = strtoupper($currency['attributes']['isoCode']);
- $this->currencyMapping[$isoCode] = $currency['id'];
- }
- }
-
- /**
- * @param array $internalArticleData
- * @param string $articleIdInShopware
- * @return bool
- */
- public function exportSeoUrls(array $internalArticleData, string $articleIdInShopware): bool
- {
- if (empty($articleIdInShopware)) {
- return false;
- }
-
- $preparedSeoInformation = [];
- foreach ($internalArticleData['freifelder'] as $countryIsoCode => $freeFieldInformation) {
- if($countryIsoCode === 'EN'){
- $countryIsoCode = 'GB';
- }
- if($countryIsoCode === 'DE'){
- foreach ($freeFieldInformation as $freeFieldName => $freeFieldValue) {
- if (stripos($freeFieldName, 'shopware6_seo_url') !== false) {
- $preparedSeoInformation[$countryIsoCode][$freeFieldName] = $freeFieldValue;
- }
- }
- }else{
- foreach ($freeFieldInformation as $freeFieldData) {
- if (stripos($freeFieldData['mapping'], 'shopware6_seo_url') !== false) {
- $preparedSeoInformation[$countryIsoCode][$freeFieldData['mapping']] = $freeFieldData['wert'];
- }
- }
- }
- }
- foreach ($internalArticleData['eigenschaften'] as $property) {
- if (stripos($property['name'], 'shopware6_seo_url') !== false) {
- $preparedSeoInformation['DE'][$property['name']] = $property['values'];
- }
- }
- foreach ($internalArticleData['eigenschaftenuebersetzungen'] as $propertyTranslation) {
- if($propertyTranslation['language_to'] === 'EN'){
- $propertyTranslation['language_to'] = 'GB';
- }
- if (stripos($propertyTranslation['property_to'], 'shopware6_seo_url') !== false) {
- $preparedSeoInformation[$propertyTranslation['language_to']][$propertyTranslation['property_to']] = $propertyTranslation['property_value_to'];
- }
- }
-
- $specificSalesChannelSeoUrls = [];
- $defaultSeoUrls = [];
- foreach ($preparedSeoInformation as $countryIsoCode => $channelAssociations) {
- foreach ($channelAssociations as $fieldName => $fieldValue){
- if(strtolower($fieldName) === 'shopware6_seo_url'){
- $defaultSeoUrls[$countryIsoCode] = $fieldValue;
- }else{
- $seoInformation = explode('|', $fieldName);
- $specificSalesChannelSeoUrls[$countryIsoCode][array_pop($seoInformation)] = $fieldValue;
- }
- }
- }
-
- if (empty($specificSalesChannelSeoUrls) && empty($defaultSeoUrls)) {
- return false;
- }
-
- $salesChannelsIdToName = [];
- $salesChannels = $this->shopwareRequest('GET','sales-channel');
- foreach ($salesChannels['data'] as $salesChannel) {
- $salesChannelsIdToName[$salesChannel['id']] = $salesChannel['attributes']['name'];
- }
-
- foreach ($preparedSeoInformation as $countryIsoCode => $x){
- $languageId = $this->getLanguageIdByCountryIso($countryIsoCode);
- if (empty($languageId)) {
- $this->Shopware6Log('Language Id not found for country: ' . $countryIsoCode);
- continue;
- }
-
- $headerInformation = ['sw-language-id: ' . $languageId];
- foreach ($salesChannelsIdToName as $salesChannelId => $salesChannelName) {
- $seoUrlToUse = $defaultSeoUrls[$countryIsoCode];
- if (!empty($specificSalesChannelSeoUrls[$countryIsoCode][$salesChannelName])) {
- $seoUrlToUse = $specificSalesChannelSeoUrls[$countryIsoCode][$salesChannelsIdToName[$salesChannelName]];
- }
- if (empty($seoUrlToUse)) {
- continue;
- }
- $seoDataToSend = [
- 'seoPathInfo' => $seoUrlToUse,
- '_isNew' => true,
- 'isModified' => true,
- 'isCanonical' => true,
- 'isDeleted' => false,
- 'routeName' => 'frontend.detail.page',
- 'foreignKey' => $articleIdInShopware,
- 'pathInfo' => '/detail/'.$articleIdInShopware,
- 'languageId' => $languageId,
- 'salesChannelId' => $salesChannelId];
- $this->shopwareRequest('PATCH', '_action/seo-url/canonical', $seoDataToSend, $headerInformation);
- }
- }
-
- return true;
- }
-
- /**
- * @param array $article
- * @param string $articleIdShopware
- * @param string $currencyId
- *
- * @return bool
- */
- protected function exportVariants($article, $articleIdShopware, $currencyId): bool
- {
- $languageId = $this->getLanguageIdByCountryIso('DE');
- if (empty($languageId)) {
- return false;
- }
- if (empty($article['matrix_varianten']) || empty($articleIdShopware)) {
- return false;
- }
- $internalGroupPropertiesToShopwareId = [];
- foreach ($article['matrix_varianten']['gruppen'] as $propertyGroupName => $internalPropertyGroupValues) {
- $propertyGroupId = '';
- if (array_key_exists($propertyGroupName, $this->knownPropertyGroupIds)) {
- $propertyGroupId = $this->knownPropertyGroupIds[$propertyGroupName];
- }
- if (empty($propertyGroupId)) {
- $propertyGroupId = $this->getPropertyGroupId($propertyGroupName);
- }
- if (empty($propertyGroupId)) {
- $propertyGroupId = $this->createPropertyGroup($propertyGroupName);
- }
- if (empty($propertyGroupId)) {
- $this->Shopware6Log('PropertyGroup kann nicht erstellt werden: ' . $propertyGroupName);
- return false;
- }
-
- if (!empty($article['matrix_varianten']['texte'])) {
- $this->createTranslationForPropertyGroup($propertyGroupId, $propertyGroupName, 'DE');
-
- foreach ($article['matrix_varianten']['texte']['gruppen'] as $countryIsoCode => $matrixGroupTranslation) {
- if ($countryIsoCode === 'EN') {
- $countryIsoCode = 'GB';
- }
-
- $this->createTranslationForPropertyGroup($propertyGroupId, $matrixGroupTranslation[$propertyGroupName], $countryIsoCode);
- }
- }
-
- $languageId = $this->getLanguageIdByCountryIso('DE');
- $headerInformation = ['sw-language-id: ' . $languageId];
- $shopwarePropertyGroupOptions = $this->shopwareRequest(
- 'GET',
- 'property-group/' . $propertyGroupId . '/options?limit=100',
- $headerInformation);
- foreach ($shopwarePropertyGroupOptions['data'] as $shopwarePropertyGroupOption) {
- $propertyValue = $shopwarePropertyGroupOption['attributes']['name'];
- $internalGroupPropertiesToShopwareId[$propertyGroupName][$propertyValue] = $shopwarePropertyGroupOption['id'];
- }
-
- foreach ($internalPropertyGroupValues as $internalPropertyGroupValue => $valueNotNeeded) {
- if (!array_key_exists($internalPropertyGroupValue, $internalGroupPropertiesToShopwareId[$propertyGroupName])) {
- $newOptionData = [
- 'name' => (string)$internalPropertyGroupValue
- ];
- $optionData = $this->shopwareRequest(
- 'POST',
- 'property-group/' . $propertyGroupId . '/options?_response=true',
- $newOptionData);
- $internalGroupPropertiesToShopwareId[$propertyGroupName][$internalPropertyGroupValue] = $optionData['data']['id'];
- }
- }
-
- if (!empty($article['matrix_varianten']['texte'])) {
- foreach ($internalPropertyGroupValues as $optionValue => $valueNotNeeded) {
- $optionId = $internalGroupPropertiesToShopwareId[$propertyGroupName][$optionValue];
- $this->createTranslationForPropertyOption(
- $optionId,
- $optionValue,
- 'DE');
- foreach ($article['matrix_varianten']['texte']['werte'] as $countryIsoCode => $matrixOptionTranslations) {
- if ($countryIsoCode === 'EN') {
- $countryIsoCode = 'GB';
- }
- if (array_key_exists($optionValue, $matrixOptionTranslations)) {
- $this->createTranslationForPropertyOption(
- $optionId,
- $matrixOptionTranslations[$optionValue],
- $countryIsoCode);
- }
- }
- }
- }
- }
-
- $existingCombinations = $this->shopwareRequest(
- 'GET',
- '_action/product/' . $articleIdShopware . '/combinations');
- $existingCombinationsByNumber = [];
-
- foreach ($existingCombinations as $combinationId => $combinationInfo) {
- $existingCombinationsByNumber[$combinationInfo['productNumber']] = [
- 'id' => $combinationId,
- 'options' => [],
- ];
- foreach ($combinationInfo['options'] as $combinationOption) {
- $existingCombinationsByNumber[$combinationInfo['productNumber']]['options'][$combinationOption] = $combinationOption;
- }
- }
-
-
- foreach ($article['artikel_varianten'] as $variant) {
- $internalVariantMatrixData = $article['matrix_varianten']['artikel'][$variant['artikel']];
- $productNumber = $internalVariantMatrixData[0]['nummer'];
- $name = $variant['name_de'];
- $stock = $variant['lag'];
- $ean = $variant['ean'];
- $weight = (float)$variant['gewicht'];
- $pseudoPrice = $variant['pseudopreis'];
- if (empty($pseudoPrice)) {
- $pseudoPrice = 0;
- }
- if (!empty($variant['pseudolager'])) {
- $stock = $variant['pseudolager'];
- }
- $active = true;
- if (!empty($variant['inaktiv'])) {
- $active = false;
- }
- $isCloseOut = false;
- if (!empty($variant['restmenge'])) {
- $isCloseOut = true;
- }
-
- $variantProductData = [
- 'active' => $active,
- 'isCloseout' => $isCloseOut,
- 'name' => $name,
- 'description' => null,
- 'weight' => null,
- 'price' => [
- [
- 'currencyId' => $currencyId,
- 'gross' => $variant['bruttopreis'],
- 'net' => $variant['preis'],
- 'linked' => true,
- 'listPrice' => [
- 'currencyId' => $currencyId,
- 'gross' => $pseudoPrice,
- 'linked' => true,
- 'net' => $pseudoPrice / (1 + $variant['steuersatz'] / 100)
- ]
- ]
- ],
- 'stock' => (int)$stock,
- 'ean' => null,
- 'taxId' => $this->getTaxIdByRate($variant['steuersatz']),
- ];
- if(!empty($weight)){
- $variantProductData['weight'] = $weight;
- }
- if(!empty($ean)){
- $variantProductData['ean'] = $ean;
- }
- if (!empty($variant['uebersicht_de'])) {
- $variantProductData['description'] = $variant['uebersicht_de'];
- }
-
- $renewVariant = false;
- $options = [];
- foreach ($internalVariantMatrixData as $expression) {
- if (!in_array(
- $internalGroupPropertiesToShopwareId[$expression['name']][$expression['values']],
- $existingCombinationsByNumber[$productNumber]['options'],
- false)) {
- $renewVariant = true;
- } else {
- unset($existingCombinationsByNumber[$productNumber]['options'][$internalGroupPropertiesToShopwareId[$expression['name']][$expression['values']]]);
- }
- $options[] = ['id' => $internalGroupPropertiesToShopwareId[$expression['name']][$expression['values']]];
- }
-
- if (!empty($existingCombinationsByNumber[$productNumber]['options'])) {
- $renewVariant = true;
- }
-
- $variantImageData = [
- 'Dateien' => []
- ];
- $variantProductId = '';
- if (!empty($existingCombinationsByNumber[$productNumber]['id']) && !$renewVariant) {
- $variantProductId = $existingCombinationsByNumber[$productNumber]['id'];
- }
- if (!empty($variant['Dateien']['id'])) {
- foreach ($variant['Dateien']['id'] as $index => $fileId) {
- $variantImageData['Dateien'][] = [
- 'filename' => $variant['Dateien']['filename'][$index],
- 'extension' => $variant['Dateien']['extension'][$index],
- 'datei' => $variant['Dateien']['datei'][$index],
- 'beschreibung' => $variant['Dateien']['beschreibung'][$index],
- 'titel' => $variant['Dateien']['titel'][$index],
- 'id' => $fileId,
- ];
- }
- }
- $mediaToAdd = $this->mediaToExport($variantImageData, $variantProductId);
- $variantProductData['media'] = $mediaToAdd;
-
- if ($renewVariant) {
- if (!empty($existingCombinationsByNumber[$productNumber]['id'])) {
- $this->shopwareRequest('DELETE', 'product/' . $existingCombinationsByNumber[$productNumber]['id']);
- }
- $variantProductData['productNumber'] = $productNumber;
- $variantProductData['parentId'] = $articleIdShopware;
- $variantProductData['options'] = $options;
-
- $result = $this->shopwareRequest('POST', 'product?_response=true', $variantProductData);
- $variantProductId = $result['data']['id'];
- } else {
- $variantProductId = $existingCombinationsByNumber[$productNumber]['id'];
- $this->shopwareRequest('PATCH', 'product/' . $variantProductId, $variantProductData);
- }
-
- $defaultPrices = $this->getPricesFromArray($variant['staffelpreise_standard'] ?? []);
- $groupPrices = $this->getPricesFromArray($variant['staffelpreise_gruppen'] ?? []);
-
- $this->deleteOldBulkPrices($variantProductId);
- if (!empty($defaultPrices)) {
- foreach ($defaultPrices as $priceData) {
- $this->exportBulkPriceForGroup($variantProductId, $this->defaultRuleName, $priceData);
- }
- }
- if (!empty($groupPrices)) {
- foreach ($groupPrices as $priceData) {
- $this->exportBulkPriceForGroup($variantProductId, $priceData->getGroupName(), $priceData);
- }
- }
-
- $this->addCoverImage($variantImageData, $variantProductId);
- }
-
- $existingConfigurations = $this->shopwareRequest(
- 'GET', 'product/' . $articleIdShopware . '/configuratorSettings');
- $optionIdsToAdd = [];
- foreach ($article['artikel_varianten'] as $variant) {
- foreach ($article['matrix_varianten']['artikel'][$variant['artikel']] as $matrixInfo) {
- $configurationExists = false;
- foreach ($existingConfigurations['data'] as $configuration) {
- if ($configuration['attributes']['optionId'] === $internalGroupPropertiesToShopwareId[$matrixInfo['name']][$matrixInfo['values']]) {
- $configurationExists = true;
- break;
- }
- }
- if (!$configurationExists) {
- $optionIdsToAdd[] = $internalGroupPropertiesToShopwareId[$matrixInfo['name']][$matrixInfo['values']];
- }
- }
- }
- if (!empty($optionIdsToAdd)) {
- $optionIdsToAdd = array_flip(array_flip($optionIdsToAdd));
- $configurationData = [
- 'configuratorSettings' => []
- ];
- foreach ($optionIdsToAdd as $id) {
- $configurationData['configuratorSettings'][] = ['optionId' => $id];
- }
-
- $this->shopwareRequest(
- 'PATCH',
- sprintf('product/%s', $articleIdShopware),
- $configurationData
- );
-
- $existingConfigurations = $this->shopwareRequest(
- 'GET', 'product/' . $articleIdShopware . '/configuratorSettings');
- $optionsToSort = [];
- foreach ($article['artikel_varianten'] as $variant) {
- foreach ($article['matrix_varianten']['artikel'][$variant['artikel']] as $matrixInfo) {
- foreach ($existingConfigurations['data'] as $configuration) {
- if ($configuration['attributes']['optionId'] === $internalGroupPropertiesToShopwareId[$matrixInfo['name']][$matrixInfo['values']]) {
- $optionsToSort[] = $configuration['id'];
- break;
- }
- }
- }
- }
- if (!empty($optionsToSort)) {
- $optionsToSort = array_flip(array_flip($optionsToSort));
- $configurationData = [
- 'configuratorSettings' => []
- ];
- $position = 1;
-
- foreach ($optionsToSort as $id) {
- $configurationData['configuratorSettings'][] = [
- 'id' => $id,
- 'position' => $position];
- $position++;
- }
-
- $this->shopwareRequest(
- 'PATCH',
- sprintf('product/%s', $articleIdShopware),
- $configurationData
- );
- }
- }
-
- return true;
- }
-
- /**
- * @param $priceArray
- * @return PriceData[]
- */
- protected function getPricesFromArray($priceArray): array{
- return array_map(static function($price){
- return new PriceData(
- (int)$price['ab_menge'],
- (float)$price['preis'],
- (float)$price['bruttopreis'],
- $price['waehrung'],
- $price['gruppeextern'] ?? '') ;
- },$priceArray);
- }
-
- /**
- * delete all old price entries for a product
- *
- * @param string $productId
- */
- protected function deleteOldBulkPrices($productId)
- {
- //TODO Instead of deleting all old prices we should rather check first whether they are still in order
- $oldPrices = $this->shopwareRequest(
- 'GET',
- sprintf('product-price?filter[product_price.productId]=%s', $productId)
- );
- if (is_array($oldPrices)) {
- foreach ($oldPrices['data'] as $deletePrice) {
- $this->shopwareRequest('DELETE', 'product-price/' . $deletePrice['id']);
- }
- } else {
- $this->Shopware6Log('Fehler: Alte Preise wurden nicht gelöscht', $productId);
- }
- }
-
- /**
- * @return int
- */
- public function getOrderSearchLimit(): int
- {
- if(in_array($this->orderSearchLimit, ['50', '75', '100'])) {
- return (int)$this->orderSearchLimit;
- }
-
- return 25;
- }
-
- /**
- * @return int
- */
- public function ImportGetAuftraegeAnzahl()
- {
- $order = null;
- $dataToGet = $this->CatchRemoteCommand('data');
-
- if (empty($this->statesToFetch)) {
- return false;
- }
-
- $ordersToProcess = $this->getOrdersToProcess($this->getOrderSearchLimit());
-
- return count($ordersToProcess['data']);
- }
-
- /**
- * @param string $parameter1
- * @param string $parameter2
- */
- public function Shopware6ErrorLog($parameter1, $parameter2 = '')
- {
- $this->app->DB->Insert(
- sprintf(
- "INSERT INTO `shopexport_log`
- (shopid, typ, parameter1, parameter2, bearbeiter, zeitstempel)
- VALUES (%d, 'fehler', '%s','%s','%s',NOW())",
- $this->shopid,
- $this->app->DB->real_escape_string($parameter1),
- $this->app->DB->real_escape_string($parameter2),
- $this->app->DB->real_escape_string($this->app->User->GetName())
- )
- );
- }
-
- /**
- * @param array $stateMachinesIds
- * @return array
- */
- protected function getTransactionStateIdsToFetch($stateMachinesIds): array
- {
- $transactionStateIdsToFetch = [];
- if (!empty($this->transactionStatesToFetch)) {
- $transactionStatesToFetch = explode(';', $this->transactionStatesToFetch);
- foreach ($transactionStatesToFetch as $transactionStateToFetch) {
- $stateInformation = $this->shopwareRequest('GET', 'state-machine-state?filter[technicalName]=' .
- trim($transactionStateToFetch) . '&filter[stateMachineId]=' . $stateMachinesIds['order_transaction.state']);
- if (empty($stateInformation['data'])) {
- $this->Shopware6ErrorLog('Zahlungsstatus für Abholung nicht gefunden', $transactionStateToFetch);
- return false;
- }
- foreach ($stateInformation['data'] as $state) {
- $transactionStateIdsToFetch[] = $state['id'];
- }
- }
- }
-
- return $transactionStateIdsToFetch;
- }
-
- /**
- * @param int $limit
- *
- * @return mixed
- */
- protected function getOrdersToProcess(int $limit)
- {
- $searchData = [
- 'limit' => $limit,
- 'includes' => [
- 'order' => ['id']
- ],
- 'sort' => [
- [
- 'field' => 'order.createdAt',
- 'direction' => 'DESC'
- ]
- ],
- 'filter' => []
- ];
-
- $searchData['filter'][] = [
- 'field' => 'stateMachineState.technicalName',
- 'type' => 'equalsAny',
- 'value' => explode(';', $this->statesToFetch)
- ];
-
- if (!empty($this->deliveryStatesToFetch)) {
- $searchData['filter'][] = [
- 'field' => 'deliveries.stateMachineState.technicalName',
- 'type' => 'equalsAny',
- 'value' => explode(';', $this->deliveryStatesToFetch)
- ];
- }
- if (!empty($this->transactionStatesToFetch)) {
- $searchData['filter'][] = [
- 'field' => 'transactions.stateMachineState.technicalName',
- 'type' => 'equalsAny',
- 'value' => explode(';', $this->transactionStatesToFetch)
- ];
- }
-
- if (!empty($this->salesChannelToFetch)) {
- $searchData['filter'][] = [
- 'field' => 'order.salesChannelId',
- 'type' => 'equals',
- 'value' => $this->salesChannelToFetch
- ];
- }
-
- return $this->shopwareRequest('POST', 'search/order', $searchData);
- }
-
- /**
- * @return int|mixed
- */
- public function ImportGetAuftrag()
- {
- $voucherArticleId = $this->app->DB->Select("SELECT s.artikelrabatt FROM `shopexport` AS `s` WHERE s.id='$this->shopid' LIMIT 1");
- $voucherArticleNumber = $this->app->DB->Select("SELECT a.nummer FROM `artikel` AS `a` WHERE a.id='$voucherArticleId' LIMIT 1");
-
- $dataToGet = $this->CatchRemoteCommand('data');
- if (empty($this->statesToFetch)) {
- return false;
- }
- $expectOrderArray = !empty($dataToGet['anzgleichzeitig']) && (int)$dataToGet['anzgleichzeitig'] > 1;
- $expectNumber = !empty($dataToGet['nummer']);
- $order = null;
- if($expectNumber) {
- $order = $this->shopwareRequest('GET', 'order/' . $dataToGet['nummer'] . '?associations[currency][]');
- if(empty($order['data'])) {
- return false;
- }
- $ordersToProcess = ['data' => [ ['id' => $dataToGet['nummer']] ]];
- $orderIncludedData = $order['included'];
- $order = $order['data'];
- }
- elseif(!$expectOrderArray) {
- $ordersToProcess = $this->getOrdersToProcess(1);
- }
- elseif(!$expectNumber) {
- $ordersToProcess = $this->getOrdersToProcess($this->getOrderSearchLimit());
- }
- if (empty($ordersToProcess['data'])) {
- return false;
- }
-
- $fetchedOrders = [];
- if (isset($ordersToFetch['data']['id']) && !isset($ordersToFetch['data'][0])) {
- $ordersToFetch['data'] = [$ordersToFetch['data']];
- }
- foreach ($ordersToProcess['data'] as $currentlyOpenOrder) {
- $orderIdToFetch = $currentlyOpenOrder['id'];
-
- if (empty($dataToGet['nummer']) || empty($order)) {
- $order = $this->shopwareRequest('GET', 'order/' . $orderIdToFetch.'?associations[currency][]');
- $orderIncludedData = $order['included'];
- $order = $order['data'];
- }
- $cart = [];
- try {
- $timestamp = date_create_from_format('Y-m-d\TH:i:s+', $order['attributes']['createdAt']);
- $cart['zeitstempel'] = $timestamp->format('Y-m-d H:i:s');
- } catch (Exception $ex) {
-
- }
- $cart['auftrag'] = $order['id'];
- $cart['subshop'] = $order['attributes']['salesChannelId'];
- $cart['order'] = $order;
- $cart['onlinebestellnummer'] = $order['attributes']['orderNumber'];
- $cart['gesamtsumme'] = $order['attributes']['amountTotal'];
- $cart['versandkostenbrutto'] = $order['attributes']['shippingTotal'];
- $cart['bestelldatum'] = substr($order['attributes']['orderDate'], 0, 10);
- if (!empty($order['attributes']['customerComment'])) {
- $cart['freitext'] = $order['attributes']['customerComment'];
- }
-
- foreach ($orderIncludedData as $includedDataSet){
- if($includedDataSet['type'] === 'currency'){
- $cart['waehrung'] = $includedDataSet['attributes']['isoCode'];
- }
- }
-
- $deliveryInfo = $this->shopwareRequest('GET', 'order/' . $order['id'] . '/deliveries');
- $shippingMethod = $this->shopwareRequest('GET',
- 'order-delivery/' . $deliveryInfo['data'][0]['id'] . '/shipping-method');
- $order['shippingMethod'] = $shippingMethod;
- $cart['lieferung'] = $shippingMethod['data'][0]['attributes']['name'];
-
- $customer = $this->shopwareRequest('GET', 'order/' . $order['id'] . '/order-customer');
- $order['customer'] = $customer;
- $cart['email'] = $customer['data']['0']['attributes']['email'];
-
- $addresses = $this->shopwareRequest('GET', 'order/' . $order['id'] . '/addresses?associations[salutation][]&associations[country][]');
- $order['addresses'] = $addresses;
- $deliveryCountryId = '';
- $billingCountryId = '';
- $billingSalutationId = '';
- foreach ($addresses['data'] as $address) {
- if ($address['id'] === $order['attributes']['billingAddressId']) {
- if (!empty($address['attributes']['vatId'])) {
- $cart['ustid'] = $address['attributes']['vatId'];
- }
- $cart['name'] = $address['attributes']['firstName'] . ' ' . $address['attributes']['lastName'];
- if (!empty($address['attributes']['company'])) {
- $cart['ansprechpartner'] = $cart['name'];
- $cart['name'] = $address['attributes']['company'];
- }
- $cart['strasse'] = $address['attributes']['street'];
- $cart['abteilung'] = $address['attributes']['department'];
- $cart['adresszusatz'] = trim($address['attributes']['additionalAddressLine1'].' '.
- $address['attributes']['additionalAddressLine2']);
- $cart['telefon'] = $address['attributes']['phoneNumber'];
- $cart['plz'] = $address['attributes']['zipcode'];
- $cart['ort'] = $address['attributes']['city'];
- $billingCountryId = $address['attributes']['countryId'];
- $billingSalutationId = $address['attributes']['salutationId'];
- }
- if ($address['id'] !== $order['attributes']['billingAddressId']) {
- $cart['abweichendelieferadresse'] = 1;
- if (!empty($address['attributes']['vatId'])) {
- $cart['lieferadresse_ustid'] = $address['attributes']['vatId'];
- }
- $cart['lieferadresse_name'] = $address['attributes']['firstName'] . ' ' . $address['attributes']['lastName'];
- if (!empty($address['attributes']['company'])) {
- $cart['lieferadresse_ansprechpartner'] = $cart['lieferadresse_name'];
- $cart['lieferadresse_name'] = $address['attributes']['company'];
- }
- $cart['lieferadresse_strasse'] = $address['attributes']['street'];
- $cart['lieferadresse_abteilung'] = $address['attributes']['department'];
- $cart['lieferadresse_adresszusatz'] = trim($address['attributes']['additionalAddressLine1'].' '.
- $address['attributes']['additionalAddressLine2']);
- $cart['lieferadresse_plz'] = $address['attributes']['zipcode'];
- $cart['lieferadresse_ort'] = $address['attributes']['city'];
- $deliveryCountryId = $address['attributes']['countryId'];
- }
- }
-
- $anrede = 'herr';
- $land = 'DE';
- $lieferadresseLand = 'DE';
- foreach ($addresses['included'] as $includedInfo) {
- if ($includedInfo['id'] === $billingCountryId) {
- $land = $includedInfo['attributes']['iso'];
- }
- if ($includedInfo['id'] === $deliveryCountryId) {
- $lieferadresseLand = $includedInfo['attributes']['iso'];
- }
- if ($includedInfo['id'] === $billingSalutationId) {
- $salutation = $includedInfo['attributes']['salutationKey'];
- if ($salutation === 'ms' || $salutation === 'mrs') {
- $anrede = 'frau';
- }
- }
- }
-
- $cart['anrede'] = $anrede;
- $cart['land'] = $land;
- if (!empty($cart['abweichendelieferadresse'])) {
- $cart['lieferadresse_land'] = $lieferadresseLand;
- }
-
- $transactionData = $this->shopwareRequest('GET', 'order/' . $order['id'] . '/transactions');
- $cart['transacion_data'] = $transactionData;
- if (!empty($transactionData['data'][0]['attributes']['customFields']['swag_paypal_pui_payment_instruction']['reference_number'])) {
- $cart['transaktionsnummer'] = $transactionData['data'][0]['attributes']['customFields']['swag_paypal_pui_payment_instruction']['reference_number'];
- }
- if (empty($cart['transaktionsnummer'] && !empty($transactionData['data'][0]['attributes']['customFields']['swag_paypal_order_id']))) {
- $cart['transaktionsnummer'] = (string)$transactionData['data'][0]['attributes']['customFields']['swag_paypal_order_id'];
- }
- if (empty($cart['transaktionsnummer'] && !empty($transactionData['data'][0]['attributes']['customFields']['swag_paypal_transaction_id']))) {
- $livePayPalData = $this->shopwareRequest('GET', 'paypal/payment-details/' . $order['id'] . '/' . $transactionData['data'][0]['attributes']['customFields']['swag_paypal_transaction_id']);
- if (!empty($livePayPalData['transactions'])) {
- foreach ($livePayPalData['transactions'] as $payPalData) {
- foreach ($payPalData['related_resources'] as $ressources) {
- if ($ressources['sale']['state'] === 'completed') {
- $cart['transaktionsnummer'] = $ressources['sale']['id'];
- break 2;
- }
- }
- }
- }
- }
- if(
- empty($cart['transaktionsnummer'])
- && isset($transactionData['data'][0]['attributes']['customFields']['stripe_payment_context']['payment']['payment_intent_id'])
- ){
- $cart['transaktionsnummer'] = $transactionData['data'][0]['attributes']['customFields']['stripe_payment_context']['payment']['payment_intent_id'];
- }
-
- $paymentMethodId = $transactionData['data'][0]['attributes']['paymentMethodId'];
- $paymentMethod = $this->shopwareRequest('GET', 'payment-method/' . $paymentMethodId);
- $cart['zahlungsweise'] = $paymentMethod['data']['attributes']['name'];
-
- $taxedCountry = $land;
- if($this->taxationByDestinationCountry){
- $taxedCountry = $lieferadresseLand;
- }
- if($order['attributes']['amountTotal'] === $order['attributes']['amountNet']){
- if($this->app->erp->IstEU($taxedCountry)){
- $cart['ust_befreit'] = 1;
- }elseif($this->app->erp->Export($taxedCountry)){
- $cart['ust_befreit'] = 2;
- }else{
- $cart['ust_befreit'] = 3;
- }
- }
-
- $lineItems = $this->shopwareRequest('GET', 'order/' . $order['id'] . '/line-items');
- $order['lineItems'] = $lineItems;
- $cart['articlelist'] = [];
-
- $taxRate = 0;
- foreach ($lineItems['data'] as $lineItem) {
- if ($lineItem['attributes']['price']['calculatedTaxes'][0]['taxRate'] > $taxRate) {
- $taxRate = $lineItem['attributes']['price']['calculatedTaxes'][0]['taxRate'];
- }
- }
-
- $orderPriceType = 'price';
- if(in_array($order['attributes']['taxStatus'], ['net', 'tax-free'])) {
- $orderPriceType = 'price_netto';
- $cart['versandkostennetto'] = $cart['versandkostenbrutto'];
- unset($cart['versandkostenbrutto']);
- }
-
- foreach ($lineItems['data'] as $lineItem) {
- $productPriceType = $orderPriceType;
- if(empty($lineItem['attributes']['price']['calculatedTaxes'][0]['taxRate'])){
- $productPriceType = 'price_netto';
- }
- $articleId = null;
- if($lineItem['attributes']['price']['unitPrice'] < 0) {
- $articleId = $voucherArticleNumber;
- }
- elseif(isset($lineItem['attributes']['payload']['productNumber'])){
- $articleId = $lineItem['attributes']['payload']['productNumber'];
- }
- $product = [
- 'articleid' => $articleId,
- 'name' => $lineItem['attributes']['label'],
- 'quantity' => $lineItem['attributes']['quantity'],
- $productPriceType => $lineItem['attributes']['price']['unitPrice'],
- 'steuersatz' => $lineItem['attributes']['price']['calculatedTaxes'][0]['taxRate'],
- ];
- $cart['articlelist'][] = $product;
- }
-
- $cart['order'] = $order;
- $fetchedOrders[] = [
- 'id' => $cart['auftrag'],
- 'sessionid' => '',
- 'logdatei' => '',
- 'warenkorb' => base64_encode(serialize($cart)),
- 'warenkorbjson' => base64_encode(json_encode($cart)),
- ];
- $this->Shopware6Log('Ergebnis: Auftrag', $order);
- $this->Shopware6Log('Ergebnis: Adresse', $addresses);
- $this->Shopware6Log('Ergebnis: Positionen', $lineItems);
- }
-
- return $fetchedOrders;
- }
-
- /**
- * @return void
- */
- public function ImportDeleteAuftrag()
- {
- $tmp = $this->CatchRemoteCommand('data');
- $auftrag = $tmp['auftrag'];
-
- $this->shopwareRequest('POST', '_action/order/'.$auftrag.'/state/process');
- $this->addCustomFieldToOrder((string)$auftrag);
- }
-
- /**
- * @return void
- */
- public function ImportUpdateAuftrag()
- {
- $tmp = $this->CatchRemoteCommand('data');
- $auftrag = $tmp['auftrag'];
- $tracking = $tmp['tracking'];
-
- $this->shopwareRequest('POST', '_action/order/'.$auftrag.'/state/complete');
-
- $deliveries = $this->shopwareRequest('GET', 'order/'.$auftrag.'/deliveries');
- $deliveryId = $deliveries['data'][0]['id'];
-
- if(!empty($deliveryId)){
- $this->shopwareRequest('POST', '_action/order_delivery/'.$deliveryId.'/state/ship');
-
- $deliveryData = [
- 'trackingCodes' => [$tracking]
- ];
- $this->shopwareRequest('PATCH', 'order-delivery/'.$deliveryId,$deliveryData);
- }
-
- $this->sendInvoce($auftrag);
- $this->addCustomFieldToOrder((string)$auftrag);
- if(empty($tmp['orderId'])) {
- return;
- }
- $this->updateStorageForOrderIntId((int)$tmp['orderId']);
- }
-
- public function ImportStorniereAuftrag()
- {
- $tmp = $this->CatchRemoteCommand('data');
- $auftrag = $tmp['auftrag'];
-
- $this->shopwareRequest('POST', '_action/order/'.$auftrag.'/state/cancel');
- $this->addCustomFieldToOrder((string)$auftrag);
- }
-
- /**
- * @param string $extOrderId
- */
- protected function sendInvoce($extOrderId)
- {
- $order = $this->app->DB->SelectRow(
- sprintf(
- "SELECT `rechnungid`, `id` FROM `auftrag` WHERE shopextid='%s'",
- $extOrderId
- )
- );
- $invoiceId = 0;
- if (!empty($order['rechnungid'])) {
- $invoiceId = $order['rechnungid'];
- $sql = sprintf("SELECT projekt, belegnr FROM rechnung WHERE id='%s'", $invoiceId);
- $invoiceData = $this->app->DB->SelectRow($sql);
- }
- if (empty($invoiceId) && !empty($order['id'])) {
- $invoiceData = $this->app->DB->SelectRow(
- sprintf(
- "SELECT `id`, `projekt`, `belegnr`
- FROM `rechnung`
- WHERE `auftragid` = %d AND `status` <> 'storniert' AND `status` <> 'angelegt'
- LIMIT 1",
- $order['id']
- )
- );
- if (!empty($invoiceData)) {
- $invoiceId = $invoiceData['id'];
- }
- }
-
- if (!empty($invoiceData['belegnr'])) {
- $projekt = $invoiceData['projekt'];
- if (class_exists('RechnungPDFCustom')) {
- $Brief = new RechnungPDFCustom($this->app, $projekt);
- } else {
- $Brief = new RechnungPDF($this->app, $projekt);
- }
-
- $Brief->GetRechnung($invoiceId);
- $filePath = $Brief->displayTMP(true);
-
- $documentNumber = $invoiceData['belegnr'];
- $invoiceDocumentData = [
- 'config' => [
- 'custom' => [
- 'invoiceNumber' => $documentNumber,
- ],
- 'documentComment' => 'Aus Xentral heraus erstellte Rechnung',
- 'documentNumber' => $documentNumber,
- ],
- 'referenced_document_id' => null,
- 'static' => true
- ];
-
- $documentData = $this->shopwareRequest('POST', '_action/order/' . $extOrderId . '/document/invoice', $invoiceDocumentData);
- $documentId = $documentData['documentId'];
-
- $accessToken = $this->shopwareToken();
- $url = $this->ShopUrl . 'v2/_action/document/' . $documentId . '/upload?_response=true&extension=pdf&fileName=' . $documentNumber;
-
- $ch = curl_init();
- $setHeaders = [
- 'Content-Type:application/pdf',
- 'Authorization:Bearer ' . $accessToken['token']
- ];
- curl_setopt($ch, CURLOPT_URL, $url);
- curl_setopt($ch, CURLOPT_POSTFIELDS, file_get_contents($filePath));
- curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
- curl_setopt($ch, CURLOPT_HTTPHEADER, $setHeaders);
- curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
- curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
- $response = json_decode(curl_exec($ch), true);
- curl_close($ch);
- if (!empty($response['errors'])) {
- $this->Shopware6Log(
- 'Fehler bei Rechnugnsübertragung für ' . $documentNumber, $response['errors']
- );
- }
- }
- }
-
- /**
- * @return string
- */
- public function ImportAuth()
- {
- $tokeninfo = $this->shopwareToken();
-
-
- if (!$tokeninfo['success']) {
- return 'failed: ' . $tokeninfo['message'];
- }
- if($this->data === 'info'){
- $salesChannelsInShopware = $this->client->getAllSalesChannels();
- $salesChannelsToShow = ['subshops' => []];
- foreach ($salesChannelsInShopware['data'] as $salesChannelInShopware){
- $salesChannelsToShow['subshops'][] = [
- 'id'=>$salesChannelInShopware['id'],
- 'name'=>$salesChannelInShopware['name'],
- 'aktiv'=>$salesChannelInShopware['active']
- ];
- }
- return $salesChannelsToShow;
- }
-
- return 'success';
- }
-
- /**
- * Build category tree as displayed in article info
- * May be useful for setting category in the future
- * but probably obsolete
- *
- * @param string $categoryName
- * @param array $categoryTree
- *
- * @return array
- */
- protected function appendCategoryTree($categoryName, $categoryTree = [])
- {
- $shopwareCategory = $this->shopwareRequest(
- 'GET',
- 'category?filter[category.name]=' . urlencode($categoryName)
- );
- if (!isset($shopwareCategory['data'][0]['id'])) {
- return $categoryTree;
- }
- $categoryInfo = $shopwareCategory['data'][0]['attributes'];
- $categories[] = [(int)$categoryInfo['level'], $shopwareCategory['data'][0]['id']];
- $path = $categoryInfo['path'];
- if (!empty($path)) {
- $pathArray = explode('|', $path);
- foreach ($pathArray as $nodeId) {
- if ($nodeId === '') {
- continue;
- }
- $nodeCategory = $this->shopwareRequest('GET', 'category/' . $nodeId);
- if (isset($nodeCategory['data']['id'])) {
- $categories[] = [(int)$nodeCategory['data']['attributes']['level'], $nodeId];
- unset($nodeCategory);
- }
- }
- }
- foreach ($categories as $category) {
- $level = $category[0];
- if (!isset($categoryTree[$level])) {
- $categoryTree[$level] = [];
- }
- if (!in_array($category, $categoryTree[$level], true)) {
- $categoryTree[$level][] = $category[1];
- }
- }
- ksort($categoryTree);
-
- return $categoryTree;
- }
-
- /**
- * @param array $postData
- *
- * @return array
- */
- public function updatePostDataForAssistent($postData)
- {
- if(!empty($this->ShopUrl)) {
- $postData['shopwareUrl'] = $this->ShopUrl;
- }
- return $postData;
- }
-
- /**
- * @param array $shopArr
- * @param array $postData
- *
- * @return array
- */
- public function updateShopexportArr($shopArr, $postData)
- {
- $shopArr['stornoabgleich'] = 1;
- $shopArr['demomodus'] = 0;
-
- return $shopArr;
- }
-
- /**
- * @return JsonResponse|null
- */
- public function AuthByAssistent()
- {
- $shopwareUrl = $this->app->Secure->GetPOST('shopwareUrl');
- $shopwareUserName = $this->app->Secure->GetPOST('shopwareUserName');
- $shopwarePassword = $this->app->Secure->GetPOST('shopwarePassword');
- $step = (int)$this->app->Secure->GetPOST('step');
-
- if($step <= 1){
- if(empty($shopwareUrl)){
- return new JsonResponse(['error' => 'Bitte die URL des Shops angeben.'], JsonResponse::HTTP_BAD_REQUEST);
- }
- if(empty($shopwareUserName)){
- return new JsonResponse(['error' => 'Bitte den Benutzernamen angeben'], JsonResponse::HTTP_BAD_REQUEST);
- }
- if(empty($shopwarePassword)){
- return new JsonResponse(['error' => 'Bitte das Passwort angeben'], JsonResponse::HTTP_BAD_REQUEST);
- }
-
- $this->UserName = $shopwareUserName;
- $this->Password = $shopwarePassword;
- $shopwareUrl = rtrim($shopwareUrl, '/') . '/';
- $testUrls = [];
- $hasNoHttp = strpos($shopwareUrl,'http') !== 0;
- if(substr($shopwareUrl, -5) !== '/api/') {
- if($hasNoHttp) {
- $testUrls[] = 'https://'.$shopwareUrl.'api/';
- $testUrls[] = 'http://'.$shopwareUrl.'api/';
- }
- $testUrls[] = $shopwareUrl.'api/';
- }
- elseif($hasNoHttp) {
- $testUrls[] = 'https://'.$shopwareUrl;
- $testUrls[] = 'http://'.$shopwareUrl;
- }
- else {
- $testUrls[] = $shopwareUrl;
- }
- foreach($testUrls as $testUrl) {
- $this->ShopUrl = $testUrl;
- $tokeninfo = $this->shopwareToken();
- if(!empty($tokeninfo['success'])) {
- break;
- }
- }
-
- if(!$tokeninfo['success']){
- return new JsonResponse(['error' => $tokeninfo['message']], JsonResponse::HTTP_BAD_REQUEST);
- }
- }
-
- return null;
- }
-
- /**
- * @return string
- */
- public function getClickByClickHeadline()
- {
- return 'Bitte im Shopware Backend einen eigenen Benutzer für Xentral anlegen und diese
- Zugangsdaten hier eintragen.';
- }
-
- /**
- * @return array
- */
- public function getStructureDataForClickByClickSave()
- {
- return [
- 'shopwareAllowCreateManufacturer' => 1,
- ];
- }
-
- /**
- * @return array[]
- */
- public function getCreateForm()
- {
- return [
- [
- 'id' => 0,
- 'name' => 'urls',
- 'inputs' => [
- [
- 'label' => 'URL des Shops',
- 'type' => 'text',
- 'name' => 'shopwareUrl',
- 'validation' => true,
- ],
- ],
- ],
- [
- 'id' => 1,
- 'name' => 'username',
- 'inputs' => [
- [
- 'label' => 'Benutzername aus Shopware',
- 'type' => 'text',
- 'name' => 'shopwareUserName',
- 'validation' => true,
- ],
- ],
- ],
- [
- 'id' => 2,
- 'name' => 'password',
- 'inputs' => [
- [
- 'label' => 'Passwort aus Shopware',
- 'type' => 'password',
- 'name' => 'shopwarePassword',
- 'validation' => true,
- ],
- ],
- ],
- ];
- }
-
- public function getBoosterHeadline(): string
- {
- return 'Shopware 6 Business Booster App';
- }
-
- public function getBoosterSubHeadline(): string
- {
- return 'Bitte gehe auf Shopware 6 und installiere dort das Plugin Xentral Business Booster App.
- Dort kann man sich dann mit ein paar Klicks mit Xentral verbinden.';
- }
-
- /**
- * @param int $intOrderId
- *
- * @return array
- */
- protected function getArticleShopLinks(int $intOrderId): array
- {
- return $this->app->DB->SelectPairs(
- "SELECT DISTINCT ao.artikel, a.nummer
- FROM `auftrag_position` AS `ap`
- INNER JOIN `auftrag` AS `ab` ON ap.auftrag = ab.id
- INNER JOIN `artikel` AS `a` ON ap.artikel = a.id
- INNER JOIN `artikel_onlineshops` AS `ao` ON ab.shop = ao.shop AND a.id = ao.artikel
- WHERE ab.id = {$intOrderId} AND ao.aktiv = 1"
- );
- }
-
- /**
- * @param array $articleIds
- */
- protected function updateArticleCacheToSync(array $articleIds): void
- {
- if(empty($articleIds)) {
- return;
- }
- $articleIdsString = implode(', ', $articleIds);
- $this->app->DB->Update(
- "UPDATE `artikel`
- SET `laststorage_changed` = DATE_ADD(NOW(), INTERVAL 1 SECOND)
- WHERE `id` IN ({$articleIdsString})"
- );
- }
-
- /**
- * @param array $articleIds
- */
- protected function updateArticleOnlineShopCache(array $articleIds): void
- {
- if(empty($articleIds)) {
- return;
- }
- $articleIdsString = implode(', ', $articleIds);
- $this->app->DB->Update(
- "UPDATE `artikel_onlineshops`
- SET `storage_cache` = -999, `pseudostorage_cache` = -999
- WHERE `artikel` IN ({$articleIdsString}) AND `aktiv` = 1 AND `shop` = {$this->shopid}"
- );
- }
-
- /**
- * @param int $intOrderId
- */
- protected function updateStorageForOrderIntId(int $intOrderId): void
- {
- $articles = $this->getArticleShopLinks($intOrderId);
- if(empty($articles)) {
- return;
- }
- $articleIds = array_keys($articles);
- $this->updateArticleCacheToSync($articleIds);
- $this->updateArticleOnlineShopCache($articleIds);
-
- $isStorageSyncCronjobActive = (int)$this->app->DB->Select(
- "SELECT COUNT(`id`) FROM `prozessstarter` WHERE `aktiv` = 1 AND `parameter` = 'lagerzahlen'"
- ) > 0;
- if(!$isStorageSyncCronjobActive) {
- return;
- }
- foreach($articleIds as $articleId) {
- try {
- $this->app->erp->LagerSync($articleId, false, [$this->shopid]);
- }
- catch (Exception $e) {
- $articleNumber = $articles[$articleId];
- $this->Shopware6ErrorLog('LagerSync konnte nicht ausgeführt werden', $articleNumber);
- }
- }
-
- $this->updateArticleCacheToSync($articleIds);
- }
-}
+app = $app;
+ $this->intern = true;
+ if ($intern) {
+ return;
+ }
+ $this->app->ActionHandlerInit($this);
+
+ $this->app->ActionHandler('list', 'Shopimporter_Shopware6List');
+ $this->app->ActionHandler('auth', 'ImportAuth');
+ $this->app->ActionHandler('sendlistlager', 'ImportSendListLager');
+ $this->app->ActionHandler('getauftraegeanzahl', 'ImportGetAuftraegeAnzahl');
+ $this->app->ActionHandler('getauftrag', 'ImportGetAuftrag');
+ $this->app->ActionHandler('deleteauftrag', 'ImportDeleteAuftrag');
+ $this->app->ActionHandler('updateauftrag', 'ImportUpdateAuftrag');
+ $this->app->ActionHandler('storniereauftrag','ImportStorniereAuftrag');
+ $this->app->ActionHandler('getarticle','ImportGetArticle');
+ $this->app->ActionHandler('getarticlelist','ImportGetArticleList');
+ $this->app->ActionHandler("updatezahlungsstatus","ImportUpdateZahlungsstatus");
+ $this->app->DefaultActionHandler('list');
+
+ $this->app->ActionHandlerListen($app);
+ }
+
+ /**
+ * @param string $productId
+ *
+ * @return mixed
+ */
+ public function addSyncCustomFieldToProduct(string $productId)
+ {
+ $customField = [
+ 'customFields' => [
+ 'wawision_shopimporter_syncstate' => 1
+ ]
+ ];
+
+ return $this->shopwareRequest('PATCH', "product/{$productId}", $customField);
+ }
+
+ /**
+ * @param string $orderId
+ *
+ * @return mixed
+ */
+ public function addCustomFieldToOrder(string $orderId)
+ {
+ $customField = [
+ 'customFields' => [
+ 'wawision_shopimporter_syncstate' => 1
+ ]
+ ];
+
+ return $this->shopwareRequest('PATCH', "order/{$orderId}", $customField);
+ }
+
+ public function ImportGetArticleList()
+ {
+ $page = 1;
+ $limit = 500;
+
+ do {
+ $productIdsToAdd = [];
+ $searchdata = [
+ 'limit' => $limit,
+ 'page' => $page,
+ 'filter' => [
+ [
+ 'field' => 'product.parentId',
+ 'type' => 'equals',
+ 'value' => null
+ ]
+ ]
+ ];
+
+ $productsInShop = $this->shopwareRequest('POST', 'search/product', $searchdata);
+ if (!empty($productsInShop['data'])) {
+ foreach ($productsInShop['data'] as $productInShop) {
+ $productIdsToAdd[] = $productInShop['id'];
+ }
+ }
+
+ foreach ($productIdsToAdd as $productId) {
+ $this->app->DB->Insert("INSERT INTO shopexport_getarticles (shop, nummer) VALUES ('$this->shopid', '" . $this->app->DB->real_escape_string($productId) . "')");
+ }
+ $page++;
+ } while (count($productsInShop['data']) === $limit);
+
+
+ $anzahl = $this->app->DB->Select("SELECT COUNT(id) FROM shopexport_getarticles WHERE shop=$this->shopid");
+ $this->app->erp->SetKonfigurationValue('artikelimportanzahl_' . $this->shopid, $anzahl);
+
+ }
+
+ /**
+ * @param string $method
+ * @param string $endpoint
+ * @param string $data
+ *
+ * @param array $headerInformation
+ * @return mixed
+ */
+ public function shopwareRequest($method, $endpoint, $data = '', $headerInformation = [])
+ {
+ $accessToken = $this->shopwareToken();
+ $url = $this->ShopUrl;
+ $url .= 'v2/' . $endpoint;
+
+ $ch = curl_init();
+ $headerInformation[] = 'Content-Type:application/json';
+ $headerInformation[] = 'Authorization:Bearer ' . $accessToken['token'];
+ curl_setopt($ch, CURLOPT_URL, $url);
+ if (!empty($data)) {
+ curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
+ }
+ curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
+ curl_setopt($ch, CURLOPT_HTTPHEADER, $headerInformation);
+ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
+ $response = curl_exec($ch);
+ if (curl_error($ch)) {
+ $this->error[] = curl_error($ch);
+ }
+ curl_close($ch);
+
+ return json_decode($response, true);
+ }
+
+ /**
+ * @return array
+ */
+ protected function shopwareToken()
+ {
+ $result = [];
+
+ $result['success'] = true;
+ $result['token'] = $this->accessToken;
+ $result['message'] = 'Keine Antwort von API erhalten.';
+
+ if (!empty($result['token'])) {
+ return $result;
+ }
+
+ $result['success'] = false;
+
+ $data = [
+ 'username' => $this->UserName,
+ 'password' => $this->Password,
+ 'grant_type' => 'password',
+ 'scopes' => 'write',
+ 'client_id' => 'administration',
+ ];
+
+ $ch = curl_init($this->ShopUrl . 'oauth/token');
+ curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
+ curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
+ curl_setopt($ch, CURLOPT_HTTPHEADER, [
+ 'Accept: application/json',
+ 'Content-Type: application/json',
+ 'Cache-Control: no-cache',
+ ]
+ );
+ $response = json_decode(curl_exec($ch), true);
+
+ if (!empty((string)$response['title'])) {
+ $result['message'] = $response['title'];
+ }
+
+ if (!empty($response['access_token'])) {
+ $result['success'] = true;
+ $this->accessToken = $response['access_token'];
+ $result['token'] = $response['access_token'];
+ }
+
+ return $result;
+ }
+
+ public function ImportGetArticle()
+ {
+ $tmp = $this->CatchRemoteCommand('data');
+
+ if (isset($tmp['nummerintern'])) {
+ $nummer = $tmp['nummerintern'];
+ $response = $this->shopwareRequest('GET', 'product/' . $nummer);
+ if (empty($response['data'])) {
+ $this->error[] = 'Artikel in der Shop Datenbank nicht gefunden!';
+ return;
+ }
+ $nummer = $response['data']['attributes']['productNumber'];
+ } else {
+ $nummer = $tmp['nummer'];
+ }
+ $articleInfo = $this->shopwareRequest('GET', 'product?filter[product.productNumber]=' . $nummer .
+ '&associations[manufacturer][]&associations[properties][]');
+ if (empty($articleInfo['data'][0])) {
+ $this->error[] = 'Artikel in der Shop Datenbank nicht gefunden!';
+ return;
+ }
+ $articleIdInShop = $articleInfo['data'][0]['id'];
+ if(empty($articleInfo['data'][0]['customFields'])
+ || empty($articleInfo['data'][0]['customFields']['wawision_shopimporter_syncstate'])){
+ $this->addSyncCustomFieldToProduct((string)$articleIdInShop);
+ }
+
+ $articleInfo = $this->shopwareRequest('GET', 'product?filter[product.productNumber]=' . $nummer .
+ '&associations[manufacturer][]&associations[properties][]');
+ $associatedInformation = [];
+ $properties = [];
+ foreach ($articleInfo['included'] as $includedInformation) {
+ if ($includedInformation['type'] === 'property_group_option') {
+ $properties[$includedInformation['id']] = $includedInformation['attributes'];
+ } else {
+ $associatedInformation[$includedInformation['id']] = $includedInformation['attributes'];
+ }
+ }
+ $groups = [];
+ if (!empty($properties)) {
+ $groupsInShop = $this->shopwareRequest('GET', 'property-group');
+ foreach ($groupsInShop['data'] as $groupInShop) {
+ $groups[$groupInShop['id']] = $groupInShop['attributes']['name'];
+ }
+ }
+ $media = $this->shopwareRequest('GET', 'product/' . $articleIdInShop . '/media');
+ $imagesToAdd = [];
+ if (!empty($media['included'])) {
+ foreach ($media['included'] as $mediaInfo) {
+ if ($mediaInfo['type'] === 'media') {
+ $imagesToAdd[] = [
+ 'content' => base64_encode(@file_get_contents($mediaInfo['attributes']['url'])),
+ 'path' => $mediaInfo['attributes']['url'],
+ 'id' => $mediaInfo['id']
+ ];
+ }
+ }
+ }
+ $articleInfo = $articleInfo['data'][0]['attributes'];
+
+ $data = [];
+ $data['name'] = $articleInfo['name'];
+ if (isset($tmp['nummerintern'])) {
+ $data['nummer'] = $articleInfo['productNumber'];
+ }
+
+
+ $data['artikelnummerausshop'] = $articleInfo['productNumber'];
+ $data['restmenge'] = $articleInfo['stock'];
+ $data['uebersicht_de'] = $articleInfo['description'];
+ $data['preis_netto'] = $articleInfo['price'][0]['net'];
+ if (!empty($articleInfo['price'][0]['listPrice'])) {
+ $data['pseudopreis'] = $articleInfo['price'][0]['listPrice'];
+ }
+ $data['aktiv'] = $articleInfo['active'];
+ if (!empty($articleInfo['weight'])) {
+ $data['gewicht'] = $articleInfo['weight'];
+ }
+ if (!empty($articleInfo['manufacturerNumber'])) {
+ $data['herstellernummer'] = $articleInfo['manufacturerNumber'];
+ }
+ if (!empty($articleInfo['ean'])) {
+ $data['ean'] = $articleInfo['ean'];
+ }
+ if (!empty($articleInfo['manufacturerId'])) {
+ $data['hersteller'] = $associatedInformation[$articleInfo['manufacturerId']]['name'];
+ }
+ if (!empty($articleInfo['taxId'])) {
+ $data['umsatzsteuer'] = $associatedInformation[$articleInfo['taxId']]['taxRate'];
+ }
+ if (!empty($properties)) {
+ foreach ($properties as $property) {
+ if ($this->propertyOption === 'toProperties') {
+ $data['eigenschaften'][] = [
+ 'name' => $groups[$property['groupId']],
+ 'values' => $property['name'],
+ ];
+ }
+ if ($this->propertyOption === 'toCustomFields') {
+ $data['freifeld_' . $groups[$property['groupId']]] = $property['name'];
+ }
+ }
+ }
+ if (!empty($articleInfo['customFields'])) {
+ foreach ($articleInfo['customFields'] as $customFieldName => $customFieldValue) {
+ if ($this->freeFieldOption === 'toProperties') {
+ $data['eigenschaften'][] = [
+ 'name' => $customFieldName,
+ 'values' => $customFieldValue
+ ];
+ }
+ if ($this->freeFieldOption === 'toCustomFields') {
+ $data['freifeld_' . $customFieldName] = $customFieldValue;
+ }
+ }
+ }
+ if (!empty($imagesToAdd)) {
+ $data['bilder'] = $imagesToAdd;
+ }
+
+
+ if ($articleInfo['childCount'] > 0) {
+ $data = [$data];
+
+ $limit = 50;
+ $page = 1;
+ $optionInfo = [];
+ $optionGroupInfo = [];
+ do {
+
+ $searchdata = [
+ 'limit' => $limit,
+ 'page' => $page,
+ 'filter' => [
+ [
+ 'field' => 'product.parentId',
+ 'type' => 'equals',
+ 'value' => $articleIdInShop
+ ]
+ ],
+ 'sort' => [
+ [
+ 'field' => 'product.options.groupId',
+ 'naturalSorting' => false,
+ 'order' => 'ASC'
+ ],
+ [
+ 'field' => 'product.options.id',
+ 'naturalSorting' => false,
+ 'order' => 'ASC'
+ ]
+ ],
+ 'associations' => [
+ 'options' => [
+ 'sort' => [
+ [
+ 'field' => 'groupId',
+ 'naturalSorting' => false,
+ 'order' => 'ASC'
+ ],
+ [
+ 'field' => 'id',
+ 'naturalSorting' => false,
+ 'order' => 'ASC'
+ ]
+ ]
+ ]
+ ]
+ ];
+ $variantsInShop = $this->shopwareRequest('POST', 'search/product', $searchdata);
+ foreach ($variantsInShop['included'] as $includedInfo) {
+ if ($includedInfo['type'] === 'property_group_option') {
+ $optionInfo[$includedInfo['id']] = $includedInfo['attributes'];
+ if (empty($optionGroupInfo[$includedInfo['attributes']['groupId']])) {
+ $optionGroupInfo[$includedInfo['attributes']['groupId']] = (!empty($optionGroupInfo)?count($optionGroupInfo):0) + 1;
+ }
+ }
+ }
+
+ foreach ($variantsInShop['data'] as $variantInShop) {
+ $variantData = [];
+ $variantName = $data[0]['name'];
+ foreach ($variantInShop['attributes']['optionIds'] as $optionId) {
+ $variantData['matrixprodukt_wert' . $optionGroupInfo[$optionInfo[$optionId]['groupId']]] =
+ $optionInfo[$optionId]['name'];
+ $variantName .= ' - ' . $optionInfo[$optionId]['name'];
+ }
+
+ $variantData['name'] = $variantName;
+ $variantData['nummer'] = $variantInShop['attributes']['productNumber'];
+ $variantData['artikelnummerausshop'] = $variantInShop['attributes']['productNumber'];
+ $variantData['restmenge'] = $variantInShop['attributes']['stock'];
+ $variantData['uebersicht_de'] = $variantInShop['attributes']['description'];
+ if (empty($variantInShop['attributes']['price'][0]['net'])) {
+ $variantData['preis_netto'] = $data[0]['preis_netto'];
+ } else {
+ $variantData['preis_netto'] = $variantInShop['attributes']['price'][0]['net'];
+ }
+ if (!empty($variantInShop['attributes']['price'][0]['listPrice'])) {
+ $variantData['pseudopreis'] = $variantInShop['attributes']['price'][0]['listPrice'];
+ }
+ $variantData['aktiv'] = $variantInShop['attributes']['active'];
+ if (!empty($variantInShop['attributes']['weight'])) {
+ $variantData['gewicht'] = $variantInShop['attributes']['weight'];
+ }
+ if (!empty($variantInShop['attributes']['manufacturerNumber'])) {
+ $variantData['herstellernummer'] = $variantInShop['attributes']['manufacturerNumber'];
+ }
+ if (!empty($variantInShop['attributes']['ean'])) {
+ $variantData['ean'] = $variantInShop['attributes']['ean'];
+ }
+ if (!empty($data[0]['umsatzsteuer'])) {
+ $variantData['umsatzsteuer'] = $data[0]['umsatzsteuer'];
+ }
+
+ $data[] = $variantData;
+ }
+
+ $page++;
+ } while (count($variantsInShop['data']) > $limit);
+
+ foreach ($optionGroupInfo as $groupId => $sorting) {
+ $data[0]['matrixprodukt_gruppe' . $sorting] = $groups[$groupId];
+ }
+ foreach ($optionInfo as $optionData) {
+ $data[0]['matrixprodukt_optionen' . $optionGroupInfo[$optionData['groupId']]][] = $optionData['name'];
+ }
+ }
+
+ //TODO Staffelpreise
+ //TODO Kategorien
+ //TODO Freifelder
+ //TODO Crossselling
+
+ return $data;
+ }
+
+ /**
+ * @param array $data
+ *
+ * @return array
+ */
+ public function checkApiApp($data)
+ {
+ foreach (['shopwareUserName', 'shopwarePassword', 'shopwareUrl'] as $field) {
+ if (empty($data['data'][$field])) {
+ return ['success' => false, 'error' => sprintf('%s is empty', $field)];
+ }
+ }
+
+ $shops = $this->app->DB->SelectArr(
+ sprintf(
+ "SELECT `einstellungen_json`, `bezeichnung`,`id`
+ FROM `shopexport`
+ WHERE `modulename` = 'shopimporter_shopware6'
+ AND `einstellungen_json` IS NOT NULL AND `einstellungen_json` <> ''"
+ )
+ );
+ if (empty($shops)) {
+ return [
+ 'info' => [
+ 'Shop' => 'Shopware',
+ 'info' => 'Url ' . $data['data']['shopwareUrl'],
+ ]
+ ];
+ }
+ foreach ($shops as $shop) {
+ if (empty($shop['einstellungen_json'])) {
+ continue;
+ }
+ $json = @json_decode($shop['einstellungen_json'], true);
+ if (empty($json['felder']) || empty($json['felder']['shopwareUrl'])) {
+ continue;
+ }
+ if ($json['felder']['shopwareUrl'] === $data['data']['shopwareUrl']) {
+ return [
+ 'success' => false,
+ 'error' => sprintf('Shop with url %s allready exists', $data['data']['shopwareUrl'])
+ ];
+ }
+ }
+
+ return [
+ 'info' => [
+ 'Shop' => 'Shopware',
+ 'info' => 'Url ' . $data['data']['shopwareUrl'],
+ ]
+ ];
+ }
+
+ /**
+ *
+ */
+ public function Shopimporter_Shopware6List()
+ {
+ $msg = $this->app->erp->base64_url_encode('Sie können hier die Shops einstellen
');
+ header('Location: index.php?module=onlineshops&action=list&msg=' . $msg);
+ exit;
+ }
+
+ /**
+ * @param $shopid
+ * @param $data
+ */
+ public function getKonfig($shopid, $data)
+ {
+ $this->shopid = $shopid;
+ $this->data = $data;
+ $importerSettings = $this->app->DB->SelectArr("SELECT `einstellungen_json`, `kategorienuebertragen` FROM `shopexport` WHERE `id` = '$shopid' LIMIT 1");
+ $importerSettings = reset($importerSettings);
+
+ $this->exportCategories = (bool) $importerSettings['kategorienuebertragen'];
+
+ $einstellungen = [];
+ if (!empty($importerSettings['einstellungen_json'])) {
+ $einstellungen = json_decode($importerSettings['einstellungen_json'], true);
+ }
+ $this->protocol = $einstellungen['felder']['protocol'];
+ $this->UserName = $einstellungen['felder']['shopwareUserName'];
+ $this->Password = $einstellungen['felder']['shopwarePassword'];
+ $this->ShopUrl = rtrim($einstellungen['felder']['shopwareUrl'], '/') . '/';
+ $this->createManufacturerAllowed = false;
+ if ($einstellungen['felder']['shopwareAllowCreateManufacturer'] === '1') {
+ $this->createManufacturerAllowed = true;
+ }
+ $this->defaultManufacturer = $einstellungen['felder']['shopwareDefaultManufacturer'];
+ $this->defaultRuleName = $einstellungen['felder']['shopwareDefaultRuleName'];
+ $this->statesToFetch = $einstellungen['felder']['statesToFetch'];
+ $this->deliveryStatesToFetch = $einstellungen['felder']['deliveryStatesToFetch'];
+ $this->transactionStatesToFetch = $einstellungen['felder']['transactionStatesToFetch'];
+ $this->salesChannelToFetch = $einstellungen['felder']['salesChannelToFetch'];
+ $this->orderSearchLimit = $einstellungen['felder']['orderSearchLimit'];
+ $this->freeFieldOption = $einstellungen['felder']['shopwareFreeFieldOption'];
+ $this->propertyOption = $einstellungen['felder']['shopwarePropertyOption'];
+ $this->shopwareDefaultSalesChannel = $einstellungen['felder']['shopwareDefaultSalesChannel'];
+ $this->shopwareMediaFolder = $einstellungen['felder']['shopwareMediaFolder'];
+ $query = sprintf('SELECT `steuerfreilieferlandexport` FROM `shopexport` WHERE `id` = %d', $this->shopid);
+ $this->taxationByDestinationCountry = !empty($this->app->DB->Select($query));
+
+ $this->client = $this->app->Container->get('Shopware6Client');
+ $this->client->setCredentials(
+ $this->UserName,
+ $this->Password,
+ $this->ShopUrl
+ );
+ }
+
+ /**
+ * @return array
+ */
+ public function EinstellungenStruktur()
+ {
+ return
+ [
+ 'ausblenden' => ['abholmodus' => ['ab_nummer']],
+ 'functions' => ['exportartikelbaum','getarticlelist','updatezahlungsstatus'],
+ 'felder' => [
+ 'protocol' => [
+ 'typ' => 'checkbox',
+ 'bezeichnung' => '{|Protokollierung im Logfile|}:',
+ ],
+ 'shopwareUserName' => [
+ 'typ' => 'text',
+ 'bezeichnung' => '{|Benutzername|}:',
+ 'size' => 40,
+ ],
+ 'shopwarePassword' => [
+ 'typ' => 'text',
+ 'bezeichnung' => '{|Passwort|}:',
+ 'size' => 40,
+ ],
+ 'shopwareUrl' => [
+ 'typ' => 'text',
+ 'bezeichnung' => '{|Shop API URL|}:',
+ 'size' => 40,
+ ],
+ 'shopwareDefaultManufacturer' => [
+ 'typ' => 'text',
+ 'bezeichnung' => '{|Standard Hersteller|}:',
+ 'size' => 40,
+ 'default' => 'Keine Herstellerinformation',
+ ],
+ 'shopwareAllowCreateManufacturer' => [
+ 'typ' => 'checkbox',
+ 'bezeichnung' => '{|Bei Artikelexport Hersteller anlegen|}:',
+ ],
+ 'shopwareDefaultRuleName' => [
+ 'typ' => 'text',
+ 'bezeichnung' => '{|Name der Standardpreisgruppe|}:',
+ 'size' => 40,
+ 'default' => 'All customers',
+ ],
+ 'shopwarePropertyOption' => [
+ 'heading' => '{|Eigenschaften / Freifeld Zuordnung|}',
+ 'typ' => 'select',
+ 'bezeichnung' => '{|Xentral Artikel Eigenschaften|}:',
+ 'size' => 40,
+ 'default' => 'toProperties',
+ 'optionen' => ['toProperties' => '{|Shopware Eigenschaften|}', 'toCustomFields' => '{|Shopware Zusatzfelder|}', 'doNotExport' => '{|Nicht übertragen|}']
+ ],
+ 'shopwareFreeFieldOption' => [
+ 'typ' => 'select',
+ 'bezeichnung' => '{|Xentral Artikel Freifelder|}:',
+ 'size' => 40,
+ 'default' => 'toCustomFields',
+ 'optionen' => ['toProperties' => '{|Shopware Eigenschaften|}', 'toCustomFields' => '{|Shopware Zusatzfelder|}', 'doNotExport' => '{|Nicht übertragen|}']
+ ],
+ 'shopwareDefaultSalesChannel' => [
+ 'heading' => '{|Artikelexport Standardeinstellungen|}',
+ 'typ' => 'text',
+ 'bezeichnung' => '{|Standard Sichtbarkeit|}:',
+ 'size' => 40
+ ],
+ 'shopwareMediaFolder' => [
+ 'typ' => 'text',
+ 'bezeichnung' => '{|Media Folder für Artikelbilder|}:',
+ 'size' => 40,
+ 'default' => 'Product Media'
+ ],
+ 'statesToFetch' => [
+ 'typ' => 'text',
+ 'bezeichnung' => '{|Abzuholender Bestellstatus|}:',
+ 'size' => 40,
+ 'default' => 'open',
+ 'col' => 2,
+ 'info' => '
Erlaubte Werte: open;in_progress;completed;cancelled'
+ ],
+ 'deliveryStatesToFetch' => [
+ 'typ' => 'text',
+ 'bezeichnung' => '{|Eingrenzen auf Lieferstatus|}:',
+ 'size' => 40,
+ 'default' => '',
+ 'col' => 2,
+ 'info' => '
Erlaubte Werte: open;shipped_partially;shipped;returned;returned_partially;cancelled'
+ ],
+ 'transactionStatesToFetch' => [
+ 'typ' => 'text',
+ 'bezeichnung' => '{|Eingrenzen auf Bezahlstatus|}:',
+ 'size' => 40,
+ 'default' => '',
+ 'col' => 2,
+ 'info' => '
Erlaubte Werte: open;paid;authorized;paid_partially;refunded;refunded_partially;reminded;cancelled'
+ ],
+ 'salesChannelToFetch' => [
+ 'typ' => 'text',
+ 'bezeichnung' => '{|Eingrenzen auf Sales Channel|}:',
+ 'size' => 40,
+ 'default' => '',
+ 'col' => 2,
+ 'info' => '
Klicke auf "Verbindung prüfen" um die verfügbaren Channels (bitte die Id verwenden) anzuzeigen.'
+ ],
+ 'orderSearchLimit' => [
+ 'typ' => 'select',
+ 'bezeichnung' => '{|Anzahl Aufträge abholen|}:',
+ 'optionen' => [
+ '25' => '25',
+ '50' => '50',
+ '75' => '75',
+ '100' => '100',
+ ],
+ 'default' => '25',
+ 'col' => 2
+ ],
+ ],
+ ];
+ }
+
+ public function ImportUpdateZahlungsstatus()
+ {
+ $tmp = $this->CatchRemoteCommand('data');
+ $auftrag = $tmp['auftrag'];
+
+ $transactions = $this->shopwareRequest('GET', 'order/'.$auftrag.'/transactions');
+ $transactionId = $transactions['data'][0]['id'];
+
+ if(empty($transactionId)){
+ return;
+ }
+
+ $response = $this->shopwareRequest('POST', '_action/order_transaction/'.$transactionId.'/state/paid');
+ if (!empty($response['id'])) {
+ return 'ok';
+ }
+ }
+
+ public function ImportSendArtikelbaum(){
+ $xentralCategoryTree = [];
+ $this->app->erp->GetKategorienbaum($xentralCategoryTree, 0, 0, $this->shopid);
+
+ $xentralCategoryIdToParentId = [];
+ foreach ($xentralCategoryTree as $key => $value) {
+ $xentralCategoryTree[$key]['erledigt'] = false;
+ $xentralCategoryTree[$key]['shopid'] = '';
+ $xentralCategoryTree[$key]['aktiv'] = false;
+ $xentralCategoryIdToParentId[$value['id']] = $key;
+ }
+
+ $parentCategoryId = null;
+ foreach ($xentralCategoryTree as $index => $categoryData) {
+ $this->createCategoryTree($index, $xentralCategoryTree, $xentralCategoryIdToParentId, $parentCategoryId);
+ }
+ }
+
+ protected function createCategoryTree($id, &$xentralCategoryTree, $xentralCategoryIdToParentId, $parentCategoryId)
+ {
+ $parentId = $parentCategoryId;
+ if ($xentralCategoryTree[$id]['parent']) {
+ $parentId = $xentralCategoryTree[$xentralCategoryIdToParentId[$xentralCategoryTree[$id]['parent']]]['shopid'];
+ }
+ if ($xentralCategoryTree[$id]['parent'] && !$xentralCategoryTree[$xentralCategoryIdToParentId[$xentralCategoryTree[$id]['parent']]]['erledigt']) {
+ $this->createCategoryTree($xentralCategoryIdToParentId[$xentralCategoryTree[$id]['parent']], $xentralCategoryTree, $xentralCategoryIdToParentId, $parentCategoryId);
+ }
+ $xentralCategoryTree[$id]['erledigt'] = true;
+
+ $categoryName = $xentralCategoryTree[$id]['bezeichnung'];
+ $searchdata = [
+ 'limit' => 25,
+ 'filter' => [
+ [
+ 'field' => 'category.name',
+ 'type' => 'equals',
+ 'value' => $categoryName
+ ],
+ [
+ 'field' => 'category.parentId',
+ 'type' => 'equals',
+ 'value' => $parentId
+ ]
+ ]
+ ];
+
+ $categoriesInShop = $this->shopwareRequest('POST', 'search/category', $searchdata);
+
+ $categoryId = '';
+ if (!empty($categoriesInShop['data'])) {
+ $categoryId = $categoriesInShop['data'][0]['id'];
+ }
+
+ if (!$categoryId) {
+ $categoryData = [
+ 'parentId' => $parentId,
+ 'name' => $categoryName
+ ];
+ $result = $this->shopwareRequest('POST', 'category?_response=true', $categoryData);
+ if ($result['data']['id']) {
+ $categoryId = $result['data']['id'];
+ }
+ }
+
+ if ($categoryId) {
+ $xentralCategoryTree[$id]['shopid'] = $categoryId;
+ }
+ }
+
+ /**
+ * @return int
+ */
+ public function ImportSendListLager()
+ {
+ $tmp = $this->CatchRemoteCommand('data');
+
+ $count = 0;
+ foreach ($tmp as $article) {
+ $artikel = $article['artikel'];
+ if ($artikel === 'ignore') {
+ continue;
+ }
+ $nummer = $article['nummer'];
+ $fremdnummer = $article['fremdnummer'];
+ if (!empty($fremdnummer)) {
+ $nummer = $fremdnummer;
+ }
+ $articleInfo = $this->shopwareRequest('GET', 'product?filter[product.productNumber]=' . $nummer);
+
+ if (empty($articleInfo['data'][0]['id'])) {
+ $this->Shopware6Log('Artikel wurde nicht im Shop gefunden: ' . $nummer, $articleInfo);
+ continue;
+ }
+ if(empty($articleInfo['data'][0]['customFields'])
+ || empty($articleInfo['data'][0]['customFields']['wawision_shopimporter_syncstate'])){
+ $this->addSyncCustomFieldToProduct((string)$articleInfo['data'][0]['id']);
+ }
+
+ $active = true;
+ if ($article['inaktiv']) {
+ $active = false;
+ }
+
+ $stock = $article['anzahl_lager'];
+ if (!empty($article['pseudolager'])) {
+ $stock = $article['pseudolager'];
+ }
+ $stock = $this->getCorrectedStockFromAvailable($active, (int)$stock, $articleInfo);
+ $data = [
+ 'stock' => $stock,
+ 'active' => $active,
+ ];
+ $response = $this->shopwareRequest('PATCH', 'product/' . $articleInfo['data'][0]['id'], $data);
+ $this->Shopware6Log('Lagerbestand konnte nicht uebertragen werden fuer Artikel: ' . $nummer, $response);
+ $count++;
+ }
+
+ return $count;
+ }
+
+ /**
+ * @param bool $isStockActive
+ * @param int $stock
+ * @param array|null $articleInfo
+ *
+ * @return int
+ */
+ public function getCorrectedStockFromAvailable(bool $isStockActive, int $stock, ?array $articleInfo): int
+ {
+ if(!$isStockActive) {
+ return $stock;
+ }
+ if(empty($articleInfo)) {
+ return $stock;
+ }
+ if(!isset($articleInfo['data'][0]['attributes']['availableStock'])) {
+ return $stock;
+ }
+ if(!isset($articleInfo['data'][0]['attributes']['availableStock'])) {
+ return $stock;
+ }
+ $reserved = (int)$articleInfo['data'][0]['attributes']['stock']
+ - (int)$articleInfo['data'][0]['attributes']['availableStock'];
+ if($reserved <= 0) {
+ return $stock;
+ }
+
+ return $stock + $reserved;
+ }
+
+ /**
+ * @param string $message
+ * @param mixed $dump
+ */
+ public function Shopware6Log($message, $dump = '')
+ {
+ if ($this->protocol) {
+ $this->app->erp->Logfile($message, print_r($dump, true));
+ }
+ }
+
+ /**
+ * @return int
+ */
+ public function ImportSendList()
+ {
+ $articleList = $this->CatchRemoteCommand('data');
+
+ $successCounter = 0;
+ foreach ($articleList as $article) {
+ $number = $article['nummer'];
+ $articleInfo = $this->shopwareRequest(
+ 'GET',
+ sprintf('product?filter[product.productNumber]=%s', $number)
+ );
+ $articleIdShopware = '';
+ if (!empty($articleInfo['data'][0]['id'])) {
+ $articleIdShopware = $articleInfo['data'][0]['id'];
+ }
+
+ $quantity = $article['anzahl_lager'];
+ if (!empty($article['pseudolager'])) {
+ $quantity = $article['pseudolager'];
+ }
+ $inaktiv = $article['inaktiv'];
+ $active = true;
+ if (!empty($inaktiv)) {
+ $active = false;
+ }
+ $quantity = $this->getCorrectedStockFromAvailable($active, (int)$quantity, $articleInfo);
+ $taxRate = (float)$article['steuersatz'];
+
+ $taxId = $this->getTaxIdByRate($taxRate);
+
+ $mediaToAdd = $this->mediaToExport($article, $articleIdShopware);
+
+ $categoriesToAdd = [];
+ if($this->exportCategories){
+ $categoriesToAdd = $this->categoriesToExport($article, $articleIdShopware);
+ }
+
+ $propertiesToAdd = $this->propertiesToExport($article, $articleIdShopware);
+
+ $crosselingToAdd = $this->crosssellingToExport($article, $articleIdShopware);
+
+ $systemFieldsToAdd = $this->systemFieldsToExport($article, $articleIdShopware);
+
+ $deliveryTimeId = null;
+ if(!empty($article['lieferzeitmanuell'])){
+ $deliveryTimeId = $this->getDeliveryTimeId($article['lieferzeitmanuell']);
+ }
+
+ if (empty($systemFieldsToAdd['visibilities']) && !empty($this->shopwareDefaultSalesChannel)) {
+ $systemFieldsToAdd['visibilities'] = $this->modifySalesChannel(explode(',', $this->shopwareDefaultSalesChannel), $articleIdShopware);
+ }
+
+ if(empty($systemFieldsToAdd['unitId']) && !empty($article['einheit']) ){
+ $systemFieldsToAdd['unitId'] = $this->unitToAdd($article['einheit']);
+ }
+
+
+ //Hersteller in Shopware suchen bzw. Anlegen
+ $manufacturerName = $article['hersteller'];
+ $manufacturerId = $this->getManufacturerIdByName($manufacturerName);
+
+ if ($manufacturerId === null && $this->createManufacturerAllowed === true) {
+ $manufacturerId = $this->createManufacturer($manufacturerName);
+ }
+
+ if (empty($manufacturerId)) {
+ return 'error: Für den Artikelexport ist die Herstellerinformation zwingend erforderlich';
+ }
+
+ $isCloseOut = false;
+ if(!empty($article['restmenge'])){
+ $isCloseOut = true;
+ }
+
+ $description = $this->prepareDescription($article['uebersicht_de']);
+ $ean = $article['ean'];
+ $metaTitle = $article['metatitle_de'];
+ $metaDescription = $article['metadescription_de'];
+ $metaKeywords = $article['metakeywords_de'];
+
+ $manufacturerNumber = $article['herstellernummer'];
+ if (empty($manufacturerNumber)) {
+ $manufacturerNumber = '';
+ }
+
+ $weight = (float)$article['gewicht'];
+ $length = (float)$article['laenge'] * 10;
+ $height = (float)$article['hoehe'] * 10;
+ $width = (float)$article['breite'] * 10;
+
+ $purchasePrice = (float)$article['einkaufspreis'];
+
+ $currencyId = $this->findCurrencyId($article['waehrung']);
+ $price = [
+ 'net' => $article['preis'],
+ 'gross' => $article['bruttopreis'],
+ 'currencyId' => $currencyId,
+ 'linked' => true];
+
+ if (!empty($article['pseudopreis'])) {
+ $price['listPrice'] = [
+ 'currencyId' => $currencyId,
+ 'gross' => $article['pseudopreis'],
+ 'linked' => true,
+ 'net' => $article['pseudopreis']/(1+$taxRate/100)
+ ];
+ }
+
+ $data = [
+ 'name' => $article['name_de'],
+ 'isCloseout' => $isCloseOut,
+ 'productNumber' => $number,
+ 'manufacturerId' => $manufacturerId,
+ 'stock' => (int)$quantity,
+ 'taxId' => $taxId,
+ 'active' => $active,
+ 'description' => $description,
+ 'ean' => $ean,
+ 'metaTitle' => $metaTitle,
+ 'metaDescription' => $metaDescription,
+ 'keywords' => $metaKeywords,
+ 'manufacturerNumber' => $manufacturerNumber,
+ 'length' => $length,
+ 'width' => $width,
+ 'height' => $height,
+ 'weight' => $weight,
+ 'purchasePrice' => $purchasePrice,
+ 'price' => [$price],
+ 'categories' => $categoriesToAdd,
+ 'properties' => $propertiesToAdd,
+ 'crossSellings' => $crosselingToAdd,
+ 'media' => $mediaToAdd,
+ 'deliveryTimeId' => $deliveryTimeId
+ ];
+
+ $data = array_merge($data, $systemFieldsToAdd);
+ if(empty($data['customFields'])
+ || empty($data['customFields']['wawision_shopimporter_syncstate'])){
+ $data['customFields']['wawision_shopimporter_syncstate'] = 1;
+ }
+
+ if (empty($articleIdShopware)) {
+ $result = $this->shopwareRequest('POST',
+ 'product?_response=true', $data);
+ if (!empty($result['data']['id'])) {
+ $articleIdShopware = $result['data']['id'];
+ $articleInfo['data'][0] = $result['data'];
+ }
+ } else {
+ $headerInformation = [];
+ $languageId = $this->getLanguageIdByCountryIso('DE');
+ if (!empty($languageId)) {
+ $headerInformation[] = 'sw-language-id: ' . $languageId;
+ }
+ $result = $this->shopwareRequest('PATCH',
+ sprintf('product/%s?_response=true', $articleIdShopware), $data, $headerInformation);
+ }
+
+ if(!empty($articleIdShopware)){
+ $this->exportTranslationsForArticle($article, $articleIdShopware);
+ }
+
+ $this->addCoverImage($article, $articleIdShopware);
+
+ if (empty($result['data']) || is_array($result['errors'])) {
+ $this->Shopware6Log('Artikelexport fehlgeschlagen', ['data:' => $data, 'response' => $result]);
+ continue;
+ }
+
+ $this->exportSeoUrls($article, $articleIdShopware);
+
+ $this->exportVariants($article, $articleIdShopware, $currencyId);
+
+ if (empty($result['data']) || is_array($result['errors'])) {
+ $this->Shopware6Log('Artikelexport bei Bildübertragung fehlgeschlagen', ['data:' => $data, 'response' => $result]);
+ continue;
+ }
+
+ $defaultPrices = $this->getPricesFromArray($article['staffelpreise_standard'] ?? []);
+ $groupPrices = $this->getPricesFromArray($article['staffelpreise_gruppen'] ?? []);
+
+ if (!empty($defaultPrices) || !empty($groupPrices)) {
+ $this->deleteOldBulkPrices($articleIdShopware);
+ }
+ if (!empty($defaultPrices)) {
+ foreach ($defaultPrices as $priceData) {
+ $this->exportBulkPriceForGroup($articleIdShopware, $this->defaultRuleName, $priceData);
+ }
+ }
+ if (!empty($groupPrices)) {
+ foreach ($groupPrices as $priceData) {
+ $this->exportBulkPriceForGroup($articleIdShopware, $priceData->getGroupName(), $priceData);
+ }
+ }
+
+ $successCounter++;
+ }
+
+ return $successCounter;
+ }
+
+ protected function exportBulkPriceForGroup(string $productId, string $groupName, PriceData $priceData): void
+ {
+ $currencyId = $this->findCurrencyId($priceData->getCurrency());
+
+ $groupRuleId = $this->client->getGroupRuleId($groupName);
+ if (empty($groupRuleId)) {
+ $this->Shopware6Log("Fehler: Gruppe {$groupName} konnte im Shop nicht gefunden werden");
+ return;
+ }
+
+ $result = $this->client->saveBulkPrice($productId, $groupRuleId, $currencyId, $priceData);
+ if (empty($result['data'])) {
+ $this->Shopware6Log("Fehler: Staffelpreis für Gruppe {$groupName} konnte nicht exportiert werden", $result);
+ }
+ }
+
+ /**
+ * @param string $deliveryTimeText
+ *
+ * @return string|null
+ */
+ protected function getDeliveryTimeId(string $deliveryTimeText): ?string
+ {
+ $searchCommand = [
+ 'limit' => 5,
+ 'filter' => [
+ [
+ 'field' => 'name',
+ 'type' => 'equals',
+ 'value' => $deliveryTimeText
+ ]
+ ]
+ ];
+ $result = $this->shopwareRequest('POST', 'search/delivery-time', $searchCommand);
+
+ if (empty($result['data'][0]['id'])) {
+ return null;
+ }
+
+ return $result['data'][0]['id'];
+ }
+
+ /**
+ * @param string $description
+ * @return string
+ */
+ protected function prepareDescription($description): string
+ {
+ $markupSubstitute = [
+ '/"/' => '"',
+ '/<([^&]+)>/' => '<\1>',
+ '/\\/' => '',
+ '/\\<\/strong>/' => '',
+ '/\\/' => '',
+ '/\\<\/em>/' => '',
+ '/&/' => '&',
+ ];
+
+ return (string)preg_replace(array_keys($markupSubstitute), array_values($markupSubstitute), $description);
+ }
+
+ /**
+ * @param array $article
+ * @param string $articleIdShopware
+ */
+ protected function exportTranslationsForArticle(array $article, string $articleIdShopware): void
+ {
+ $customFieldsToAdd = $this->customFieldsToExport($article, $articleIdShopware);
+
+ $preparedTranslations = [];
+ $preparedTranslations['DE'] = [
+ 'name' => $article['name_de'],
+ 'description' => $this->prepareDescription($article['uebersicht_de']),
+ 'metaTitle' => $article['metatitle_de'],
+ 'metaDescription' => $article['metadescription_de'],
+ 'keywords' => $article['metakeywords_de'],
+ 'customFields' => []
+ ];
+ if(!empty($customFieldsToAdd['DE'])){
+ $preparedTranslations['DE']['customFields'] = $customFieldsToAdd['DE'];
+ }
+ $preparedTranslations['GB'] = [
+ 'name' => $article['name_en'],
+ 'description' => $this->prepareDescription($article['uebersicht_en']),
+ 'metaTitle' => $article['metatitle_en'],
+ 'metaDescription' => $article['metadescription_en'],
+ 'keywords' => $article['metakeywords_en'],
+ 'customFields' => [],
+ ];
+ if(!empty($customFieldsToAdd['GB'])){
+ $preparedTranslations['GB']['customFields'] = $customFieldsToAdd['GB'];
+ }
+ foreach ($article['texte'] as $translation) {
+ if ($translation['sprache'] === 'EN') {
+ $translation['sprache'] = 'GB';
+ }
+ $preparedTranslations[$translation['sprache']] = [
+ 'name' => $translation['name'],
+ 'description' => $this->prepareDescription($translation['beschreibung_online']),
+ 'metaTitle' => $translation['meta_title'],
+ 'metaDescription' => $translation['meta_description'],
+ 'keywords' => $translation['meta_keywords'],
+ ];
+ if(!empty($customFieldsToAdd[$translation['sprache']])){
+ $preparedTranslations[$translation['sprache']]['customFields'] = $customFieldsToAdd[$translation['sprache']];
+ }
+ }
+
+ foreach ($preparedTranslations as $countryIsoCode => $translation) {
+ $languageId = $this->getLanguageIdByCountryIso($countryIsoCode);
+ if (empty($languageId)) {
+ $this->Shopware6Log('Language Id not found for country: ' . $countryIsoCode);
+ continue;
+ }
+
+ $headerInformation = ['sw-language-id: ' . $languageId];
+ $this->shopwareRequest(
+ 'PATCH',
+ sprintf('product/%s', $articleIdShopware),
+ $translation, $headerInformation
+ );
+ }
+ }
+
+ /**
+ * @param string $countryIso
+ *
+ * @return string|null
+ */
+ protected function getLanguageIdByCountryIso(string $countryIso): ?string
+ {
+ if(array_key_exists($countryIso, $this->knownShopLanguageIds)){
+ return $this->knownShopLanguageIds[$countryIso];
+ }
+
+ $searchCommand = [
+ 'limit' => 5,
+ 'filter' => [
+ [
+ 'field' => 'country.iso',
+ 'type' => 'equals',
+ 'value' => $countryIso
+ ]
+ ]
+ ];
+ $countryInformation = $this->shopwareRequest('POST', 'search/country', $searchCommand);
+
+ foreach ($countryInformation['data'] as $country){
+ $searchCommand = [
+ 'limit' => 5,
+ 'filter' => [
+ [
+ 'field' => 'locale.territory',
+ 'type' => 'equals',
+ 'value' => $country['attributes']['name']
+ ]
+ ]
+ ];
+ $localeInformation = $this->shopwareRequest('POST', 'search/locale', $searchCommand);
+ foreach ($localeInformation['data'] as $locale) {
+ $searchCommand = [
+ 'limit' => 5,
+ 'filter' => [
+ [
+ 'field' => 'language.localeId',
+ 'type' => 'equals',
+ 'value' => $locale['id']
+ ]
+ ]
+ ];
+ $languageInformation = $this->shopwareRequest('POST', 'search/language', $searchCommand);
+ if (!empty($languageInformation['data'][0]['id'])) {
+ $this->knownShopLanguageIds[$countryIso] = $languageInformation['data'][0]['id'];
+ return $languageInformation['data'][0]['id'];
+ }
+ }
+ }
+ $this->knownShopLanguageIds[$countryIso] = null;
+
+ return null;
+ }
+
+ /**
+ * @param string $manufacturerName
+ *
+ * @return null|string
+ */
+ protected function createManufacturer(string $manufacturerName): ?string
+ {
+ $data = ['name' => $manufacturerName];
+ $response = $this->shopwareRequest('POST', 'product-manufacturer?_response=true', $data);
+
+ $manufacturerId = null;
+ if(!empty($response['data']['id'])){
+ $manufacturerId = $response['data']['id'];
+ $this->knownManufacturerIds[$manufacturerName] = $manufacturerId;
+ }
+
+ return $manufacturerId;
+ }
+
+ /**
+ * @param string $manufacturerName
+ *
+ * @return null|string
+ */
+ protected function getManufacturerIdByName(string $manufacturerName): ?string
+ {
+ if (!empty($this->knownManufacturerIds[$manufacturerName])) {
+ return $this->knownManufacturerIds[$manufacturerName];
+ }
+
+ $manufacturerId = null;
+ if (empty($manufacturerName)) {
+ $manufacturerName = $this->defaultManufacturer;
+ }
+ $manufacturer = $this->shopwareRequest(
+ 'GET',
+ 'product-manufacturer?filter[product_manufacturer.name]=' . urlencode($manufacturerName)
+ );
+ $manufacturerId = $manufacturer['data'][0]['id'];
+ $this->knownManufacturerIds[$manufacturerName] = $manufacturerId;
+
+ return $manufacturerId;
+ }
+
+ /**
+ * @param float $taxRate
+ *
+ * @return string
+ */
+ protected function getTaxIdByRate(float $taxRate): string{
+ if(empty($this->taxesInShop)){
+ $this->taxesInShop = $this->shopwareRequest('GET', 'tax');
+ }
+ foreach ($this->taxesInShop['data'] as $taxData) {
+ if (abs(($taxData['attributes']['taxRate']-$taxRate)) < 0.0001 ) {
+ return $taxData['id'];
+ }
+ }
+
+ return $this->taxesInShop['data'][0]['id'];
+ }
+
+ /**
+ * @param array $internalArticleData
+ * @param string $articleIdShopware
+ *
+ * @return array
+ */
+ protected function mediaToExport($internalArticleData, $articleIdShopware)
+ {
+ $mediaToAdd = [
+ ];
+
+ if (empty($internalArticleData['Dateien'])) {
+ return $mediaToAdd;
+ }
+ $internalMediaIds = [];
+
+ $searchdata = [
+ 'limit' => 1,
+ 'filter' => [
+ [
+ 'field' => 'name',
+ 'type' => 'equals',
+ 'value' => $this->shopwareMediaFolder
+ ]
+ ]
+ ];
+ $mediaFolderData = $this->shopwareRequest('POST', 'search/media-folder', $searchdata);
+ if(empty($mediaFolderData['data'][0]['id'])){
+ $this->Shopware6ErrorLog('Kein Media Folder gefunden für: ', $this->shopwareMediaFolder);
+ return [];
+ }
+
+ $mediaFolderId = $mediaFolderData['data'][0]['id'];
+
+ foreach ($internalArticleData['Dateien'] as $internalFile) {
+ $filename = explode('.', $internalFile['filename']);
+ unset($filename[(!empty($filename)?count($filename):0) - 1]);
+ $filename = $internalFile['id'].'_'.implode($filename);
+ $extension = $internalFile['extension'];
+ $imageTitle = (string)$internalFile['titel'];
+ $imageAltText = (string)$internalFile['beschreibung'];
+ $accessToken = $this->shopwareToken();
+
+ $searchdata = [
+ 'limit' => 5,
+ 'filter' => [
+ [
+ 'field' => 'media.fileName',
+ 'type' => 'equals',
+ 'value' => $filename
+ ]
+ ]
+ ];
+ $mediaData = $this->shopwareRequest('POST', 'search/media', $searchdata);
+ if (!empty($mediaData['data'][0]['id'])) {
+ $internalMediaIds[] = $mediaData['data'][0]['id'];
+ if($mediaData['data'][0]['attributes']['title'] !== $imageTitle
+ || $mediaData['data'][0]['attributes']['alt'] !== $imageAltText){
+ $this->setMediaTitleAndAltText($mediaData['data'][0]['id'], $imageTitle, $imageAltText);
+ }
+ continue;
+ }
+
+ $mediaData = $this->shopwareRequest('POST', 'media?_response=true', []);
+ if(empty($mediaData['data']['id'])){
+ $this->Shopware6Log('Error when creating media for sku: ' . $internalArticleData['nummer'],
+ ['mediaData' => $mediaData, 'title' => $imageTitle, 'text' => $imageAltText]);
+ continue;
+ }
+ $mediaId = $mediaData['data']['id'];
+ $this->setMediaTitleAndAltText($mediaId, $imageTitle, $imageAltText);
+
+ $mediaAssociationData = [
+ [
+ 'action' => 'upsert',
+ 'entity' => 'media',
+ 'payload' => [
+ [
+ 'id' => $mediaId,
+ 'mediaFolderId' => $mediaFolderId
+ ]
+ ]
+ ]
+ ];
+ $this->shopwareRequest('POST', '_action/sync?_response=true', $mediaAssociationData);
+
+ $url = $this->ShopUrl . 'v2/_action/media/' . $mediaId . '/upload?extension=' . $extension . '&fileName=' . $filename;
+ $ch = curl_init();
+ $setHeaders = [
+ 'Content-Type:image/' . $extension,
+ 'Authorization:Bearer ' . $accessToken['token']
+ ];
+ curl_setopt($ch, CURLOPT_URL, $url);
+ curl_setopt($ch, CURLOPT_POSTFIELDS, base64_decode($internalFile['datei']));
+ curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
+ curl_setopt($ch, CURLOPT_HTTPHEADER, $setHeaders);
+ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
+ curl_exec($ch);
+
+ $internalMediaIds[] = $mediaId;
+ }
+
+ $existingMediaConnection = [];
+ if (!empty($articleIdShopware)) {
+ $existingMediaConnection = $this->shopwareRequest('GET', 'product/' . $articleIdShopware . '/media?limit=100');
+ foreach ($existingMediaConnection['data'] as $existingConnection) {
+ if (!in_array($existingConnection['attributes']['mediaId'], $internalMediaIds, false)) {
+ $this->shopwareRequest('DELETE', 'product/' . $articleIdShopware . '/media/' . $existingConnection['id']);
+ }
+ }
+ }
+
+ $alreadyAddedMediaIDs = [];
+ if (!empty($existingMediaConnection)) {
+ foreach ($existingMediaConnection['data'] as $existingConnection) {
+ $alreadyAddedMediaIDs[$existingConnection['attributes']['mediaId']] = $existingConnection['id'];
+ }
+ }
+ $position = 0;
+ foreach ($internalMediaIds as $mediaId) {
+ $mediaDataSet = [
+ 'mediaId' => $mediaId,
+ 'position' => $position
+ ];
+ if (array_key_exists($mediaId, $alreadyAddedMediaIDs)) {
+ $mediaDataSet['id'] = $alreadyAddedMediaIDs[$mediaId];
+ }
+ $mediaToAdd[] = $mediaDataSet;
+ $position++;
+ }
+
+ return $mediaToAdd;
+ }
+
+ /**
+ * @param string $mediaId
+ * @param string $title
+ * @param string $altText
+ */
+ protected function setMediaTitleAndAltText(string $mediaId, string $title, string $altText): void
+ {
+ $this->shopwareRequest('PATCH', 'media/' . $mediaId,
+ ['title' => $title,
+ 'alt' => $altText
+ ]
+ );
+ }
+
+ /**
+ * @param array $articleInXentral
+ * @param string $articleIdShopware
+ */
+ protected function addCoverImage($articleInXentral, $articleIdShopware){
+ if(empty($articleIdShopware)){
+ return;
+ }
+ if(empty($articleInXentral['Dateien'])){
+ return;
+ }
+ $existingMediaConnection = $this->shopwareRequest('GET', 'product/' . $articleIdShopware . '/media?limit=100');
+ if(empty($existingMediaConnection['data'])){
+ return;
+ }
+ foreach ($articleInXentral['Dateien'] as $xentralFile) {
+ $filename = explode('.', $xentralFile['filename']);
+ unset($filename[(!empty($filename)?count($filename):0) - 1]);
+ $filename = $xentralFile['id'].'_'.implode($filename);
+
+ $searchdata = [
+ 'limit' => 5,
+ 'filter' => [
+ [
+ 'field' => 'media.fileName',
+ 'type' => 'equals',
+ 'value' => $filename
+ ]
+ ]
+ ];
+ $mediaData = $this->shopwareRequest('POST', 'search/media', $searchdata);
+ $mediaId = $mediaData['data'][0]['id'];
+
+ foreach ($existingMediaConnection['data'] as $mediaConnection){
+ if($mediaId === $mediaConnection['attributes']['mediaId']){
+
+ $this->shopwareRequest('PATCH',
+ sprintf('product/%s?_response=true', $articleIdShopware),['coverId' => $mediaConnection['id']]);
+ return;
+ }
+ }
+ }
+ }
+
+ /**
+ * @param array $articleInXentral
+ * @param string $articleIdShopware
+ * @return array
+ */
+ protected function categoriesToExport($articleInXentral, $articleIdShopware)
+ {
+ $categoryName = $articleInXentral['kategoriename'];
+ $categoryTree = $articleInXentral['kategorien'];
+
+ $categoriesToAdd = [];
+ if (empty($categoryName) && empty($categoryTree)) {
+ return $categoriesToAdd;
+ }
+
+ $categoriesInXentral = [];
+ if (!empty($categoryTree)) {
+ $rootcategory = null;
+ $categoryTreeid = [];
+ foreach ($categoryTree as $categoryData) {
+ $categoryData['shopwareparent'] = 0;
+ if (!$categoryData['parent']) {
+ $categoryData['shopwareid'] = $rootcategory;
+ }
+ $categoryTreeid[$categoryData['id']] = $categoryData;
+ }
+
+ foreach ($categoryTree as $categoryData) {
+ $parentid = $rootcategory;
+ if (!empty($categoryData['parent'])) {
+ $parentid = $this->getCategoryParentId($categoryData, $categoryTreeid);
+ }
+
+ $searchdata = [
+ 'limit' => 25,
+ 'filter' => [
+ [
+ 'field' => 'category.name',
+ 'type' => 'equals',
+ 'value' => $categoryData['name']
+ ]
+ ]
+ ];
+ if (!empty($parentid)) {
+ $searchdata['filter'][] = [
+ 'field' => 'category.parentId',
+ 'type' => 'equals',
+ 'value' => $parentid
+ ];
+ }
+ $result = $this->shopwareRequest('POST', 'search/category', $searchdata);
+
+
+ if (!empty($result['data'][0]['id'])) {
+ $categoryTreeid[$categoryData['id']]['shopwareid'] = $result['data'][0]['id'];
+ $categoriesInXentral[] = $result['data'][0]['id'];
+ }
+ }
+ } else if (!empty($categoryName)) {
+ $searchdata = [
+ 'limit' => 25,
+ 'filter' => [
+ [
+ 'field' => 'category.name',
+ 'type' => 'equals',
+ 'value' => $categoryName
+ ]
+ ]
+ ];
+
+ $result = $this->shopwareRequest('POST', 'search/category', $searchdata);
+
+ if (!empty($result['data'][0]['id'])) {
+ $categoriesInXentral[] = $result['data'][0]['id'];
+ }
+ }
+
+ if (!empty($articleIdShopware)) {
+ $existingCategories = $this->shopwareRequest('GET', 'product/' . $articleIdShopware . '/categories?limit=50');
+ foreach ($existingCategories['data'] as $existingCategory) {
+ if (!in_array($existingCategory['id'], $categoriesInXentral, false)) {
+ $this->shopwareRequest('DELETE', 'product/' . $articleIdShopware . '/categories/' . $existingCategory['id']);
+ }
+ }
+ }
+ foreach ($categoriesInXentral as $categoryId) {
+ $categoriesToAdd[] = ['id' => $categoryId];
+ }
+
+
+ return $categoriesToAdd;
+ }
+
+ /**
+ * @param $categoryData
+ * @param $categoryTreeId
+ * @return string|null
+ */
+ protected function getCategoryParentId($categoryData, &$categoryTreeId)
+ {
+ $parentId = $categoryTreeId[$categoryData['parent']]['shopwareid'];
+ if (!empty($parentId)) {
+ return $parentId;
+ }
+
+ $parentCategoryData = $this->app->DB->SelectRow("SELECT id,parent,bezeichnung AS name FROM artikelkategorien WHERE id<>'' AND id<>'0' AND id='" . $categoryData['parent'] . "' LIMIT 1");
+ if (empty($parentCategoryData)) {
+ return null;
+ }
+
+ $searchData = [
+ 'limit' => 25,
+ 'filter' => [
+ [
+ 'field' => 'category.name',
+ 'type' => 'equals',
+ 'value' => $parentCategoryData['name']
+ ]
+ ]
+ ];
+ $result = $this->shopwareRequest('POST', 'search/category', $searchData);
+
+ if (count($result['data']) < 1) {
+ return null;
+ }
+
+ if (count($result['data']) === 1) {
+ $parentCategoryData['shopwareid'] = $result['data'][0]['id'];
+ $categoryTreeId[$parentCategoryData['id']] = $parentCategoryData;
+ return $result['data'][0]['id'];
+ }
+
+ $grandparentId = $this->getCategoryParentId($parentCategoryData, $categoryTreeId);
+
+ $searchData = [
+ 'limit' => 25,
+ 'filter' => [
+ [
+ 'field' => 'category.name',
+ 'type' => 'equals',
+ 'value' => $parentCategoryData['name']
+ ],
+ [
+ 'field' => 'category.parentId',
+ 'type' => 'equals',
+ 'value' => $grandparentId
+ ]
+ ]
+ ];
+ $result = $this->shopwareRequest('POST', 'search/category', $searchData);
+
+
+ if (count($result['data']) === 1) {
+ $parentCategoryData['shopwareid'] = $result['data'][0]['id'];
+ $categoryTreeId[$parentCategoryData['id']] = $parentCategoryData;
+ return $result['data'][0]['id'];
+ }
+ return null;
+ }
+
+ /**
+ * @param string $propertyName
+ *
+ * @return string|null
+ */
+ protected function getPropertyGroupId($propertyName): ?string
+ {
+ if(array_key_exists($propertyName, $this->knownPropertyGroupIds)){
+ return $this->knownPropertyGroupIds[$propertyName];
+ }
+
+ $searchData = [
+ 'limit' => 25,
+ 'filter' => [
+ [
+ 'field' => 'property_group.name',
+ 'type' => 'equals',
+ 'value' => $propertyName
+ ]
+ ]
+ ];
+
+ $germanLanguageId = $this->getLanguageIdByCountryIso('DE');
+ $headerInformation = ['sw-language-id: ' . $germanLanguageId];
+ $propertyData = $this->shopwareRequest(
+ 'POST',
+ 'search/property-group',
+ $searchData,
+ $headerInformation);
+ if (empty($propertyData['data'][0]['id'])) {
+ return null;
+ }
+
+ $this->knownPropertyGroupIds[$propertyName] = $propertyData['data'][0]['id'];
+
+ return $propertyData['data'][0]['id'];
+ }
+
+ /**
+ * @param string $propertyName
+ * @return null|string
+ */
+ protected function createPropertyGroup($propertyName): ?string
+ {
+ $propertyGroupData = [
+ 'displayType' => 'text',
+ 'name' => $propertyName,
+ 'sortingType' => 'alphanumeric'
+ ];
+ $propertyGroup = $this->shopwareRequest(
+ 'POST',
+ 'property-group?_response=true',
+ $propertyGroupData);
+
+ $this->knownPropertyGroupIds[$propertyName] = $propertyGroup['data']['id'];
+
+ if (empty($propertyGroup['data']['id'])) {
+ return null;
+ }
+
+ return $propertyGroup['data']['id'];
+ }
+
+ /**
+ * @param string $propertyGroupId
+ * @param string $propertyName
+ * @param string $countryIsoCode
+ */
+ protected function createTranslationForPropertyGroup($propertyGroupId, $propertyName, $countryIsoCode): void
+ {
+ $languageId = $this->getLanguageIdByCountryIso($countryIsoCode);
+ if (empty($languageId)) {
+ return;
+ }
+
+ $headerInformation = ['sw-language-id: ' . $languageId];
+
+ $translation = [
+ 'name' => $propertyName,
+ ];
+
+ $this->shopwareRequest(
+ 'PATCH',
+ sprintf('property-group/%s', $propertyGroupId),
+ $translation,
+ $headerInformation);
+ }
+
+ /**
+ * @param string $propertyGroupId
+ * @param string $propertyOptionName
+ * @param string $countryIsoCode
+ * @return mixed|null
+ */
+ protected function getPropertyOptionId($propertyGroupId, $propertyOptionName, $countryIsoCode = 'DE'): ?string
+ {
+ $searchData = [
+ 'limit' => 25,
+ 'filter' => [
+ [
+ 'field' => 'property_group_option.name',
+ 'type' => 'equals',
+ 'value' => $propertyOptionName
+ ]
+ ]
+ ];
+ $languageId = $this->getLanguageIdByCountryIso($countryIsoCode);
+ $headerInformation = ['sw-language-id: ' . $languageId];
+ $optionData = $this->shopwareRequest(
+ 'POST',
+ 'search/property-group/' . $propertyGroupId . '/options',
+ $searchData,
+ $headerInformation);
+
+ if (empty($optionData['data'][0]['id'])) {
+ return null;
+ }
+
+ return $optionData['data'][0]['id'];
+ }
+
+ /**
+ * @param string $propertyGroupId
+ * @param string $propertyOptionName
+ * @return null|string
+ */
+ protected function createPropertyOption($propertyGroupId, $propertyOptionName): ?string
+ {
+ $propertyOptionData = [
+ 'id' => '',
+ 'name' => $propertyOptionName
+ ];
+ $createdPropertyOption = $this->shopwareRequest(
+ 'POST',
+ 'property-group/' . $propertyGroupId . '/options?_response=true',
+ $propertyOptionData);
+
+ if (empty($createdPropertyOption['data']['id'])) {
+ return null;
+ }
+
+ return $createdPropertyOption['data']['id'];
+ }
+
+ /**
+ * @param string $optionId
+ * @param string $optionName
+ * @param string $countryIsoCode
+ */
+ protected function createTranslationForPropertyOption($optionId, $optionName, $countryIsoCode): void
+ {
+ $languageId = $this->getLanguageIdByCountryIso($countryIsoCode);
+ if (empty($languageId)) {
+ return;
+ }
+ $headerInformation = ['sw-language-id: ' . $languageId];
+ $translation = [
+ 'name' => $optionName,
+ ];
+
+ $this->shopwareRequest(
+ 'PATCH',
+ sprintf('property-group-option/%s', $optionId),
+ $translation,
+ $headerInformation);
+ }
+
+ /**
+ * @param array $internalArticle
+ * @param string $articleIdShopware
+ * @return array
+ */
+ protected function propertiesToExport($internalArticle, $articleIdShopware): array
+ {
+ $propertiesToAdd = $this->getPropertiesFromArticle($internalArticle);
+ if (empty($propertiesToAdd)) {
+ return [];
+ }
+ $assignedProperties = [];
+
+ foreach ($propertiesToAdd as $propertyDefaultName => $countryIsoToPropertyTranslation) {
+ if (empty($countryIsoToPropertyTranslation['DE'])) {
+ continue;
+ }
+ $propertyGroupId = '';
+ if (array_key_exists($propertyDefaultName, $this->knownPropertyGroupIds)) {
+ $propertyGroupId = $this->knownPropertyGroupIds[$propertyDefaultName];
+ }
+ if (empty($propertyGroupId)) {
+ $propertyGroupId = $this->getPropertyGroupId($propertyDefaultName);
+ }
+ if (empty($propertyGroupId)) {
+ $propertyGroupId = $this->createPropertyGroup($propertyDefaultName);
+ }
+ if (empty($propertyGroupId)) {
+ $this->Shopware6Log('PropertyGroup kann nicht erstellt werden: ' . $propertyDefaultName);
+ continue;
+ }
+
+ foreach ($countryIsoToPropertyTranslation as $countryIsoCode => $translation) {
+ $this->createTranslationForPropertyGroup($propertyGroupId, $translation['name'], $countryIsoCode);
+ }
+
+
+ $optionId = $this->getPropertyOptionId($propertyGroupId, $countryIsoToPropertyTranslation['DE']['value'], 'DE');
+ if (empty($optionId)) {
+ $optionId = $this->createPropertyOption($propertyGroupId, $countryIsoToPropertyTranslation['DE']['value']);
+ }
+ if (empty($optionId)) {
+ $this->Shopware6Log('Option kann nicht erstellt werden: ' . $countryIsoToPropertyTranslation['DE']['value']);
+ continue;
+ }
+
+ $assignedProperties[] = $optionId;
+
+ foreach ($countryIsoToPropertyTranslation as $countryIsoCode => $translation) {
+ $this->createTranslationForPropertyOption($optionId, $translation['value'], $countryIsoCode);
+ }
+ }
+
+ if (!empty($articleIdShopware)) {
+ $existingProperties = $this->shopwareRequest('GET', 'product/' . $articleIdShopware . '/properties?limit=100');
+ foreach ($existingProperties['data'] as $existingProperty) {
+ if (!in_array($existingProperty['id'], $assignedProperties, false)) {
+ $this->shopwareRequest('DELETE', 'product/' . $articleIdShopware . '/properties/' . $existingProperty['id']);
+ }
+ }
+ }
+
+ $propertiesToAdd = [];
+ foreach ($assignedProperties as $propertyOptionId) {
+ $propertiesToAdd[] = ['id' => $propertyOptionId];
+ }
+
+ return $propertiesToAdd;
+ }
+
+ /**
+ * @param string $name
+ * @param string $value
+ * @return bool
+ */
+ protected function propertyMustBeIgnored(string $name, string $value): bool
+ {
+ return empty($value) ||
+ strpos($name, 'customField_') === 0 ||
+ stripos($name, 'shopware6_') !== false;
+ }
+
+ /**
+ * @param array $internalArticleData
+ * @return array
+ */
+ protected function getPropertiesFromArticle($internalArticleData): array
+ {
+ //'Farbe' => [['DE' => ['name' => 'Farbe, 'value' => 'Gelb']],
+ // ['EN' => ['name' => 'Colour, 'value' => 'Yellow']]]
+ $propertiesToAdd = [];
+ if (!empty($internalArticleData['eigenschaften'])) {
+ foreach ($internalArticleData['eigenschaften'] as $property) {
+ if ($this->propertyMustBeIgnored($property['name'], $property['values'])) {
+ continue;
+ }
+ if (strpos($property['name'], 'property_') === 0) {
+ $propertyName = substr($property['name'], 9);
+ $propertiesToAdd[$propertyName]['DE'] = [
+ 'name' => $propertyName,
+ 'value' => $property['values']];
+ continue;
+ }
+ if ($this->propertyOption === 'toProperties') {
+ $propertiesToAdd[$property['name']]['DE'] = [
+ 'name' => $property['name'],
+ 'value' => $property['values']];
+ }
+ }
+ }
+
+ if (!empty($internalArticleData['eigenschaftenuebersetzungen'])) {
+ foreach ($internalArticleData['eigenschaftenuebersetzungen'] as $translatedProperty) {
+ if ($translatedProperty['language_to'] === 'EN') {
+ $translatedProperty['language_to'] = 'GB';
+ }
+ if ($this->propertyMustBeIgnored($translatedProperty['property_to'], $translatedProperty['property_value_to'])) {
+ continue;
+ }
+ if (strpos($translatedProperty['property_to'], 'property_') === 0) {
+ $propertiesToAdd[$translatedProperty['property_from']][$translatedProperty['language_to']] = [
+ 'name' => substr($translatedProperty['property_to'], 9),
+ 'value' => $translatedProperty['property_value_to']];
+ continue;
+ }
+ if ($this->propertyOption === 'toProperties') {
+ $propertiesToAdd[$translatedProperty['property_from']][$translatedProperty['language_to']] = [
+ 'name' => $translatedProperty['property_to'],
+ 'value' => $translatedProperty['property_value_to']];
+ }
+ }
+ }
+
+ if (!empty($internalArticleData['freifelder'])) {
+ foreach ($internalArticleData['freifelder']['DE'] as $freeFieldKey => $freeFieldValue) {
+ if ($this->propertyMustBeIgnored($freeFieldKey, $freeFieldValue)) {
+ continue;
+ }
+ if (strpos($freeFieldKey, 'property_') === 0) {
+ $propertyName = substr($freeFieldKey, 9);
+ $propertiesToAdd[$propertyName]['DE'] = [
+ 'name' => $propertyName,
+ 'value' => $freeFieldValue
+ ];
+ continue;
+ }
+ if ($this->freeFieldOption === 'toProperties') {
+ $propertiesToAdd[$freeFieldKey]['DE'] = [
+ 'name' => $freeFieldKey,
+ 'value' => $freeFieldValue
+ ];
+ }
+ }
+
+ foreach ($internalArticleData['freifelder'] as $languageIso => $freeFields) {
+ if ($languageIso === 'DE') {
+ continue;
+ }
+ if ($languageIso === 'EN') {
+ $languageIso = 'GB';
+ }
+ foreach ($freeFields as $freeFieldData) {
+ if ($this->propertyMustBeIgnored($freeFieldData['mapping'], $freeFieldData['wert'])) {
+ continue;
+ }
+ if (strpos($freeFieldData['mapping'], 'property_') === 0) {
+ $propertyName = substr($freeFieldData['mapping'], 9);
+ $propertiesToAdd[$propertyName][$languageIso] = [
+ 'name' => $propertyName,
+ 'value' => $freeFieldData['wert']
+ ];
+ continue;
+ }
+ if ($this->freeFieldOption === 'toProperties') {
+ $propertiesToAdd[$freeFieldData['mapping']][$languageIso] = [
+ 'name' => $freeFieldData['mapping'],
+ 'value' => $freeFieldData['wert']
+ ];
+ }
+ }
+ }
+ }
+
+ return $propertiesToAdd;
+ }
+
+ /**
+ * @param array $articleInXentral
+ * @param string $articleIdShopware
+ *
+ * @return array
+ */
+ protected function customFieldsToExport($articleInXentral, $articleIdShopware): array
+ {
+ $customFieldsToAdd = $this->getCustomFieldsFromArticle($articleInXentral);
+ if (empty($customFieldsToAdd)) {
+ return [];
+ }
+ $languageId = $this->getLanguageIdByCountryIso('DE');
+ $headerInformation = ['sw-language-id: ' . $languageId];
+
+ $customFields = [];
+ if (!empty($articleIdShopware)) {
+ $articleInfo = $this->shopwareRequest(
+ 'GET', 'product/' . $articleIdShopware,
+ [],
+ $headerInformation);
+ $customFields['DE'] = $articleInfo['data'][0]['attributes']['customFields'];
+ if ($customFields === null) {
+ $customFields = [];
+ }
+ }
+
+ foreach ($customFieldsToAdd as $defaultFieldName => $countryIsoCodeToCustomFieldData) {
+ $customFieldDefinition = $this->shopwareRequest(
+ 'GET',
+ sprintf('custom-field?filter[custom_field.name]=%s', $defaultFieldName),
+ [],
+ $headerInformation
+ );
+ if (empty($customFieldDefinition)) {
+ $this->Shopware6Log('Freifeld entspricht keinem shopware Freifeld', $defaultFieldName);
+ continue;
+ }
+
+ foreach ($countryIsoCodeToCustomFieldData as $countryIsoCode => $customFieldData) {
+ $name = $customFieldData['name'];
+ $value = $customFieldData['value'];
+ if ($value === '') {
+ continue;
+ }
+ if($countryIsoCode === 'EN'){
+ $countryIsoCode = 'GB';
+ }
+ $fieldType = $customFieldDefinition['data'][0]['attributes']['type'];
+ $controlType = $customFieldDefinition['data'][0]['attributes']['config']['componentName'];
+
+ switch ($fieldType) {
+ case 'text':
+ case 'html':
+ if ($controlType === 'sw-media-field') {
+ $this->Shopware6Log(
+ 'Warnung: Freifelder vom Type "medium" werden nicht unterstützt.'
+ );
+ } else {
+ $customFields[$countryIsoCode][$name] = (string)$value;
+ }
+ break;
+ case 'bool':
+ $customFields[$countryIsoCode][$name] = filter_var($value, FILTER_VALIDATE_BOOLEAN);
+ break;
+ case 'int':
+ $customFields[$countryIsoCode][$name] = (int)$value;
+ break;
+ case 'float':
+ $customFields[$countryIsoCode][$name] = (float)$value;
+ break;
+ case 'select':
+ $options = $customFieldDefinition['data'][0]['attributes']['config']['options'];
+ $allowedValues = [];
+ foreach ($options as $option) {
+ $allowedValues[] = $option['value'];
+ }
+ if ($controlType === 'sw-single-select') {
+ if (in_array($value, $allowedValues, true)) {
+ $customFields[$countryIsoCode][$name] = $value;
+ } else {
+ $this->Shopware6Log(
+ sprintf('Warnung: Freifeld "%s"="%s"; ungültiger Wert', $name, $value),
+ ['allowed values' => $allowedValues]
+ );
+ }
+ }
+ if ($controlType === 'sw-multi-select') {
+ $value = explode(',', $value);
+ foreach ($value as &$item) {
+ $item = trim($item);
+ }
+ unset($item);
+ if (array_intersect($value, $allowedValues) === $value) {
+ $customFields[$countryIsoCode][$name] = $value;
+ } else {
+ $this->Shopware6Log(
+ sprintf('Warnung: Freifeld "%s"; ungültiger Wert', $name),
+ ['values' => $value, 'allowed values' => $allowedValues]
+ );
+ }
+ }
+ break;
+ default:
+ $this->Shopware6Log(
+ 'Warnung: Freifeld enthält falschen Typ.',
+ ['freifeld' => $name, 'wert' => $value]
+ );
+ continue 2;
+ }
+ }
+ }
+
+
+ return $customFields;
+ }
+
+ /**
+ * @param string $name
+ * @param string $value
+ * @return bool
+ */
+ protected function customFieldMustBeIgnored(string $name, string $value): bool
+ {
+ return empty($value) ||
+ strpos($name, 'property_') === 0 ||
+ stripos($name, 'shopware6_') !== false;
+ }
+
+ /**
+ * @param array $articleInXentral
+ * @return array
+ */
+ protected function getCustomFieldsFromArticle($articleInXentral): array
+ {
+ $customFieldsToAdd = [];
+ if (!empty($articleInXentral['eigenschaften'])) {
+ foreach ($articleInXentral['eigenschaften'] as $propertyInXentral) {
+ if ($this->customFieldMustBeIgnored($propertyInXentral['name'], $propertyInXentral['values'])) {
+ continue;
+ }
+ if (strpos($propertyInXentral['name'], 'customField_') === 0) {
+ $customFieldName = substr($propertyInXentral['name'], 12);
+ $customFieldsToAdd[$customFieldName]['DE'] = [
+ 'name' => $customFieldName,
+ 'value' => $propertyInXentral['values']
+ ];
+ continue;
+ }
+ if ($this->propertyOption === 'toCustomFields') {
+ $customFieldsToAdd[$propertyInXentral['name']]['DE'] = [
+ 'name' => $propertyInXentral['name'],
+ 'value' => $propertyInXentral['values']
+ ];
+ }
+ }
+ }
+ if (!empty($articleInXentral['eigenschaftenuebersetzungen'])) {
+ foreach ($articleInXentral['eigenschaftenuebersetzungen'] as $translatedProperty) {
+ if ($this->customFieldMustBeIgnored($translatedProperty['property_to'], $translatedProperty['property_value_to'])) {
+ continue;
+ }
+ if (strpos($translatedProperty['property_to'], 'customField_') === 0) {
+ $customFieldName = substr($translatedProperty['property_to'], 12);
+ $customFieldsToAdd[$customFieldName][$translatedProperty['language_to']] = [
+ 'name' => $customFieldName,
+ 'value' => $translatedProperty['property_value_to']
+ ];
+ continue;
+ }
+ if ($this->propertyOption === 'toCustomFields') {
+ $customFieldsToAdd[$translatedProperty['property_to']][$translatedProperty['language_to']] = [
+ 'name' => $translatedProperty['property_to'],
+ 'value' => $translatedProperty['property_value_to']
+ ];
+ }
+ }
+ }
+
+ if (!empty($articleInXentral['freifelder'])) {
+ foreach ($articleInXentral['freifelder']['DE'] as $freeFieldKey => $freeFieldValue) {
+ if ($this->customFieldMustBeIgnored($freeFieldKey, $freeFieldValue)) {
+ continue;
+ }
+ if (strpos($freeFieldKey, 'customField_') === 0) {
+ $customFieldName = substr($freeFieldKey, 12);
+ $customFieldsToAdd[$customFieldName]['DE'] = [
+ 'name' => $customFieldName,
+ 'value' => $freeFieldValue
+ ];
+ continue;
+ }
+ if ($this->freeFieldOption === 'toCustomFields') {
+ $customFieldsToAdd[$freeFieldKey]['DE'] = [
+ 'name' => $freeFieldKey,
+ 'value' => $freeFieldValue
+ ];
+ }
+ }
+
+ foreach ($articleInXentral['freifelder'] as $countryIsoCode => $freeFieldTranslations) {
+ if ($countryIsoCode === 'DE') {
+ continue;
+ }
+ foreach ($freeFieldTranslations as $freeFieldTranslation){
+ if ($this->customFieldMustBeIgnored($freeFieldTranslation['mapping'], $freeFieldTranslation['wert'])) {
+ continue;
+ }
+ if ($countryIsoCode === 'EN') {
+ $countryIsoCode = 'GB';
+ }
+ if (strpos($freeFieldTranslation['mapping'], 'customField_') === 0) {
+ $customFieldName = substr($freeFieldTranslation['mapping'], 12);
+ $customFieldsToAdd[$customFieldName][$countryIsoCode] = [
+ 'name' => $customFieldName,
+ 'value' => $freeFieldTranslation['wert']
+ ];
+ continue;
+ }
+ if ($this->freeFieldOption === 'toCustomFields') {
+ $customFieldsToAdd[$freeFieldTranslation['mapping']][$countryIsoCode] = [
+ 'name' => $freeFieldTranslation['mapping'],
+ 'value' => $freeFieldTranslation['wert']
+ ];
+ }
+ }
+ }
+ }
+
+ return $customFieldsToAdd;
+ }
+
+ /**
+ * @param array $articleInXentral
+ * @param int $articleIdShopware
+ *
+ * @return array
+ */
+ protected function crosssellingToExport($articleInXentral, $articleIdShopware){
+ if (empty($articleInXentral['crosssellingartikel'])) {
+ return [];
+ }
+
+ $crosssellingArticles = [];
+ foreach ($articleInXentral['crosssellingartikel'] as $crosssellingArticle){
+ $type = 'Ähnlich';
+ if($crosssellingArticle['art'] == 2){
+ $type = 'Zubehör';
+ }
+ $crosssellingArticles[$type][] = $crosssellingArticle['nummer'];
+ }
+ $crossselingInformation = [];
+ foreach ($crosssellingArticles as $type => $articles){
+ if(!empty($articleIdShopware)){
+ $existingCrossSellings = $this->shopwareRequest('GET', sprintf('product/%s/cross-sellings/',
+ $articleIdShopware));
+ if(!empty($existingCrossSellings['data'])){
+ foreach ($existingCrossSellings['data'] as $existingCrossSelling){
+ if($existingCrossSelling['attributes']['name'] === $type){
+ $this->shopwareRequest('DELETE', sprintf('product/%s/cross-sellings/%s/',
+ $articleIdShopware, $existingCrossSelling['id']));
+ }
+ }
+ }
+ }
+
+ $crosselingToAdd = [];
+ foreach ($articles as $articleNumber) {
+ $articleInfo = $this->shopwareRequest(
+ 'GET',
+ sprintf('product?filter[product.productNumber]=%s', $articleNumber)
+ );
+
+ if(empty($articleInfo['data'][0]['id'])){
+ continue;
+ }
+ $crosselingToAdd[] = $articleInfo['data'][0]['id'];
+ }
+ if(empty($crosselingToAdd)){
+ continue;
+ }
+ $crossselingInformationForType = [
+ 'active' => true,
+ 'name' => $type,
+ 'assignedProducts' => [],
+ 'type' => 'productList',
+ 'sortBy' => 'name',
+ 'limit' => 24,
+ 'position' => 1
+ ];
+ $position = 1;
+ foreach ($crosselingToAdd as $articleId){
+ $crossselingInformationForType['assignedProducts'][] = [
+ 'productId' => $articleId,
+ 'position' => $position,
+ ];
+ $position++;
+ }
+ $crossselingInformation[] = $crossselingInformationForType;
+ }
+
+
+ return $crossselingInformation;
+ }
+
+ /**
+ * @param string $unitShortCode
+ *
+ * @return string
+ */
+ protected function unitToAdd(string $unitShortCode): string{
+ $searchData = [
+ 'limit' => 25,
+ 'source' => [
+ 'id'
+ ],
+ 'filter' => [
+ [
+ 'field' => 'unit.shortCode',
+ 'type' => 'equals',
+ 'value' => $unitShortCode
+ ]
+ ]
+ ];
+ $unitInShopware = $this->shopwareRequest(
+ 'POST',
+ 'search/unit',
+ $searchData);
+
+ if(!empty($unitInShopware['data'][0]['id'])){
+ return $unitInShopware['data'][0]['id'];
+ }
+
+ $query = sprintf("SELECT `internebemerkung` FROM `artikeleinheit` WHERE `einheit_de` = '%s' LIMIT 1",
+ $unitShortCode);
+ $unitName = $this->app->DB->Select($query);
+ if(empty($unitName)){
+ $unitName = $unitShortCode;
+ }
+
+ $unitInformation = [
+ 'name' => $unitName,
+ 'shortCode' => $unitShortCode
+ ];
+ $result = $this->shopwareRequest('POST', 'unit?_response=true', $unitInformation);
+
+ if(empty($result['data']['id'])){
+ return '';
+ }
+
+ return $result['data']['id'];
+ }
+
+ /**
+ * @param array $internArticle
+ * @param int $articleIdShopware
+ *
+ * @return array
+ */
+ protected function systemFieldsToExport($internArticle, $articleIdShopware): array
+ {
+ $internalSpecialFields = [];
+ foreach ($internArticle['freifelder']['DE'] as $freeFieldName => $freeFieldValue) {
+ if (stripos($freeFieldName, 'shopware6_') !== false) {
+ $internalSpecialFields[$freeFieldName] = $freeFieldValue;
+ }
+ }
+ foreach ($internArticle['eigenschaften'] as $property) {
+ if (stripos($property['name'], 'shopware6_') !== false) {
+ $internalSpecialFields[$property['name']] = $property['values'];
+ }
+ }
+
+ $systemFields = [];
+ foreach ($internalSpecialFields as $fieldName => $fieldValue) {
+ switch (strtolower($fieldName)) {
+ case 'shopware6_sales_channel':
+ $systemFields['visibilities'] = $this->modifySalesChannel(explode(',', $fieldValue), $articleIdShopware);
+ break;
+ case 'shopware6_purchase_unit':
+ $systemFields['purchaseUnit'] = (float)str_replace(',', '.', $fieldValue);
+ break;
+ case 'shopware6_reference_unit':
+ $systemFields['referenceUnit'] = (float)str_replace(',', '.', $fieldValue);
+ break;
+ case 'shopware6_unit':
+ $systemFields['unitId'] = $this->unitToAdd($fieldValue);
+ break;
+ case 'shopware6_pack_unit':
+ $systemFields['packUnit'] = (string)$fieldValue;
+ break;
+ case 'shopware6_restock_time':
+ $systemFields['restockTime'] = (int)$fieldValue;
+ break;
+ case 'shopware6_pack_unit_plural':
+ $systemFields['packUnitPlural'] = (string)$fieldValue;
+ break;
+ }
+ }
+
+ return $systemFields;
+ }
+
+ /**
+ * @param array $salesChannelNames
+ * @param string $articleIdInShopware
+ *
+ * @return array
+ */
+ protected function modifySalesChannel($salesChannelNames, $articleIdInShopware)
+ {
+ $salesChannelInXentralIds = [];
+ foreach ($salesChannelNames as $salesChannelName) {
+ $salesChannelInfo = $this->shopwareRequest('GET',
+ sprintf('sales-channel?filter[sales_channel.name]=%s', urlencode(trim($salesChannelName)))
+ );
+ if (!empty($salesChannelInfo['data'][0]['id'])) {
+ $salesChannelInXentralIds[] = $salesChannelInfo['data'][0]['id'];
+ }
+ }
+
+ $existingVisibilities = $this->shopwareRequest(
+ 'GET',
+ sprintf('product/%s/visibilities', $articleIdInShopware)
+ );
+
+ $existingSalesChannelIds = [];
+ if (!empty($existingVisibilities['data'])) {
+ foreach ($existingVisibilities['data'] as $visibility) {
+ $existingSalesChannelIds[$visibility['id']] = $visibility['attributes']['salesChannelId'];
+ }
+ }
+
+ foreach ($existingSalesChannelIds as $associationId => $existingSalesChannelId){
+ if (!in_array($existingSalesChannelId, $salesChannelInXentralIds,true)) {
+ $this->shopwareRequest('DELETE', sprintf('product/%s/visibilities/%s/',
+ $articleIdInShopware, $associationId));
+ }
+ }
+
+ $salesChannelsToAdd = [];
+ foreach ($salesChannelInXentralIds as $salesChannelInXentralId){
+ if (!in_array($salesChannelInXentralId, $existingSalesChannelIds,true)) {
+ $salesChannelsToAdd[] = $salesChannelInXentralId;
+ }
+ }
+
+ $visibilities = [];
+ foreach ($salesChannelsToAdd as $salesChannelIdToAdd) {
+ $visibilities[] = [
+ 'salesChannelId' => $salesChannelIdToAdd,
+ 'visibility' => 30
+ ];
+ }
+
+ return $visibilities;
+ }
+
+ /**
+ * @param string $isoCode
+ *
+ * @return string
+ */
+ protected function findCurrencyId($isoCode)
+ {
+
+ $this->requestCurrencyMappingLazy();
+ if (isset($this->currencyMapping[strtoupper($isoCode)])) {
+ return $this->currencyMapping[strtoupper($isoCode)];
+ }
+ $this->Shopware6Log(
+ sprintf('Warnung: Kein Mapping für Waehrung "%s" gefunden.', $isoCode),
+ $this->currencyMapping
+ );
+
+ return null;
+ }
+
+ /**
+ * request currency mapping only once
+ */
+ protected function requestCurrencyMappingLazy()
+ {
+
+ if ($this->currencyMapping !== null) {
+ return;
+ }
+ $currencies = $this->shopwareRequest('GET', 'currency');
+ if (!isset($currencies['data'])) {
+ $this->Shopware6Log('Kann Währungsmapping nicht abrufen', $currencies);
+ }
+ foreach ($currencies['data'] as $currency) {
+ $isoCode = strtoupper($currency['attributes']['isoCode']);
+ $this->currencyMapping[$isoCode] = $currency['id'];
+ }
+ }
+
+ /**
+ * @param array $internalArticleData
+ * @param string $articleIdInShopware
+ * @return bool
+ */
+ public function exportSeoUrls(array $internalArticleData, string $articleIdInShopware): bool
+ {
+ if (empty($articleIdInShopware)) {
+ return false;
+ }
+
+ $preparedSeoInformation = [];
+ foreach ($internalArticleData['freifelder'] as $countryIsoCode => $freeFieldInformation) {
+ if($countryIsoCode === 'EN'){
+ $countryIsoCode = 'GB';
+ }
+ if($countryIsoCode === 'DE'){
+ foreach ($freeFieldInformation as $freeFieldName => $freeFieldValue) {
+ if (stripos($freeFieldName, 'shopware6_seo_url') !== false) {
+ $preparedSeoInformation[$countryIsoCode][$freeFieldName] = $freeFieldValue;
+ }
+ }
+ }else{
+ foreach ($freeFieldInformation as $freeFieldData) {
+ if (stripos($freeFieldData['mapping'], 'shopware6_seo_url') !== false) {
+ $preparedSeoInformation[$countryIsoCode][$freeFieldData['mapping']] = $freeFieldData['wert'];
+ }
+ }
+ }
+ }
+ foreach ($internalArticleData['eigenschaften'] as $property) {
+ if (stripos($property['name'], 'shopware6_seo_url') !== false) {
+ $preparedSeoInformation['DE'][$property['name']] = $property['values'];
+ }
+ }
+ foreach ($internalArticleData['eigenschaftenuebersetzungen'] as $propertyTranslation) {
+ if($propertyTranslation['language_to'] === 'EN'){
+ $propertyTranslation['language_to'] = 'GB';
+ }
+ if (stripos($propertyTranslation['property_to'], 'shopware6_seo_url') !== false) {
+ $preparedSeoInformation[$propertyTranslation['language_to']][$propertyTranslation['property_to']] = $propertyTranslation['property_value_to'];
+ }
+ }
+
+ $specificSalesChannelSeoUrls = [];
+ $defaultSeoUrls = [];
+ foreach ($preparedSeoInformation as $countryIsoCode => $channelAssociations) {
+ foreach ($channelAssociations as $fieldName => $fieldValue){
+ if(strtolower($fieldName) === 'shopware6_seo_url'){
+ $defaultSeoUrls[$countryIsoCode] = $fieldValue;
+ }else{
+ $seoInformation = explode('|', $fieldName);
+ $specificSalesChannelSeoUrls[$countryIsoCode][array_pop($seoInformation)] = $fieldValue;
+ }
+ }
+ }
+
+ if (empty($specificSalesChannelSeoUrls) && empty($defaultSeoUrls)) {
+ return false;
+ }
+
+ $salesChannelsIdToName = [];
+ $salesChannels = $this->shopwareRequest('GET','sales-channel');
+ foreach ($salesChannels['data'] as $salesChannel) {
+ $salesChannelsIdToName[$salesChannel['id']] = $salesChannel['attributes']['name'];
+ }
+
+ foreach ($preparedSeoInformation as $countryIsoCode => $x){
+ $languageId = $this->getLanguageIdByCountryIso($countryIsoCode);
+ if (empty($languageId)) {
+ $this->Shopware6Log('Language Id not found for country: ' . $countryIsoCode);
+ continue;
+ }
+
+ $headerInformation = ['sw-language-id: ' . $languageId];
+ foreach ($salesChannelsIdToName as $salesChannelId => $salesChannelName) {
+ $seoUrlToUse = $defaultSeoUrls[$countryIsoCode];
+ if (!empty($specificSalesChannelSeoUrls[$countryIsoCode][$salesChannelName])) {
+ $seoUrlToUse = $specificSalesChannelSeoUrls[$countryIsoCode][$salesChannelsIdToName[$salesChannelName]];
+ }
+ if (empty($seoUrlToUse)) {
+ continue;
+ }
+ $seoDataToSend = [
+ 'seoPathInfo' => $seoUrlToUse,
+ '_isNew' => true,
+ 'isModified' => true,
+ 'isCanonical' => true,
+ 'isDeleted' => false,
+ 'routeName' => 'frontend.detail.page',
+ 'foreignKey' => $articleIdInShopware,
+ 'pathInfo' => '/detail/'.$articleIdInShopware,
+ 'languageId' => $languageId,
+ 'salesChannelId' => $salesChannelId];
+ $this->shopwareRequest('PATCH', '_action/seo-url/canonical', $seoDataToSend, $headerInformation);
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * @param array $article
+ * @param string $articleIdShopware
+ * @param string $currencyId
+ *
+ * @return bool
+ */
+ protected function exportVariants($article, $articleIdShopware, $currencyId): bool
+ {
+ $languageId = $this->getLanguageIdByCountryIso('DE');
+ if (empty($languageId)) {
+ return false;
+ }
+ if (empty($article['matrix_varianten']) || empty($articleIdShopware)) {
+ return false;
+ }
+ $internalGroupPropertiesToShopwareId = [];
+ foreach ($article['matrix_varianten']['gruppen'] as $propertyGroupName => $internalPropertyGroupValues) {
+ $propertyGroupId = '';
+ if (array_key_exists($propertyGroupName, $this->knownPropertyGroupIds)) {
+ $propertyGroupId = $this->knownPropertyGroupIds[$propertyGroupName];
+ }
+ if (empty($propertyGroupId)) {
+ $propertyGroupId = $this->getPropertyGroupId($propertyGroupName);
+ }
+ if (empty($propertyGroupId)) {
+ $propertyGroupId = $this->createPropertyGroup($propertyGroupName);
+ }
+ if (empty($propertyGroupId)) {
+ $this->Shopware6Log('PropertyGroup kann nicht erstellt werden: ' . $propertyGroupName);
+ return false;
+ }
+
+ if (!empty($article['matrix_varianten']['texte'])) {
+ $this->createTranslationForPropertyGroup($propertyGroupId, $propertyGroupName, 'DE');
+
+ foreach ($article['matrix_varianten']['texte']['gruppen'] as $countryIsoCode => $matrixGroupTranslation) {
+ if ($countryIsoCode === 'EN') {
+ $countryIsoCode = 'GB';
+ }
+
+ $this->createTranslationForPropertyGroup($propertyGroupId, $matrixGroupTranslation[$propertyGroupName], $countryIsoCode);
+ }
+ }
+
+ $languageId = $this->getLanguageIdByCountryIso('DE');
+ $headerInformation = ['sw-language-id: ' . $languageId];
+ $shopwarePropertyGroupOptions = $this->shopwareRequest(
+ 'GET',
+ 'property-group/' . $propertyGroupId . '/options?limit=100',
+ $headerInformation);
+ foreach ($shopwarePropertyGroupOptions['data'] as $shopwarePropertyGroupOption) {
+ $propertyValue = $shopwarePropertyGroupOption['attributes']['name'];
+ $internalGroupPropertiesToShopwareId[$propertyGroupName][$propertyValue] = $shopwarePropertyGroupOption['id'];
+ }
+
+ foreach ($internalPropertyGroupValues as $internalPropertyGroupValue => $valueNotNeeded) {
+ if (!array_key_exists($internalPropertyGroupValue, $internalGroupPropertiesToShopwareId[$propertyGroupName])) {
+ $newOptionData = [
+ 'name' => (string)$internalPropertyGroupValue
+ ];
+ $optionData = $this->shopwareRequest(
+ 'POST',
+ 'property-group/' . $propertyGroupId . '/options?_response=true',
+ $newOptionData);
+ $internalGroupPropertiesToShopwareId[$propertyGroupName][$internalPropertyGroupValue] = $optionData['data']['id'];
+ }
+ }
+
+ if (!empty($article['matrix_varianten']['texte'])) {
+ foreach ($internalPropertyGroupValues as $optionValue => $valueNotNeeded) {
+ $optionId = $internalGroupPropertiesToShopwareId[$propertyGroupName][$optionValue];
+ $this->createTranslationForPropertyOption(
+ $optionId,
+ $optionValue,
+ 'DE');
+ foreach ($article['matrix_varianten']['texte']['werte'] as $countryIsoCode => $matrixOptionTranslations) {
+ if ($countryIsoCode === 'EN') {
+ $countryIsoCode = 'GB';
+ }
+ if (array_key_exists($optionValue, $matrixOptionTranslations)) {
+ $this->createTranslationForPropertyOption(
+ $optionId,
+ $matrixOptionTranslations[$optionValue],
+ $countryIsoCode);
+ }
+ }
+ }
+ }
+ }
+
+ $existingCombinations = $this->shopwareRequest(
+ 'GET',
+ '_action/product/' . $articleIdShopware . '/combinations');
+ $existingCombinationsByNumber = [];
+
+ foreach ($existingCombinations as $combinationId => $combinationInfo) {
+ $existingCombinationsByNumber[$combinationInfo['productNumber']] = [
+ 'id' => $combinationId,
+ 'options' => [],
+ ];
+ foreach ($combinationInfo['options'] as $combinationOption) {
+ $existingCombinationsByNumber[$combinationInfo['productNumber']]['options'][$combinationOption] = $combinationOption;
+ }
+ }
+
+
+ foreach ($article['artikel_varianten'] as $variant) {
+ $internalVariantMatrixData = $article['matrix_varianten']['artikel'][$variant['artikel']];
+ $productNumber = $internalVariantMatrixData[0]['nummer'];
+ $name = $variant['name_de'];
+ $stock = $variant['lag'];
+ $ean = $variant['ean'];
+ $weight = (float)$variant['gewicht'];
+ $pseudoPrice = $variant['pseudopreis'];
+ if (empty($pseudoPrice)) {
+ $pseudoPrice = 0;
+ }
+ if (!empty($variant['pseudolager'])) {
+ $stock = $variant['pseudolager'];
+ }
+ $active = true;
+ if (!empty($variant['inaktiv'])) {
+ $active = false;
+ }
+ $isCloseOut = false;
+ if (!empty($variant['restmenge'])) {
+ $isCloseOut = true;
+ }
+
+ $variantProductData = [
+ 'active' => $active,
+ 'isCloseout' => $isCloseOut,
+ 'name' => $name,
+ 'description' => null,
+ 'weight' => null,
+ 'price' => [
+ [
+ 'currencyId' => $currencyId,
+ 'gross' => $variant['bruttopreis'],
+ 'net' => $variant['preis'],
+ 'linked' => true,
+ 'listPrice' => [
+ 'currencyId' => $currencyId,
+ 'gross' => $pseudoPrice,
+ 'linked' => true,
+ 'net' => $pseudoPrice / (1 + $variant['steuersatz'] / 100)
+ ]
+ ]
+ ],
+ 'stock' => (int)$stock,
+ 'ean' => null,
+ 'taxId' => $this->getTaxIdByRate($variant['steuersatz']),
+ ];
+ if(!empty($weight)){
+ $variantProductData['weight'] = $weight;
+ }
+ if(!empty($ean)){
+ $variantProductData['ean'] = $ean;
+ }
+ if (!empty($variant['uebersicht_de'])) {
+ $variantProductData['description'] = $variant['uebersicht_de'];
+ }
+
+ $renewVariant = false;
+ $options = [];
+ foreach ($internalVariantMatrixData as $expression) {
+ if (!in_array(
+ $internalGroupPropertiesToShopwareId[$expression['name']][$expression['values']],
+ $existingCombinationsByNumber[$productNumber]['options'],
+ false)) {
+ $renewVariant = true;
+ } else {
+ unset($existingCombinationsByNumber[$productNumber]['options'][$internalGroupPropertiesToShopwareId[$expression['name']][$expression['values']]]);
+ }
+ $options[] = ['id' => $internalGroupPropertiesToShopwareId[$expression['name']][$expression['values']]];
+ }
+
+ if (!empty($existingCombinationsByNumber[$productNumber]['options'])) {
+ $renewVariant = true;
+ }
+
+ $variantImageData = [
+ 'Dateien' => []
+ ];
+ $variantProductId = '';
+ if (!empty($existingCombinationsByNumber[$productNumber]['id']) && !$renewVariant) {
+ $variantProductId = $existingCombinationsByNumber[$productNumber]['id'];
+ }
+ if (!empty($variant['Dateien']['id'])) {
+ foreach ($variant['Dateien']['id'] as $index => $fileId) {
+ $variantImageData['Dateien'][] = [
+ 'filename' => $variant['Dateien']['filename'][$index],
+ 'extension' => $variant['Dateien']['extension'][$index],
+ 'datei' => $variant['Dateien']['datei'][$index],
+ 'beschreibung' => $variant['Dateien']['beschreibung'][$index],
+ 'titel' => $variant['Dateien']['titel'][$index],
+ 'id' => $fileId,
+ ];
+ }
+ }
+ $mediaToAdd = $this->mediaToExport($variantImageData, $variantProductId);
+ $variantProductData['media'] = $mediaToAdd;
+
+ if ($renewVariant) {
+ if (!empty($existingCombinationsByNumber[$productNumber]['id'])) {
+ $this->shopwareRequest('DELETE', 'product/' . $existingCombinationsByNumber[$productNumber]['id']);
+ }
+ $variantProductData['productNumber'] = $productNumber;
+ $variantProductData['parentId'] = $articleIdShopware;
+ $variantProductData['options'] = $options;
+
+ $result = $this->shopwareRequest('POST', 'product?_response=true', $variantProductData);
+ $variantProductId = $result['data']['id'];
+ } else {
+ $variantProductId = $existingCombinationsByNumber[$productNumber]['id'];
+ $this->shopwareRequest('PATCH', 'product/' . $variantProductId, $variantProductData);
+ }
+
+ $defaultPrices = $this->getPricesFromArray($variant['staffelpreise_standard'] ?? []);
+ $groupPrices = $this->getPricesFromArray($variant['staffelpreise_gruppen'] ?? []);
+
+ $this->deleteOldBulkPrices($variantProductId);
+ if (!empty($defaultPrices)) {
+ foreach ($defaultPrices as $priceData) {
+ $this->exportBulkPriceForGroup($variantProductId, $this->defaultRuleName, $priceData);
+ }
+ }
+ if (!empty($groupPrices)) {
+ foreach ($groupPrices as $priceData) {
+ $this->exportBulkPriceForGroup($variantProductId, $priceData->getGroupName(), $priceData);
+ }
+ }
+
+ $this->addCoverImage($variantImageData, $variantProductId);
+ }
+
+ $existingConfigurations = $this->shopwareRequest(
+ 'GET', 'product/' . $articleIdShopware . '/configuratorSettings');
+ $optionIdsToAdd = [];
+ foreach ($article['artikel_varianten'] as $variant) {
+ foreach ($article['matrix_varianten']['artikel'][$variant['artikel']] as $matrixInfo) {
+ $configurationExists = false;
+ foreach ($existingConfigurations['data'] as $configuration) {
+ if ($configuration['attributes']['optionId'] === $internalGroupPropertiesToShopwareId[$matrixInfo['name']][$matrixInfo['values']]) {
+ $configurationExists = true;
+ break;
+ }
+ }
+ if (!$configurationExists) {
+ $optionIdsToAdd[] = $internalGroupPropertiesToShopwareId[$matrixInfo['name']][$matrixInfo['values']];
+ }
+ }
+ }
+ if (!empty($optionIdsToAdd)) {
+ $optionIdsToAdd = array_flip(array_flip($optionIdsToAdd));
+ $configurationData = [
+ 'configuratorSettings' => []
+ ];
+ foreach ($optionIdsToAdd as $id) {
+ $configurationData['configuratorSettings'][] = ['optionId' => $id];
+ }
+
+ $this->shopwareRequest(
+ 'PATCH',
+ sprintf('product/%s', $articleIdShopware),
+ $configurationData
+ );
+
+ $existingConfigurations = $this->shopwareRequest(
+ 'GET', 'product/' . $articleIdShopware . '/configuratorSettings');
+ $optionsToSort = [];
+ foreach ($article['artikel_varianten'] as $variant) {
+ foreach ($article['matrix_varianten']['artikel'][$variant['artikel']] as $matrixInfo) {
+ foreach ($existingConfigurations['data'] as $configuration) {
+ if ($configuration['attributes']['optionId'] === $internalGroupPropertiesToShopwareId[$matrixInfo['name']][$matrixInfo['values']]) {
+ $optionsToSort[] = $configuration['id'];
+ break;
+ }
+ }
+ }
+ }
+ if (!empty($optionsToSort)) {
+ $optionsToSort = array_flip(array_flip($optionsToSort));
+ $configurationData = [
+ 'configuratorSettings' => []
+ ];
+ $position = 1;
+
+ foreach ($optionsToSort as $id) {
+ $configurationData['configuratorSettings'][] = [
+ 'id' => $id,
+ 'position' => $position];
+ $position++;
+ }
+
+ $this->shopwareRequest(
+ 'PATCH',
+ sprintf('product/%s', $articleIdShopware),
+ $configurationData
+ );
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * @param $priceArray
+ * @return PriceData[]
+ */
+ protected function getPricesFromArray($priceArray): array{
+ return array_map(static function($price){
+ return new PriceData(
+ (int)$price['ab_menge'],
+ (float)$price['preis'],
+ (float)$price['bruttopreis'],
+ $price['waehrung'],
+ $price['gruppeextern'] ?? '') ;
+ },$priceArray);
+ }
+
+ /**
+ * delete all old price entries for a product
+ *
+ * @param string $productId
+ */
+ protected function deleteOldBulkPrices($productId)
+ {
+ //TODO Instead of deleting all old prices we should rather check first whether they are still in order
+ $oldPrices = $this->shopwareRequest(
+ 'GET',
+ sprintf('product-price?filter[product_price.productId]=%s', $productId)
+ );
+ if (is_array($oldPrices)) {
+ foreach ($oldPrices['data'] as $deletePrice) {
+ $this->shopwareRequest('DELETE', 'product-price/' . $deletePrice['id']);
+ }
+ } else {
+ $this->Shopware6Log('Fehler: Alte Preise wurden nicht gelöscht', $productId);
+ }
+ }
+
+ /**
+ * @return int
+ */
+ public function getOrderSearchLimit(): int
+ {
+ if(in_array($this->orderSearchLimit, ['50', '75', '100'])) {
+ return (int)$this->orderSearchLimit;
+ }
+
+ return 25;
+ }
+
+ /**
+ * @return int
+ */
+ public function ImportGetAuftraegeAnzahl()
+ {
+ $order = null;
+ $dataToGet = $this->CatchRemoteCommand('data');
+
+ if (empty($this->statesToFetch)) {
+ return false;
+ }
+
+ $ordersToProcess = $this->getOrdersToProcess($this->getOrderSearchLimit());
+
+ return (!empty(count($ordersToProcess['data'])?count($ordersToProcess['data']):0);
+ }
+
+ /**
+ * @param string $parameter1
+ * @param string $parameter2
+ */
+ public function Shopware6ErrorLog($parameter1, $parameter2 = '')
+ {
+ $this->app->DB->Insert(
+ sprintf(
+ "INSERT INTO `shopexport_log`
+ (shopid, typ, parameter1, parameter2, bearbeiter, zeitstempel)
+ VALUES (%d, 'fehler', '%s','%s','%s',NOW())",
+ $this->shopid,
+ $this->app->DB->real_escape_string($parameter1),
+ $this->app->DB->real_escape_string($parameter2),
+ $this->app->DB->real_escape_string($this->app->User->GetName())
+ )
+ );
+ }
+
+ /**
+ * @param array $stateMachinesIds
+ * @return array
+ */
+ protected function getTransactionStateIdsToFetch($stateMachinesIds): array
+ {
+ $transactionStateIdsToFetch = [];
+ if (!empty($this->transactionStatesToFetch)) {
+ $transactionStatesToFetch = explode(';', $this->transactionStatesToFetch);
+ foreach ($transactionStatesToFetch as $transactionStateToFetch) {
+ $stateInformation = $this->shopwareRequest('GET', 'state-machine-state?filter[technicalName]=' .
+ trim($transactionStateToFetch) . '&filter[stateMachineId]=' . $stateMachinesIds['order_transaction.state']);
+ if (empty($stateInformation['data'])) {
+ $this->Shopware6ErrorLog('Zahlungsstatus für Abholung nicht gefunden', $transactionStateToFetch);
+ return false;
+ }
+ foreach ($stateInformation['data'] as $state) {
+ $transactionStateIdsToFetch[] = $state['id'];
+ }
+ }
+ }
+
+ return $transactionStateIdsToFetch;
+ }
+
+ /**
+ * @param int $limit
+ *
+ * @return mixed
+ */
+ protected function getOrdersToProcess(int $limit)
+ {
+ $searchData = [
+ 'limit' => $limit,
+ 'includes' => [
+ 'order' => ['id']
+ ],
+ 'sort' => [
+ [
+ 'field' => 'order.createdAt',
+ 'direction' => 'DESC'
+ ]
+ ],
+ 'filter' => []
+ ];
+
+ $searchData['filter'][] = [
+ 'field' => 'stateMachineState.technicalName',
+ 'type' => 'equalsAny',
+ 'value' => explode(';', $this->statesToFetch)
+ ];
+
+ if (!empty($this->deliveryStatesToFetch)) {
+ $searchData['filter'][] = [
+ 'field' => 'deliveries.stateMachineState.technicalName',
+ 'type' => 'equalsAny',
+ 'value' => explode(';', $this->deliveryStatesToFetch)
+ ];
+ }
+ if (!empty($this->transactionStatesToFetch)) {
+ $searchData['filter'][] = [
+ 'field' => 'transactions.stateMachineState.technicalName',
+ 'type' => 'equalsAny',
+ 'value' => explode(';', $this->transactionStatesToFetch)
+ ];
+ }
+
+ if (!empty($this->salesChannelToFetch)) {
+ $searchData['filter'][] = [
+ 'field' => 'order.salesChannelId',
+ 'type' => 'equals',
+ 'value' => $this->salesChannelToFetch
+ ];
+ }
+
+ return $this->shopwareRequest('POST', 'search/order', $searchData);
+ }
+
+ /**
+ * @return int|mixed
+ */
+ public function ImportGetAuftrag()
+ {
+ $voucherArticleId = $this->app->DB->Select("SELECT s.artikelrabatt FROM `shopexport` AS `s` WHERE s.id='$this->shopid' LIMIT 1");
+ $voucherArticleNumber = $this->app->DB->Select("SELECT a.nummer FROM `artikel` AS `a` WHERE a.id='$voucherArticleId' LIMIT 1");
+
+ $dataToGet = $this->CatchRemoteCommand('data');
+ if (empty($this->statesToFetch)) {
+ return false;
+ }
+ $expectOrderArray = !empty($dataToGet['anzgleichzeitig']) && (int)$dataToGet['anzgleichzeitig'] > 1;
+ $expectNumber = !empty($dataToGet['nummer']);
+ $order = null;
+ if($expectNumber) {
+ $order = $this->shopwareRequest('GET', 'order/' . $dataToGet['nummer'] . '?associations[currency][]');
+ if(empty($order['data'])) {
+ return false;
+ }
+ $ordersToProcess = ['data' => [ ['id' => $dataToGet['nummer']] ]];
+ $orderIncludedData = $order['included'];
+ $order = $order['data'];
+ }
+ elseif(!$expectOrderArray) {
+ $ordersToProcess = $this->getOrdersToProcess(1);
+ }
+ elseif(!$expectNumber) {
+ $ordersToProcess = $this->getOrdersToProcess($this->getOrderSearchLimit());
+ }
+ if (empty($ordersToProcess['data'])) {
+ return false;
+ }
+
+ $fetchedOrders = [];
+ if (isset($ordersToFetch['data']['id']) && !isset($ordersToFetch['data'][0])) {
+ $ordersToFetch['data'] = [$ordersToFetch['data']];
+ }
+ foreach ($ordersToProcess['data'] as $currentlyOpenOrder) {
+ $orderIdToFetch = $currentlyOpenOrder['id'];
+
+ if (empty($dataToGet['nummer']) || empty($order)) {
+ $order = $this->shopwareRequest('GET', 'order/' . $orderIdToFetch.'?associations[currency][]');
+ $orderIncludedData = $order['included'];
+ $order = $order['data'];
+ }
+ $cart = [];
+ try {
+ $timestamp = date_create_from_format('Y-m-d\TH:i:s+', $order['attributes']['createdAt']);
+ $cart['zeitstempel'] = $timestamp->format('Y-m-d H:i:s');
+ } catch (Exception $ex) {
+
+ }
+ $cart['auftrag'] = $order['id'];
+ $cart['subshop'] = $order['attributes']['salesChannelId'];
+ $cart['order'] = $order;
+ $cart['onlinebestellnummer'] = $order['attributes']['orderNumber'];
+ $cart['gesamtsumme'] = $order['attributes']['amountTotal'];
+ $cart['versandkostenbrutto'] = $order['attributes']['shippingTotal'];
+ $cart['bestelldatum'] = substr($order['attributes']['orderDate'], 0, 10);
+ if (!empty($order['attributes']['customerComment'])) {
+ $cart['freitext'] = $order['attributes']['customerComment'];
+ }
+
+ foreach ($orderIncludedData as $includedDataSet){
+ if($includedDataSet['type'] === 'currency'){
+ $cart['waehrung'] = $includedDataSet['attributes']['isoCode'];
+ }
+ }
+
+ $deliveryInfo = $this->shopwareRequest('GET', 'order/' . $order['id'] . '/deliveries');
+ $shippingMethod = $this->shopwareRequest('GET',
+ 'order-delivery/' . $deliveryInfo['data'][0]['id'] . '/shipping-method');
+ $order['shippingMethod'] = $shippingMethod;
+ $cart['lieferung'] = $shippingMethod['data'][0]['attributes']['name'];
+
+ $customer = $this->shopwareRequest('GET', 'order/' . $order['id'] . '/order-customer');
+ $order['customer'] = $customer;
+ $cart['email'] = $customer['data']['0']['attributes']['email'];
+
+ $addresses = $this->shopwareRequest('GET', 'order/' . $order['id'] . '/addresses?associations[salutation][]&associations[country][]');
+ $order['addresses'] = $addresses;
+ $deliveryCountryId = '';
+ $billingCountryId = '';
+ $billingSalutationId = '';
+ foreach ($addresses['data'] as $address) {
+ if ($address['id'] === $order['attributes']['billingAddressId']) {
+ if (!empty($address['attributes']['vatId'])) {
+ $cart['ustid'] = $address['attributes']['vatId'];
+ }
+ $cart['name'] = $address['attributes']['firstName'] . ' ' . $address['attributes']['lastName'];
+ if (!empty($address['attributes']['company'])) {
+ $cart['ansprechpartner'] = $cart['name'];
+ $cart['name'] = $address['attributes']['company'];
+ }
+ $cart['strasse'] = $address['attributes']['street'];
+ $cart['abteilung'] = $address['attributes']['department'];
+ $cart['adresszusatz'] = trim($address['attributes']['additionalAddressLine1'].' '.
+ $address['attributes']['additionalAddressLine2']);
+ $cart['telefon'] = $address['attributes']['phoneNumber'];
+ $cart['plz'] = $address['attributes']['zipcode'];
+ $cart['ort'] = $address['attributes']['city'];
+ $billingCountryId = $address['attributes']['countryId'];
+ $billingSalutationId = $address['attributes']['salutationId'];
+ }
+ if ($address['id'] !== $order['attributes']['billingAddressId']) {
+ $cart['abweichendelieferadresse'] = 1;
+ if (!empty($address['attributes']['vatId'])) {
+ $cart['lieferadresse_ustid'] = $address['attributes']['vatId'];
+ }
+ $cart['lieferadresse_name'] = $address['attributes']['firstName'] . ' ' . $address['attributes']['lastName'];
+ if (!empty($address['attributes']['company'])) {
+ $cart['lieferadresse_ansprechpartner'] = $cart['lieferadresse_name'];
+ $cart['lieferadresse_name'] = $address['attributes']['company'];
+ }
+ $cart['lieferadresse_strasse'] = $address['attributes']['street'];
+ $cart['lieferadresse_abteilung'] = $address['attributes']['department'];
+ $cart['lieferadresse_adresszusatz'] = trim($address['attributes']['additionalAddressLine1'].' '.
+ $address['attributes']['additionalAddressLine2']);
+ $cart['lieferadresse_plz'] = $address['attributes']['zipcode'];
+ $cart['lieferadresse_ort'] = $address['attributes']['city'];
+ $deliveryCountryId = $address['attributes']['countryId'];
+ }
+ }
+
+ $anrede = 'herr';
+ $land = 'DE';
+ $lieferadresseLand = 'DE';
+ foreach ($addresses['included'] as $includedInfo) {
+ if ($includedInfo['id'] === $billingCountryId) {
+ $land = $includedInfo['attributes']['iso'];
+ }
+ if ($includedInfo['id'] === $deliveryCountryId) {
+ $lieferadresseLand = $includedInfo['attributes']['iso'];
+ }
+ if ($includedInfo['id'] === $billingSalutationId) {
+ $salutation = $includedInfo['attributes']['salutationKey'];
+ if ($salutation === 'ms' || $salutation === 'mrs') {
+ $anrede = 'frau';
+ }
+ }
+ }
+
+ $cart['anrede'] = $anrede;
+ $cart['land'] = $land;
+ if (!empty($cart['abweichendelieferadresse'])) {
+ $cart['lieferadresse_land'] = $lieferadresseLand;
+ }
+
+ $transactionData = $this->shopwareRequest('GET', 'order/' . $order['id'] . '/transactions');
+ $cart['transacion_data'] = $transactionData;
+ if (!empty($transactionData['data'][0]['attributes']['customFields']['swag_paypal_pui_payment_instruction']['reference_number'])) {
+ $cart['transaktionsnummer'] = $transactionData['data'][0]['attributes']['customFields']['swag_paypal_pui_payment_instruction']['reference_number'];
+ }
+ if (empty($cart['transaktionsnummer'] && !empty($transactionData['data'][0]['attributes']['customFields']['swag_paypal_order_id']))) {
+ $cart['transaktionsnummer'] = (string)$transactionData['data'][0]['attributes']['customFields']['swag_paypal_order_id'];
+ }
+ if (empty($cart['transaktionsnummer'] && !empty($transactionData['data'][0]['attributes']['customFields']['swag_paypal_transaction_id']))) {
+ $livePayPalData = $this->shopwareRequest('GET', 'paypal/payment-details/' . $order['id'] . '/' . $transactionData['data'][0]['attributes']['customFields']['swag_paypal_transaction_id']);
+ if (!empty($livePayPalData['transactions'])) {
+ foreach ($livePayPalData['transactions'] as $payPalData) {
+ foreach ($payPalData['related_resources'] as $ressources) {
+ if ($ressources['sale']['state'] === 'completed') {
+ $cart['transaktionsnummer'] = $ressources['sale']['id'];
+ break 2;
+ }
+ }
+ }
+ }
+ }
+ if(
+ empty($cart['transaktionsnummer'])
+ && isset($transactionData['data'][0]['attributes']['customFields']['stripe_payment_context']['payment']['payment_intent_id'])
+ ){
+ $cart['transaktionsnummer'] = $transactionData['data'][0]['attributes']['customFields']['stripe_payment_context']['payment']['payment_intent_id'];
+ }
+
+ $paymentMethodId = $transactionData['data'][0]['attributes']['paymentMethodId'];
+ $paymentMethod = $this->shopwareRequest('GET', 'payment-method/' . $paymentMethodId);
+ $cart['zahlungsweise'] = $paymentMethod['data']['attributes']['name'];
+
+ $taxedCountry = $land;
+ if($this->taxationByDestinationCountry){
+ $taxedCountry = $lieferadresseLand;
+ }
+ if($order['attributes']['amountTotal'] === $order['attributes']['amountNet']){
+ if($this->app->erp->IstEU($taxedCountry)){
+ $cart['ust_befreit'] = 1;
+ }elseif($this->app->erp->Export($taxedCountry)){
+ $cart['ust_befreit'] = 2;
+ }else{
+ $cart['ust_befreit'] = 3;
+ }
+ }
+
+ $lineItems = $this->shopwareRequest('GET', 'order/' . $order['id'] . '/line-items');
+ $order['lineItems'] = $lineItems;
+ $cart['articlelist'] = [];
+
+ $taxRate = 0;
+ foreach ($lineItems['data'] as $lineItem) {
+ if ($lineItem['attributes']['price']['calculatedTaxes'][0]['taxRate'] > $taxRate) {
+ $taxRate = $lineItem['attributes']['price']['calculatedTaxes'][0]['taxRate'];
+ }
+ }
+
+ $orderPriceType = 'price';
+ if(in_array($order['attributes']['taxStatus'], ['net', 'tax-free'])) {
+ $orderPriceType = 'price_netto';
+ $cart['versandkostennetto'] = $cart['versandkostenbrutto'];
+ unset($cart['versandkostenbrutto']);
+ }
+
+ foreach ($lineItems['data'] as $lineItem) {
+ $productPriceType = $orderPriceType;
+ if(empty($lineItem['attributes']['price']['calculatedTaxes'][0]['taxRate'])){
+ $productPriceType = 'price_netto';
+ }
+ $articleId = null;
+ if($lineItem['attributes']['price']['unitPrice'] < 0) {
+ $articleId = $voucherArticleNumber;
+ }
+ elseif(isset($lineItem['attributes']['payload']['productNumber'])){
+ $articleId = $lineItem['attributes']['payload']['productNumber'];
+ }
+ $product = [
+ 'articleid' => $articleId,
+ 'name' => $lineItem['attributes']['label'],
+ 'quantity' => $lineItem['attributes']['quantity'],
+ $productPriceType => $lineItem['attributes']['price']['unitPrice'],
+ 'steuersatz' => $lineItem['attributes']['price']['calculatedTaxes'][0]['taxRate'],
+ ];
+ $cart['articlelist'][] = $product;
+ }
+
+ $cart['order'] = $order;
+ $fetchedOrders[] = [
+ 'id' => $cart['auftrag'],
+ 'sessionid' => '',
+ 'logdatei' => '',
+ 'warenkorb' => base64_encode(serialize($cart)),
+ 'warenkorbjson' => base64_encode(json_encode($cart)),
+ ];
+ $this->Shopware6Log('Ergebnis: Auftrag', $order);
+ $this->Shopware6Log('Ergebnis: Adresse', $addresses);
+ $this->Shopware6Log('Ergebnis: Positionen', $lineItems);
+ }
+
+ return $fetchedOrders;
+ }
+
+ /**
+ * @return void
+ */
+ public function ImportDeleteAuftrag()
+ {
+ $tmp = $this->CatchRemoteCommand('data');
+ $auftrag = $tmp['auftrag'];
+
+ $this->shopwareRequest('POST', '_action/order/'.$auftrag.'/state/process');
+ $this->addCustomFieldToOrder((string)$auftrag);
+ }
+
+ /**
+ * @return void
+ */
+ public function ImportUpdateAuftrag()
+ {
+ $tmp = $this->CatchRemoteCommand('data');
+ $auftrag = $tmp['auftrag'];
+ $tracking = $tmp['tracking'];
+
+ $this->shopwareRequest('POST', '_action/order/'.$auftrag.'/state/complete');
+
+ $deliveries = $this->shopwareRequest('GET', 'order/'.$auftrag.'/deliveries');
+ $deliveryId = $deliveries['data'][0]['id'];
+
+ if(!empty($deliveryId)){
+ $this->shopwareRequest('POST', '_action/order_delivery/'.$deliveryId.'/state/ship');
+
+ $deliveryData = [
+ 'trackingCodes' => [$tracking]
+ ];
+ $this->shopwareRequest('PATCH', 'order-delivery/'.$deliveryId,$deliveryData);
+ }
+
+ $this->sendInvoce($auftrag);
+ $this->addCustomFieldToOrder((string)$auftrag);
+ if(empty($tmp['orderId'])) {
+ return;
+ }
+ $this->updateStorageForOrderIntId((int)$tmp['orderId']);
+ }
+
+ public function ImportStorniereAuftrag()
+ {
+ $tmp = $this->CatchRemoteCommand('data');
+ $auftrag = $tmp['auftrag'];
+
+ $this->shopwareRequest('POST', '_action/order/'.$auftrag.'/state/cancel');
+ $this->addCustomFieldToOrder((string)$auftrag);
+ }
+
+ /**
+ * @param string $extOrderId
+ */
+ protected function sendInvoce($extOrderId)
+ {
+ $order = $this->app->DB->SelectRow(
+ sprintf(
+ "SELECT `rechnungid`, `id` FROM `auftrag` WHERE shopextid='%s'",
+ $extOrderId
+ )
+ );
+ $invoiceId = 0;
+ if (!empty($order['rechnungid'])) {
+ $invoiceId = $order['rechnungid'];
+ $sql = sprintf("SELECT projekt, belegnr FROM rechnung WHERE id='%s'", $invoiceId);
+ $invoiceData = $this->app->DB->SelectRow($sql);
+ }
+ if (empty($invoiceId) && !empty($order['id'])) {
+ $invoiceData = $this->app->DB->SelectRow(
+ sprintf(
+ "SELECT `id`, `projekt`, `belegnr`
+ FROM `rechnung`
+ WHERE `auftragid` = %d AND `status` <> 'storniert' AND `status` <> 'angelegt'
+ LIMIT 1",
+ $order['id']
+ )
+ );
+ if (!empty($invoiceData)) {
+ $invoiceId = $invoiceData['id'];
+ }
+ }
+
+ if (!empty($invoiceData['belegnr'])) {
+ $projekt = $invoiceData['projekt'];
+ if (class_exists('RechnungPDFCustom')) {
+ $Brief = new RechnungPDFCustom($this->app, $projekt);
+ } else {
+ $Brief = new RechnungPDF($this->app, $projekt);
+ }
+
+ $Brief->GetRechnung($invoiceId);
+ $filePath = $Brief->displayTMP(true);
+
+ $documentNumber = $invoiceData['belegnr'];
+ $invoiceDocumentData = [
+ 'config' => [
+ 'custom' => [
+ 'invoiceNumber' => $documentNumber,
+ ],
+ 'documentComment' => 'Aus Xentral heraus erstellte Rechnung',
+ 'documentNumber' => $documentNumber,
+ ],
+ 'referenced_document_id' => null,
+ 'static' => true
+ ];
+
+ $documentData = $this->shopwareRequest('POST', '_action/order/' . $extOrderId . '/document/invoice', $invoiceDocumentData);
+ $documentId = $documentData['documentId'];
+
+ $accessToken = $this->shopwareToken();
+ $url = $this->ShopUrl . 'v2/_action/document/' . $documentId . '/upload?_response=true&extension=pdf&fileName=' . $documentNumber;
+
+ $ch = curl_init();
+ $setHeaders = [
+ 'Content-Type:application/pdf',
+ 'Authorization:Bearer ' . $accessToken['token']
+ ];
+ curl_setopt($ch, CURLOPT_URL, $url);
+ curl_setopt($ch, CURLOPT_POSTFIELDS, file_get_contents($filePath));
+ curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
+ curl_setopt($ch, CURLOPT_HTTPHEADER, $setHeaders);
+ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
+ $response = json_decode(curl_exec($ch), true);
+ curl_close($ch);
+ if (!empty($response['errors'])) {
+ $this->Shopware6Log(
+ 'Fehler bei Rechnugnsübertragung für ' . $documentNumber, $response['errors']
+ );
+ }
+ }
+ }
+
+ /**
+ * @return string
+ */
+ public function ImportAuth()
+ {
+ $tokeninfo = $this->shopwareToken();
+
+
+ if (!$tokeninfo['success']) {
+ return 'failed: ' . $tokeninfo['message'];
+ }
+ if($this->data === 'info'){
+ $salesChannelsInShopware = $this->client->getAllSalesChannels();
+ $salesChannelsToShow = ['subshops' => []];
+ foreach ($salesChannelsInShopware['data'] as $salesChannelInShopware){
+ $salesChannelsToShow['subshops'][] = [
+ 'id'=>$salesChannelInShopware['id'],
+ 'name'=>$salesChannelInShopware['name'],
+ 'aktiv'=>$salesChannelInShopware['active']
+ ];
+ }
+ return $salesChannelsToShow;
+ }
+
+ return 'success';
+ }
+
+ /**
+ * Build category tree as displayed in article info
+ * May be useful for setting category in the future
+ * but probably obsolete
+ *
+ * @param string $categoryName
+ * @param array $categoryTree
+ *
+ * @return array
+ */
+ protected function appendCategoryTree($categoryName, $categoryTree = [])
+ {
+ $shopwareCategory = $this->shopwareRequest(
+ 'GET',
+ 'category?filter[category.name]=' . urlencode($categoryName)
+ );
+ if (!isset($shopwareCategory['data'][0]['id'])) {
+ return $categoryTree;
+ }
+ $categoryInfo = $shopwareCategory['data'][0]['attributes'];
+ $categories[] = [(int)$categoryInfo['level'], $shopwareCategory['data'][0]['id']];
+ $path = $categoryInfo['path'];
+ if (!empty($path)) {
+ $pathArray = explode('|', $path);
+ foreach ($pathArray as $nodeId) {
+ if ($nodeId === '') {
+ continue;
+ }
+ $nodeCategory = $this->shopwareRequest('GET', 'category/' . $nodeId);
+ if (isset($nodeCategory['data']['id'])) {
+ $categories[] = [(int)$nodeCategory['data']['attributes']['level'], $nodeId];
+ unset($nodeCategory);
+ }
+ }
+ }
+ foreach ($categories as $category) {
+ $level = $category[0];
+ if (!isset($categoryTree[$level])) {
+ $categoryTree[$level] = [];
+ }
+ if (!in_array($category, $categoryTree[$level], true)) {
+ $categoryTree[$level][] = $category[1];
+ }
+ }
+ ksort($categoryTree);
+
+ return $categoryTree;
+ }
+
+ /**
+ * @param array $postData
+ *
+ * @return array
+ */
+ public function updatePostDataForAssistent($postData)
+ {
+ if(!empty($this->ShopUrl)) {
+ $postData['shopwareUrl'] = $this->ShopUrl;
+ }
+ return $postData;
+ }
+
+ /**
+ * @param array $shopArr
+ * @param array $postData
+ *
+ * @return array
+ */
+ public function updateShopexportArr($shopArr, $postData)
+ {
+ $shopArr['stornoabgleich'] = 1;
+ $shopArr['demomodus'] = 0;
+
+ return $shopArr;
+ }
+
+ /**
+ * @return JsonResponse|null
+ */
+ public function AuthByAssistent()
+ {
+ $shopwareUrl = $this->app->Secure->GetPOST('shopwareUrl');
+ $shopwareUserName = $this->app->Secure->GetPOST('shopwareUserName');
+ $shopwarePassword = $this->app->Secure->GetPOST('shopwarePassword');
+ $step = (int)$this->app->Secure->GetPOST('step');
+
+ if($step <= 1){
+ if(empty($shopwareUrl)){
+ return new JsonResponse(['error' => 'Bitte die URL des Shops angeben.'], JsonResponse::HTTP_BAD_REQUEST);
+ }
+ if(empty($shopwareUserName)){
+ return new JsonResponse(['error' => 'Bitte den Benutzernamen angeben'], JsonResponse::HTTP_BAD_REQUEST);
+ }
+ if(empty($shopwarePassword)){
+ return new JsonResponse(['error' => 'Bitte das Passwort angeben'], JsonResponse::HTTP_BAD_REQUEST);
+ }
+
+ $this->UserName = $shopwareUserName;
+ $this->Password = $shopwarePassword;
+ $shopwareUrl = rtrim($shopwareUrl, '/') . '/';
+ $testUrls = [];
+ $hasNoHttp = strpos($shopwareUrl,'http') !== 0;
+ if(substr($shopwareUrl, -5) !== '/api/') {
+ if($hasNoHttp) {
+ $testUrls[] = 'https://'.$shopwareUrl.'api/';
+ $testUrls[] = 'http://'.$shopwareUrl.'api/';
+ }
+ $testUrls[] = $shopwareUrl.'api/';
+ }
+ elseif($hasNoHttp) {
+ $testUrls[] = 'https://'.$shopwareUrl;
+ $testUrls[] = 'http://'.$shopwareUrl;
+ }
+ else {
+ $testUrls[] = $shopwareUrl;
+ }
+ foreach($testUrls as $testUrl) {
+ $this->ShopUrl = $testUrl;
+ $tokeninfo = $this->shopwareToken();
+ if(!empty($tokeninfo['success'])) {
+ break;
+ }
+ }
+
+ if(!$tokeninfo['success']){
+ return new JsonResponse(['error' => $tokeninfo['message']], JsonResponse::HTTP_BAD_REQUEST);
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * @return string
+ */
+ public function getClickByClickHeadline()
+ {
+ return 'Bitte im Shopware Backend einen eigenen Benutzer für Xentral anlegen und diese
+ Zugangsdaten hier eintragen.';
+ }
+
+ /**
+ * @return array
+ */
+ public function getStructureDataForClickByClickSave()
+ {
+ return [
+ 'shopwareAllowCreateManufacturer' => 1,
+ ];
+ }
+
+ /**
+ * @return array[]
+ */
+ public function getCreateForm()
+ {
+ return [
+ [
+ 'id' => 0,
+ 'name' => 'urls',
+ 'inputs' => [
+ [
+ 'label' => 'URL des Shops',
+ 'type' => 'text',
+ 'name' => 'shopwareUrl',
+ 'validation' => true,
+ ],
+ ],
+ ],
+ [
+ 'id' => 1,
+ 'name' => 'username',
+ 'inputs' => [
+ [
+ 'label' => 'Benutzername aus Shopware',
+ 'type' => 'text',
+ 'name' => 'shopwareUserName',
+ 'validation' => true,
+ ],
+ ],
+ ],
+ [
+ 'id' => 2,
+ 'name' => 'password',
+ 'inputs' => [
+ [
+ 'label' => 'Passwort aus Shopware',
+ 'type' => 'password',
+ 'name' => 'shopwarePassword',
+ 'validation' => true,
+ ],
+ ],
+ ],
+ ];
+ }
+
+ public function getBoosterHeadline(): string
+ {
+ return 'Shopware 6 Business Booster App';
+ }
+
+ public function getBoosterSubHeadline(): string
+ {
+ return 'Bitte gehe auf Shopware 6 und installiere dort das Plugin Xentral Business Booster App.
+ Dort kann man sich dann mit ein paar Klicks mit Xentral verbinden.';
+ }
+
+ /**
+ * @param int $intOrderId
+ *
+ * @return array
+ */
+ protected function getArticleShopLinks(int $intOrderId): array
+ {
+ return $this->app->DB->SelectPairs(
+ "SELECT DISTINCT ao.artikel, a.nummer
+ FROM `auftrag_position` AS `ap`
+ INNER JOIN `auftrag` AS `ab` ON ap.auftrag = ab.id
+ INNER JOIN `artikel` AS `a` ON ap.artikel = a.id
+ INNER JOIN `artikel_onlineshops` AS `ao` ON ab.shop = ao.shop AND a.id = ao.artikel
+ WHERE ab.id = {$intOrderId} AND ao.aktiv = 1"
+ );
+ }
+
+ /**
+ * @param array $articleIds
+ */
+ protected function updateArticleCacheToSync(array $articleIds): void
+ {
+ if(empty($articleIds)) {
+ return;
+ }
+ $articleIdsString = implode(', ', $articleIds);
+ $this->app->DB->Update(
+ "UPDATE `artikel`
+ SET `laststorage_changed` = DATE_ADD(NOW(), INTERVAL 1 SECOND)
+ WHERE `id` IN ({$articleIdsString})"
+ );
+ }
+
+ /**
+ * @param array $articleIds
+ */
+ protected function updateArticleOnlineShopCache(array $articleIds): void
+ {
+ if(empty($articleIds)) {
+ return;
+ }
+ $articleIdsString = implode(', ', $articleIds);
+ $this->app->DB->Update(
+ "UPDATE `artikel_onlineshops`
+ SET `storage_cache` = -999, `pseudostorage_cache` = -999
+ WHERE `artikel` IN ({$articleIdsString}) AND `aktiv` = 1 AND `shop` = {$this->shopid}"
+ );
+ }
+
+ /**
+ * @param int $intOrderId
+ */
+ protected function updateStorageForOrderIntId(int $intOrderId): void
+ {
+ $articles = $this->getArticleShopLinks($intOrderId);
+ if(empty($articles)) {
+ return;
+ }
+ $articleIds = array_keys($articles);
+ $this->updateArticleCacheToSync($articleIds);
+ $this->updateArticleOnlineShopCache($articleIds);
+
+ $isStorageSyncCronjobActive = (int)$this->app->DB->Select(
+ "SELECT COUNT(`id`) FROM `prozessstarter` WHERE `aktiv` = 1 AND `parameter` = 'lagerzahlen'"
+ ) > 0;
+ if(!$isStorageSyncCronjobActive) {
+ return;
+ }
+ foreach($articleIds as $articleId) {
+ try {
+ $this->app->erp->LagerSync($articleId, false, [$this->shopid]);
+ }
+ catch (Exception $e) {
+ $articleNumber = $articles[$articleId];
+ $this->Shopware6ErrorLog('LagerSync konnte nicht ausgeführt werden', $articleNumber);
+ }
+ }
+
+ $this->updateArticleCacheToSync($articleIds);
+ }
+}