Merge pull request #57 from exciler/prestashop

Prestashop
This commit is contained in:
OpenXE-ERP 2023-03-13 13:00:06 +01:00 committed by GitHub
commit f5b326682c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 504 additions and 20 deletions

View File

@ -29243,11 +29243,23 @@ function Firmendaten($field,$projekt="")
$process_lock = $this->app->erp->ProzessLock("erpapi_getnextnummer");
$eigenernummernkreis = 0;
$eigenernummernkreis = $this->app->DB->Select("SELECT eigenernummernkreis FROM projekt WHERE id='$projekt' LIMIT 1");
$belegnr = '';
if($eigenernummernkreis=='1')
{
$allowedtypes = ['angebot', 'auftrag', 'rechnung', 'lieferschein', 'arbeitsnachweis', 'reisekosten',
'bestellung', 'gutschrift', 'kundennummer', 'lieferantennummer', 'mitarbeiternummer', 'waren',
'produktion', 'sonstiges', 'anfrage', 'artikelnummer', 'kalkulation', 'preisanfrage', 'proformarechnung',
'retoure', 'verbindlichkeit', 'goodspostingdocument', 'receiptdocument'];
} else {
$dbfield = "next_$type";
$belegnr = $this->app->DB->Select("SELECT $dbfield FROM projekt WHERE id='$projekt' LIMIT 1");
if (!empty($belegnr)) {
$newbelegnr = $this->CalcNextNummer($belegnr);
$this->app->DB->Update("UPDATE projekt SET $dbfield='$newbelegnr' WHERE id='$projekt' LIMIT 1");
}
}
if (empty($belegnr)) {
// naechste
switch($type)
{

View File

@ -1,4 +1,11 @@
<?php
<?php
/*
* SPDX-FileCopyrightText: 2022 Andreas Palm
* SPDX-FileCopyrightText: 2019 Xentral (c) Xentral ERP Software GmbH, Fuggerstrasse 11, D-86150 Augsburg, Germany
*
* SPDX-License-Identifier: LicenseRef-EGPL-3.1
*/
/*
**** COPYRIGHT & LICENSE NOTICE *** DO NOT REMOVE ****
*
@ -10,8 +17,8 @@
* to obtain the text of the corresponding license version.
*
**** END OF COPYRIGHT & LICENSE NOTICE *** DO NOT REMOVE ****
*/
?>
*/
?>
<?php
use Xentral\Modules\Onlineshop\Data\ShopConnectorResponseInterface;
@ -734,8 +741,12 @@ class Remote
if($v['path'] != '' && $v['content'] != '')
{
$path_parts = pathinfo($v['path']);
$fileid = $this->app->erp->CreateDatei($path_parts['basename'], 'Shopbild', '', '', base64_decode($v['content']), 'Cronjob');
$tmpfilename = tempnam($this->app->erp->GetTMP(), 'img');
file_put_contents($tmpfilename, base64_decode($v['content']));
$fileid = $this->app->erp->CreateDatei($path_parts['basename'], 'Shopbild', '', '', $tmpfilename, 'Cronjob');
$this->app->erp->AddDateiStichwort($fileid, 'Shopbild', 'artikel', $articleid);
if (@is_file($tmpfilename))
unlink($tmpfilename);
}
}
}elseif($dateien[0]['subjekt'] === 'shopbild'){
@ -766,12 +777,16 @@ class Remote
if($v['path'] != '' && $v['content'] != '')
{
$path_parts = pathinfo($v['path']);
$fileid = $this->app->erp->CreateDatei($path_parts['basename'], 'Shopbild', '', '', base64_decode($v['content']), 'Cronjob');
$tmpfilename = tempnam($this->app->erp->GetTMP(), 'img');
file_put_contents($tmpfilename, base64_decode($v['content']));
$fileid = $this->app->erp->CreateDatei($path_parts['basename'], 'Shopbild', '', '', $tmpfilename, 'Cronjob');
if(isset($v['id']))
{
$this->ShopexportMappingSet($id, 'datei', $fileid, $v['id'], $articleid);
}
$this->app->erp->AddDateiStichwort($fileid, 'Shopbild', 'artikel', $articleid);
if (@is_file($tmpfilename))
unlink($tmpfilename);
}
}
}

View File

@ -1,4 +1,11 @@
<?php
<?php
/*
* SPDX-FileCopyrightText: 2022 Andreas Palm
* SPDX-FileCopyrightText: 2019 Xentral (c) Xentral ERP Software GmbH, Fuggerstrasse 11, D-86150 Augsburg, Germany
*
* SPDX-License-Identifier: LicenseRef-EGPL-3.1
*/
/*
**** COPYRIGHT & LICENSE NOTICE *** DO NOT REMOVE ****
*
@ -10,8 +17,8 @@
* to obtain the text of the corresponding license version.
*
**** END OF COPYRIGHT & LICENSE NOTICE *** DO NOT REMOVE ****
*/
?>
*/
?>
<?php
use Xentral\Components\Http\JsonResponse;
use Xentral\Modules\SystemConfig\SystemConfigModule;
@ -2620,7 +2627,7 @@ class Appstore {
,'shopimporter_presta'=>array('Bezeichnung'=>'Presta',
'Link'=>'index.php?module=onlineshops&action=create&cmd=shopimporter_presta',
'Icon'=>'Icons_dunkel_1.gif',
'Versionen'=>'ENT','install'=>true, 'beta' => false,'kategorie'=>'{|Shop Schnittstelle|}')
'Versionen'=>'ALL','install'=>true, 'beta' => false,'kategorie'=>'{|Shop Schnittstelle|}')
,'shopimporter_shopify'=>array(
'Bezeichnung'=>'Shopify API Advanced',
'Link'=>'index.php?module=onlineshops&action=create&cmd=shopimporter_shopify',

View File

@ -1,4 +1,11 @@
<?php
<?php
/*
* SPDX-FileCopyrightText: 2022 Andreas Palm
* SPDX-FileCopyrightText: 2019 Xentral (c) Xentral ERP Software GmbH, Fuggerstrasse 11, D-86150 Augsburg, Germany
*
* SPDX-License-Identifier: LicenseRef-EGPL-3.1
*/
/*
**** COPYRIGHT & LICENSE NOTICE *** DO NOT REMOVE ****
*
@ -10,8 +17,8 @@
* to obtain the text of the corresponding license version.
*
**** END OF COPYRIGHT & LICENSE NOTICE *** DO NOT REMOVE ****
*/
?>
*/
?>
<?php
class Shopimport
@ -830,7 +837,7 @@ class Shopimport
// denn fall das es kunde 1:1 schon gibt = alte Kundennummer verwenden kommt vor allem vor, wenn ein Kunde an einem Tag oefters bestellt hat
// $adresse = $this->app->erp->KundeAnlegen($typ,$name,$abteilung,
// $unterabteilung,$ansprechpartner,$adresszusatz,$strasse,$land,$plz,$ort,$email,$telefon,$telefax,$ustid,$partner,$projekt);
if(strlen($warenkorb['kundennummer'])!=''){
if(!empty($warenkorb['kundennummer'])){
$adresse = $this->app->DB->Select("SELECT id FROM adresse WHERE kundennummer='{$warenkorb['kundennummer']}' $adresseprojekt AND geloescht!=1 LIMIT 1");
}

View File

@ -0,0 +1,436 @@
<?php
/*
* SPDX-FileCopyrightText: 2022 Andreas Palm
*
* SPDX-License-Identifier: LicenseRef-EGPL-3.1
*/
class Shopimporter_Presta extends ShopimporterBase
{
private $app;
private $intern;
private $shopid;
private $data;
private $protocol;
private $apiKey;
private $shopUrl;
private $createManufacturerAllowed = false;
private $idsabholen;
private $idbearbeitung;
private $idabgeschlossen;
// TODO
private $langidToIso = [3 => 'de', 1 => 'en'];
private $taxationByDestinationCountry;
public function __construct($app, $intern = false)
{
$this->app = $app;
$this->intern = $intern;
if ($intern)
return;
}
public function EinstellungenStruktur()
{
return [
'ausblenden' => ['abholmodus' => ['ab_nummer', 'zeitbereich']],
'functions' => ['getarticlelist'],
'felder' => [
'protokoll' => [
'typ' => 'checkbox',
'bezeichnung' => '{|Protokollierung im Logfile|}:'
],
'textekuerzen' => [
'typ' => 'checkbox',
'bezeichnung' => '{|Texte bei Artikelexport auf Maximallänge kürzen|}:'
],
'useKeyAsParameter' => [
'typ' => 'checkbox',
'bezeichnung' => '{|Shop Version ist mindestens 1.6.1.1|}:'
],
'apikey' => [
'typ' => 'text',
'bezeichnung' => '{|API Key|}:',
'size' => 40,
],
'shopurl' => [
'typ' => 'text',
'bezeichnung' => '{|Shop URL|}:',
'size' => 40,
],
'shopidpresta' => [
'typ' => 'text',
'bezeichnung' => '{|Shop ID des Shops|}:',
'size' => 40,
],
'steuergruppen' => [
'typ' => 'text',
'bezeichnung' => '{|Steuergruppenmapping|}:',
'size' => 40,
],
'zustand' => [
'typ' => 'text',
'bezeichnung' => '{|Freifeld Zustand|}:',
'size' => 40,
],
'abholen' => [
'typ' => 'text',
'bezeichnung' => '{|\'Abholen\' Status IDs|}:',
'size' => 40,
],
'bearbeitung' => [
'typ' => 'text',
'bezeichnung' => '{|\'In Bearbeitung\' Status IDs|}:',
'size' => 40,
],
'abgeschlossen' => [
'typ' => 'text',
'bezeichnung' => '{|\'Abgeschlossen\' Status IDs|}:',
'size' => 40,
],
'autoerstellehersteller' => [
'typ' => 'checkbox',
'bezeichnung' => '{|Fehlende Hersteller automatisch anlegen|}:',
'col' => 2
],
'zeigezustand' => [
'typ' => 'checkbox',
'bezeichnung' => '{|Artikelzustand im Shop anzeigen|}:',
'col' => 2
],
'zeigepreis' => [
'typ' => 'checkbox',
'bezeichnung' => '{|Artikelpreis im Shop anzeigen|}:',
'col' => 2
],
]
];
}
public function getKonfig($shopid, $data)
{
$this->shopid = $shopid;
$this->data = $data;
$importerSettings = $this->app->DB->SelectArr("SELECT `einstellungen_json` FROM `shopexport` WHERE `id` = '$shopid' LIMIT 1");
$importerSettings = reset($importerSettings);
$einstellungen = [];
if (!empty($importerSettings['einstellungen_json'])) {
$einstellungen = json_decode($importerSettings['einstellungen_json'], true);
}
$this->protocol = $einstellungen['felder']['protokoll'];
$this->apiKey = $einstellungen['felder']['apikey'];
$this->shopUrl = rtrim($einstellungen['felder']['shopurl'], '/') . '/';
if ($einstellungen['felder']['autoerstellehersteller'] === '1') {
$this->createManufacturerAllowed = true;
}
$this->idsabholen = $einstellungen['felder']['abholen'];
$this->idbearbeitung = $einstellungen['felder']['bearbeitung'];
$this->idabgeschlossen = $einstellungen['felder']['abgeschlossen'];
$query = sprintf('SELECT `steuerfreilieferlandexport` FROM `shopexport` WHERE `id` = %d', $this->shopid);
$this->taxationByDestinationCountry = !empty($this->app->DB->Select($query));
}
public function ImportAuth() {
$ch = curl_init($this->shopUrl);
curl_setopt($ch, CURLOPT_USERNAME, $this->apiKey);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
$code = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
if ($code == 200)
return 'success';
return $response;
}
public function ImportDeleteAuftrag()
{
$auftrag = $this->data['auftrag'];
$obj = $this->prestaRequest('GET', 'order_histories?schema=blank');
$obj->order_history->id_order = $auftrag;
$obj->order_history->id_order_state = $this->idbearbeitung;
$this->prestaRequest('POST', 'order_histories', $obj->asXML());
}
public function ImportUpdateAuftrag()
{
$auftrag = $this->data['auftrag'];
$obj = $this->prestaRequest('GET', 'order_histories?schema=blank');
$obj->order_history->id_order = $auftrag;
$obj->order_history->id_order_state = $this->idabgeschlossen;
$this->prestaRequest('POST', 'order_histories', $obj->asXML());
$req = $this->prestaRequest('GET', "order_carriers?filter[id_order]=$auftrag&display=[id]");
$orderCarrierId = strval($req->order_carriers->order_carrier[0]->id);
$req = $this->prestaRequest('GET', "order_carriers/$orderCarrierId");
$req->order_carrier->tracking_number = $this->data['tracking'];
$this->prestaRequest('PUT', "order_carriers/$orderCarrierId", $req->asXML());
}
public function ImportGetAuftraegeAnzahl()
{
$ordersToProcess = $this->getOrdersToProcess($this->getOrderSearchLimit());
return count($ordersToProcess);
}
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");
if (empty($this->idsabholen)) {
return false;
}
$expectOrderArray = !empty($this->data['anzgleichzeitig']) && (int)$this->data['anzgleichzeitig'] > 1;
$expectNumber = !empty($this->data['nummer']);
if ($expectNumber) {
$ordersToProcess = [$this->data['nummer']];
} elseif (!$expectOrderArray) {
$ordersToProcess = $this->getOrdersToProcess(1);
} else {
$ordersToProcess = $this->getOrdersToProcess($this->getOrderSearchLimit());
}
$fetchedOrders = [];
foreach ($ordersToProcess as $currentOrderId) {
$order = $this->prestaRequest('GET', "orders/$currentOrderId");
$order = $order->order;
$cart = [];
$cart['zeitstempel'] = strval($order->date_add);
$cart['auftrag'] = strval($order->id);
$cart['onlinebestellnummer'] = strval($order->reference);
$cart['gesamtsumme'] = strval($order->total_paid);
$cart['versandkostennetto'] = strval($order->total_shipping_tax_excl);
$cart['bestelldatum'] = strval($order->date_add);
$carrier = $this->prestaRequest('GET', "carriers/$order->id_carrier");
$cart['lieferung'] = strval($carrier->carrier->name);
$customer = $this->prestaRequest('GET', "customers/$order->id_customer");
$cart['email'] = strval($customer->customer->email);
$language = $this->prestaRequest('GET', "languages/{$customer->customer->id_lang}");
if ($language->language->iso_code == "en") {
$cart['kunde_sprache'] = 'englisch';
}
$invoiceAddress = $this->prestaRequest('GET', "addresses/$order->id_address_invoice");
$invoiceAddress = $invoiceAddress->address;
$invoiceCountry = $this->prestaRequest('GET', "countries/$invoiceAddress->id_country");
$invoiceCountry = $invoiceCountry->country;
$cart['name'] = "$invoiceAddress->firstname $invoiceAddress->lastname";
if (!empty(strval($invoiceAddress->company))) {
$cart['ansprechpartner'] = $cart['name'];
$cart['name'] = strval($invoiceAddress->company);
}
$cart['strasse'] = strval($invoiceAddress->address1);
$cart['adresszusatz'] = strval($invoiceAddress->address2);
$cart['telefon'] = strval($invoiceAddress->phone_mobile);
if (empty($cart['telefon']))
$cart['telefon'] = strval($invoiceAddress->phone);
$cart['plz'] = strval($invoiceAddress->postcode);
$cart['ort'] = strval($invoiceAddress->city);
$cart['ustid'] = strval($invoiceAddress->vat_number);
$cart['land'] = strval($invoiceCountry->iso_code);
if (strval($order->id_address_invoice) != strval($order->id_address_delivery)) {
$deliveryAddress = $this->prestaRequest('GET', "addresses/$order->id_address_delivery");
$deliveryAddress = $deliveryAddress->address;
$deliveryCountry = $this->prestaRequest('GET', "countries/$deliveryAddress->id_country");
$deliveryCountry = $deliveryCountry->country;
$cart['abweichendelieferadresse'] = 1;
$cart['lieferadresse_name'] = "$deliveryAddress->firstname $deliveryAddress->lastname";
if (!empty(strval($deliveryAddress->company))) {
$cart['lieferadresse_ansprechpartner'] = $cart['lieferadresse_name'];
$cart['lieferadresse_name'] = strval($deliveryAddress->company);
}
$cart['lieferadresse_strasse'] = strval($deliveryAddress->address1);
$cart['lieferadresse_adresszusatz'] = strval($deliveryAddress->address2);
$cart['lieferadresse_plz'] = strval($deliveryAddress->postcode);
$cart['lieferadresse_ort'] = strval($deliveryAddress->city);
$cart['lieferadresse_land'] = strval($deliveryCountry->iso_code);
}
//TODO
//$cart['transaktionsnummer']
$cart['zahlungsweise'] = strval($order->payment);
$taxedCountry = $cart['land'];
if (!empty($cart['lieferadresse_land']) && $this->taxationByDestinationCountry) {
$taxedCountry = $cart['lieferadresse_land'];
}
$lieferschwelle = $this->app->DB->SelectArr("SELECT * FROM lieferschwelle WHERE empfaengerland='$taxedCountry' LIMIT 1");
if ($this->app->erp->IstEU($taxedCountry) || !empty($lieferschwelle['ueberschreitungsdatum'])) {
$cart['ust_befreit'] = 1;
} elseif ($this->app->erp->Export($taxedCountry)) {
$cart['ust_befreit'] = 2;
}
$taxes = [];
$this->app->erp->RunHook('getTaxRatesFromShopOrder', 2, $taxedCountry, $taxes);
if (isset($taxes['normal']) && $taxes['normal'] > 0)
$cart['steuersatz_normal'] = $taxes['normal'];
if (isset($taxes['ermaessigt']) && $taxes['ermaessigt'] > 0)
$cart['steuersatz_ermaessigt'] = $taxes['ermaessigt'];
$cart['articlelist'] = [];
foreach ($order->associations->order_rows->order_row as $order_row) {
$steuersatz = (strval($order_row->unit_price_tax_incl) / strval($order_row->unit_price_tax_excl)) - 1;
$steuersatz = round($steuersatz, 1);
$cart['articlelist'][] = [
'articleid' => strval($order_row->product_reference),
'name' => strval($order_row->product_name),
'quantity' => strval($order_row->product_quantity),
'price_netto' => strval($order_row->unit_price_tax_excl),
'steuersatz' => $steuersatz
];
}
$fetchedOrders[] = [
'id' => $cart['auftrag'],
'sessionid' => '',
'logdatei' => '',
'warenkorb' => base64_encode(serialize($cart)),
'warenkorbjson' => base64_encode(json_encode($cart)),
];
}
$this->Log('Precessed order from presta', $fetchedOrders);
return $fetchedOrders;
}
public function ImportGetArticleList()
{
$result = [];
$response = $this->prestaRequest('GET', 'products?display=[reference]');
foreach ($response->products->product as $product) {
$result[] = $product->reference;
}
array_unique($result);
return $result;
}
public function ImportGetArticle()
{
$nummer = $this->data['nummer'];
if (isset($this->data['nummerintern'])) {
$nummer = $this->data['nummerintern'];
}
$nummer = trim($nummer);
if (empty($nummer))
return;
$searchresult = $this->prestaRequest('GET', 'products?filter[reference]='.$nummer);
if (empty($searchresult)) {
$this->Log('No product found in Shop', $this->data);
return;
}
if (count($searchresult->products->product) > 1) {
$this->Log('Got multiple results from Shop', $this->data);
}
$productid = $searchresult->products->product->attributes()->id;
$product = $this->prestaRequest('GET', "products/$productid");
$res = [];
$res['nummer'] = strval($product->product->reference);
$res['artikelnummerausshop'] = strval($product->product->reference);
$names = $this->toMultilangArray($product->product->name->language);
$descriptions = $this->toMultilangArray($product->product->description->language);
$shortdescriptions = $this->toMultilangArray($product->product->description_short->language);
$res['name'] = $names['de'];
$res['name_en'] = $names['en'];
$res['uebersicht_de'] = $descriptions['de'];
$res['uebersicht_en'] = $descriptions['en'];
$res['preis_netto'] = strval($product->product->price);
$res['hersteller'] = strval($product->product->manufacturer_name);
$res['ean'] = strval($product->product->ean13);
$images = [];
foreach ($product->product->associations->images->image as $img) {
$endpoint = "images/products/$productid/$img->id";
$imgdata = $this->prestaRequest('GET', $endpoint, '', true);
$images[] = [
'content' => base64_encode($imgdata),
'path' => "$img->id.jpg",
'id' => $img->id
];
}
$res['bilder'] = $images;
return $res;
}
private function toMultilangArray($xmlnode) {
$res = [];
foreach ($xmlnode as $item) {
$iso = $this->langidToIso[strval($item->attributes()->id)];
$res[$iso] = strval($item);
}
return $res;
}
private function getOrdersToProcess(int $limit)
{
$states = implode('|', explode(',', $this->idsabholen));
$response = $this->prestaRequest('GET', "orders?display=[id]&limit=$limit&filter[current_state]=[$states]");
$result = [];
foreach ($response->orders->order as $order) {
$result[] = strval($order->id);
}
return $result;
}
public function getOrderSearchLimit(): int
{
if(in_array($this->orderSearchLimit, ['50', '75', '100'])) {
return (int)$this->orderSearchLimit;
}
return 25;
}
private function Log($message, $dump = '')
{
if ($this->protocol) {
$this->app->erp->Logfile($message, print_r($dump, true));
}
}
private function prestaRequest($method, $endpoint, $data = '', $raw = false)
{
$url = $this->shopUrl . $endpoint;
$url = str_replace('[', '%5b', $url);
$url = str_replace(']', '%5d', $url);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
if (!empty($data)) {
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
}
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
curl_setopt($ch, CURLOPT_USERNAME, $this->apiKey);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
if (curl_error($ch)) {
$this->error[] = curl_error($ch);
}
curl_close($ch);
if ($raw)
return $response;
return simplexml_load_string($response);
}
}

View File

@ -1,4 +1,11 @@
<?php
<?php
/*
* SPDX-FileCopyrightText: 2022 Andreas Palm
* SPDX-FileCopyrightText: 2019 Xentral (c) Xentral ERP Software GmbH, Fuggerstrasse 11, D-86150 Augsburg, Germany
*
* SPDX-License-Identifier: LicenseRef-EGPL-3.1
*/
/*
**** COPYRIGHT & LICENSE NOTICE *** DO NOT REMOVE ****
*
@ -10,8 +17,8 @@
* to obtain the text of the corresponding license version.
*
**** END OF COPYRIGHT & LICENSE NOTICE *** DO NOT REMOVE ****
*/
?>
*/
?>
<?php
use Xentral\Components\Http\JsonResponse;
@ -154,7 +161,7 @@ class Steuersaetze {
$ret = [];
$taxes = $this->app->DB->SelectArr(
sprintf(
"SELECT DISTINCT `satz`
"SELECT DISTINCT `type`, `satz`
FROM `steuersaetze`
WHERE `aktiv` = 1
AND (`country_code` = '%s' OR (`bezeichnung` = '%s' AND `country_code` = ''))",
@ -163,7 +170,7 @@ class Steuersaetze {
);
if(!empty($taxes)) {
foreach($taxes as $rates) {
$ret[] = $rates['satz'];
$ret[$rates['type']] = $rates['satz'];
}
}