mirakl create product initial

This commit is contained in:
OpenXE 2024-06-15 18:52:46 +02:00
parent f95918647a
commit b06e0aa3e4

View File

@ -29,6 +29,7 @@ class Shopimporter_Mirakl extends ShopimporterBase {
private $category_identifier; private $category_identifier;
private $offer_field_map; private $offer_field_map;
private $product_field_map;
public function __construct($app, $intern = false) { public function __construct($app, $intern = false) {
$this->app = $app; $this->app = $app;
@ -81,6 +82,31 @@ class Shopimporter_Mirakl extends ShopimporterBase {
'info' => '', 'info' => '',
'default' => 'kategoriename' 'default' => 'kategoriename'
], ],
'product_field_map' => [
'typ' => 'textarea',
'bezeichnung' => '{|Zuordnung Produkt-Felder je Kategorie (JSON)|}:',
'cols' => 80,
'rows' => 20,
'info' => 'Die Felder werden vom Mirakl-Betreiber vorgegeben. Ist keine Kategorie definiert, gilt der Eintrag für alle Artikel. Jedes Feld kann wie folgt zugeordnet werden:<br>Artikelfeld: &quot;Mirakel-Feldname&quot;: {&quot;feld&quot;: &quot;xyz&quot;} oder kurz &quot;Mirakel-Feldname&quot;: &quot;xyz&quot;,<br>Freifeld: &quot;Mirakel-Feldname&quot;: {&quot;freifeld&quot;: &quot;Bezeichnung in Shop&quot;} (Siehe Reiter &quot;Freifelder&quot;),<br>Eigenschaft: &quot;Mirakel-Feldname&quot;: {&quot;eigenschaft&quot;: &quot;Eigenschaftenname xyz&quot;},<br>Fester Wert: &quot;Mirakel-Feldname&quot;: {&quot;wert&quot;: &quot;xyz&quot;}<br><br>Zusatzfelder zusätzlich mit der Eigenschaft &quot;zusatzfeld&quot;: true versehen: z.B. &quot;Mirakel-Feldname&quot;: {&quot;feld&quot;: &quot;name_de&quot;, &quot;zusatzfeld&quot;: true}',
'placeholder' => '[
{
&quot;kategorien&quot;: [
&quot;Schuhe&quot;, &quot;Hosen&quot;
],
&quot;felder&quot;: {
&quot;category&quot;: {&quot;freifeld&quot;: &quot;Kategorie&quot;},
&quot;Product.SellerProductID&quot;: {&quot;feld&quot;: &quot;nummer&quot;},
&quot;SHOP.PRODUCT.TITLE&quot;: {&quot;feld&quot;: &quot;nummer&quot;},
&quot;ATT.GLOBAL.Brandname&quot;: {&quot;feld&quot;: &quot;preis&quot;},
&quot;Product.BaseUnit&quot;: {&quot;freifeld&quot;: &quot;Kategorie&quot;},
&quot;ATT.GLOBAL.NoCUperOU&quot;: {&quot;eigenschaft&quot;: &quot;Mirakl Steuertext&quot;},
&quot;ATT.GLOBAL.NoCUperOU__UNIT&quot;: {&quot;wert&quot;: &quot;false&quot;,&quot;zusatzfeld&quot;: true},
&quot;Product.TaxIndicator&quot;: {&quot;wert&quot;: &quot;1&quot;,&quot;zusatzfeld&quot;: true}
}
}
]'
],
'offer_field_map' => [ 'offer_field_map' => [
'typ' => 'textarea', 'typ' => 'textarea',
'bezeichnung' => '{|Zuordnung Angebots-Felder je Kategorie (JSON)|}:', 'bezeichnung' => '{|Zuordnung Angebots-Felder je Kategorie (JSON)|}:',
@ -146,9 +172,10 @@ class Shopimporter_Mirakl extends ShopimporterBase {
$this->category_identifier = array($einstellungen['felder']['category_identifier_source'] => $einstellungen['felder']['category_identifier_source_value']); $this->category_identifier = array($einstellungen['felder']['category_identifier_source'] => $einstellungen['felder']['category_identifier_source_value']);
$this->offer_field_map = json_decode($einstellungen['felder']['offer_field_map'], true, flags: JSON_THROW_ON_ERROR); $this->offer_field_map = json_decode($einstellungen['felder']['offer_field_map'], true, flags: JSON_THROW_ON_ERROR);
$this->product_field_map = json_decode($einstellungen['felder']['product_field_map'], true, flags: JSON_THROW_ON_ERROR);
} }
private function miraklRequest(string $endpoint, $postdata = null, array $getdata = null, string $content_type = null, bool $raw = false) { private function miraklRequest(string $endpoint, $postdata = null, array $getdata = null, string $content_type = null, bool $raw = false, $debug = false, $debugurl = null) {
$ch = curl_init(); $ch = curl_init();
$url_addition = ""; $url_addition = "";
@ -171,10 +198,17 @@ class Shopimporter_Mirakl extends ShopimporterBase {
if (!empty($postdata)) { if (!empty($postdata)) {
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST'); curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
curl_setopt($ch, CURLOPT_POSTFIELDS, $postdata); curl_setopt($ch, CURLOPT_POSTFIELDS, $postdata);
$headers[] = 'Content-Type: ' . $content_type; $headers[] = 'Content-Type: ' . $content_type;
} }
curl_setopt($ch, CURLOPT_URL, $this->shopUrl . $endpoint . $url_addition); if ($debugurl) {
$url = $debugurl;
} else {
$url = $this->shopUrl;
}
curl_setopt($ch, CURLOPT_URL, $url . $endpoint . $url_addition);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLINFO_HEADER_OUT, true); curl_setopt($ch, CURLINFO_HEADER_OUT, true);
curl_setopt($ch, CURLOPT_VERBOSE, true); curl_setopt($ch, CURLOPT_VERBOSE, true);
@ -187,11 +221,12 @@ class Shopimporter_Mirakl extends ShopimporterBase {
$information = curl_getinfo($ch); $information = curl_getinfo($ch);
/* print_r($information); if ($debug) {
print_r($postdata); print_r($information);
print_r($response); print_r($postdata);
exit(); print_r($response);
*/ exit();
}
if ($raw) if ($raw)
return $response; return $response;
@ -288,6 +323,8 @@ class Shopimporter_Mirakl extends ShopimporterBase {
$articleList = $this->CatchRemoteCommand('data'); $articleList = $this->CatchRemoteCommand('data');
$this->Log('ImportSendList start', print_r($articleList,true));
// First gather all articles as offers and send them // First gather all articles as offers and send them
// Wait for import to finish // Wait for import to finish
// Evaluate import // Evaluate import
@ -378,12 +415,15 @@ class Shopimporter_Mirakl extends ShopimporterBase {
$json_for_mirakl = json_encode($data_for_mirakl); $json_for_mirakl = json_encode($data_for_mirakl);
$this->Log('posting offer data', $json_for_mirakl);
$result = []; $result = [];
$response = $this->miraklRequest('offers', postdata: $json_for_mirakl, content_type: 'application/json', raw: true); $response = $this->miraklRequest('offers', postdata: $json_for_mirakl, content_type: 'application/json', raw: true);
$result = json_decode($response); $result = json_decode($response);
if (!isset($result->import_id)) { if (!isset($result->import_id)) {
$this->Log('posting offer data error', print_r($response,true));
return(array('status' => false, 'message' => "Angebotsimport in Mirakl abgelehnt: ".print_r($response,true))); return(array('status' => false, 'message' => "Angebotsimport in Mirakl abgelehnt: ".print_r($response,true)));
} }
@ -405,16 +445,120 @@ class Shopimporter_Mirakl extends ShopimporterBase {
} }
if ($status == 'FAILED') { if ($status == 'FAILED') {
$this->Log('importing of offer data failed in mirakl', print_r($response,true));
return(array('status' => false, 'message' => "Angebotsimport in Mirakl fehlgeschlagen: ".print_r($response,true))); return(array('status' => false, 'message' => "Angebotsimport in Mirakl fehlgeschlagen: ".print_r($response,true)));
} }
if ($result->lines_in_error == 0) { if ($result->lines_in_error == 0) {
$this->Log('importing of offer data ok', print_r($response,true));
return($result->lines_in_success); return($result->lines_in_success);
} }
// Check errors $this->Log('importing of offer returned with '.$result->lines_in_error.' lines', print_r($response,true));
$result = array();
// Check errors with CSV unfucking...
$response = $this->miraklRequest('offers/imports/'.$import_id.'/error_report', raw: true); $response = $this->miraklRequest('offers/imports/'.$import_id.'/error_report', raw: true);
return(array('status' => false, 'message' => "Angebotsimport in Mirakl hat Fehler: ".print_r($response,true))); $response_lines = preg_split('/\R/', $response, flags: PREG_SPLIT_NO_EMPTY);
$error_message_key = null;
$firstline = true;
foreach ($response_lines as $response_line) {
$response_array = str_getcsv($response_line,';','"');
if ($firstline) {
$error_message_key = array_search("error-message",$response_array);
$firstline = false;
continue;
}
switch ($response_array[$error_message_key]) {
case 'The product does not exist':
// Try to create the product
$product_for_mirakl = array();
print_r($this->product_field_map);
foreach ($this->product_field_map as $product_field_entry) {
foreach ($product_field_entry['felder'] as $product_field => $product_field_source) {
if (!is_array($product_field_source)) {
$product_field_source = array('feld' => $product_field_source);
}
$product_field_value = null;
$product_field_value = $this->GetFieldValue($article, $product_field_source);
$product_for_mirakl[$product_field] = $product_field_value;
}
}
$this->Log('creating product', print_r($product_for_mirakl,true));
// Create CSV from array
$csv1 .= '"'.implode('";"',array_keys($product_for_mirakl)).'"';
$csv2 .= '"'.implode('";"',$product_for_mirakl).'"';
$csv = $csv1."\r\n".$csv2;
$result = [];
$this->Log('creating product csv', print_r($csv,true));
$postdata = array('file' => new CURLStringFile(postname: 'import.csv', data: $csv));
$response = $this->miraklRequest('products/imports', postdata: $postdata, content_type: 'multipart/form-data', raw: true);
$result = json_decode($response);
$this->Log('posting product data posted', print_r($result,true));
if (!isset($result->import_id)) {
$this->Log('posting product data error', print_r($response,true));
return(array('status' => false, 'message' => "Produktimport in Mirakl abgelehnt: ".print_r($response,true)));
}
$import_id = $result->import_id;
// Wait for import to finish
$status = null;
/*
WAITING_SYNCHRONIZATION_PRODUCT, WAITING, RUNNING, COMPLETE, FAILED
*/
while ($status != 'COMPLETE' && $status != 'FAILED') {
sleep(5);
$response = $this->miraklRequest('products/imports/'.$import_id, raw: true);
$result = json_decode($response);
$status = $result->import_status;
}
if ($status == 'FAILED') {
$this->Log('importing of product data failed in mirakl', print_r($response,true));
return(array('status' => false, 'message' => "Produktimport in Mirakl fehlgeschlagen: ".print_r($response,true)));
}
if ($result->transform_lines_in_error == 0) {
$this->Log('importing of product data ok', print_r($response,true));
return($result->lines_in_success);
}
$this->Log('importing of product returned with '.$result->transform_lines_in_error.' error lines', print_r($response,true));
$response = $this->miraklRequest('products/imports/'.$import_id.'/transformation_error_report', raw: true);
$this->Log('product import error report', print_r($response,true));
break;
default:
$result[] = array('Unhandled error' => $response_array);
break;
}
}
return(array('status' => false, 'message' => "Angebotsimport in Mirakl hat Fehler: ".print_r($result,true)));
} }
@ -424,7 +568,7 @@ class Shopimporter_Mirakl extends ShopimporterBase {
private function Log($message, $dump = '') { private function Log($message, $dump = '') {
if ($this->protocol) { if ($this->protocol) {
$this->app->erp->Logfile($message, print_r($dump, true)); $this->app->erp->Logfile('Mirakl (Shop '.$this->shopid.') '.$message, print_r($dump, true));
} }
} }