diff --git a/README.md b/README.md
index cca69b7..ed922b7 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,21 @@
-Repository with Teclib modules for Dolibarr ERP CRM
+Use it at you onwn risk
+Open-DSI does not provide support for the use, installation or bug fixing for this software. For this you have to acquire a time credit on our online shop.
+https://www.open-dsi.fr/boutique/
+You can also consult our company for any installation, configuration or development services.
+Forker Repository of Teclib modules for Dolibarr ERP CRM
+Only use to maintain ecommerceng module for Woocommerce
+Before any use, please refer to the wiki to check the available functionnality
+https://wiki.dolibarr.org/index.php/Module_woocommerce_EN
+and read the document in
+htdocs/ecommerceng/doc/
+
+Utilisation à vos risques et périls.
+Open-DSI ne fournit pas de support à l’utilisation, à l'installation ni de correction de bugs pour ce logiciel. Pour cela vous devrez faire l’acquisition d’un crédit temps sur notre boutique en ligne.
+https://www.open-dsi.fr/boutique/
+Vous pouvez également nous consulter pour toute prestation d’installation, configuration ou développement.
+Dépôt forké depuis celui de Teclib
+Utilisé pour maintenir et publier le module ecommerceng pour WooCommerce
+Avant toute utilisation, merci de prendre connaissance du wiki pour vérifier si le module répond en l'état à vos besoins
+https://wiki.dolibarr.org/index.php/Module_woocommerce_EN
+et lire la documentaion disponible dans
+htdocs/ecommerceng/doc/
diff --git a/htdocs/ecommerceng/ChangeLog.md b/htdocs/ecommerceng/ChangeLog.md
index cadd7d9..888c674 100644
--- a/htdocs/ecommerceng/ChangeLog.md
+++ b/htdocs/ecommerceng/ChangeLog.md
@@ -1,5 +1,60 @@
# ChangeLog
+## 4.0.3.0
+
+- Enregistre la société pour les clients anonymes pour chaque site et non dans l'option ECOMMERCENG_USE_THIS_THIRDPARTY_FOR_NONLOGGED_CUSTOMER
+- Correction de la quantités des éléments lié au site pour la fiche du site (en non pour tous les sites)
+- Ajout d'une option ECOMMERCENG_NO_COUNT_UPDATE pour ne pas récupérer les quantités à mettre à jour et afficher tous les boutons de synchronisation sur la fiche du site.
+- Correction de la recherche de correspondance lors de la synchro des catégories
+- Correction de la récupération des produits et de ses variantes
+- Correction de la recherche de la ref du produits dans Dolibarr lors de la synchro
+- Ne re-télécharge pas les informations du client pour recupérer les adresses du clients lors de la synchro des sociétés
+- Lors de la synchro des contacts, rempli le nom si vide par "\[nom non renseigné\]" ou "Pas de nom/prénom renseigné" en fonction des cas
+- Similaire pour les nom des tiers
+- Ajout de l'option ECOMMERCENG_WOOCOMMERCE_ORDER_PROCESSING_STATUS_TO_DRAFT pour ne forcer les commandes woocommerce au statut "En cours" redescende au statut "Brouillon" dans Dolibarr
+- Les commandes woocommerce au statut "Remboursées" redescende au statut "Annulée" dans Dolibarr
+- Definie la description d'une ligne de produit vide par "L'api n'a pas pu récupérer la description du produit"
+- Cherche la societe du contact d'une commande par son adresse mail si fourni pour les commandes anonymes
+- Correction de la recherche d'un contact par ses informations
+- Correction d'une partie de la gestion des erreurs
+- Les logs bas niveaux woocommerce sont au niveau DEBUG et plus au niveau INFO
+- Corrections mineures
+
+## 4.0.2.0
+
+- D'un champ complémetaire oublié pour la fiche d'un produit d'un site woocommerce
+- Affiche du lien de test sur les parametres du site que si l'adresse du site est renseigné
+- Ajout de la description de l'erreur lors du fonctionnement de l'OAuth 2
+- Corrections mineures
+
+## 4.0.1.0
+
+- Ajout OAuth2 pour Wordpress
+- Mise en commun du type de prix renvoyé par la boutique (HT / TTC)
+- Lien de test en fonction du type du site
+- Creation de champ complémentaire à l'ajout d'un site Woocommerce
+- Ajout de la gestion des classes de TVA Woocommerce pour les produits + Dictionnaire
+- Ajout des fonctions de recherche, insert et update à la classe eCommerceDict
+- Ajout et modification de traductions
+- Corrections du decodage de la reponse de l'API Woocommerce
+- Ajout de la synchronisation du produit lors de l'ajout de la catégorie mère "E-Commerce" (Trigger)
+- Ne synchronise pas le produit lorsque l'on envèle la catégorie mère "E-Commerce" (Trigger)
+- Creation du produit sur le site depuis dolibarr (Trigger)
+- Correction du statut réel de la commande lors de la synchro de Dolibarr vers E-Commerce (Trigger)
+- Ajout test connection a l'appel de la fonction connect de la classe remote access de Woocommerce
+- Correction de la gestion des dates lors des fonctions ToUpdate de Woocommerce
+- Modification gestion des tiers (avec recherche doublon par email, nom, ...) et distinctions entreprise/particulier
+- Modification gestion des contacts/adresses avec recherche doublon
+- Modification gestion des catégories avec recherche doublon
+- Modification de mise a jour du prix du produit
+- Ajout de gestion des extrafields sur les produits et commandes
+- Ajout de la synchro methode de paiment sur la commande dans la synchro E-Commerce vers Dolibarr
+- Ajout ECOMMERCENG_WOOCOMMERCE_FORCE_ORDER_STATUS_TO_DRAFT pour forcer le statut de la commande en brouillon lors de la synchro Woocommerce vers Dolibarr- Ajout de la possibilité d'ignorer les commandes anonyme avec la variable ECOMMERCENG_PASS_ORDER_FOR_NONLOGGED_CUSTOMER
+- Ajout synchronisation des images avec E-commerce (possibilité de l'activer avec la variable ECOMMERCENG_ENABLE_SYNCHRO_IMAGES) (Necessite paramétrage OAuth2 pour l'envoi des images vers Woocommerce)
+- Ajout envoie PDF facture / expedition à la génération du PDF sur la commande Woocommerce via Wordpress (Necessite paramétrage OAuth2) (l'activer avec la variable ECOMMERCENG_ENABLE_SEND_FILE_TO_ORDER)
+- Ajout synchro des catégories de Woocommerce vers Dolibarr
+- Corrections diverses
+
## 3.9.1.0
- Add option ECOMMERCENG_THIRDPARTY_UNIQUE_ON to search existing thirdparties from email instead of name.
diff --git a/htdocs/ecommerceng/admin/class/data/eCommerceDict.class.php b/htdocs/ecommerceng/admin/class/data/eCommerceDict.class.php
index 611300a..7d98c8a 100644
--- a/htdocs/ecommerceng/admin/class/data/eCommerceDict.class.php
+++ b/htdocs/ecommerceng/admin/class/data/eCommerceDict.class.php
@@ -94,6 +94,141 @@ public function getAll()
return $lines;
}
+ /**
+ * Get all lines from database match with keys (array(field=>array(value, type)))
+ * @param array $keys Keys for the search array(field_name=>array('value'=>value, 'type'=>type) (type (optionnel: string, like, date)
+ * @return array
+ */
+ public function search($keys)
+ {
+ $lines = array();
+
+ $sql = "SELECT * FROM `".$this->table."`";
+ if (is_array($keys) && count($keys) > 0) {
+ $fields = array();
+ foreach ($keys as $field => $value) {
+ switch ($value['type']) {
+ case 'string':
+ $key = "= '".$this->db->escape($value['value'])."'";
+ break;
+ case 'like':
+ $key = "LIKE '".$this->db->escape($value['value'])."'";
+ break;
+ case 'date':
+ $key = "= '".$this->db->idate($value['value'])."'";
+ break;
+ default:
+ $key = '= '.$this->db->escape($value['value']);
+ break;
+ }
+ $fields[] = $field.' '.$key;
+ }
+ $sql .= " WHERE ".implode(' AND ', $fields);
+ }
+
+ $result = $this->db->query($sql);
+ if ($result) {
+ while ($obj = $this->db->fetch_array($result)) {
+ $lines[] = $obj;
+ }
+ }
+
+ return $lines;
+ }
+
+ /**
+ * Update all lines from database match with keys
+ * @param array $values Values for the search array(field_name=>array('value'=>value, 'type'=>type) (type (optionnel: string, date)
+ * @param array $keys Keys for the search array(field_name=>array('value'=>value, 'type'=>type) (type (optionnel: string, like, date)
+ * @return boolean
+ */
+ public function update($values, $keys)
+ {
+ $sql = "UPDATE `".$this->table."` SET ";
+ if (is_array($values) && count($values) > 0) {
+ $fields = array();
+ foreach ($values as $field => $value) {
+ switch ($value['type']) {
+ case 'string':
+ $key = "= '" . $this->db->escape($value['value']) . "'";
+ break;
+ case 'date':
+ $key = "= '" . $this->db->idate($value['value']) . "'";
+ break;
+ default:
+ $key = '= ' . $this->db->escape($value['value']);
+ break;
+ }
+ $fields[] = $field . ' ' . $key;
+ }
+ $sql .= implode(' AND ', $fields);
+ }
+ if (is_array($keys) && count($keys) > 0) {
+ $fields = array();
+ foreach ($keys as $field => $value) {
+ switch ($value['type']) {
+ case 'string':
+ $key = "= '" . $this->db->escape($value['value']) . "'";
+ break;
+ case 'like':
+ $key = "LIKE '" . $this->db->escape($value['value']) . "'";
+ break;
+ case 'date':
+ $key = "= '" . $this->db->idate($value['value']) . "'";
+ break;
+ default:
+ $key = '= ' . $this->db->escape($value['value']);
+ break;
+ }
+ $fields[] = $field . ' ' . $key;
+ }
+ $sql .= " WHERE " . implode(' AND ', $fields);
+ }
+
+ $result = $this->db->query($sql);
+ if ($result) {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Insert line to database
+ * @param array $fields Fields for insert
+ * @param array $values Values for the insert array(field_name=>array('value'=>value, 'type'=>type) (type (optionnel: string, date)
+ * @return boolean
+ */
+ public function insert($fields, $values)
+ {
+ $values_list = array();
+ if (is_array($values) && count($values) > 0) {
+ foreach ($fields as $field) {
+ if (isset($values[$field])) {
+ switch ($values[$field]['type']) {
+ case 'string':
+ $values_list[] = "'" . $this->db->escape($values[$field]['value']) . "'";
+ break;
+ case 'date':
+ $values_list[] = "'" . $this->db->idate($values[$field]['value']) . "'";
+ break;
+ default:
+ $values_list[] = $this->db->escape($values[$field]['value']);
+ break;
+ }
+ }
+ }
+ }
+
+ $sql = "INSERT INTO `".$this->table."` (".implode(', ', $fields).") VALUES(".implode(', ', $values_list).")";
+ $result = $this->db->query($sql);
+ if ($result) {
+ return true;
+ }
+
+ return false;
+ }
+
/**
* Get the value of ECOMMERCE_COMPANY_ANONYMOUS from db
* @return int > 0 if OK, 0 if KO
diff --git a/htdocs/ecommerceng/admin/eCommerceSetup.php b/htdocs/ecommerceng/admin/eCommerceSetup.php
old mode 100755
new mode 100644
index 82383c4..21595a5
--- a/htdocs/ecommerceng/admin/eCommerceSetup.php
+++ b/htdocs/ecommerceng/admin/eCommerceSetup.php
@@ -37,14 +37,18 @@
require_once(DOL_DOCUMENT_ROOT . '/categories/class/categorie.class.php');
require_once(DOL_DOCUMENT_ROOT . '/core/lib/admin.lib.php');
+require_once DOL_DOCUMENT_ROOT.'/includes/OAuth/bootstrap.php';
dol_include_once('/ecommerceng/class/data/eCommerceSite.class.php');
dol_include_once('/ecommerceng/admin/class/gui/eCommerceMenu.class.php');
dol_include_once('/ecommerceng/lib/eCommerce.lib.php');
+use OAuth\Common\Storage\DoliStorage;
$langs->load('admin');
$langs->load('companies');
+$langs->load("oauth");
$langs->load('ecommerce@ecommerceng');
+$langs->load('woocommerce@ecommerceng');
$siteId = null;
$errors = array();
@@ -53,6 +57,11 @@
if (!$user->admin || !$user->rights->ecommerceng->site)
accessforbidden();
+$error = GETPOST('error', 'alpha');
+if (!empty($error)) {
+ setEventMessage($error, 'errors');
+}
+
//DATABASE ACCESS
$siteDb = new eCommerceSite($db);
@@ -118,15 +127,16 @@
$siteDb->filter_value = $_POST['ecommerce_filter_value'];
$siteDb->fk_cat_societe = $_POST['ecommerce_fk_cat_societe'];
$siteDb->fk_cat_product = $_POST['ecommerce_fk_cat_product'];
+ $siteDb->fk_anonymous_thirdparty = $_POST['ecommerce_fk_anonymous_thirdparty']>0?$_POST['ecommerce_fk_anonymous_thirdparty']:null;
$siteDb->fk_warehouse = $_POST['ecommerce_fk_warehouse'];
$siteDb->stock_sync_direction = $_POST['ecommerce_stock_sync_direction'];
$siteDb->last_update = $_POST['ecommerce_last_update'];
//$siteDb->timeout = $_POST['ecommerce_timeout'];
$siteDb->magento_use_special_price = ($_POST['ecommerce_magento_use_special_price'] ? 1 : 0);
- $siteDb->magento_price_type = $_POST['ecommerce_magento_price_type'];
+ $siteDb->ecommerce_price_type = $_POST['ecommerce_price_type'];
- // TODO Save this into table of ecommerce_site, field fk_thirdparty instead of global var.
- dolibarr_set_const($db, 'ECOMMERCENG_USE_THIS_THIRDPARTY_FOR_NONLOGGED_CUSTOMER', GETPOST('ECOMMERCENG_USE_THIS_THIRDPARTY_FOR_NONLOGGED_CUSTOMER','int'));
+ $siteDb->oauth_id = $_POST['ecommerce_oauth_id'];
+ $siteDb->oauth_secret = $_POST['ecommerce_oauth_secret'];
$result = 0;
if (intval($_POST['ecommerce_id']))
@@ -138,12 +148,102 @@
$result = $siteDb->create($user);
}
+ $error = '';
+ if ($result > 0) {
+ if ($siteDb->type == 2) { // Woocommerce
+ $result = ecommerceng_add_extrafields($db, $langs, [
+ [
+ 'attrname' => "ecommerceng_wc_status_{$siteDb->id}_{$conf->entity}",
+ 'label' => $langs->trans('ECommercengWoocommerceStatus', $siteDb->name),
+ 'type' => 'select',
+ 'pos' => 1,
+ 'size' => '',
+ 'elementtype' => 'product',
+ 'unique' => 0,
+ 'required' => 0,
+ 'default_value' => '',
+ 'param' => array('options' => array(
+ "draft" => $langs->trans('ECommercengWoocommerceStatusDraft', $siteDb->name),
+ "pending" => $langs->trans('ECommercengWoocommerceStatusPending', $siteDb->name),
+ "private" => $langs->trans('ECommercengWoocommerceStatusPrivate', $siteDb->name),
+ "publish" => $langs->trans('ECommercengWoocommerceStatusPublish', $siteDb->name),
+ )),
+ 'alwayseditable' => 1,
+ 'perms' => '',
+ 'list' => 0,
+ ],[
+ 'attrname' => "ecommerceng_description_{$conf->entity}",
+ 'label' => 'ECommercengWoocommerceDescription',
+ 'type' => 'text',
+ 'pos' => 2,
+ 'size' => '',
+ 'elementtype' => 'product',
+ 'unique' => 0,
+ 'required' => 0,
+ 'default_value' => '',
+ 'param' => '',
+ 'alwayseditable' => 1,
+ 'perms' => '',
+ 'list' => 0,
+ ],
+ [
+ 'attrname' => "ecommerceng_short_description_{$conf->entity}",
+ 'label' => 'ECommercengWoocommerceShortDescription',
+ 'type' => 'text',
+ 'pos' => 3,
+ 'size' => '',
+ 'elementtype' => 'product',
+ 'unique' => 0,
+ 'required' => 0,
+ 'default_value' => '',
+ 'param' => '',
+ 'alwayseditable' => 1,
+ 'perms' => '',
+ 'list' => 0,
+ ],
+ [
+ 'attrname' => "ecommerceng_tax_class_{$siteDb->id}_{$conf->entity}",
+ 'label' => $langs->trans('ECommercengWoocommerceTaxClass', $siteDb->name),
+ 'type' => 'sellist',
+ 'pos' => 4,
+ 'size' => '',
+ 'elementtype' => 'product',
+ 'unique' => 0,
+ 'required' => 0,
+ 'default_value' => '',
+ 'param' => array('options' => array("c_ecommerceng_tax_class:label:code::active=1 AND site_id={$siteDb->id} AND entity={$conf->entity}" => null)),
+ 'alwayseditable' => 1,
+ 'perms' => '',
+ 'list' => 0,
+ ],
+ [
+ 'attrname' => "ecommerceng_online_payment_{$conf->entity}",
+ 'label' => 'ECommercengWoocommerceOnlinePayment',
+ 'type' => 'boolean',
+ 'pos' => 1,
+ 'size' => '1',
+ 'elementtype' => 'commande',
+ 'unique' => 0,
+ 'required' => 0,
+ 'default_value' => '',
+ 'param' => '',
+ 'alwayseditable' => 1,
+ 'perms' => '',
+ 'list' => 0,
+ ],
+ ], $error);
+ }
+ }
+
if ($result > 0)
{
$eCommerceMenu = new eCommerceMenu($db, $siteDb);
$eCommerceMenu->updateMenu();
$db->commit();
+ if ($siteDb->type == 2) { // Woocommerce
+ ecommerceng_update_woocommerce_dict_tax_class($db, $siteDb);
+ }
if (!empty($conf->global->PRODUIT_MULTIPRICES) && $siteDb->price_level != $last_price_level) {
updatePriceLevel($siteDb);
}
@@ -152,7 +252,11 @@
} else
{
$db->rollback();
- setEventMessages($siteDb->error, $siteDb->errors, 'errors');
+ if (!empty($error)) {
+ setEventMessage($error, 'errors');
+ } else {
+ setEventMessages($siteDb->error, $siteDb->errors, 'errors');
+ }
}
}
else
@@ -178,6 +282,12 @@
unset($_POST);
}
}
+// Update dictionary for tax class of woocommerce
+elseif ($_POST['site_form_detail_action'] == 'update_woocommerce_tax_class') {
+ if (ecommerceng_update_woocommerce_dict_tax_class($db, $siteDb)) {
+ setEventMessage($langs->trans('ECommercengWoocommerceDictTaxClassUpdated'));
+ }
+}
@@ -212,6 +322,17 @@
$ecommerceName = ($_POST['ecommerce_name'] ? $_POST['ecommerce_name'] : $siteDb->name);
$ecommerceType = ($_POST['ecommerce_type'] ? $_POST['ecommerce_type'] : intval($siteDb->type));
$ecommerceWebserviceAddress = ($_POST['ecommerce_webservice_address'] ? $_POST['ecommerce_webservice_address'] : $siteDb->webservice_address);
+$ecommerceWebserviceAddressTest = '';
+if (!empty($ecommerceWebserviceAddress)) {
+ switch ($ecommerceType) {
+ case 1: // Magento
+ $ecommerceWebserviceAddressTest = $ecommerceWebserviceAddress .(substr($ecommerceWebserviceAddress, -1, 1)!='/'?'/':''). 'api/?wsdl';
+ break;
+ case 2: // Woocommerce
+ $ecommerceWebserviceAddressTest = $ecommerceWebserviceAddress .(substr($ecommerceWebserviceAddress, -1, 1)!='/'?'/':''). 'wp-json/';
+ break;
+ }
+}
$ecommerceUserName = ($_POST['ecommerce_user_name'] ? $_POST['ecommerce_user_name'] : $siteDb->user_name);
$ecommerceUserPassword = ($_POST['ecommerce_user_password'] ? $_POST['ecommerce_user_password'] : $siteDb->user_password);
$ecommercePriceLevel = ($_POST['ecommerce_price_level'] ? $_POST['ecommerce_price_level'] : $siteDb->price_level);
@@ -219,15 +340,55 @@
$ecommerceFilterValue = ($_POST['ecommerce_filter_value'] ? $_POST['ecommerce_filter_value'] : $siteDb->filter_value);
$ecommerceFkCatSociete = ($_POST['ecommerce_fk_cat_societe'] ? $_POST['ecommerce_fk_cat_societe'] : intval($siteDb->fk_cat_societe));
$ecommerceFkCatProduct = ($_POST['ecommerce_fk_cat_product'] ? $_POST['ecommerce_fk_cat_product'] : intval($siteDb->fk_cat_product));
+$ecommerceFkAnonymousThirdparty = ($_POST['ecommerce_fk_anonymous_thirdparty'] ? $_POST['ecommerce_fk_anonymous_thirdparty'] : intval($siteDb->fk_anonymous_thirdparty));
$ecommerceFkWarehouse = ($_POST['ecommerce_fk_warehouse'] ? $_POST['ecommerce_fk_warehouse'] : intval($siteDb->fk_warehouse));
$ecommerceStockSyncDirection = ($_POST['ecommerce_stock_sync_direction'] ? $_POST['ecommerce_stock_sync_direction'] : $siteDb->stock_sync_direction);
$ecommerceMagentoUseSpecialPrice = ($_POST['ecommerce_magento_use_special_price'] ? $_POST['ecommerce_magento_use_special_price'] : intval($siteDb->magento_use_special_price));
-$ecommerceMagentoPriceType = ($_POST['ecommerce_magento_price_type'] ? $_POST['ecommerce_magento_price_type'] : $siteDb->ecommerce_magento_price_type);
+$ecommercePriceType = ($_POST['ecommerce_price_type'] ? $_POST['ecommerce_price_type'] : $siteDb->ecommerce_price_type);
/*$ecommerceTimeout = 300;
if (isset($_POST['ecommerce_timeout']))
$ecommerceTimeout = $_POST['ecommerce_timeout'];
elseif (isset($siteDb->timeout))
$ecommerceTimeout = $siteDb->timeout;*/
+$ecommerceOAuth = false;
+$ecommerceOAuthGenerateToken = false;
+if (!empty($ecommerceId)) {
+ if ($ecommerceType == 2) {
+ $ecommerceOAuth = true;
+ $ecommerceOAuthWordpressOAuthSetupUri = $ecommerceWebserviceAddress . (substr($ecommerceWebserviceAddress, -1, 1) != '/' ? '/' : '') . 'wp-admin/admin.php?page=wo_settings#clients';
+ }
+
+ if ($ecommerceOAuth) {
+ $ecommerceOAuthRedirectUri = dol_buildpath('/custom/ecommerceng/core/modules/oauth/wordpress_oauthcallback.php', 2).'?ecommerce_id='.$ecommerceId;
+ $ecommerceOAuthId = ($_POST['ecommerce_oauth_id'] ? $_POST['ecommerce_oauth_id'] : $siteDb->oauth_id);
+ $ecommerceOAuthSecret = ($_POST['ecommerce_oauth_secret'] ? $_POST['ecommerce_oauth_secret'] : $siteDb->oauth_secret);
+
+ // Token
+ $ecommerceOAuthTokenObj = null;
+ $storage = new DoliStorage($db, $conf);
+ try {
+ $ecommerceOAuthTokenObj = $storage->retrieveAccessToken('ECommerce_'.$ecommerceId);
+ } catch(Exception $e) {}
+ $ecommerceOAuthGenerateToken = (!empty($ecommerceOAuthId) && !empty($ecommerceOAuthSecret) || is_object($ecommerceOAuthTokenObj));
+
+ $ecommerceOAuthBackToUri = urlencode(dol_buildpath('/custom/ecommerceng/admin/eCommerceSetup.php', 2).'?ecommerce_id='.$ecommerceId);
+
+ if (is_object($ecommerceOAuthTokenObj)) {
+ $ecommerceOAuthTokenExpired = ($ecommerceOAuthTokenObj->getEndOfLife() !== $ecommerceOAuthTokenObj::EOL_NEVER_EXPIRES && $ecommerceOAuthTokenObj->getEndOfLife() !== $ecommerceOAuthTokenObj::EOL_UNKNOWN && time() > ($ecommerceOAuthTokenObj->getEndOfLife() - 30));
+
+ $ecommerceOAuthHasRefreshToken = !empty($ecommerceOAuthTokenObj->getRefreshToken());
+
+ $endoflife = $ecommerceOAuthTokenObj->getEndOfLife();
+ if ($endoflife == $ecommerceOAuthTokenObj::EOL_NEVER_EXPIRES) {
+ $ecommerceOAuthTokenExpireDate = $langs->trans("Never");
+ } elseif ($endoflife == $ecommerceOAuthTokenObj::EOL_UNKNOWN) {
+ $ecommerceOAuthTokenExpireDate = $langs->trans("Unknown");
+ } else {
+ $ecommerceOAuthTokenExpireDate = dol_print_date($endoflife, "dayhour");
+ }
+ }
+ }
+}
$ecommerceLastUpdate = $siteDb->last_update;
$var = true;
diff --git a/htdocs/ecommerceng/admin/tpl/eCommerceSetup.tpl.php b/htdocs/ecommerceng/admin/tpl/eCommerceSetup.tpl.php
old mode 100755
new mode 100644
index 41f3130..fa18c35
--- a/htdocs/ecommerceng/admin/tpl/eCommerceSetup.tpl.php
+++ b/htdocs/ecommerceng/admin/tpl/eCommerceSetup.tpl.php
@@ -146,9 +146,7 @@
$langs->trans('None'), 'ecommerce2dolibarr'=>'eCommerce to Dolibarr', 'dolibarr2ecommerce'=>'Dolibarr to eCommerce');
+ $array=array('none'=>$langs->trans('None'), 'ecommerce2dolibarr'=>$langs->trans('ECommerceToDolibarr'), 'dolibarr2ecommerce'=>$langs->trans('DolibarrToeCommerce'));
print $form->selectarray('ecommerce_stock_sync_direction', $array, $ecommerceStockSyncDirection);
?>
@@ -327,6 +419,14 @@
{
?>
+type == 2)
+{
+?>
+ ")'>trans('ECommerceWoocommerceUpdateDictTaxClasses') ?>
+
")'>trans('Delete') ?>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+dol_include_once('/ecommerceng/class/business/eCommerceSynchro.class.php');
+
+/**
+ * \file htdocs/ecommerceng/class/actions_ecommerceng.class.php
+ * \ingroup ecommerceng
+ * \brief File for hooks
+ */
+
+class ActionsECommerceNg
+{
+ /**
+ * Overloading the doActions function : replacing the parent's function with the one below
+ *
+ * @param array() $parameters Hook metadatas (context, etc...)
+ * @param CommonObject &$object The object to process (an invoice if you are in invoice module, a propale in propale's module, etc...)
+ * @param string &$action Current action (if set). Generally create or edit or null
+ * @param HookManager $hookmanager Hook manager propagated to allow calling another hook
+ * @return int < 0 on error, 0 on success, 1 to replace standard code
+ */
+ function doActions($parameters, &$object, &$action, $hookmanager)
+ {
+ global $conf, $user, $langs;
+
+ if (in_array('productdocuments', explode(':', $parameters['context'])) && $action == 'synchronize_images') {
+ if (!empty($conf->global->ECOMMERCENG_ENABLE_SYNCHRO_IMAGES)) {
+ $result = $object->call_trigger('PRODUCT_MODIFY', $user);
+ if ($result < 0) {
+ if (count($object->errors)) setEventMessages($object->error, $object->errors, 'errors');
+ else setEventMessages($langs->trans($object->error), null, 'errors');
+ } else {
+ setEventMessage($langs->trans('ECommerceProductImagesSynchronized'));
+ }
+ }
+ }
+
+ return 0; // or return 1 to replace standard code
+ }
+
+ /**
+ * Overloading the formObjectOptions function : replacing the parent's function with the one below
+ *
+ * @param array() $parameters Hook metadatas (context, etc...)
+ * @param CommonObject &$object The object to process (an invoice if you are in invoice module, a propale in propale's module, etc...)
+ * @param string &$action Current action (if set). Generally create or edit or null
+ * @param HookManager $hookmanager Hook manager propagated to allow calling another hook
+ * @return int < 0 on error, 0 on success, 1 to replace standard code
+ */
+ function formObjectOptions($parameters, &$object, &$action, $hookmanager)
+ {
+ global $conf, $langs;
+
+ if (in_array('productdocuments', explode(':', $parameters['context']))) {
+ if (!empty($conf->global->ECOMMERCENG_ENABLE_SYNCHRO_IMAGES)) {
+ $buttons = '
';
+
+ print '';
+ }
+ }
+
+ return 0; // or return 1 to replace standard code
+ }
+
+ /**
+ * Overloading the afterODTCreation function : replacing the parent's function with the one below
+ *
+ * @param array() $parameters Hook metadatas (context, etc...)
+ * @param CommonObject &$object The object to process (an invoice if you are in invoice module, a propale in propale's module, etc...)
+ * @param string &$action Current action (if set). Generally create or edit or null
+ * @param HookManager $hookmanager Hook manager propagated to allow calling another hook
+ * @return int < 0 on error, 0 on success, 1 to replace standard code
+ */
+ function afterODTCreation($parameters, &$object, &$action, $hookmanager)
+ {
+ global $conf, $user, $langs, $db;
+
+ if ((in_array('expeditioncard', explode(':', $parameters['context'])) && $action == 'confirm_valid') ||
+ (in_array('invoicecard', explode(':', $parameters['context'])) && $action == 'confirm_valid')) {
+ if (!empty($conf->global->ECOMMERCENG_ENABLE_SEND_FILE_TO_ORDER)) {
+ $commande_id = 0;
+ $societe_id = 0;
+ $object_src = $parameters['object'];
+ $object_src->fetchObjectLinked('', 'commande', $object_src->id, $object_src->element);
+ if (!empty($object_src->linkedObjects)) {
+ foreach ($object_src->linkedObjects['commande'] as $element) {
+ $commande_id = $element->id;
+ $societe_id = $element->socid;
+ }
+ }
+
+ if ($commande_id > 0) {
+ $db->begin();
+
+ $error = 0; // Error counter
+ $eCommerceSite = new eCommerceSite($db);
+ $sites = $eCommerceSite->listSites('object');
+
+ foreach ($sites as $site) {
+ if (!$error) {
+ $eCommerceCommande = new eCommerceCommande($db);
+ $eCommerceCommande->fetchByCommandeId($commande_id, $site->id);
+
+ $eCommerceSociete = new eCommerceSociete($db);
+ $eCommerceSociete->fetchByFkSociete($societe_id, $site->id);
+
+ if ($eCommerceCommande->remote_id > 0 && $eCommerceSociete->remote_id > 0) {
+ $eCommerceSynchro = new eCommerceSynchro($db, $site);
+ dol_syslog("Hook ActionsECommerceNg::afterPDFCreation try to connect to eCommerce site " . $site->name);
+ $eCommerceSynchro->connect();
+ if (count($eCommerceSynchro->errors)) {
+ $error++;
+ setEventMessages($eCommerceSynchro->error, $eCommerceSynchro->errors, 'errors');
+ }
+
+ if (!$error) {
+ $result = $eCommerceSynchro->eCommerceRemoteAccess->sendFileForCommande($eCommerceCommande->remote_id, $eCommerceSociete->remote_id, $object_src, $parameters['file'], $parameters['outputlangs']);
+ if (!$result) {
+ $error++;
+ $this->errors[] = $eCommerceSynchro->eCommerceRemoteAccess->error;
+ }
+ }
+ } else {
+ dol_syslog("Order with id " . $commande_id . " is not linked to an ecommerce record so we don't send file to it.");
+ }
+ }
+ }
+
+ if ($error) {
+ $db->rollback();
+ return -1;
+ } else {
+ $db->commit();
+ return 0;
+ }
+ }
+ }
+ }
+
+ return 0; // or return 1 to replace standard code
+ }
+
+ /**
+ * Overloading the afterPDFCreation function : replacing the parent's function with the one below
+ *
+ * @param array() $parameters Hook metadatas (context, etc...)
+ * @param CommonObject &$object The object to process (an invoice if you are in invoice module, a propale in propale's module, etc...)
+ * @param string &$action Current action (if set). Generally create or edit or null
+ * @param HookManager $hookmanager Hook manager propagated to allow calling another hook
+ * @return int < 0 on error, 0 on success, 1 to replace standard code
+ */
+ function afterPDFCreation($parameters, &$object, &$action, $hookmanager)
+ {
+ global $conf, $user, $langs, $db;
+
+ if ((in_array('expeditioncard', explode(':', $parameters['context'])) && $action == 'confirm_valid') ||
+ (in_array('invoicecard', explode(':', $parameters['context'])) && $action == 'confirm_valid')) {
+ if (!empty($conf->global->ECOMMERCENG_ENABLE_SEND_FILE_TO_ORDER)) {
+ $commande_id = 0;
+ $societe_id = 0;
+ $object_src = $parameters['object'];
+ $object_src->fetchObjectLinked('', 'commande', $object_src->id, $object_src->element);
+ if (!empty($object_src->linkedObjects)) {
+ foreach ($object_src->linkedObjects['commande'] as $element) {
+ $commande_id = $element->id;
+ $societe_id = $element->socid;
+ }
+ }
+
+ if ($commande_id > 0) {
+ $db->begin();
+
+ $error = 0; // Error counter
+ $eCommerceSite = new eCommerceSite($db);
+ $sites = $eCommerceSite->listSites('object');
+
+ foreach ($sites as $site) {
+ if (!$error) {
+ $eCommerceCommande = new eCommerceCommande($db);
+ $eCommerceCommande->fetchByCommandeId($commande_id, $site->id);
+
+ $eCommerceSociete = new eCommerceSociete($db);
+ $eCommerceSociete->fetchByFkSociete($societe_id, $site->id);
+
+ if ($eCommerceCommande->remote_id > 0 && $eCommerceSociete->remote_id > 0) {
+ $eCommerceSynchro = new eCommerceSynchro($db, $site);
+ dol_syslog("Hook ActionsECommerceNg::afterPDFCreation try to connect to eCommerce site " . $site->name);
+ $eCommerceSynchro->connect();
+ if (count($eCommerceSynchro->errors)) {
+ $error++;
+ setEventMessages($eCommerceSynchro->error, $eCommerceSynchro->errors, 'errors');
+ }
+
+ if (!$error) {
+ $result = $eCommerceSynchro->eCommerceRemoteAccess->sendFileForCommande($eCommerceCommande->remote_id, $eCommerceSociete->remote_id, $object_src, $parameters['file'], $parameters['outputlangs']);
+ if (!$result) {
+ $error++;
+ $this->errors[] = $eCommerceSynchro->eCommerceRemoteAccess->error;
+ }
+ }
+ } else {
+ dol_syslog("Order with id " . $commande_id . " is not linked to an ecommerce record so we don't send file to it.");
+ }
+ }
+ }
+
+ if ($error) {
+ $db->rollback();
+ return -1;
+ } else {
+ $db->commit();
+ return 0;
+ }
+ }
+ }
+ }
+
+ return 0; // or return 1 to replace standard code
+ }
+}
\ No newline at end of file
diff --git a/htdocs/ecommerceng/class/business/eCommerceSynchro.class.php b/htdocs/ecommerceng/class/business/eCommerceSynchro.class.php
old mode 100755
new mode 100644
index 663f7a5..372d601
--- a/htdocs/ecommerceng/class/business/eCommerceSynchro.class.php
+++ b/htdocs/ecommerceng/class/business/eCommerceSynchro.class.php
@@ -305,7 +305,7 @@ public function getNbCategoriesInDolibarr()
public function getNbCategoriesInDolibarrLinkedToE($excludeid = 0)
{
- $sql="SELECT COUNT(rowid) as nb FROM ".MAIN_DB_PREFIX."ecommerce_category WHERE type = 0";
+ $sql="SELECT COUNT(rowid) as nb FROM ".MAIN_DB_PREFIX."ecommerce_category WHERE type = 0 AND fk_site=".$this->eCommerceSite->id;
$sql.=" AND fk_category <> ".$excludeid;
$resql=$this->db->query($sql);
if ($resql)
@@ -336,7 +336,7 @@ public function getNbProductInDolibarr()
public function getNbProductInDolibarrLinkedToE()
{
- $sql="SELECT COUNT(rowid) as nb FROM ".MAIN_DB_PREFIX."ecommerce_product";
+ $sql="SELECT COUNT(rowid) as nb FROM ".MAIN_DB_PREFIX."ecommerce_product WHERE fk_site=".$this->eCommerceSite->id;
$resql=$this->db->query($sql);
if ($resql)
{
@@ -370,7 +370,7 @@ public function getNbSocieteInDolibarr()
public function getNbSocieteInDolibarrLinkedToE()
{
- $sql="SELECT COUNT(s.rowid) as nb FROM ".MAIN_DB_PREFIX."ecommerce_societe as s";
+ $sql="SELECT COUNT(s.rowid) as nb FROM ".MAIN_DB_PREFIX."ecommerce_societe as s WHERE fk_site=".$this->eCommerceSite->id;
$resql=$this->db->query($sql);
if ($resql)
@@ -401,7 +401,7 @@ public function getNbCommandeInDolibarr()
public function getNbCommandeInDolibarrLinkedToE()
{
- $sql="SELECT COUNT(rowid) as nb FROM ".MAIN_DB_PREFIX."ecommerce_commande";
+ $sql="SELECT COUNT(rowid) as nb FROM ".MAIN_DB_PREFIX."ecommerce_commande WHERE fk_site=".$this->eCommerceSite->id;
$resql=$this->db->query($sql);
if ($resql)
{
@@ -431,7 +431,7 @@ public function getNbFactureInDolibarr()
public function getNbFactureInDolibarrLinkedToE()
{
- $sql="SELECT COUNT(rowid) as nb FROM ".MAIN_DB_PREFIX."ecommerce_facture";
+ $sql="SELECT COUNT(rowid) as nb FROM ".MAIN_DB_PREFIX."ecommerce_facture WHERE fk_site=".$this->eCommerceSite->id;
$resql=$this->db->query($sql);
if ($resql)
{
@@ -761,7 +761,7 @@ public function synchCategory($toNb=0)
$counter++;
if ($toNb > 0 && $counter > $toNb) break;
- dol_syslog("synchCategory Process sync of magento category remote_id=".$categoryArray['category_id']." name=".$categoryArray['name']." remote parent_id=".$categoryArray['parent_id']);
+ dol_syslog("synchCategory Process sync of ecommerce category remote_id=".$categoryArray['category_id']." name=".$categoryArray['name']." remote parent_id=".$categoryArray['parent_id']);
$this->db->begin();
@@ -769,59 +769,33 @@ public function synchCategory($toNb=0)
$dBCategorie = new Categorie($this->db);
- // Get parent (if already synch)
- $this->eCommerceMotherCategory->fetchByRemoteId($categoryArray['parent_id'], $this->eCommerceSite->id);
-
- // If there is a parent, we check we set it into $this->eCommerceMotherCategory
- /*if ($parentremoteid > 0 && empty($this->eCommerceMotherCategory->id))
- {
- $error++;
- $this->errors[]="Failed to get/create parent category";
- }*/
-
- /*
- // Check if the ecommerce category has an ecommerce parent category, if not, that implies it is root.
- // !!!!!! This is true only if categories are returned in order of parent first.
- $motherExists = $this->eCommerceMotherCategory->fetchByRemoteId($parentremoteid, $this->eCommerceSite->id);
+ // Check if the ecommerce category has an ecommerce parent category, if not, that implies it is root
+ $motherExists = $this->eCommerceMotherCategory->fetchByRemoteId($categoryArray['parent_id'], $this->eCommerceSite->id);
// Now $this->eCommerceMotherCategory contains the mother category or null
- if ($motherExists < 1) // Not found.
+ // if fetch on eCommerceMotherCategory has failed, it is root
+ /* Disable automatic creation in dolibarr of link to parent into table of links
+ because, we can't know what is the parent. Here code suppose it is the root category defined into setup
+ but we may have several levels
+ if ($motherExists < 1 && ($this->eCommerceMotherCategory->fetchByFKCategory($this->eCommerceSite->fk_cat_product, $this->eCommerceSite->id) < 0))
{
- // if remote fetch on eCommerceMotherCategory has failed, it is root
- // !!!!!! This is true only if categories are returned in order of parent first.
-
- // We get the ROOT category.
- if ($this->eCommerceMotherCategory->fetchByFKCategory($this->eCommerceSite->fk_cat_product, $this->eCommerceSite->id) < 0)
- {
- // get the importRootCategory of Dolibarr set for the eCommerceSite
- $dBCategorie->fetch($this->eCommerceSite->fk_cat_product);
-
- // We rely on first parent of current record because root is not already synch,
- // it means, it's first synch, in such a case, the first record is just under ROOT.
- // TODO Make remote call until we found the true ROOT and the the first parent
- $parentremoteid=$categoryArray['parent_id'];
-
- $this->eCommerceMotherCategory->label = $dBCategorie->label;
- $this->eCommerceMotherCategory->type = $dBCategorie->type;
- $this->eCommerceMotherCategory->description = $dBCategorie->description;
- $this->eCommerceMotherCategory->fk_category = $dBCategorie->id;
- $this->eCommerceMotherCategory->fk_site = $this->eCommerceSite->id;
- $this->eCommerceMotherCategory->remote_id = $parentremoteid;
- $this->eCommerceMotherCategory->last_update = strtotime($categoryArray['updated_at']);
-
- // reset $dBCategorie
- $dBCategorie = new Categorie($this->db);
-
- // Create an entry to map importRootCategory in eCommerceCategory
- $this->eCommerceMotherCategory->create($this->user);
- }
- else
- {
- // The root category is already synch.
- }
- }*/
-
- // Process category to synch.
+ // get the importRootCategory of Dolibarr set for the eCommerceSite
+ $dBCategorie->fetch($this->eCommerceSite->fk_cat_product);
+
+ $this->eCommerceMotherCategory->label = $dBCategorie->label;
+ $this->eCommerceMotherCategory->type = $dBCategorie->type;
+ $this->eCommerceMotherCategory->description = $dBCategorie->description;
+ $this->eCommerceMotherCategory->fk_category = $dBCategorie->id;
+ $this->eCommerceMotherCategory->fk_site = $this->eCommerceSite->id;
+ $this->eCommerceMotherCategory->remote_id = $categoryArray['parent_id'];
+
+ // reset $dBCategorie
+ $dBCategorie = new Categorie($this->db);
+
+ // Create an entry to map importRootCategory in eCommerceCategory
+ $this->eCommerceMotherCategory->create($this->user);
+ } */
+
$eCommerceCatExists = $this->eCommerceCategory->fetchByRemoteId($categoryArray['category_id'], $this->eCommerceSite->id);
if ($this->eCommerceCategory->fk_category > 0)
@@ -829,7 +803,7 @@ public function synchCategory($toNb=0)
$synchExists = $eCommerceCatExists >= 0 ? $dBCategorie->fetch($this->eCommerceCategory->fk_category) : -1;
if ($synchExists == 0)
{
- // Category entry exists into table link ecommerce_category with fk_category exists but it links to a non existing category in dolibarr
+ // Category entry exists into ecommerce_category with fk_category that link to non existing category
// Should not happend because we added a cleaned of all orphelins entries into getCategoriesToUpdate
$synchExists = -1;
}
@@ -863,9 +837,21 @@ public function synchCategory($toNb=0)
if ($synchExists >= 0)
{
$result = $dBCategorie->update($this->user);
- } else
+ }
+ else
{
- $result = $dBCategorie->create($this->user);
+ /* Disabled, not sure this is good/required
+ if ($dBCategorie->already_exists()) {
+ $cats = $dBCategorie->rechercher('', $dBCategorie->label, $dBCategorie->type, true, true);
+ foreach ($cats as $cat) {
+ if ($cat->fk_parent == $dBCategorie->fk_parent) {
+ $dBCategorie->id = $cat->id;
+ $result = $dBCategorie->update($this->user);
+ }
+ }
+ } else { */
+ $result = $dBCategorie->create($this->user);
+ /* } */
}
// if synchro category ok
if ($result >= 0)
@@ -873,7 +859,7 @@ public function synchCategory($toNb=0)
$this->eCommerceCategory->label = $dBCategorie->label;
$this->eCommerceCategory->description = $dBCategorie->description;
$this->eCommerceCategory->remote_parent_id = $categoryArray['parent_id'];
- $this->eCommerceCategory->last_update = strtotime($categoryArray['updated_at']);
+ if (!empty($categoryArray['updated_at'])) $this->eCommerceCategory->last_update = strtotime($categoryArray['updated_at']);
if ($synchExists > 0) // update it remotely
{
if ($this->eCommerceCategory->update($this->user) < 0)
@@ -915,7 +901,7 @@ public function synchCategory($toNb=0)
$this->eCommerceCategory->fk_site = $this->eCommerceSite->id;
$this->eCommerceCategory->remote_id = $categoryArray['category_id'];
$this->eCommerceCategory->remote_parent_id = $categoryArray['parent_id'];
- $this->eCommerceCategory->last_update = strtotime($categoryArray['updated_at']);
+ if (!empty($categoryArray['updated_at'])) $this->eCommerceCategory->last_update = strtotime($categoryArray['updated_at']);
if ($this->eCommerceCategory->create($this->user) < 0) // insert into table lxx_ecommerce_category
{
@@ -935,6 +921,8 @@ public function synchCategory($toNb=0)
$this->errors[] = $this->langs->trans('ECommerceSynchCategoryError').' '.$dBCategorie->error;
break;
}
+
+
}
//var_dump($nbgoodsunchronize);exit;
@@ -1044,12 +1032,14 @@ public function synchSociete($toNb=0)
if ($refExists >= 0)
{
$dBSociete->name = $societeArray['name'];
- $dBSociete->name_alias = $societeArray['name_alias'];
//$dBSociete->ref_ext = $this->eCommerceSite->name.'-'.$societeArray['remote_id']; // No need of ref_ext, we will search if already exists on name
- $dBSociete->email = $societeArray['email'];
$dBSociete->client = $societeArray['client'];
- $dBSociete->tva_intra = $societeArray['vatnumber'];
- $dBSociete->tva_assuj = 1; // tba_intra is not saved if this field is not set
+ if (isset($societeArray['name_alias'])) $dBSociete->name_alias = $societeArray['name_alias'];
+ if (isset($societeArray['email'])) $dBSociete->email = $societeArray['email'];
+ if (isset($societeArray['vatnumber'])) {
+ $dBSociete->tva_intra = $societeArray['vatnumber'];
+ }
+ $dBSociete->tva_assuj = 1; // tva_intra is not saved if this field is not set
$dBSociete->context['fromsyncofecommerceid'] = $this->eCommerceSite->id;
$result = $dBSociete->update($dBSociete->id, $this->user);
@@ -1069,45 +1059,55 @@ public function synchSociete($toNb=0)
//if societe not exists in eCommerceSociete, societe is created
else
{
+ $result = 0;
+
// First, we check object does not alreay exists. If not, we create it, if it exists, do nothing.
- //$result = $dBSociete->fetch(0, '', $this->eCommerceSite->name.'-'.$societeArray['remote_id']); // No need of ref_ext, we will search if already exists on name
+ if (isset($societeArray['email_key']) && !empty($societeArray['email_key'])) {
+ // Search into email company and contact
+ $result = get_company_by_email($this->db, $societeArray['email_key']);
- $unicity='name';
- if (! empty($conf->global->ECOMMERCENG_THIRDPARTY_UNIQUE_ON) && $conf->global->ECOMMERCENG_THIRDPARTY_UNIQUE_ON == 'email')
- {
- $unicity='email';
+ if ($result > 0 && $result != $this->eCommerceSite->fk_anonymous_thirdparty) {
+ $result = $dBSociete->fetch($result);
+ }
}
- $result = 0;
- // If unicity is on NAME
- if ($unicity == 'name')
- {
- $result = $dBSociete->fetch(0, $societeArray['name']);
- }
- // If unicity is on EMAIL
- if ($unicity == 'email')
- {
- $sql = 'SELECT s.rowid FROM '.MAIN_DB_PREFIX."societe as s where email like '".$this->db->escape($societeArray['email'])."'";
- $resqlid = $this->db->query($sql);
- if ($resqlid)
- {
- $obj = $this->db->fetch_object($resqlid);
- if ($obj)
- {
- $thirdpartyid = $obj->rowid;
- $result = $dBSociete->fetch(0, $thirdpartyid);
- }
- }
- else
- {
- $error++;
- $this->error='Error in getting id from email.';
- $this->errors[]=$this->error;
- }
+ if ($result < 1 && (!isset($societeArray['type']) || $societeArray['type'] == 'company')) {
+
+ $unicity='name';
+ if (! empty($conf->global->ECOMMERCENG_THIRDPARTY_UNIQUE_ON) && $conf->global->ECOMMERCENG_THIRDPARTY_UNIQUE_ON == 'email')
+ {
+ $unicity='email';
+ }
+
+ // If unicity is on NAME
+ if ($unicity == 'name')
+ {
+ $result = $dBSociete->fetch(0, $societeArray['name']);
+ }
+ // If unicity is on EMAIL
+ if ($unicity == 'email')
+ {
+ $sql = 'SELECT s.rowid FROM '.MAIN_DB_PREFIX."societe as s where email = '".$this->db->escape($societeArray['email'])."'";
+ $resqlid = $this->db->query($sql);
+ if ($resqlid)
+ {
+ $obj = $this->db->fetch_object($resqlid);
+ if ($obj)
+ {
+ $thirdpartyid = $obj->rowid;
+ $result = $dBSociete->fetch(0, $thirdpartyid);
+ }
+ }
+ else
+ {
+ $error++;
+ $this->error='Error in getting id from email.';
+ $this->errors[]=$this->error;
+ }
+ }
}
- if ($result == -2)
- {
+ if ($result == -2) {
$error++;
$this->error='Several thirdparties with name '.$societeArray['name'].' were found in Dolibarr. Sync is not possible. Please rename one of it to avoid duplicate.';
$this->errors[]=$this->error;
@@ -1133,15 +1133,17 @@ public function synchSociete($toNb=0)
if ($result == 0)
{
$dBSociete->name = $societeArray['name'];
- $dBSociete->name_alias = $societeArray['name_alias'];
//$dBSociete->ref_ext = $this->eCommerceSite->name.'-'.$societeArray['remote_id']; // No need of ref_ext, we will search if already exists on name
- $dBSociete->email = $societeArray['email'];
$dBSociete->client = $societeArray['client'];
- $dBSociete->tva_intra = dol_trunc($societeArray['vatnumber'], 20, 'right', 'UTF-8', 1);
+ if (isset($societeArray['name_alias'])) $dBSociete->name_alias = $societeArray['name_alias'];
+ if (isset($societeArray['email'])) $dBSociete->email = $societeArray['email'];
+ if (isset($societeArray['vatnumber'])) {
+ $dBSociete->tva_intra = dol_trunc($societeArray['vatnumber'], 20, 'right', 'UTF-8', 1);
+ }
$dBSociete->tva_assuj = 1; // tva_intra is not saved if this field is not set
+ $dBSociete->context['fromsyncofecommerceid'] = $this->eCommerceSite->id;
$dBSociete->code_client = -1; // Automatic code
$dBSociete->code_fournisseur = -1; // Automatic code
- $dBSociete->context['fromsyncofecommerceid'] = $this->eCommerceSite->id;
$result = $dBSociete->create($this->user);
if ($result < 0)
@@ -1150,16 +1152,20 @@ public function synchSociete($toNb=0)
$this->errors[]=$this->langs->trans('ECommerceSynchSocieteCreateError').' '.$dBSociete->error;
$this->errors = array_merge($this->errors, $dBSociete->errors);
}
+
+ $dBSociete->update_note($societeArray['note_private'],'_private');
}
else if ($result > 0)
{
$dBSociete->name = $societeArray['name'];
- $dBSociete->name_alias = $societeArray['name_alias'];
//$dBSociete->ref_ext = $this->eCommerceSite->name.'-'.$societeArray['remote_id']; // No need of ref_ext, we will search if already exists on name
- $dBSociete->email = $societeArray['email'];
$dBSociete->client = $societeArray['client'];
- $dBSociete->tva_intra = $societeArray['vatnumber'];
- $dBSociete->tva_assuj = 1; // tba_intra is not saved if this field is not set
+ if (isset($societeArray['name_alias'])) $dBSociete->name_alias = $societeArray['name_alias'];
+ if (isset($societeArray['email'])) $dBSociete->email = $societeArray['email'];
+ if (isset($societeArray['vatnumber'])) {
+ $dBSociete->tva_intra = $societeArray['vatnumber'];
+ }
+ $dBSociete->tva_assuj = 1; // tva_intra is not saved if this field is not set
$dBSociete->context['fromsyncofecommerceid'] = $this->eCommerceSite->id;
$result = $dBSociete->update($dBSociete->id, $this->user);
@@ -1216,6 +1222,9 @@ public function synchSociete($toNb=0)
{
dol_syslog("Make a remote call to get contacts"); // Slow because done on each thirdparty to sync.
$listofaddressids=$this->eCommerceRemoteAccess->getRemoteAddressIdForSociete($societeArray['remote_id']); // Ask contacts to magento
+ if ($this->eCommerceSite->type == 2) { // Woocommerce
+ $listofaddressids = $societeArray['remote_datas'];
+ }
if (is_array($listofaddressids))
{
$socpeoples = $this->eCommerceRemoteAccess->convertRemoteObjectIntoDolibarrSocpeople($listofaddressids);
@@ -1287,6 +1296,10 @@ public function synchSocpeople($socpeopleArray)
global $conf;
$error=0;
+ $synchExists = 0;
+ $contactExists = 0;
+
+ $dBContact = new Contact($this->db);
try {
dol_syslog("***** eCommerceSynchro synchSocPeople remote_id=".$socpeopleArray['remote_id']." site=".$this->eCommerceSite->id);
@@ -1297,92 +1310,74 @@ public function synchSocpeople($socpeopleArray)
//print "Work on remote_id = " .$socpeopleArray['remote_id']." type = ".$socpeopleArray['type']."\n";
//check if contact exists in eCommerceSocpeople table
- // $socpeopleArray['type'] = 1 = Contact de tiers
- // $socpeopleArray['type'] = 2 = Contact de commande
- // $socpeopleArray['type'] = 3 = Contact de facture
- // $socpeopleArray['type'] = 4 = Contact de livraison
- $synchExists = $this->eCommerceSocpeople->fetchByRemoteId($socpeopleArray['remote_id'], $socpeopleArray['type'], $this->eCommerceSite->id);
+ if (!empty($socpeopleArray['remote_id'])) {
+ // $socpeopleArray['type'] = 1 = Contact de tiers
+ // $socpeopleArray['type'] = 2 = Contact de commande
+ // $socpeopleArray['type'] = 3 = Contact de facture
+ // $socpeopleArray['type'] = 4 = Contact de livraison
+ $synchExists = $this->eCommerceSocpeople->fetchByRemoteId($socpeopleArray['remote_id'], $socpeopleArray['type'], $this->eCommerceSite->id);
+
+ if ($synchExists > 0) {
+ $contactExists = $dBContact->fetch($this->eCommerceSocpeople->fk_socpeople);
+ }
+ }
//set data into contact
- $dBContact = new Contact($this->db);
-
- $contactExists = 0;
-
- if ($synchExists > 0)
+ $dBContact->socid = $socpeopleArray['fk_soc'];
+ $dBContact->fk_soc = $socpeopleArray['fk_soc'];
+ $dBContact->firstname = $socpeopleArray['firstname'];
+ $dBContact->lastname = $socpeopleArray['lastname'];
+ $dBContact->address = $socpeopleArray['address'];
+ $dBContact->cp = $socpeopleArray['zip'];
+ if ((float) DOL_VERSION >= 6.0)
{
- $test = $dBContact->fetch($this->eCommerceSocpeople->fk_socpeople);
- if ($test > 0)
- {
- $contactExists = $dBContact->id;
- }
+ $dBContact->zip = dol_trunc($socpeopleArray['zip'], 25, 'right', 'UTF-8', 1);
}
-
- if (! $contactExists)
+ else
{
- $dBContact->socid = $socpeopleArray['fk_soc'];
- $dBContact->fk_soc = $socpeopleArray['fk_soc'];
- //$dBContact->fk_pays = $socpeopleArray['fk_pays'];
- $dBContact->lastname = $socpeopleArray['lastname'];
- $dBContact->town = dol_trunc($socpeopleArray['town'], 30, 'right', 'UTF-8', 1);
- $dBContact->ville = $dBContact->town;
- $dBContact->firstname = $socpeopleArray['firstname'];
- if ((float) DOL_VERSION >= 6.0)
- {
- $dBContact->zip = dol_trunc($socpeopleArray['zip'], 25, 'right', 'UTF-8', 1);
- }
- else
- {
- $dBContact->zip = dol_trunc($socpeopleArray['zip'], 10, 'right', 'UTF-8', 1);
- }
- $dBContact->cp = $socpeopleArray['zip'];
- $dBContact->address = $socpeopleArray['address'];
- $dBContact->phone_pro = dol_trunc($socpeopleArray['phone'], 30, 'right', 'UTF-8', 1);
- $dBContact->fax = dol_trunc($socpeopleArray['fax'], 30, 'right', 'UTF-8', 1);
- $dBContact->context['fromsyncofecommerceid'] = $this->eCommerceSite->id;
-
+ $dBContact->zip = dol_trunc($socpeopleArray['zip'], 10, 'right', 'UTF-8', 1);
+ }
+ $dBContact->town = dol_trunc($socpeopleArray['town'], 30, 'right', 'UTF-8', 1);
+ $dBContact->ville = $dBContact->town;
+ $dBContact->country_id = $socpeopleArray['country_id'];
+ $dBContact->email = $socpeopleArray['email'];
+ $dBContact->phone_pro = dol_trunc($socpeopleArray['phone'], 30, 'right', 'UTF-8', 1);
+ $dBContact->fax = dol_trunc($socpeopleArray['fax'], 30, 'right', 'UTF-8', 1);
+ $dBContact->context['fromsyncofecommerceid'] = $this->eCommerceSite->id;
+
+ if (!$contactExists) {
$contactExists = $this->getContactIdFromInfos($dBContact);
+ if ($contactExists > 0) {
+ $contactExists = $dBContact->fetch($contactExists);
+ if (isset($socpeopleArray['country_id'])) $dBContact->country_id = $socpeopleArray['country_id'];
+ if (isset($socpeopleArray['email'])) $dBContact->email = $socpeopleArray['email'];
+ if (isset($socpeopleArray['phone'])) $dBContact->phone_pro = dol_trunc($socpeopleArray['phone'], 30, 'right', 'UTF-8', 1);
+ if (isset($socpeopleArray['fax'])) $dBContact->fax = dol_trunc($socpeopleArray['fax'], 30, 'right', 'UTF-8', 1);
+ $dBContact->context['fromsyncofecommerceid'] = $this->eCommerceSite->id;
+ $synchExists = $this->eCommerceSocpeople->fetchByFkSocpeople($dBContact->id, $this->eCommerceSite->id);
+ }
}
- if ($contactExists)
- $dBContact->id = $contactExists;
-
- //if contact exists in eCommerceSocpeople, contact should exists also in llx_socpeople
- if (($synchExists > 0 && $this->eCommerceSocpeople->fk_socpeople > 0) || $contactExists > 0)
- {
- $refExists = $dBContact->fetch($contactExists > 0 ? $contactExists : $this->eCommerceSocpeople->fk_socpeople);
-
- if ($refExists > 0)
- {
- //dol_syslog("We don't know if contact on ecommerce was modified so we force update of all fields");
- //$result = $dBContact->update($dBContact->id, $this->user);
- $result = 0;
- }
- else if ($refExists == 0) // If not, we create it
- {
- $result = $dBContact->create($this->user);
- if ($result < 0)
- {
- $error++;
- $this->errors[]=$this->langs->trans('ECommerceSynchContactCreateError').' (remote id = '.$socpeopleArray['remote_id'].') '.$dBContact->error;
- $this->errors = array_merge($this->errors, $this->dBContact->errors);
- }
- }
- else if ($refExists < 0)
- {
- $this->errors[] = $this->langs->trans('ECommerceSynchSocieteErrorBetweenECommerceSocpeopleAndContact');
- return false;
+ if ($contactExists > 0) {
+ $result = $dBContact->update($dBContact->id, $this->user);
+ if ($result < 0) {
+ $error++;
+ $this->error = $this->langs->trans('ECommerceSynchContactUpdateError') . ' ' . $dBContact->error;
+ $this->errors[] = $this->error;
}
- }
- //if no previous synchro exists (not found in table of links)
- else
- {
+ } else if ($contactExists == 0) {
$result = $dBContact->create($this->user);
- if ($result < 0)
- {
+ if ($result < 0) {
$error++;
- $this->errors[]=$this->langs->trans('ECommerceSynchContactCreateError').' (remote id = '.$socpeopleArray['remote_id'].') '.$dBContact->error;
- $this->errors = array_merge($this->errors, $dBContact->errors);
+ $this->error = $this->langs->trans('ECommerceSynchContactCreateError') . ' ' . $dBContact->error;
+ $this->errors[] = $this->error;
}
+ } else if ($synchExists > 0 && $contactExists < 0) {
+ $error++;
+ $this->errors[] = $this->langs->trans('ECommerceSynchSocieteErrorBetweenECommerceSocpeopleAndContact');
+ } else if ($contactExists < 0) {
+ $error++;
+ $this->errors[] = $this->langs->trans('ECommerceSynchContactFetchError') . ' ' . $dBContact->error;
}
//if create/update of contact table is ok
@@ -1406,11 +1401,11 @@ public function synchSocpeople($socpeopleArray)
{
//eCommerce create
$this->eCommerceSocpeople->fk_site = $this->eCommerceSite->id;
- $this->eCommerceSocpeople->remote_id = $socpeopleArray['remote_id'];
+ $this->eCommerceSocpeople->remote_id = isset($socpeopleArray['remote_id']) ? $socpeopleArray['remote_id'] : 'none-'.$dBContact->id;
$this->eCommerceSocpeople->type = $socpeopleArray['type'];
if ($this->eCommerceSocpeople->create($this->user) < 0)
{
- $this->errors[] = $this->langs->trans('ECommerceSyncheCommerceSocpeopleCreateError');
+ $this->errors[] = $this->langs->trans('ECommerceSynchECommerceSocpeopleCreateError', $socpeopleArray['fk_soc'], $socpeopleArray['firstname'], $socpeopleArray['lastname']) . ' : ' . $this->eCommerceSocpeople->error;
$this->errors = array_merge($this->errors, $this->eCommerceSocpeople->errors);
return false;
}
@@ -1557,7 +1552,7 @@ public function synchProduct($toNb=0)
dol_syslog("- Process synch of product remote_id=".$productArray['remote_id']);
$counter++;
- if ($toNb > 0 && $counter > $toNb) break;
+ // if ($toNb > 0 && $counter > $toNb) break;
if (empty($productArray['remote_id']))
{
@@ -1569,93 +1564,93 @@ public function synchProduct($toNb=0)
$this->db->begin();
- //check if product exists in eCommerceProduct (with remote id)
- $synchExists = $this->eCommerceProduct->fetchByRemoteId($productArray['remote_id'], $this->eCommerceSite->id);
-
$dBProduct = new Product($this->db);
+ //check if product exists in eCommerceProduct (with remote id)
+ $idProduct = '';
+ $synchExists = $this->eCommerceProduct->fetchByRemoteId($productArray['remote_id'], $this->eCommerceSite->id);
+ if ($synchExists > 0) {
+ $idProduct = $this->eCommerceProduct->fk_product;
+ } else {
// First, we check object does not alreay exists. If not, we create it, if it exists, update it.
- $refExists = $dBProduct->fetch('', dol_string_nospecial(trim($productArray['ref'])));
- $result = -1;
+ $refExists = $dBProduct->fetch('', dol_string_nospecial(trim($productArray['ref'])));
+ if ($refExists > 0 && $this->eCommerceProduct->fetchByProductId($dBProduct->id, $this->eCommerceSite->id) > 0) {
+ $refExists = '';
+ }
+ }
//libelle of product object = label into database
+ $dBProduct->ref = dol_string_nospecial(trim($productArray['ref']));
$dBProduct->label = $productArray['label'];
- $dBProduct->description = $productArray['description'];
+ $dBProduct->description = isset($productArray['description']) ? $productArray['description'] : $dBProduct->description;
$dBProduct->weight = $productArray['weight'];
$dBProduct->type = $productArray['fk_product_type'];
$dBProduct->finished = $productArray['finished'];
$dBProduct->status = $productArray['envente'];
+ $dBProduct->status_buy = $productArray['enachat'];
$dBProduct->country_id = $productArray['fk_country'];
$dBProduct->context['fromsyncofecommerceid'] = $this->eCommerceSite->id;
$dBProduct->ref_ext = $this->eCommerceSite->name.'-'.$productArray['remote_id'];
$dBProduct->url = $productArray['url'];
+ if ($conf->barcode->enabled)
+ $dBProduct->barcode = -1;
+
+ if (is_array($productArray['extrafields'])) {
+ foreach ($productArray['extrafields'] as $extrafield => $extrafield_value) {
+ $dBProduct->array_options['options_'.$extrafield] = $extrafield_value;
+ }
+ }
if ($refExists > 0 && isset($dBProduct->id))
{
//update
$result = $dBProduct->update($dBProduct->id, $this->user);
- if ($result >= 0)// rajouter constante TTC/HT
+ if ($result >= 0)
{
- if (empty($productArray['price_base_type'])) $productArray['price_base_type']='HT';
-
- /*
- var_dump($this->eCommerceSite->price_level);
- // Result from ecommerce
- var_dump($productArray['price_base_type'].' - '.$productArray['price'].' - '.price2num((float) $productArray['tax_rate']).' - '.$productArray['price_min']);
- // Into dolibarr database
- var_dump($dBProduct->price_base_type." - ".$dBProduct->price." - ".price2num((float) $dBProduct->tva_tx)." - ".$dBProduct->price_min);
- var_dump($dBProduct->multiprices_base_type[$this->eCommerceSite->price_level]." - ".$dBProduct->multiprices[$this->eCommerceSite->price_level]." - ".$dBProduct->multiprices_tva_tx[$this->eCommerceSite->price_level]." - ".$dBProduct->multiprices_min[$this->eCommerceSite->price_level]);
- */
-
- // Update price
- if (!empty($conf->global->PRODUIT_MULTIPRICES))
- {
- $price_level = $this->eCommerceSite->price_level;
- $price_min = $dBProduct->multiprices_min[$price_level];
- if (isset($productArray['price_min'])) $price_min = $productArray['price_min'];
-
- if ($productArray['price'] != $dBProduct->multiprices[$price_level] || $productArray['price_base_type'] != $dBProduct->multiprices_base_type[$price_level] || (price2num((float) $productArray['tax_rate']) != price2num((float) $dBProduct->multiprices_tva_tx[$price_level])) || (isset($productArray['price_min']) && ($productArray['price_min'] != $dBProduct->multiprices_min[$price_level])))
- {
- $dBProduct->updatePrice($productArray['price'], $productArray['price_base_type'], $this->user, $productArray['tax_rate'], $price_min, $price_level);
- }
- else
- {
- //print 'No change in price for '.$dBProduct->ref."\n";
- }
- }
- else
- {
- $price_min = $dBProduct->price_min;
- if (isset($productArray['price_min'])) $price_min = $productArray['price_min'];
-
- if ($productArray['price'] != $dBProduct->price || $productArray['price_base_type'] != $dBProduct->price_base_type || (price2num((float) $productArray['tax_rate']) != price2num((float) $dBProduct->tva_tx)) || (isset($productArray['price_min']) && ($productArray['price_min'] != $dBProduct->price_min)))
- {
- $dBProduct->updatePrice($productArray['price'], $productArray['price_base_type'], $this->user, $productArray['tax_rate'], $price_min);
- }
- else
- {
- print 'No change in price for '.$dBProduct->ref."\n";
- }
+ // Update price if need
+ $price_level = empty($this->eCommerceSite->price_level) ? 1 : $this->eCommerceSite->price_level;
+
+ // Get current product values
+ if (empty($conf->global->PRODUIT_MULTIPRICES)) {
+ $price_base_type_org = $dBProduct->price_base_type;
+ $price_org = $dBProduct->price;
+ $price_min_org = $dBProduct->price_min;
+ $tax_rate_org = $dBProduct->tva_tx;
+ } else {
+ $price_base_type_org = $dBProduct->multiprices_base_type[$price_level];
+ $price_org = $dBProduct->multiprices[$price_level];
+ $price_min_org = $dBProduct->multiprices_min[$price_level];
+ $tax_rate_org = $dBProduct->multiprices_tva_tx[$price_level];
}
- // If eCommerce setup has changed and now prices are switch TI/TE (Tax Include / Tax Excluded)
- if ($dBProduct->price_base_type != $this->eCommerceSite->magento_price_type && empty($conf->global->ECOMMERCENG_DISABLE_MAGENTO_PRICE_TYPE))
- {
- dol_syslog("Setup price for eCommerce are switched from TE toTI or TI to TE, we update price of product");
+ $price_base_type = $this->eCommerceSite->ecommerce_price_type;
+ if (isset($productArray['price_base_type'])) $price_base_type = $productArray['price_base_type'];
+
+ if ($price_base_type_org != $price_base_type ||
+ $price_org != $productArray['price'] ||
+ (isset($productArray['price_min']) && $price_min_org != $productArray['price_min']) ||
+ price2num((float) $productArray['tax_rate']) != price2num((float) $tax_rate_org)
+ ) {
+ // The price type from eCommerce is defined for the site: TI/TE (Tax Include / Tax Excluded)
if (empty($conf->global->PRODUIT_MULTIPRICES)) {
- $dBProduct->updatePrice($dBProduct->price, $this->eCommerceSite->magento_price_type, $this->user);
+ $dBProduct->updatePrice($productArray['price'], $price_base_type, $this->user, $productArray['tax_rate'], $productArray['price_min']);
} else {
- $price_level = $this->eCommerceSite->price_level;
- $dBProduct->updatePrice($dBProduct->multiprices[$price_level], $this->eCommerceSite->magento_price_type, $this->user, $dBProduct->multiprices_tva_tx[$price_level], $dBProduct->multiprices_min[$price_level], $price_level);
+ $dBProduct->updatePrice($productArray['price'], $price_base_type, $this->user, $productArray['tax_rate'], $productArray['price_min'], $price_level);
}
}
}
+ else
+ {
+ $error++;
+ $this->error=$this->langs->trans('ECommerceSynchProductUpdateError').' '.$dBProduct->error;
+ $this->errors[]=$this->error;
+ }
// We must set the initial stock
if ($this->eCommerceSite->stock_sync_direction == 'ecommerce2dolibarr' && ($productArray['stock_qty'] != $dBProduct->stock_reel)) // Note: $dBProduct->stock_reel is 0 after a creation
{
- dol_syslog("Stock for product updated is ".$productArray['stock_qty']," in ecommerce, but ".$dBProduct->stock_reel." in Dolibarr, we must update it");
+ dol_syslog("Stock for product updated is ".$productArray['stock_qty']." in ecommerce, but ".$dBProduct->stock_reel." in Dolibarr, we must update it");
if (empty($this->eCommerceSite->fk_warehouse))
{
$error++;
@@ -1676,7 +1671,7 @@ public function synchProduct($toNb=0)
{
$error++;
$this->error=$this->langs->trans('ECommerceSynchMouvementStockChangeError').' '.$movement->error;
- $this->errors = array_merge($this->errors, $movement->errors);
+ $this->errors[] = $this->error;
}
}
}
@@ -1684,28 +1679,20 @@ public function synchProduct($toNb=0)
else
{
//create
- $dBProduct->ref = dol_string_nospecial(trim($productArray['ref']));
$dBProduct->canvas = $productArray['canvas'];
$dBProduct->note = 'Initialy created from '.$this->eCommerceSite->name;
$result = $dBProduct->create($this->user);
- if ($result >= 0)// rajouter constante TTC/HT
+ if ($result >= 0)
{
- if (!empty($conf->global->PRODUIT_MULTIPRICES)) {
- $price_level = $this->eCommerceSite->price_level;
- $dBProduct->updatePrice($productArray['price'], $dBProduct->multiprices_base_type[$price_level], $this->user, $productArray['tax_rate'], $productArray['price_min'], $price_level);
- }
-
- // If eCommerce setup hase change and now prices are switch TI/TE (Tax Include / Tax Excluded)
- if (empty($conf->global->ECOMMERCENG_DISABLE_MAGENTO_PRICE_TYPE))
- {
- dol_syslog("Setup price for eCommerce are switched from TE toTI or TI to TE, we update price of product");
- if (empty($conf->global->PRODUIT_MULTIPRICES)) {
- $dBProduct->updatePrice($dBProduct->price, $this->eCommerceSite->magento_price_type, $this->user);
- } else {
- $price_level = $this->eCommerceSite->price_level;
- $dBProduct->updatePrice($dBProduct->multiprices[$price_level], $this->eCommerceSite->magento_price_type, $this->user, $dBProduct->multiprices_tva_tx[$price_level], $dBProduct->multiprices_min[$price_level], $price_level);
- }
+ // Set price
+ $price_level = !empty($this->eCommerceSite->price_level) ? $this->eCommerceSite->price_level : 1;
+
+ // The price type from eCommerce is defined for the site: TI/TE (Tax Include / Tax Excluded)
+ if (empty($conf->global->PRODUIT_MULTIPRICES)) {
+ $dBProduct->updatePrice($productArray['price'], $this->eCommerceSite->ecommerce_price_type, $this->user, $productArray['tax_rate'], $productArray['price_min']);
+ } else {
+ $dBProduct->updatePrice($productArray['price'], $this->eCommerceSite->ecommerce_price_type, $this->user, $productArray['tax_rate'], $productArray['price_min'], $price_level);
}
}
else
@@ -1713,7 +1700,7 @@ public function synchProduct($toNb=0)
$error++;
if ($dBProduct->error == 'ErrorProductAlreadyExists') $this->error=$this->langs->trans('ECommerceSynchProductCreateError').' '.$this->langs->trans($dBProduct->error, $dBProduct->ref);
else $this->error=$this->langs->trans('ECommerceSynchProductCreateError').' '.$dBProduct->error;
- $this->errors = array_merge($this->errors, $dBProduct->errors);
+ $this->errors[] = $this->error;
}
// We must set the initial stock
@@ -1738,8 +1725,8 @@ public function synchProduct($toNb=0)
if ($result <= 0)
{
$error++;
- $this->errors[]=$this->langs->trans('ECommerceSynchMouvementStockChangeError').' '.$movement->error;
- $this->errors = array_merge($this->errors, $movement->errors);
+ $this->error=$this->langs->trans('ECommerceSynchMouvementStockChangeError').' '.$movement->error;
+ $this->errors[] = $this->error;
}
}
}
@@ -1784,6 +1771,34 @@ public function synchProduct($toNb=0)
}
//$cat = new Categorie($this->db, $this->eCommerceSite->fk_cat_product);
//$cat->add_type($dBProduct, 'product');
+
+ // Synchronize images
+ if (!empty($conf->global->ECOMMERCENG_ENABLE_SYNCHRO_IMAGES)) {
+ if (is_array($productArray['images'])) {
+ foreach ($productArray['images'] as $image) {
+ $ret = ecommerceng_download_image($image, $dBProduct, $error_message);
+
+ if (!$ret) {
+ $error++;
+ $error_label = $this->langs->trans('ECommerceSyncheCommerceProductDownloadImageError',
+ implode(',', $image), $dBProduct->id, $productArray['remote_id'], $this->eCommerceSite->name) . ': ' . $error_message;
+ $this->errors[] = $error_label;
+ dol_syslog($error_label, LOG_ERR);
+ }
+ }
+ }
+
+ // Remove obsolete image
+ $ret = ecommerceng_remove_obsolete_image($dBProduct, $productArray['images'], $error_message);
+ if (!$ret) {
+ $error++;
+ $error_label = $this->langs->trans('ECommerceSyncheCommerceProductDownloadImageError',
+ $dBProduct->id, $productArray['remote_id'], $this->eCommerceSite->name) . ': ' . $error_message;
+ $this->errors[] = $error_label;
+ dol_syslog($error_label, LOG_ERR);
+ }
+ }
+
$this->eCommerceProduct->last_update = $productArray['last_update'];
$this->eCommerceProduct->fk_product = $dBProduct->id;
@@ -1794,9 +1809,9 @@ public function synchProduct($toNb=0)
if ($this->eCommerceProduct->update($this->user) < 0)
{
$error++;
- $this->errors[] = $this->langs->trans('ECommerceSyncheCommerceProductUpdateError') . ' ' . $productArray['label'];
- $this->errors = array_merge($this->errors, $this->eCommerceProduct->errors);
- dol_syslog($this->langs->trans('ECommerceSyncheCommerceProductUpdateError') . ' ' . $productArray['label'], LOG_WARNING);
+ $this->error = $this->langs->trans('ECommerceSyncheCommerceProductUpdateError') . ' ' . $productArray['label'];
+ $this->errors[] = $this->error;
+ dol_syslog($this->error, LOG_WARNING);
}
}
// if not previous synchro exists into link table (we faild to find it from the remote_id)
@@ -1812,17 +1827,18 @@ public function synchProduct($toNb=0)
if ($this->eCommerceProduct->create($this->user) < 0)
{
$error++;
- $this->errors[] = $this->langs->trans('ECommerceSyncheCommerceProductCreateError') . ' ' . $productArray['label'].', '.$this->eCommerceProduct->error;
- $this->errors = array_merge($this->errors, $this->eCommerceProduct->errors);
- dol_syslog($this->langs->trans('ECommerceSyncheCommerceProductCreateError') . ' ' . $productArray['label'].', '.$this->eCommerceProduct->error, LOG_WARNING);
+ $this->error = $this->langs->trans('ECommerceSyncheCommerceProductCreateError') . ' ' . $productArray['label'].', '.$this->eCommerceProduct->error;
+ $this->errors[] = $this->error;
+ dol_syslog($this->error, LOG_WARNING);
}
}
}
else
{
$error++;
- $this->errors[] = $this->langs->trans('ECommerceSynchProductError') . ' ' . $productArray['label'];
- dol_syslog($this->langs->trans('ECommerceSynchProductError') . ' ' . $productArray['label'], LOG_WARNING);
+ $this->error = $this->langs->trans('ECommerceSynchProductError') . ' Ref:' . $productArray['ref'] . ' Nom:' . $productArray['label'] . ', remote ID:' . $productArray['remote_id'];
+ $this->errors[] = $this->error;
+ dol_syslog($this->error, LOG_WARNING);
}
unset($dBProduct);
@@ -1863,8 +1879,9 @@ public function synchProduct($toNb=0)
$this->errors[] = $this->error;
}
} catch (Exception $e) {
- $this->errors[] = $this->langs->trans('ECommerceErrorsynchProduct');
- dol_syslog($this->langs->trans('ECommerceSynchProductError'), LOG_WARNING);
+ $this->error = $this->langs->trans('ECommerceErrorsynchProduct');
+ $this->errors[] = $this->error;
+ dol_syslog($this->error, LOG_WARNING);
}
return -1;
@@ -1941,10 +1958,10 @@ public function synchCommande($toNb=0)
else
{
// This is an unknown customer. May be a non logged customer.
- if (! empty($conf->global->ECOMMERCENG_USE_THIS_THIRDPARTY_FOR_NONLOGGED_CUSTOMER))
+ if ($this->eCommerceSite->fk_anonymous_thirdparty > 0)
{
$societeExists = 1;
- $this->eCommerceSociete->fk_societe = $conf->global->ECOMMERCENG_USE_THIS_THIRDPARTY_FOR_NONLOGGED_CUSTOMER;
+ $this->eCommerceSociete->fk_societe = $this->eCommerceSite->fk_anonymous_thirdparty;
}
else
{
@@ -1968,6 +1985,12 @@ public function synchCommande($toNb=0)
$dBCommande->context['fromsyncofecommerceid'] = $this->eCommerceSite->id;
+ if (is_array($commandeArray['extrafields'])) {
+ foreach ($commandeArray['extrafields'] as $extrafield => $extrafield_value) {
+ $dBCommande->array_options['options_'.$extrafield] = $extrafield_value;
+ }
+ }
+
if ($dBCommande->ref_client != $commandeArray['ref_client']
|| $tmpdateorder1 != $tmpdateorder2
|| $tmpdatedeliv1 != $tmpdatedeliv2
@@ -1984,7 +2007,7 @@ public function synchCommande($toNb=0)
{
$error++;
$this->errors[]=$this->langs->trans('ECommerceSynchCommandeUpdateError').' '.$dBCommande->error;
- $this->errors = array_merge($this->errors, $dbCommande->errors);
+ $this->errors = array_merge($this->errors, $dBCommande->errors);
}
}
@@ -2025,14 +2048,14 @@ public function synchCommande($toNb=0)
{
if ($dBCommande->statut != Commande::STATUS_VALIDATED)
{
- $dBCommande->setStatut(Commande::STATUS_VALIDATED, $dbCommande->id, $dbCommande->table_element);
+ $dBCommande->setStatut(Commande::STATUS_VALIDATED, $dBCommande->id, $dBCommande->table_element);
}
}
if ($commandeArray['status'] == 2) // Should be Commande::STATUS_SHIPMENTONPROCESS but not defined in dolibarr 3.9
{
if ($dBCommande->statut != 2)
{
- $dBCommande->setStatut(2, $dbCommande->id, $dbCommande->table_element);
+ $dBCommande->setStatut(2, $dBCommande->id, $dBCommande->table_element);
}
}
if ($commandeArray['status'] == Commande::STATUS_CANCELED)
@@ -2042,7 +2065,7 @@ public function synchCommande($toNb=0)
$idWareHouse = 0;
// We don't change stock here, even if dolibarr option is on because, this should be already done by product sync
//if ($this->eCommerceSite->stock_sync_direction == 'ecommerce2dolibarr') $idWareHouse=$this->eCommerceSite->fk_warehouse;
- $dBCommande->cancel(0, $idWarehouse);
+ $dBCommande->cancel(0, $idWareHouse);
}
}
if ($commandeArray['status'] == Commande::STATUS_CLOSED)
@@ -2082,7 +2105,13 @@ public function synchCommande($toNb=0)
$dBCommande->note_private=isset($commandeArray['note'])?$commandeArray['note']:"";
if (! empty($conf->global->ECOMMERCENG_ENABLE_LOG_IN_NOTE))
{
- $dBCommande->note_private.="Last eCommerce order received:\n".dol_trunc(serialize(var_export($commandeArray['remote_order'], true)), 65000);
+ $dBCommande->note_private.="Last eCommerce order received:\n".serialize(var_export($commandeArray['remote_order'], true));
+ }
+
+ if (is_array($commandeArray['extrafields'])) {
+ foreach ($commandeArray['extrafields'] as $extrafield => $extrafield_value) {
+ $dBCommande->array_options['options_'.$extrafield] = $extrafield_value;
+ }
}
$result = $dBCommande->create($this->user);
@@ -2090,8 +2119,8 @@ public function synchCommande($toNb=0)
{
dol_syslog("synchCommande result=".$result." ".$dBCommande->error, LOG_ERR);
$error++;
- $this->errors[]=$this->langs->trans('ECommerceSynchCommandeCreateError').' '.$dBCommande->error;
- $this->errors = array_merge($this->errors, $dbCommande->errors);
+ $this->error = $this->langs->trans('ECommerceSynchCommandeCreateError').' '.$dBCommande->error;
+ $this->errors[] = $this->error;
}
// Add lines
@@ -2110,7 +2139,7 @@ public function synchCommande($toNb=0)
if (($result = $dBCommande->defineBuyPrice($item['price'], 0, $fk_product)) < 0)
{
$this->error = $this->langs->trans('ECommerceSyncheCommerceCommandeUpdateError').' '.$dBCommande->error;
- $this->errors = array_merge($this->errors, $dbCommande->errors);
+ $this->errors[] = $this->error;
$error++;
break; // break on items
}
@@ -2135,8 +2164,18 @@ public function synchCommande($toNb=0)
$buyprice = $productFournisseur->fourn_unitprice;
}*/
- $result = $dBCommande->addline($item['description'], $item['price'], $item['qty'], $item['tva_tx'], 0, 0,
- $this->eCommerceProduct->fk_product, //fk_product
+ $description = $item['description'];
+ if (empty($description) && $fk_product > 0) {
+ $dBProduct = new Product($this->db);
+ $dBProduct->fetch($fk_product);
+ $description = $dBProduct->label;
+ }
+ if (empty($description)) {
+ $description = $this->langs->trans('ECommerceNoDescForProductLine');
+ }
+
+ $result = $dBCommande->addline($description, $item['price'], $item['qty'], $item['tva_tx'], 0, 0,
+ $fk_product, //fk_product
0, //remise_percent
0, //info_bits
0, //fk_remise_except
@@ -2154,8 +2193,8 @@ public function synchCommande($toNb=0)
dol_syslog("result=".$result);
if ($result <= 0)
{
- $this->errors[] = $this->langs->trans('ECommerceSyncheCommerceCommandeUpdateError').' '.$dBCommande->error;
- $this->errors = array_merge($this->errors, $dbCommande->errors);
+ $this->error = $this->langs->trans('ECommerceSyncheCommerceCommandeUpdateError').' '.$dBCommande->error;
+ $this->errors[] = $this->error;
$error++;
break; // break on items
}
@@ -2191,8 +2230,8 @@ public function synchCommande($toNb=0)
);
if ($result <= 0)
{
- $this->errors[] = $this->langs->trans('ECommerceSyncheCommerceCommandeUpdateError').' '.$dBCommande->error;
- $this->errors = array_merge($this->errors, $dbCommande->errors);
+ $this->error = $this->langs->trans('ECommerceSyncheCommerceCommandeUpdateError').' '.$dBCommande->error;
+ $this->errors[] = $this->error;
$error++;
}
}
@@ -2265,9 +2304,23 @@ public function synchCommande($toNb=0)
}
//add or update contacts of order ($this->eCommerceSociete->fk_societe is id in Dolibarr of thirdparty but may be id of the generic "non logged user")
- $commandeArray['socpeopleCommande']['fk_soc'] = $this->eCommerceSociete->fk_societe;
- $commandeArray['socpeopleFacture']['fk_soc'] = $this->eCommerceSociete->fk_societe;
- $commandeArray['socpeopleLivraison']['fk_soc'] = $this->eCommerceSociete->fk_societe;
+ $fk_soc_socpeopleCommande = $this->eCommerceSociete->fk_societe;
+ $fk_soc_socpeopleFacture = $this->eCommerceSociete->fk_societe;
+ $fk_soc_socpeopleLivraison = $this->eCommerceSociete->fk_societe;
+ if ($this->eCommerceSociete->fk_societe == $this->eCommerceSite->fk_anonymous_thirdparty) {
+ if (!empty(trim($commandeArray['socpeopleCommande']['email']))) {
+ $fk_soc_socpeopleCommande = get_company_by_email($this->db, $commandeArray['socpeopleCommande']['email'], $this->eCommerceSite->id);
+ }
+ if (!empty(trim($commandeArray['socpeopleFacture']['email']))) {
+ $fk_soc_socpeopleFacture = get_company_by_email($this->db, $commandeArray['socpeopleFacture']['email'], $this->eCommerceSite->id);
+ }
+ if (!empty(trim($commandeArray['socpeopleLivraison']['email']))) {
+ $fk_soc_socpeopleLivraison = get_company_by_email($this->db, $commandeArray['socpeopleLivraison']['email'], $this->eCommerceSite->id);
+ }
+ }
+ $commandeArray['socpeopleCommande']['fk_soc'] = $fk_soc_socpeopleCommande;
+ $commandeArray['socpeopleFacture']['fk_soc'] = $fk_soc_socpeopleFacture;
+ $commandeArray['socpeopleLivraison']['fk_soc'] = $fk_soc_socpeopleLivraison;
if (! $error)
{
@@ -2288,6 +2341,16 @@ public function synchCommande($toNb=0)
}
}
+ // Update Payment method
+ if (! $error) {
+ if (isset($commandeArray['payment_method'])) {
+ $payment_method = dol_getIdFromCode($this->db, $commandeArray['payment_method'], 'c_paiement', 'libelle', 'id');
+ if ($payment_method != '' && $payment_method > 0) {
+ $dBCommande->setPaymentMethods($payment_method);
+ }
+ }
+ }
+
//if synchro commande ok
if (! $error)
{
@@ -2300,8 +2363,8 @@ public function synchCommande($toNb=0)
if ($this->eCommerceCommande->update($this->user) < 0)
{
$error++;
- $this->errors[] = $this->langs->trans('ECommerceSyncheCommerceCommandeUpdateError').' '.$this->eCommerceCommande->error;
- $this->errors = array_merge($this->errors, $this->eCommerceCommande->errors);
+ $this->error = $this->langs->trans('ECommerceSyncheCommerceCommandeUpdateError').' '.$this->eCommerceCommande->error;
+ $this->errors[] = $this->error;
}
}
//if not previous synchro exists
@@ -2318,9 +2381,9 @@ public function synchCommande($toNb=0)
if ($this->eCommerceCommande->create($this->user) < 0)
{
$error++;
- $this->errors[] = $this->langs->trans('ECommerceSyncheCommerceCommandeCreateError').' '.$dBCommande->id.', '.$this->eCommerceCommande->error;
- $this->errors = array_merge($this->errors, $this->eCommerceCommande->errors);
- dol_syslog($this->langs->trans('ECommerceSyncheCommerceCommandeCreateError') . ' ' . $dBCommande->id.', '.$this->eCommerceCommande->error, LOG_WARNING);
+ $this->error = $this->langs->trans('ECommerceSyncheCommerceCommandeCreateError').' '.$dBCommande->id.', '.$this->eCommerceCommande->error;
+ $this->errors[] = $this->error;
+ dol_syslog($this->error, LOG_WARNING);
}
}
}
@@ -2333,23 +2396,30 @@ public function synchCommande($toNb=0)
else {
if ($commandeArray['remote_id_societe'] != 0) {
$error++;
- $this->errors[] = $this->langs->trans('ECommerceSynchCommandeErrorSocieteNotExists') . ' (remote_id='.$commandeArray['remote_id'].') ' . $commandeArray['remote_id_societe'];
+ $this->errors[] = $this->langs->trans('ECommerceSynchCommandeErrorSocieteNotExists') . ' (Commande ID='.$commandeArray['remote_id'].', Client ID:' . $commandeArray['remote_id_societe'].')';
} else
{
$error++;
$this->errors[] = $this->langs->trans('ECommerceSynchCommandeErrorSocieteNotExists') . ' (remote_id='.$commandeArray['remote_id'].') - Unknown customer.';
- $this->errors[] = 'This order is not linked to a dedicated customer. Try to set option ECOMMERCENG_USE_THIS_THIRDPARTY_FOR_NONLOGGED_CUSTOMER';
+ if (empty($this->eCommerceSite->fk_anonymous_thirdparty)) {
+ $this->errors[] = 'This order is not linked to a dedicated customer. Try to set option Anonymous thirdparty into the site parameters';
+ }
}
}
unset($dBCommande);
unset($this->eCommerceSociete);
unset($this->eCommerceCommande);
- if ($error || ! empty($this->errors))
+ if ($error)
{
$this->db->rollback();
$nbrecorderror++;
- break; // We decide to stop on first error
+ // We decide to stop on first error (Can continue if anonymous order with const ECOMMERCENG_PASS_ORDER_FOR_NONLOGGED_CUSTOMER)
+ if ($commandeArray['remote_id_societe'] != 0 || empty($conf->global->ECOMMERCENG_PASS_ORDER_FOR_NONLOGGED_CUSTOMER)) {
+ break;
+ } else {
+ $error = 0;
+ }
}
else
{
@@ -2457,10 +2527,10 @@ public function synchFacture($toNb=0)
else
{
// This is an unknown customer. May be a non logged customer.
- if (! empty($conf->global->ECOMMERCENG_USE_THIS_THIRDPARTY_FOR_NONLOGGED_CUSTOMER))
+ if ($this->eCommerceSite->fk_anonymous_thirdparty > 0)
{
$societeExists = 1;
- $this->eCommerceSociete->fk_societe = $conf->global->ECOMMERCENG_USE_THIS_THIRDPARTY_FOR_NONLOGGED_CUSTOMER;
+ $this->eCommerceSociete->fk_societe = $this->eCommerceSite->fk_anonymous_thirdparty;
}
else
{
@@ -3085,7 +3155,8 @@ public function dropImportedAndSyncData($deletealsoindolibarr, $mode='')
}
//Drop socPeople
- if (empty($mode) || preg_match('/^contacts/', $mode))
+ if (empty($mode) || preg_match('/^thirdparties/', $mode))
+// if (empty($mode) || preg_match('/^contacts/', $mode))
{
$dolObjectsDeleted = 0;
$synchObjectsDeleted = 0;
@@ -3136,6 +3207,9 @@ public function dropImportedAndSyncData($deletealsoindolibarr, $mode='')
$this->initECommerceSociete();
if ($this->eCommerceSociete->fetch($idSociete) > 0)
{
+ // Skip anonymous thirdparty
+ if ($this->eCommerceSociete->remote_id == 0) continue;
+
if ($deletealsoindolibarr)
{
$dbSociete = new Societe($this->db);
@@ -3219,12 +3293,16 @@ function getContactIdFromInfos($contact)
$contactId = -1;
$sql = 'SELECT rowid FROM '.MAIN_DB_PREFIX.'socpeople';
- $sql .= ' WHERE lastname="'.$db->escape(trim($contact->lastname)).'"';
- $sql .= ' AND firstname="'.$db->escape(trim($contact->firstname)).'"';
- $sql .= ' AND address="'.$db->escape(trim($contact->address)).'"';
- $sql .= ' AND town="'.$db->escape(trim($contact->town)).'"';
- $sql .= ' AND zip="'.$db->escape(trim($contact->zip)).'"';
- $sql .= ' AND fk_soc="'.$contact->fk_soc.'"';
+ $sql .= ' WHERE lastname LIKE "'.$db->escape(trim($contact->lastname)).'"';
+ $sql .= ' AND firstname LIKE "'.$db->escape(trim($contact->firstname)).'"';
+ $sql .= ' AND address LIKE "'.$db->escape(trim($contact->address)).'"';
+ $sql .= ' AND town LIKE "'.$db->escape(trim($contact->town)).'"';
+ $sql .= ' AND zip LIKE "'.$db->escape(trim($contact->zip)).'"';
+ if (isset($contact->country_id)) $sql .= ' AND fk_pays='.($contact->country_id>0?$contact->country_id:'NULL');
+ if (isset($contact->email)) $sql .= ' AND email LIKE "'.$db->escape(trim($contact->email)).'"';
+ if (isset($contact->phone_pro)) $sql .= ' AND phone LIKE "'.$db->escape(trim($contact->phone_pro)).'"';
+ if (isset($contact->fax)) $sql .= ' AND fax LIKE "'.$db->escape(trim($contact->fax)).'"';
+ $sql .= ' AND fk_soc='.$contact->fk_soc;
$resql = $this->db->query($sql);
if($resql)
@@ -3246,7 +3324,7 @@ function getContactIdFromInfos($contact)
{
$this->error=$this->db->lasterror();
dol_syslog("eCommerceSynchro::getContactIdFromInfos ".$this->error, LOG_ERR);
- return -1;
+ return $contactId;
}
}
diff --git a/htdocs/ecommerceng/class/data/eCommerceCategory.class.php b/htdocs/ecommerceng/class/data/eCommerceCategory.class.php
index 054de82..4f8eef4 100644
--- a/htdocs/ecommerceng/class/data/eCommerceCategory.class.php
+++ b/htdocs/ecommerceng/class/data/eCommerceCategory.class.php
@@ -95,8 +95,8 @@ function create($user, $notrigger = 0)
$sql.= " '" . $this->db->escape($this->description) . "',";
$sql.= " " . $this->db->escape($this->fk_category) . ",";
$sql.= " " . $this->db->escape($this->fk_site) . ",";
- $sql.= " " . $this->db->escape($this->remote_id) . ",";
- $sql.= " " . $this->db->escape($this->remote_parent_id) . ",";
+ $sql.= " '" . $this->db->escape($this->remote_id) . "',";
+ $sql.= " '" . $this->db->escape($this->remote_parent_id) . "',";
$sql.= " '" . $this->db->idate($this->last_update) . "'";
$sql.= ")";
@@ -380,7 +380,7 @@ public function checkForUpdate($siteId, $toDate, $remoteCatToCheck)
global $langs;
$updateRequired = 0; // If any error occurs, category won't appears in update array
- $sql = "SELECT t.last_update as lastdate, t.remote_parent_id as parentid FROM " . MAIN_DB_PREFIX . $this->table_element . " as t";
+ $sql = "SELECT t.last_update as lastdate, t.remote_parent_id as parentid, t.fk_category FROM " . MAIN_DB_PREFIX . $this->table_element . " as t";
$sql.= " WHERE t.remote_id=" . $remoteCatToCheck['category_id'] . " AND t.fk_site = " . $siteId;
$resql = $this->db->query($sql);
@@ -390,12 +390,24 @@ public function checkForUpdate($siteId, $toDate, $remoteCatToCheck)
{
$obj = $this->db->fetch_object($resql);
- $now = $toDate; // Dolibarr's category time
- $lu = $this->db->jdate($obj->lastdate); // date of last update process
- $lumage = strtotime($remoteCatToCheck['updated_at']);
- //var_dump($lu);
- //var_dump($lumage);
- $updateRequired = ($obj->parentid != $remoteCatToCheck['parent_id'] || ($lu < $lumage)) ? 1 : 0;
+ $diffdates = false;
+ $diffvalues = false;
+ if (empty($remoteCatToCheck['updated_at'])) {
+ $catObj = new Categorie($this->db);
+ $ret = $catObj->fetch($obj->fk_category);
+ if ($ret > 0) {
+ $diffvalues = $catObj->label != trim($remoteCatToCheck['name']) || $catObj->description != trim($remoteCatToCheck['description']);
+ }
+ } else {
+ $now = $toDate; // Dolibarr's category time
+ $lu = $this->db->jdate($obj->lastdate); // date of last update process
+ $lumage = strtotime($remoteCatToCheck['updated_at']);
+ //var_dump($lu);
+ //var_dump($lumage);
+ $diffdates = $lu < $lumage;
+ }
+
+ $updateRequired = ($obj->parentid != $remoteCatToCheck['parent_id'] || $diffdates || $diffvalues) ? 1 : 0;
} else
{
$updateRequired = 1;
diff --git a/htdocs/ecommerceng/class/data/eCommerceProduct.class.php b/htdocs/ecommerceng/class/data/eCommerceProduct.class.php
index 4197d9b..46d74eb 100644
--- a/htdocs/ecommerceng/class/data/eCommerceProduct.class.php
+++ b/htdocs/ecommerceng/class/data/eCommerceProduct.class.php
@@ -190,7 +190,7 @@ function update($user=0, $notrigger=0)
$sql.= " fk_product=".(isset($this->fk_product)?intval($this->fk_product):0).",";
$sql.= " fk_site=".(isset($this->fk_site)?intval($this->fk_site):0).",";
- $sql.= " remote_id=".(isset($this->remote_id)?"'".$this->db->escape($this->remote_id)."'":"").",";
+ $sql.= " remote_id='".$this->db->escape($this->remote_id)."',";
$sql.= " last_update=".(isset($this->last_update)?"'".$this->last_update."'" : 'null')."";
$sql.= " WHERE rowid=".$this->id;
@@ -343,7 +343,7 @@ public function fetchByRemoteId($remoteId, $siteId)
$sql.= " t.last_update";
$sql.= " FROM ".MAIN_DB_PREFIX."ecommerce_product as t";
$sql.= " WHERE t.fk_site = ".$siteId;
- $sql.= " AND t.remote_id = ".$remoteId;
+ $sql.= " AND t.remote_id = '".$this->db->escape($remoteId)."'";
dol_syslog(get_class($this)."::fetchByRemoteId sql=".$sql, LOG_DEBUG);
$resql=$this->db->query($sql);
if ($resql)
diff --git a/htdocs/ecommerceng/class/data/eCommerceRemoteAccess.class.php b/htdocs/ecommerceng/class/data/eCommerceRemoteAccess.class.php
index ff2d8e2..fd63109 100644
--- a/htdocs/ecommerceng/class/data/eCommerceRemoteAccess.class.php
+++ b/htdocs/ecommerceng/class/data/eCommerceRemoteAccess.class.php
@@ -401,4 +401,36 @@ public function createRemoteLivraison($livraison, $remote_order_id)
$this->errors=$this->class->errors;
return $result;
}
+
+ /**
+ * Create a remote product
+ *
+ * @param Object $object Object product
+ * @return bool
+ */
+ public function createRemoteProduct($object)
+ {
+ $result=$this->class->createRemoteProduct($object);
+ $this->error=$this->class->error;
+ $this->errors=$this->class->errors;
+ return $result;
+ }
+
+ /**
+ * Send a file for remote commande
+ *
+ * @param int $order_remote_id Id of order on remote ecommerce
+ * @param int $societe_remote_id Id of societe on remote ecommerce
+ * @param Object $object Object product
+ * @param string $file File path
+ * @param Translate $outputlangs Lang output object
+ * @return bool
+ */
+ public function sendFileForCommande($order_remote_id, $societe_remote_id, $object, $file, $outputlangs)
+ {
+ $result=$this->class->sendFileForCommande($order_remote_id, $societe_remote_id, $object, $file, $outputlangs);
+ $this->error=$this->class->error;
+ $this->errors=$this->class->errors;
+ return $result;
+ }
}
diff --git a/htdocs/ecommerceng/class/data/eCommerceSite.class.php b/htdocs/ecommerceng/class/data/eCommerceSite.class.php
old mode 100755
new mode 100644
index 9287094..8677165
--- a/htdocs/ecommerceng/class/data/eCommerceSite.class.php
+++ b/htdocs/ecommerceng/class/data/eCommerceSite.class.php
@@ -41,12 +41,16 @@ class eCommerceSite // extends CommonObject
var $filter_value;
var $fk_cat_societe;
var $fk_cat_product;
+ var $fk_anonymous_thirdparty;
var $fk_warehouse;
var $stock_sync_direction;
var $last_update;
var $timeout;
var $magento_use_special_price;
- var $magento_price_type;
+ var $ecommerce_price_type;
+
+ var $oauth_id;
+ var $oauth_secret;
//The site type name is used to define class name in eCommerceRemoteAccess class
private $siteTypes = array(1=>'magento', 2=>'woocommerce');
@@ -111,10 +115,14 @@ function create($user, $notrigger=0)
if (isset($this->filter_value)) $this->filter_value=trim($this->filter_value);
if (isset($this->fk_cat_societe)) $this->fk_cat_societe=trim($this->fk_cat_societe);
if (isset($this->fk_cat_product)) $this->fk_cat_product=trim($this->fk_cat_product);
+ if (isset($this->fk_anonymous_thirdparty)) $this->fk_anonymous_thirdparty=trim($this->fk_anonymous_thirdparty);
if (isset($this->fk_warehouse)) $this->fk_warehouse=trim($this->fk_warehouse);
if (isset($this->stock_sync_direction)) $this->stock_sync_direction=trim($this->stock_sync_direction);
if (isset($this->timeout)) $this->timeout=trim($this->timeout);
+ if (isset($this->oauth_id)) $this->oauth_id=trim($this->oauth_id);
+ if (isset($this->oauth_secret)) $this->oauth_secret=trim($this->oauth_secret);
+
// Check parameters
// Put here code to add control on parameters values
@@ -130,29 +138,35 @@ function create($user, $notrigger=0)
$sql.= "filter_value,";
$sql.= "fk_cat_societe,";
$sql.= "fk_cat_product,";
+ $sql.= "fk_anonymous_thirdparty,";
$sql.= "fk_warehouse,";
$sql.= "stock_sync_direction,";
$sql.= "last_update,";
$sql.= "timeout,";
$sql.= "magento_use_special_price,";
- $sql.= "magento_price_type";
+ $sql.= "ecommerce_price_type,";
+ $sql.= "oauth_id,";
+ $sql.= "oauth_secret";
$sql.= ") VALUES (";
$sql.= " ".(! isset($this->name)?'NULL':"'".$this->db->escape($this->name)."'").",";
$sql.= " ".(! isset($this->type)?'NULL':"'".$this->type."'").",";
$sql.= " ".(! isset($this->webservice_address)?'NULL':"'".$this->db->escape($this->webservice_address)."'").",";
$sql.= " ".(! isset($this->user_name)?'NULL':"'".$this->db->escape($this->user_name)."'").",";
$sql.= " ".(! isset($this->user_password)?'NULL':"'".$this->db->escape($this->user_password)."'").",";
- $sql.= " ".(! isset($this->price_level)?'NULL':"'".$this->db->escape($this->price_level)."'").",";
+ $sql.= " ".(! isset($this->price_level)?'1':"'".$this->db->escape($this->price_level)."'").",";
$sql.= " ".(! isset($this->filter_label)?'NULL':"'".$this->db->escape($this->filter_label)."'").",";
$sql.= " ".(! isset($this->filter_value)?'NULL':"'".$this->db->escape($this->filter_value)."'").",";
$sql.= " ".($this->fk_cat_societe > 0 ? $this->fk_cat_societe : "NULL").",";
$sql.= " ".($this->fk_cat_product > 0 ? $this->fk_cat_product : "NULL").",";
+ $sql.= " ".($this->fk_anonymous_thirdparty > 0 ? $this->fk_anonymous_thirdparty : "NULL").",";
$sql.= " ".($this->fk_warehouse > 0 ? $this->fk_warehouse : "NULL").",";
$sql.= " ".($this->stock_sync_direction ? "'".$this->stock_sync_direction."'" : "'none'").",";
$sql.= " ".(! isset($this->last_update) || strlen($this->last_update)==0?'NULL':"'".$this->db->idate($this->last_update)."'").",";
$sql.= " ".(! isset($this->timeout)?'300':"'".intval($this->timeout)."'").",";
$sql.= " ".(! isset($this->magento_use_special_price)?'0':"'".intval($this->magento_use_special_price)."'").",";
- $sql.= " ".(! isset($this->magento_price_type)?'HT':"'".$this->magento_price_type."'")."";
+ $sql.= " ".(! isset($this->ecommerce_price_type)?'HT':"'".$this->ecommerce_price_type."'").",";
+ $sql.= " ".(! isset($this->oauth_id)?"NULL":"'".$this->db->escape($this->oauth_id)."'").",";
+ $sql.= " ".(! isset($this->oauth_secret)?"NULL":"'".$this->db->escape($this->oauth_secret)."'")."";
$sql.= ")";
$this->db->begin();
@@ -167,7 +181,7 @@ function create($user, $notrigger=0)
//create an entry for anonymous company
$eCommerceSociete = new eCommerceSociete($this->db);
- $eCommerceSociete->fk_societe = dolibarr_get_const($this->db, 'ECOMMERCE_COMPANY_ANONYMOUS');
+ $eCommerceSociete->fk_societe = $this->fk_anonymous_thirdparty;
$eCommerceSociete->fk_site = $this->id;
$eCommerceSociete->remote_id = 0;
if ($eCommerceSociete->create($user)<0)
@@ -217,12 +231,15 @@ function fetch($id)
$sql.= " t.filter_value,";
$sql.= " t.fk_cat_societe,";
$sql.= " t.fk_cat_product,";
+ $sql.= " t.fk_anonymous_thirdparty,";
$sql.= " t.fk_warehouse,";
$sql.= " t.stock_sync_direction,";
$sql.= " t.last_update,";
$sql.= " t.timeout,";
$sql.= " t.magento_use_special_price,";
- $sql.= " t.magento_price_type";
+ $sql.= " t.ecommerce_price_type,";
+ $sql.= " t.oauth_id,";
+ $sql.= " t.oauth_secret";
$sql.= " FROM ".MAIN_DB_PREFIX."ecommerce_site as t";
$sql.= " WHERE t.rowid = ".$id;
@@ -246,13 +263,16 @@ function fetch($id)
$this->filter_value = $obj->filter_value;
$this->fk_cat_societe = $obj->fk_cat_societe;
$this->fk_cat_product = $obj->fk_cat_product;
+ $this->fk_anonymous_thirdparty = $obj->fk_anonymous_thirdparty;
$this->fk_warehouse = $obj->fk_warehouse;
$this->stock_sync_direction = $obj->stock_sync_direction;
$this->last_update = $this->db->jdate($obj->last_update);
$this->timeout = $obj->timeout;
$this->magento_use_special_price = $obj->magento_use_special_price;
- $this->magento_price_type = $obj->magento_price_type;
+ $this->ecommerce_price_type = $obj->ecommerce_price_type;
+ $this->oauth_id = $obj->oauth_id;
+ $this->oauth_secret = $obj->oauth_secret;
}
$this->db->free($resql);
@@ -292,8 +312,11 @@ function update($user=0, $notrigger=0)
if (isset($this->filter_value)) $this->filter_value=trim($this->filter_value);
if (isset($this->fk_cat_societe)) $this->fk_cat_societe=trim($this->fk_cat_societe);
if (isset($this->fk_cat_product)) $this->fk_cat_product=trim($this->fk_cat_product);
+ if (isset($this->fk_anonymous_thirdparty)) $this->fk_anonymous_thirdparty=trim($this->fk_anonymous_thirdparty);
if (isset($this->fk_warehouse)) $this->fk_warehouse=trim($this->fk_warehouse);
if (isset($this->timeout)) $this->timeout=trim($this->timeout);
+ if (isset($this->oauth_id)) $this->oauth_id=trim($this->oauth_id);
+ if (isset($this->oauth_secret)) $this->oauth_secret=trim($this->oauth_secret);
// Check parameters
// Put here code to add control on parameters values
@@ -306,17 +329,20 @@ function update($user=0, $notrigger=0)
$sql.= " webservice_address=".(isset($this->webservice_address)?"'".$this->db->escape($this->webservice_address)."'":"null").",";
$sql.= " user_name=".(isset($this->user_name)?"'".$this->db->escape($this->user_name)."'":"null").",";
$sql.= " user_password=".(isset($this->user_password)?"'".$this->db->escape($this->user_password)."'":"null").",";
- $sql.= " price_level=".(isset($this->price_level)?"'".$this->db->escape($this->price_level)."'":"null").",";
+ $sql.= " price_level=".(isset($this->price_level)?"'".$this->db->escape($this->price_level)."'":"1").",";
$sql.= " filter_label=".(isset($this->filter_label)?"'".$this->db->escape($this->filter_label)."'":"null").",";
$sql.= " filter_value=".(isset($this->filter_value)?"'".$this->db->escape($this->filter_value)."'":"null").",";
$sql.= " fk_cat_societe=".($this->fk_cat_societe > 0 ? $this->fk_cat_societe:"null").",";
$sql.= " fk_cat_product=".($this->fk_cat_product > 0 ? $this->fk_cat_product:"null").",";
+ $sql.= " fk_anonymous_thirdparty=".($this->fk_anonymous_thirdparty > 0 ? $this->fk_anonymous_thirdparty:"null").",";
$sql.= " fk_warehouse=".($this->fk_warehouse > 0 ? $this->fk_warehouse:"null").",";
$sql.= " stock_sync_direction=".($this->stock_sync_direction ? "'".$this->stock_sync_direction."'":"'none'").",";
$sql.= " last_update=".((isset($this->last_update) && $this->last_update != '') ? "'".$this->db->idate($this->last_update)."'" : 'null').",";
$sql.= " timeout=".(isset($this->timeout)? "'".intval($this->timeout)."'" : '300').",";
$sql.= " magento_use_special_price=".(isset($this->magento_use_special_price)? "'".intval($this->magento_use_special_price)."'" : '0').",";
- $sql.= " magento_price_type=".(isset($this->magento_price_type)? "'".$this->magento_price_type."'" : 'HT')."";
+ $sql.= " ecommerce_price_type=".(isset($this->ecommerce_price_type)? "'".$this->ecommerce_price_type."'" : 'HT').",";
+ $sql.= " oauth_id=".(isset($this->oauth_id)?"'".$this->oauth_id."'":"NULL").",";
+ $sql.= " oauth_secret=".(isset($this->oauth_secret)?"'".$this->oauth_secret."'":"NULL")."";
$sql.= " WHERE rowid=".$this->id;
$this->db->begin();
@@ -327,7 +353,36 @@ function update($user=0, $notrigger=0)
if (! $error)
{
- if (! $notrigger)
+ $eCommerceSociete = new eCommerceSociete($this->db);
+ if ($eCommerceSociete->fetchByRemoteId(0, $this->id) > 0) {
+ if (isset($this->fk_anonymous_thirdparty)) {
+ // update an entry for anonymous company
+ $eCommerceSociete->fk_societe = $this->fk_anonymous_thirdparty;
+ if ($eCommerceSociete->update($user) < 0) {
+ $error++;
+ $this->errors[] = "Error " . $this->db->lasterror();
+ }
+ } else {
+ // delete an entry for anonymous company
+ if ($eCommerceSociete->delete($user) < 0) {
+ $error++;
+ $this->errors[] = "Error " . $this->db->lasterror();
+ }
+ }
+ } else {
+ // create an entry for anonymous company
+ $eCommerceSociete = new eCommerceSociete($this->db);
+ $eCommerceSociete->fk_societe = $this->fk_anonymous_thirdparty;
+ $eCommerceSociete->fk_site = $this->id;
+ $eCommerceSociete->remote_id = 0;
+ if ($eCommerceSociete->create($user)<0)
+ {
+ $error++;
+ $this->errors[]="Error ".$this->db->lasterror();
+ }
+ }
+
+ if (! $notrigger && !$error)
{
// Uncomment this and change MYOBJECT to your own tag if you
// want this action call a trigger.
@@ -492,12 +547,15 @@ function initAsSpecimen()
$this->filter_value='';
$this->fk_cat_societe='';
$this->fk_cat_product='';
+ $this->fk_anonymous_thirdparty='';
$this->fk_warehouse='';
$this->stock_sync_direction='none';
$this->last_update='';
$this->timeout='';
$this->magento_use_special_price='';
- $this->magento_price_type='';
+ $this->ecommerce_price_type='';
+ $this->oauth_id='';
+ $this->oauth_secret='';
}
/**
@@ -542,6 +600,30 @@ function listSites($mode='array')
return $list;
}
+ /**
+ * Check if type site is created
+ *
+ * @param integer $typeSite Type of site
+ * @return boolean true if type site has created
+ */
+ function hasTypeSite($typeSite)
+ {
+ $sql = "SELECT";
+ $sql.= " count(*) AS count";
+ $sql.= " FROM ".MAIN_DB_PREFIX."ecommerce_site as t";
+ $sql.= " WHERE t.type=".$typeSite;
+
+ $result = $this->db->query($sql);
+ if ($result) {
+ $obj = $this->db->fetch_object($result);
+ if ($obj->count > 0) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
/**
* Return list of available site types
*
@@ -576,7 +658,14 @@ public function getBackUrl()
{
// Try to guess public home page of ecommerce web site from the api url
$url=$this->getFrontUrl();
- $url.='index.php/admin';
+ switch ($this->type) {
+ case 1: // Magento
+ $url.='index.php/admin';
+ break;
+ case 2: // Woocommerce
+ $url.=(substr($url, -1, 1)!='/'?'/':'').'wp-admin';
+ break;
+ }
return $url;
}
diff --git a/htdocs/ecommerceng/class/data/eCommerceSocpeople.class.php b/htdocs/ecommerceng/class/data/eCommerceSocpeople.class.php
old mode 100755
new mode 100644
index 1625dee..2e59e7f
--- a/htdocs/ecommerceng/class/data/eCommerceSocpeople.class.php
+++ b/htdocs/ecommerceng/class/data/eCommerceSocpeople.class.php
@@ -87,7 +87,7 @@ function create($user, $notrigger=0)
$sql.= " ".(isset($this->fk_site)?intval($this->fk_site):0).",";
$sql.= " ".(isset($this->remote_id)?"'".$this->remote_id."'":"").",";
$sql.= " ".(isset($this->type)?intval($this->type):1).",";
- $sql.= " ".(isset($this->last_update)?"'".$this->last_update."'" : 'null')."";
+ $sql.= " ".(isset($this->last_update)?"'".$this->db->idate($this->last_update)."'" : 'null')."";
$sql.= ")";
diff --git a/htdocs/ecommerceng/class/data/woocommerce/eCommerceRemoteAccessWoocommerce.class.php b/htdocs/ecommerceng/class/data/woocommerce/eCommerceRemoteAccessWoocommerce.class.php
old mode 100755
new mode 100644
index 0c77508..19c6eba
--- a/htdocs/ecommerceng/class/data/woocommerce/eCommerceRemoteAccessWoocommerce.class.php
+++ b/htdocs/ecommerceng/class/data/woocommerce/eCommerceRemoteAccessWoocommerce.class.php
@@ -29,6 +29,11 @@
dol_include_once('/ecommerceng/includes/WooCommerce/HttpClient/Request.php');
dol_include_once('/ecommerceng/includes/WooCommerce/HttpClient/Response.php');
+dol_include_once('/ecommerceng/lib/eCommerce.lib.php');
+
+dol_include_once('/ecommerceng/includes/WordPressClient.php');
+
+require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php';
use Automattic\WooCommerce\Client;
@@ -39,23 +44,93 @@
*/
class eCommerceRemoteAccessWoocommerce
{
-
+ /**
+ * eCommerceSite object.
+ *
+ * @var eCommerceSite
+ */
private $site;
+
+ /**
+ * Woocommerce client new API v2.
+ *
+ * @var Client
+ */
private $client;
+ /**
+ * Woocommerce client old API v3.
+ *
+ * @var Client
+ */
private $clientOld;
- private $filter;
- private $taxRates;
+ /**
+ * WordPress client.
+ *
+ * @var WordPressClient
+ */
+ private $worpressclient;
+
+ /**
+ * Dolibarr tax rates.
+ *
+ * @var array
+ */
+ private $dolibarrTaxes;
+
+ /**
+ * Woocommerce taxes.
+ *
+ * @var array
+ */
+ private $woocommerceTaxes;
+
+ /**
+ * Database handler.
+ *
+ * @var DoliDB
+ */
private $db;
/**
- * Constructor
- * @param DoliDB $db Database handler
- * @param string $site eCommerceSite
+ * Errors list.
+ *
+ * @var array
+ */
+ public $errors;
+
+ /**
+ * GMT timezone.
+ *
+ * @var DateTimeZone
+ */
+ public $gmtTimeZone;
+
+ /**
+ * Current timezone.
+ *
+ * @var DateTimeZone
+ */
+ public $currentTimeZone;
+
+ /**
+ * Constructor
+ * @param DoliDB $db Database handler
+ * @param eCommerceSite $site eCommerceSite object
*/
function eCommerceRemoteAccessWoocommerce($db, $site)
{
+ global $langs;
+
+ $langs->load("ecommerce@ecommerceng");
+ $langs->load("woocommerce@ecommerceng");
+
$this->db = $db;
$this->site = $site;
+ $this->errors = [];
+
+ $this->gmtTimeZone = new DateTimeZone('GMT');
+ $this->currentTimeZone = new DateTimeZone(date_default_timezone_get());
+
return 1;
}
@@ -66,18 +141,13 @@ function eCommerceRemoteAccessWoocommerce($db, $site)
*/
public function connect()
{
- global $conf;
-
- try {
- require_once(DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php');
- $params=getSoapParams();
-
- @ini_set('default_socket_timeout', $params['response_timeout']);
- @ini_set("memory_limit", "1024M");
+ dol_syslog(__METHOD__ . ": Connect to API webservice_address=" . $this->site->webservice_address . " user_name=" .
+ $this->site->user_name . " user_password=" . $this->site->user_password . " for site ID {$this->site->id}", LOG_DEBUG);
+ global $conf, $langs;
- $response_timeout = (empty($conf->global->MAIN_USE_RESPONSE_TIMEOUT)?$params['response_timeout']:$conf->global->MAIN_USE_RESPONSE_TIMEOUT); // Response timeout
+ $response_timeout = (empty($conf->global->MAIN_USE_RESPONSE_TIMEOUT) ? 30 : $conf->global->MAIN_USE_RESPONSE_TIMEOUT); // Response timeout
- dol_syslog("eCommerceRemoteAccessWoocommerce Connect to API webservice_address=".$this->site->webservice_address." user_name=".$this->site->user_name." user_password=".$this->site->user_password);
+ try {
$this->client = new Client(
$this->site->webservice_address,
$this->site->user_name,
@@ -88,6 +158,8 @@ public function connect()
'timeout' => $response_timeout,
]
);
+ $this->client->get('customers', [ 'page' => 1, 'per_page' => 1 ]);
+
$this->clientOld = new Client(
$this->site->webservice_address,
$this->site->user_name,
@@ -97,42 +169,60 @@ public function connect()
'timeout' => $response_timeout,
]
);
-
- dol_syslog("eCommerceRemoteAccessWoocommerce connected with new Client ok.");
-
- return true;
+ $this->clientOld->get('customers', [ 'page' => 1, 'filter' => [ 'limit' => 1 ] ]);
} catch (HttpClientException $fault) {
- $this->errors[]=$fault->getMessage().'-'.$fault->getCode();
- dol_syslog(__METHOD__.': '.$fault->getMessage().'-'.$fault->getCode().'-'.$fault->getTraceAsString(), LOG_WARNING);
+ $this->errors[] = $langs->trans('ECommerceWoocommerceConnect', $this->site->name, $fault->getCode() . ': ' . $fault->getMessage());
+ dol_syslog(__METHOD__ .
+ ': Error:' . $langs->transnoentitiesnoconv('ECommerceWoocommerceConnect', $this->site->name, $fault->getCode() . ': ' . $fault->getMessage()) .
+ ' - Request:' . json_encode($fault->getRequest()) . ' - Response:' . json_encode($fault->getResponse()), LOG_ERR);
+ return false;
+ }
+
+ try {
+ $this->worpressclient = new WordPressClient(
+ $this->site->webservice_address,
+ $this->site->oauth_id,
+ $this->site->oauth_secret,
+ dol_buildpath('/custom/ecommerceng/core/modules/oauth/wordpress_oauthcallback.php', 2) . '?ecommerce_id=' . $this->site->id
+ );
+ } catch (Exception $e) {
+ $this->errors[] = $langs->trans('ECommerceWoocommerceConnect', $this->site->name, $e->getMessage());
+ dol_syslog(__METHOD__ . ': Error:' . $langs->transnoentitiesnoconv('ECommerceWoocommerceConnect', $this->site->name, $e->getMessage()), LOG_ERR);
return false;
}
+
+ dol_syslog(__METHOD__ . ": end, ok", LOG_DEBUG);
+ return true;
}
/**
- * Call Woocommerce API to get last updated companies
+ * Call Woocommerce API to get last updated companies. We are interested here by list of id only. We will retreive properties later.
+ *
+ * @param int $fromDate From date
+ * @param int $toDate To date
*
- * @param datetime $fromDate From date
- * @param datetime $toDate To date
- * @return boolean|mixed Response from REST Api call, normally an associative array mirroring the structure of the XML response, nothing if error
+ * @return array|boolean List of companies ID to update or false if error
*/
public function getSocieteToUpdate($fromDate, $toDate)
{
- global $conf;
+ dol_syslog(__METHOD__ . ": start gt = " . (!empty($fromDate) ? dol_print_date($fromDate, 'standard') : 'none') .
+ ", lt = " . (!empty($toDate) ? dol_print_date($toDate, 'standard') : 'none') . " for site ID {$this->site->id}", LOG_DEBUG);
+ global $conf, $langs;
- try {
- $result = array();
- $idxPage = 1;
- $per_page = empty($conf->global->ECOMMERCENG_MAXSIZE_MULTICALL) ? 100 : $conf->global->ECOMMERCENG_MAXSIZE_MULTICALL;
- $from_date = isset($fromDate) && !empty($fromDate) ? new DateTime(dol_print_date($fromDate, 'standard')) : null;
- $to_date = isset($toDate) && !empty($toDate) ? new DateTime(dol_print_date($toDate, 'standard')) : null;
-
- $filter = [ 'limit' => $per_page ];
- // Not work with customers
- //if (isset($fromDate) && !empty($fromDate)) $filter['updated_at_min'] = dol_print_date($fromDate - (24 * 60 * 60), 'dayrfc');
- //if (isset($toDate) && !empty($toDate)) $filter['updated_at_max'] = dol_print_date($toDate + (24 * 60 * 60), 'dayrfc');
-
- dol_syslog("getSocieteToUpdate start gt = " . dol_print_date($fromDate, 'standard') . ", lt = " . dol_print_date($toDate, 'standard'));
- while (true) {
+ $last_update = [];
+ $result = [];
+ $idxPage = 1;
+ $per_page = empty($conf->global->ECOMMERCENG_MAXSIZE_MULTICALL) ? 100 : min($conf->global->ECOMMERCENG_MAXSIZE_MULTICALL, 100);
+ $from_date = isset($fromDate) && !empty($fromDate) ? new DateTime(dol_print_date($fromDate, 'standard')) : null;
+ $to_date = isset($toDate) && !empty($toDate) ? new DateTime(dol_print_date($toDate, 'standard')) : null;
+
+ $filter = ['limit' => $per_page];
+ // Not work with customers
+ //if (isset($fromDate) && !empty($fromDate)) $filter['updated_at_min'] = dol_print_date($fromDate - (24 * 60 * 60), 'dayrfc');
+ //if (isset($toDate) && !empty($toDate)) $filter['updated_at_max'] = dol_print_date($toDate + (24 * 60 * 60), 'dayrfc');
+
+ while (true) {
+ try {
$page = $this->clientOld->get('customers',
[
'page' => $idxPage++,
@@ -140,169 +230,144 @@ public function getSocieteToUpdate($fromDate, $toDate)
'fields' => 'id,created_at,last_update'
]
);
- if (!isset($page['customers']) || ($nbCustomers = count($page['customers'])) == 0) break;
- $page = $page['customers'];
+ } catch (HttpClientException $fault) {
+ $this->errors[] = $langs->trans('ECommerceWoocommerceGetSocieteToUpdate', $this->site->name, $fault->getCode() . ': ' . $fault->getMessage());
+ dol_syslog(__METHOD__ .
+ ': Error:' . $langs->transnoentitiesnoconv('ECommerceWoocommerceGetSocieteToUpdate', $this->site->name, $fault->getCode() . ': ' . $fault->getMessage()) .
+ ' - Request:' . json_encode($fault->getRequest()) . ' - Response:' . json_encode($fault->getResponse()), LOG_ERR);
+ return false;
+ }
- for ($idxCustomer = 0; $idxCustomer < $nbCustomers; $idxCustomer++) {
- $created_at = new DateTime($page[$idxCustomer]['created_at']);
- $date = new DateTime($page[$idxCustomer]['last_update']);
- $date = $date < $created_at ? $created_at : $date;
+ if (!isset($page['customers']) || ($nbCustomers = count($page['customers'])) == 0) break;
+ $page = $page['customers'];
- if ((!isset($from_date) || $from_date < $date) && (!isset($to_date) || $date <= $to_date)) {
- $result[] = $page[$idxCustomer]['id'];
- }
+ foreach ($page as $customer) {
+ $date = $this->getDateTimeFromGMTDateTime(!empty($customer['updated_at']) ? $customer['updated_at'] : $customer['created_at']);
+
+ if ((!isset($from_date) || $from_date < $date) && (!isset($to_date) || $date <= $to_date)) {
+ $id = $customer['id'];
+ $result[$id] = $id;
+ $last_update[$id] = $date->format('Y-m-d H:i:s');
}
}
+ }
- dol_syslog("getSocieteToUpdate end (found ".count($result)." record)");
- return $result;
- } catch (HttpClientException $fault) {
- $this->errors[]=$fault->getMessage().'-'.$fault->getCode();
- dol_syslog(__METHOD__.': '.$fault->getMessage().'-'.$fault->getCode().'-'.$fault->getTraceAsString(), LOG_WARNING);
- return false;
+ //important - order by last update
+ if (count($result)) {
+ array_multisort($last_update, SORT_ASC, $result);
}
+
+ dol_syslog(__METHOD__ . ": end", LOG_DEBUG);
+ return $result;
}
/**
- * Call Magenta API to get last updated products. We are interested here by list of id only. We will retreive properties later.
+ * Call Woocommerce API to get last updated products. We are interested here by list of id only. We will retreive properties later.
+ *
+ * @param int $fromDate From date
+ * @param int $toDate To date
*
- * @param datetime $fromDate From date
- * @param datetime $toDate To date
- * @return boolean|mixed Response from SOAP call, normally an associative array mirroring the structure of the XML response, nothing if error
+ * @return array|boolean List of products ID to update or false if error
*/
public function getProductToUpdate($fromDate, $toDate)
{
- global $conf;
+ dol_syslog(__METHOD__ . ": start gt = " . (!empty($fromDate) ? dol_print_date($fromDate, 'standard') : 'none') .
+ ", lt = " . (!empty($toDate) ? dol_print_date($toDate, 'standard') : 'none') . " for site ID {$this->site->id}", LOG_DEBUG);
+ global $conf, $langs;
- try {
- dol_syslog("getProductToUpdate start gt=".dol_print_date($fromDate, 'standard')." lt=".dol_print_date($toDate, 'standard'));
- $result = array();
- $idxPage = 1;
- $per_page = empty($conf->global->ECOMMERCENG_MAXSIZE_MULTICALL) ? 100 : $conf->global->ECOMMERCENG_MAXSIZE_MULTICALL;
- $from_date = isset($fromDate) && !empty($fromDate) ? new DateTime(dol_print_date($fromDate, 'standard')) : null;
- $to_date = isset($toDate) && !empty($toDate) ? new DateTime(dol_print_date($toDate, 'standard')) : null;
-
- $filter = [ 'limit' => $per_page ];
- if (isset($fromDate) && !empty($fromDate)) $filter['updated_at_min'] = dol_print_date($fromDate - (24 * 60 * 60), 'dayrfc');
- if (isset($toDate) && !empty($toDate)) $filter['updated_at_max'] = dol_print_date($toDate + (24 * 60 * 60), 'dayrfc');
-
- dol_syslog("getProductToUpdate start gt=".dol_print_date($fromDate != null ? $fromDate : 0, 'standard')." lt=".dol_print_date($toDate, 'standard'));
- while (true) {
+ $last_update = [];
+ $result = [];
+ $idxPage = 1;
+ $per_page = empty($conf->global->ECOMMERCENG_MAXSIZE_MULTICALL) ? 100 : min($conf->global->ECOMMERCENG_MAXSIZE_MULTICALL, 100);
+ $from_date = isset($fromDate) && !empty($fromDate) ? new DateTime(dol_print_date($fromDate, 'standard')) : null;
+ $to_date = isset($toDate) && !empty($toDate) ? new DateTime(dol_print_date($toDate, 'standard')) : null;
+
+ $filter = ['limit' => $per_page];
+ if (isset($fromDate) && !empty($fromDate)) $filter['updated_at_min'] = dol_print_date($fromDate - (24 * 60 * 60), 'dayrfc');
+ if (isset($toDate) && !empty($toDate)) $filter['updated_at_max'] = dol_print_date($toDate + (24 * 60 * 60), 'dayrfc');
+
+ while (true) {
+ try {
$page = $this->clientOld->get('products',
[
'page' => $idxPage++,
'filter' => $filter,
- 'fields' => 'id,created_at,updated_at'
+ 'fields' => 'id,created_at,updated_at,variations'
]
);
- if (!isset($page['products']) || ($nbProducts = count($page['products'])) == 0) break;
- $page = $page['products'];
-
- for ($idxProduct = 0; $idxProduct < $nbProducts; $idxProduct++) {
- $created_at = new DateTime($page[$idxProduct]['created_at']);
- $date = new DateTime($page[$idxProduct]['updated_at']);
- $date = $date < $created_at ? $created_at : $date;
-
- if ((!isset($from_date) || $from_date < $date) && (!isset($to_date) || $date <= $to_date)) {
- $product = $page[$idxProduct];
- //if ($product['virtual'] || $product['downloadable']) continue;
- $result[] = $product['id'];
- }
- }
+ } catch (HttpClientException $fault) {
+ $this->errors[] = $langs->trans('ECommerceWoocommerceGetProductToUpdate', $this->site->name, $fault->getCode() . ': ' . $fault->getMessage());
+ dol_syslog(__METHOD__ .
+ ': Error:' . $langs->transnoentitiesnoconv('ECommerceWoocommerceGetProductToUpdate', $this->site->name, $fault->getCode() . ': ' . $fault->getMessage()) .
+ ' - Request:' . json_encode($fault->getRequest()) . ' - Response:' . json_encode($fault->getResponse()), LOG_ERR);
+ return false;
}
- dol_syslog("getProductToUpdate end (found ".count($results)." record)");
- return $result;
- } catch (HttpClientException $fault) {
- $this->errors[]=$fault->getMessage().'-'.$fault->getCode();
- dol_syslog(__METHOD__.': '.$fault->getMessage().'-'.$fault->getCode().'-'.$fault->getTraceAsString(), LOG_WARNING);
- return false;
- }
- }
-
- /**
- * Call Magenta API to get last updated orders
- *
- * @param datetime $fromDate From date
- * @param datetime $toDate To date
- * @return boolean|mixed Response from SOAP call, normally an associative array mirroring the structure of the XML response, nothing if error
- */
- public function getCommandeToUpdate($fromDate, $toDate)
- {
- global $conf;
+ if (!isset($page['products']) || ($nbProducts = count($page['products'])) == 0) break;
+ $page = $page['products'];
- try {
- $result = array();
- $idxPage = 1;
- $per_page = empty($conf->global->ECOMMERCENG_MAXSIZE_MULTICALL) ? 100 : $conf->global->ECOMMERCENG_MAXSIZE_MULTICALL;
- $from_date = isset($fromDate) && !empty($fromDate) ? new DateTime(dol_print_date($fromDate, 'standard')) : null;
- $to_date = isset($toDate) && !empty($toDate) ? new DateTime(dol_print_date($toDate, 'standard')) : null;
-
- $filter = [ 'limit' => $per_page ];
- if (isset($fromDate) && !empty($fromDate)) $filter['updated_at_min'] = dol_print_date($fromDate - (24 * 60 * 60), 'dayrfc');
- if (isset($toDate) && !empty($toDate)) $filter['updated_at_max'] = dol_print_date($toDate + (24 * 60 * 60), 'dayrfc');
-
- dol_syslog("getCommandeToUpdate start gt=".dol_print_date($fromDate, 'standard')." lt=".dol_print_date($toDate, 'standard'));
- while (true) {
- $page = $this->clientOld->get('orders',
- [
- 'page' => $idxPage++,
- 'filter' => $filter,
- 'fields' => 'id,created_at,updated_at'
- ]
- );
- if (!isset($page['orders']) || ($nbOrders = count($page['orders'])) == 0) break;
- $page = $page['orders'];
+ foreach ($page as $product) {
+ $update = false;
+ $date_product = $this->getDateTimeFromGMTDateTime(!empty($product['updated_at']) ? $product['updated_at'] : $product['created_at']);
- for ($idxOrder = 0; $idxOrder < $nbOrders; $idxOrder++) {
- $created_at = new DateTime($page[$idxOrder]['created_at']);
- $date = new DateTime($page[$idxOrder]['updated_at']);
- $date = $date < $created_at ? $created_at : $date;
+ // Product
+ if ((!isset($from_date) || $from_date < $date_product) && (!isset($to_date) || $date_product <= $to_date)) {
+ $id = $product['id'];
+ $result[$id] = $id;
+ $last_update[$id] = $date_product->format('Y-m-d H:i:s');
+ }
- if ((!isset($from_date) || $from_date < $date) && (!isset($to_date) || $date <= $to_date)) {
- $result[] = $page[$idxOrder]['id'];
+ // Variations
+ if (!$update) {
+ foreach ($product['variations'] as $variation) {
+ $date_variation = $this->getDateTimeFromGMTDateTime(!empty($variation['updated_at']) ? $variation['updated_at'] : $variation['created_at']);
+
+ if ((!isset($from_date) || $from_date < $date_variation) && (!isset($to_date) || $date_variation <= $to_date)) {
+ $id = $product['id'].'|'.$variation['id'];
+ $result[$id] = $id;
+ $last_update[$id] = $date_variation->format('Y-m-d H:i:s');
+ }
}
}
}
-
- dol_syslog("getCommandeToUpdate end (found ".count($result)." record)");
- return $result;
- } catch (HttpClientException $fault) {
- $this->errors[]=$fault->getMessage().'-'.$fault->getCode();
- dol_syslog(__METHOD__.': '.$fault->getMessage().'-'.$fault->getCode().'-'.$fault->getTraceAsString(), LOG_WARNING);
- return false;
}
- catch (Exception $e) {
- $this->errors[]=$e->getMessage().'-'.$e->getCode();
- dol_syslog(__METHOD__.': '.$e->getMessage().'-'.$e->getCode().'-'.$e->getTraceAsString(), LOG_WARNING);
- return false;
+
+ //important - order by last update
+ if (count($result)) {
+ array_multisort($last_update, SORT_ASC, $result);
}
+
+ dol_syslog(__METHOD__ . ": end", LOG_DEBUG);
+ return $result;
}
/**
- * Call Magenta API to get last updated invoices
+ * Call Woocommerce API to get last updated orders. We are interested here by list of id only. We will retreive properties later.
+ *
+ * @param int $fromDate From date
+ * @param int $toDate To date
*
- * @param datetime $fromDate From date
- * @param datetime $toDate To date
- * @return boolean|mixed Response from SOAP call, normally an associative array mirroring the structure of the XML response, nothing if error
+ * @return array|boolean List of orders ID to update or false if error
*/
- public function getFactureToUpdate($fromDate, $toDate)
+ public function getCommandeToUpdate($fromDate, $toDate)
{
- /* global $conf;
+ dol_syslog(__METHOD__ . ": start gt = " . (!empty($fromDate) ? dol_print_date($fromDate, 'standard') : 'none') .
+ ", lt = " . (!empty($toDate) ? dol_print_date($toDate, 'standard') : 'none') . " for site ID {$this->site->id}", LOG_DEBUG);
+ global $conf, $langs;
- try {
- $result = array();
- $idxPage = 1;
- $per_page = empty($conf->global->ECOMMERCENG_MAXSIZE_MULTICALL) ? 100 : $conf->global->ECOMMERCENG_MAXSIZE_MULTICALL;
- $from_date = isset($fromDate) && !empty($fromDate) ? new DateTime(dol_print_date($fromDate, 'standard')) : null;
- $to_date = isset($toDate) && !empty($toDate) ? new DateTime(dol_print_date($toDate, 'standard')) : null;
-
- $filter = [ 'limit' => $per_page ];
- if (isset($fromDate) && !empty($fromDate)) $filter['updated_at_min'] = dol_print_date($fromDate - (24 * 60 * 60), 'dayrfc');
- if (isset($toDate) && !empty($toDate)) $filter['updated_at_max'] = dol_print_date($toDate + (24 * 60 * 60), 'dayrfc');
-
- dol_syslog("getFactureToUpdate start gt=".dol_print_date($fromDate, 'standard')." lt=".dol_print_date($toDate, 'standard'));
- while (true) {
+ $last_update = [];
+ $result = [];
+ $idxPage = 1;
+ $per_page = empty($conf->global->ECOMMERCENG_MAXSIZE_MULTICALL) ? 100 : min($conf->global->ECOMMERCENG_MAXSIZE_MULTICALL, 100);
+ $from_date = isset($fromDate) && !empty($fromDate) ? new DateTime(dol_print_date($fromDate, 'standard')) : null;
+ $to_date = isset($toDate) && !empty($toDate) ? new DateTime(dol_print_date($toDate, 'standard')) : null;
+
+ $filter = ['limit' => $per_page];
+ if (isset($fromDate) && !empty($fromDate)) $filter['updated_at_min'] = dol_print_date($fromDate - (24 * 60 * 60), 'dayrfc');
+ if (isset($toDate) && !empty($toDate)) $filter['updated_at_max'] = dol_print_date($toDate + (24 * 60 * 60), 'dayrfc');
+
+ while (true) {
+ try {
$page = $this->clientOld->get('orders',
[
'page' => $idxPage++,
@@ -310,1681 +375,1996 @@ public function getFactureToUpdate($fromDate, $toDate)
'fields' => 'id,created_at,updated_at'
]
);
- if (!isset($page['orders']) || ($nbOrders = count($page['orders'])) == 0) break;
- $page = $page['orders'];
-
- for ($idxOrder = 0; $idxOrder < $nbOrders; $idxOrder++) {
- $created_at = new DateTime($page[$idxOrder]['created_at']);
- $date = new DateTime($page[$idxOrder]['updated_at']);
- $date = $date < $created_at ? $created_at : $date;
-
- if ((!isset($from_date) || $from_date < $date) && (!isset($to_date) || $date <= $to_date)) {
-// $status = $page[$idxOrder]['status'];
-// if ($status == 'completed' || $status == 'refunded') {
- $result[] = $page[$idxOrder]['id'];
-// }
- }
- }
+ } catch (HttpClientException $fault) {
+ $this->errors[] = $langs->trans('ECommerceWoocommerceGetCommandeToUpdate', $this->site->name, $fault->getCode() . ': ' . $fault->getMessage());
+ dol_syslog(__METHOD__ .
+ ': Error:' . $langs->transnoentitiesnoconv('ECommerceWoocommerceGetCommandeToUpdate', $this->site->name, $fault->getCode() . ': ' . $fault->getMessage()) .
+ ' - Request:' . json_encode($fault->getRequest()) . ' - Response:' . json_encode($fault->getResponse()), LOG_ERR);
+ return false;
}
- dol_syslog("getFactureToUpdate end (found ".count($result)." record)");
- return $result;
- } catch (HttpClientException $fault) {
- $this->errors[]=$fault->getMessage().'-'.$fault->getCode();
- dol_syslog(__METHOD__.': '.$fault->getMessage().'-'.$fault->getCode().'-'.$fault->getTraceAsString(), LOG_WARNING);
- return false;
- }*/
- }
-
-
- /**
- * Put the remote data into category dolibarr data from instantiated class in the constructor
- * Return array of category by update time.
- *
- * @param array $remoteObject Array of ids of objects to convert
- * @param int $toNb Max nb
- * @return array societe
- */
- public function convertRemoteObjectIntoDolibarrCategory($remoteObject, $toNb=0)
- {
- global $conf;
-
- $categories = array();
+ if (!isset($page['orders']) || ($nbOrders = count($page['orders'])) == 0) break;
+ $page = $page['orders'];
- // No need to make $this->client->multiCall($this->session, $calls); to get details.
+ foreach ($page as $order) {
+ $date = $this->getDateTimeFromGMTDateTime(!empty($order['updated_at']) ? $order['updated_at'] : $order['created_at']);
- // We just need to sort array on updated_at
- $categories = $remoteObject;
+ if ((!isset($from_date) || $from_date < $date) && (!isset($to_date) || $date <= $to_date)) {
+ $id = $order['id'];
+ $result[$id] = $id;
+ $last_update[$id] = $date->format('Y-m-d H:i:s');
+ }
+ }
+ }
//important - order by last update
- if (count($categories))
- {
- $last_update=array();
- foreach ($categories as $key => $row)
- {
- $last_update[$key] = $row['updated_at'];
- }
- array_multisort($last_update, SORT_ASC, $categories);
+ if (count($result)) {
+ array_multisort($last_update, SORT_ASC, $result);
}
- return $categories;
+ dol_syslog(__METHOD__ . ": end", LOG_DEBUG);
+ return $result;
}
/**
- * Put the remote data into societe dolibarr data from instantiated class in the constructor
- * Return array of thirdparty by update time.
+ * Desactivated because is not supported by woocommerce.
*
- * @param array $remoteObject Array of ids of objects to convert
- * @param int $toNb Max nb
- * @return array societe
+ * @param int $fromDate From date
+ * @param int $toDate To date
+ *
+ * @return array Empty list
*/
- public function convertRemoteObjectIntoDolibarrSociete($remoteObject, $toNb=0)
+ public function getFactureToUpdate($fromDate, $toDate)
{
- global $conf;
-
- $societes = array();
-
- $maxsizeofmulticall = (empty($conf->global->ECOMMERCENG_MAXSIZE_MULTICALL)?100:$conf->global->ECOMMERCENG_MAXSIZE_MULTICALL);
- $nbsynchro = 0;
- $nbremote = count($remoteObject);
- if ($nbremote)
- {
- // Create n groups of $maxsizeofmulticall records max to call the multiCall
- $callsgroup = array();
- $calls = array();
- foreach ($remoteObject as $rsociete)
- {
- if (($nbsynchro % $maxsizeofmulticall) == 0)
- {
- if (count($calls)) $callsgroup[] = $calls; // Add new group for lot of 1000 call arrays
- $calls = array();
- }
-
- $calls[] = $rsociete;
-
- $nbsynchro++; // nbsynchro is now number of calls to do
- }
- if (count($calls)) $callsgroup[] = $calls; // Add new group for the remain lot of calls not yet added
-
- dol_syslog("convertRemoteObjectIntoDolibarrSociete Call WS to get detail for the " . count($remoteObject) . " objects (" . count($callsgroup) . " calls with " . $maxsizeofmulticall . " max of records each) then create a Dolibarr array for each object");
- //var_dump($callsgroup);exit;
-
- $results=array();
- $nbcall=0;
- foreach ($callsgroup as $calls)
- {
- try {
- $nbcall++;
- dol_syslog("convertRemoteObjectIntoDolibarrSociete Call WS nb ".$nbcall." (".count($calls)." record)");
- $resulttmp = $this->client->get('customers',
- [
- 'per_page' => $maxsizeofmulticall,
- 'include' => implode(',', $calls),
- ]
- );
- $results=array_merge($results, $resulttmp);
- } catch (HttpClientException $fault) {
- dol_syslog('convertRemoteObjectIntoDolibarrSociete :'.$fault->getMessage().'-'.$fault->getCode().'-'.$fault->getTraceAsString(), LOG_WARNING);
- return false;
- }
- }
-
- if (count($results))
- {
- foreach ($results as $societe)
- {
- $newobj = array(
- 'remote_id' => $societe['id'],
- 'last_update' => isset($societe['date_modified']) ? $societe['date_modified'] : $societe['date_created'],
- 'name' => dolGetFirstLastname($societe['first_name'], $societe['last_name']),
- 'name_alias' => $this->site->name . ' id ' . $societe['id'], // See also the delete in eCommerceSociete
- 'email' => $societe['email'],
- 'client' => 3, //for client/prospect
- 'vatnumber' => $societe['taxvat']
- );
- $societes[] = $newobj;
- }
- }
- }
-
- //important - order by last update
- if (count($societes))
- {
- $last_update = array();
- foreach ($societes as $key => $row)
- {
- $last_update[$key] = $row['last_update'];
- }
- array_multisort($last_update, SORT_ASC, $societes);
- }
-
- dol_syslog("convertRemoteObjectIntoDolibarrSociete end (found ".count($societes)." record)");
- return $societes;
+ dol_syslog(__METHOD__ . ": Desactivated for site ID {$this->site->id}", LOG_DEBUG);
+ return [];
}
-
/**
- * Put the remote data into societe dolibarr data from instantiated class in the constructor
- * Return array of people by update time.
+ * Call Woocommerce API to get company datas and put into dolibarr company class.
*
- * @param array $listofids List of object with customer_address_id that is remote id of addresss
- * @param int $toNb Max nb. Not used for socpeople.
- * @return array societe
+ * @param array $remoteObject List of id of remote companies to convert
+ * @param int $toNb Max nb
+ * @return array|boolean List of companies sorted by update time or false if error.
*/
- public function convertRemoteObjectIntoDolibarrSocpeople($listofids, $toNb=0)
+ public function convertRemoteObjectIntoDolibarrSociete($remoteObject, $toNb=0)
{
- global $conf;
+ dol_syslog(__METHOD__ . ": Get " . count($remoteObject) . " remote companies ID: " . implode(', ', $remoteObject) . " for site ID {$this->site->id}", LOG_DEBUG);
+ global $conf, $langs;
- $socpeoples = array();
- $calls = array();
- if (count($listofids))
- {
- dol_syslog("convertRemoteObjectIntoDolibarrSocpeople Call WS to get detail for the ".count($listofids)." objects then create a Dolibarr array for each object");
- foreach ($listofids as $listofid)
- {
- $calls[] = $listofid;
- }
+ $companies = [];
+ $nb_max_by_request = empty($conf->global->ECOMMERCENG_MAXSIZE_MULTICALL) ? 100 : min($conf->global->ECOMMERCENG_MAXSIZE_MULTICALL, 100);
+ $requestGroups = $this->getRequestGroups($remoteObject, $nb_max_by_request, $toNb);
+
+ foreach ($requestGroups as $request) {
+ dol_syslog(__METHOD__ . ": Get partial remote companies ID: " . implode(', ', $request), LOG_DEBUG);
try {
- $results = $this->client->get('customers',
+ $results = $this->client->get('customers',
[
- 'per_page' => 100,
- 'include' => implode(',', $calls),
+ 'per_page' => $nb_max_by_request,
+ 'include' => implode(',', $request),
]
);
} catch (HttpClientException $fault) {
- dol_syslog('convertRemoteObjectIntoDolibarrSocpeople :'.$fault->getMessage().'-'.$fault->getCode().'-'.$fault->getTraceAsString(), LOG_WARNING);
+ $this->errors[] = $langs->trans('ECommerceWoocommerceConvertRemoteObjectIntoDolibarrSociete', $this->site->name, $fault->getCode() . ': ' . $fault->getMessage());
+ dol_syslog(__METHOD__ .
+ ': Error:' . $langs->transnoentitiesnoconv('ECommerceWoocommerceConvertRemoteObjectIntoDolibarrSociete', $this->site->name, $fault->getCode() . ': ' . $fault->getMessage()) .
+ ' - Request:' . json_encode($fault->getRequest()) . ' - Response:' . json_encode($fault->getResponse()), LOG_ERR);
+ return false;
}
- if (count($results)) {
- $billingName = (empty($conf->global->ECOMMERCENG_BILLING_CONTACT_NAME) ? 'Billing' : $conf->global->ECOMMERCENG_BILLING_CONTACT_NAME); // Contact name treated as billing address.
- $shippingName = (empty($conf->global->ECOMMERCENG_SHIPPING_CONTACT_NAME) ? 'Shipping' : $conf->global->ECOMMERCENG_SHIPPING_CONTACT_NAME); // Contact name treated as shipping address.
-
- foreach ($results as $socpeople) {
- $billing = $socpeople['billing'];
- $newobj = array(
- 'remote_id' => $socpeople['id'] . '|1',
- //'type' => eCommerceSocpeople::CONTACT_TYPE_COMPANY,
- 'last_update' => isset($socpeople['date_modified']) ? $socpeople['date_modified'] : $socpeople['date_created'],
- 'name' => $billingName,
- 'email' => $billing['email'],
- 'address' => $billing['address_1'] . (!empty($billing['address_1']) && !empty($billing['address_2']) ? "\n" : "") . $billing['address_2'],
- 'town' => $billing['city'],
- 'zip' => $billing['postcode'],
- 'country_code' => getCountry($billing['country'], 3),
- 'phone' => $billing['phone'],
- 'fax' => "",
- 'firstname' => "", // $billing['first_name'],
- 'lastname' => $billingName, // $billing['last_name'],
- 'vatnumber' => "",
- 'is_default_billing' => true,
- 'is_default_shipping' => false
- );
- $socpeoples[] = $newobj;
-
- $shipping = $socpeople['shipping'];
- if ((!empty($shipping['address_1']) || !empty($shipping['address_1'])) && !empty($shipping['city']) && !empty($shipping['postcode']) && !empty($shipping['country'])) {
- $newobj = array(
- 'remote_id' => $socpeople['id'] . '|2',
- //'type' => eCommerceSocpeople::CONTACT_TYPE_COMPANY,
- 'last_update' => isset($socpeople['date_modified']) ? $socpeople['date_modified'] : $socpeople['date_created'],
- 'name' => $shippingName,
- 'email' => "",
- 'address' => $shipping['address_1'] . (!empty($shipping['address_1']) && !empty($shipping['address_2']) ? "\n" : "") . $shipping['address_2'],
- 'town' => $shipping['city'],
- 'zip' => $shipping['postcode'],
- 'country_code' => getCountry($shipping['country'], 3),
- 'phone' => "",
- 'fax' => "",
- 'firstname' => "", // $shipping['first_name'],
- 'lastname' => $shippingName, // $shipping['last_name'],
- 'vatnumber' => "",
- 'is_default_billing' => false,
- 'is_default_shipping' => true
- );
- } else {
- $newobj = array(
- 'remote_id' => $socpeople['id'] . '|2',
- //'type' => eCommerceSocpeople::CONTACT_TYPE_COMPANY,
- 'last_update' => isset($socpeople['date_modified']) ? $socpeople['date_modified'] : $socpeople['date_created'],
- 'name' => $shippingName,
- 'email' => $billing['email'],
- 'address' => $billing['address_1'] . (!empty($billing['address_1']) && !empty($billing['address_2']) ? "\n" : "") . $billing['address_2'],
- 'town' => $billing['city'],
- 'zip' => $billing['postcode'],
- 'country_code' => getCountry($billing['country'], 3),
- 'phone' => "",
- 'fax' => "",
- 'firstname' => "", // $billing['first_name'],
- 'lastname' => $shippingName, // $billing['last_name'],
- 'vatnumber' => "",
- 'is_default_billing' => false,
- 'is_default_shipping' => true
- );
+ if (is_array($results)) {
+ foreach ($results as $company) {
+ $last_update = $this->getDateTimeFromGMTDateTime(!empty($company['date_modified_gmt']) ? $company['date_modified_gmt'] : $company['date_created_gmt']);
+
+ // Company
+ if (!empty($company['billing']['company'])) {
+ $companies[] = [
+ 'remote_id' => $company['id'],
+ 'last_update' => $last_update->format('Y-m-d H:i:s'),
+ 'type' => 'company',
+ 'name' => $company['billing']['company'],
+ 'name_alias' => null,
+ 'email' => null,
+ 'email_key' => $company['email'],
+ 'client' => 1,
+ 'vatnumber' => null,
+ 'note_private' => "Site: '{$this->site->name}' - ID: {$company['id']}",
+ 'country_id' => getCountry($company['billing']['country'], 3),
+ 'remote_datas' => $company,
+ ];
+ }
+ // User
+ else {
+ $firstname = !empty($company['first_name']) ? $company['first_name'] : $company['billing']['first_name'];
+ $lastname = !empty($company['last_name']) ? $company['last_name'] : $company['billing']['last_name'];
+ if (!empty($firstname) && !empty($lastname)) {
+ $name = dolGetFirstLastname($firstname, $lastname);
+ } elseif (!empty($firstname)) {
+ $name = dolGetFirstLastname($firstname, $langs->trans("ECommercengWoocommerceLastnameNotInformed"));
+ } else {
+ $name = $langs->trans('ECommercengWoocommerceWithoutFirstnameLastname');
+ }
+ $companies[] = [
+ 'remote_id' => $company['id'],
+ 'last_update' => $last_update->format('Y-m-d H:i:s'),
+ 'type' => 'user',
+ 'name' => $name,
+ 'name_alias' => null,
+ 'email' => $company['email'],
+ 'email_key' => $company['email'],
+ 'client' => 1,
+ 'vatnumber' => null,
+ 'note_private' => "Site: '{$this->site->name}' - ID: {$company['id']}",
+ 'country_id' => getCountry($company['billing']['country'], 3),
+ 'remote_datas' => $company,
+ ];
}
- $socpeoples[] = $newobj;
}
}
}
//important - order by last update
- if (count($socpeoples))
- {
- $last_update = array();
- foreach ($socpeoples as $key => $row)
- {
+ if (count($companies)) {
+ $last_update = [];
+ foreach ($companies as $key => $row) {
$last_update[$key] = $row['last_update'];
}
- array_multisort($last_update, SORT_ASC, $socpeoples);
+ array_multisort($last_update, SORT_ASC, $companies);
}
- dol_syslog("convertRemoteObjectIntoDolibarrSocPeople end (found ".count($socpeoples)." record)");
- return $socpeoples;
+ dol_syslog(__METHOD__ . ": end, converted " . count($companies) . " remote companies", LOG_DEBUG);
+ return $companies;
}
-
/**
- * Put the remote data into product dolibarr data from instantiated class in the constructor
- * Return array or products by update time.
+ * Call Woocommerce API to get contact datas and put into dolibarr contact class.
*
- * @param array $remoteObject Array of remote products (got by caller from getProductToUpdate. Only few properties defined)
- * @param int $toNb Max nb
- * @return array product
+ * @param array $remoteCompany Remote company infos
+ * @return array|boolean List of contact sorted by update time or false if error.
*/
- public function convertRemoteObjectIntoDolibarrProduct($remoteObject, $toNb=0)
+ public function convertRemoteObjectIntoDolibarrSocpeople($remoteCompany)
{
- global $conf;
-
- include_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php';
-
- $products = array();
-
- $canvas = '';
-
- $ecommerceurl = $this->site->getFrontUrl();
+ dol_syslog(__METHOD__ . ": Get remote contacts ID: {$remoteCompany["id"]} for site ID {$this->site->id}", LOG_DEBUG);
+ global $langs;
+
+ $contacts = [];
+ $last_update = $this->getDateTimeFromGMTDateTime(!empty($remoteCompany['date_modified_gmt']) ? $remoteCompany['date_modified_gmt'] : $remoteCompany['date_created_gmt']);
+
+ $bContact = $remoteCompany['billing'];
+ if (!empty($bContact['address_1']) || !empty($bContact['address_2']) || !empty($bContact['postcode']) ||
+ !empty($bContact['city']) || !empty($bContact['country']) ||
+ !empty($bContact['email']) || !empty($bContact['phone'])
+ ) {
+ $firstname = !empty($bContact['first_name']) ? $bContact['first_name'] : $remoteCompany['first_name'];
+ $lastname = !empty($bContact['last_name']) ? $bContact['last_name'] : $remoteCompany['last_name'];
+ if (!empty($firstname) && empty($lastname)) {
+ $lastname = $langs->trans("ECommercengWoocommerceLastnameNotInformed");
+ } elseif (empty($firstname) && empty($lastname)) {
+ $lastname = $langs->trans('ECommercengWoocommerceWithoutFirstnameLastname');
+ }
+ $contacts[] = [
+ 'remote_id' => null,
+ 'last_update' => $last_update->format('Y-m-d H:i:s'),
+ 'firstname' => $firstname,
+ 'lastname' => $lastname,
+ 'address' => $bContact['address_1'] . (!empty($bContact['address_1']) && !empty($bContact['address_2']) ? "\n" : "") . $bContact['address_2'],
+ 'zip' => $bContact['postcode'],
+ 'town' => $bContact['city'],
+ 'country_id' => getCountry($bContact['country'], 3),
+ 'email' => !empty($bContact['email']) ? $bContact['email'] : $remoteCompany['email'],
+ 'phone' => $bContact['phone'],
+ 'fax' => null,
+ ];
+ }
- $maxsizeofmulticall = (empty($conf->global->ECOMMERCENG_MAXSIZE_MULTICALL)?100:$conf->global->ECOMMERCENG_MAXSIZE_MULTICALL); // 1000 seems ok for multicall.
- $nbsynchro = 0;
- $nbremote = count($remoteObject);
- if ($nbremote)
- {
- // Create n groups of $maxsizeofmulticall records max to call the multiCall
- $callsgroup = array();
- $calls=array();
- foreach ($remoteObject as $rproduct)
- {
- if (($nbsynchro % $maxsizeofmulticall) == 0)
- {
- if (count($calls)) $callsgroup[]=$calls; // Add new group for lot of 1000 call arrays
- $calls=array();
+ $sContact = $remoteCompany['shipping'];
+ if (!empty($sContact['address_1']) || !empty($sContact['address_2']) ||
+ !empty($sContact['postcode']) || !empty($sContact['city']) ||
+ !empty($sContact['country'])
+ ) {
+ if ($bContact['first_name'] != $sContact['first_name'] || $bContact['last_name'] != $sContact['last_name'] ||
+ $bContact['address_1'] != $sContact['address_1'] || $bContact['address_2'] != $sContact['address_2'] ||
+ $bContact['postcode'] != $sContact['postcode'] || $bContact['city'] != $sContact['city'] ||
+ $bContact['country'] != $sContact['country']
+ ) {
+ $firstname = !empty($sContact['first_name']) ? $sContact['first_name'] : $remoteCompany['first_name'];
+ $lastname = !empty($sContact['last_name']) ? $sContact['last_name'] : $remoteCompany['last_name'];
+ if (!empty($firstname) && empty($lastname)) {
+ $lastname = $langs->trans("ECommercengWoocommerceLastnameNotInformed");
+ } elseif (empty($firstname) && empty($lastname)) {
+ $lastname = $langs->trans('ECommercengWoocommerceWithoutFirstnameLastname');
}
+ $contacts[] = [
+ 'remote_id' => null,
+ 'last_update' => $last_update->format('Y-m-d H:i:s'),
+ 'firstname' => $firstname,
+ 'lastname' => $lastname,
+ 'address' => $sContact['address_1'] . (!empty($sContact['address_1']) && !empty($sContact['address_2']) ? "\n" : "") . $sContact['address_2'],
+ 'zip' => $sContact['postcode'],
+ 'town' => $sContact['city'],
+ 'country_id' => getCountry($sContact['country'], 3),
+ 'email' => null,
+ 'phone' => null,
+ 'fax' => null,
+ ];
+ }
+ }
+
+ dol_syslog(__METHOD__ . ": end, converted " . count($contacts) . " remote contacts", LOG_DEBUG);
+ return $contacts;
+ }
- $calls[] = $rproduct;
+ /**
+ * Call Woocommerce API to get product datas and put into dolibarr product class.
+ *
+ * @param array $remoteObject List of id of remote products to convert
+ * @param int $toNb Max nb
+ * @return array|boolean List of products sorted by update time or false if error.
+ */
+ public function convertRemoteObjectIntoDolibarrProduct($remoteObject, $toNb=0)
+ {
+ dol_syslog(__METHOD__ . ": Get " . count($remoteObject) . " remote products ID: " . implode(', ', $remoteObject) . " for site ID {$this->site->id}", LOG_DEBUG);
+ global $conf, $langs;
- $nbsynchro++; // nbsynchro is now number of calls to do
+ $canvas = '';
+ $products = [];
+ $remoteVariationObject = [];
+ $products_last_update = [];
+ $nb_max_by_request = empty($conf->global->ECOMMERCENG_MAXSIZE_MULTICALL) ? 100 : min($conf->global->ECOMMERCENG_MAXSIZE_MULTICALL, 100);
+
+ // Products
+ $newRemoteObject = [];
+ $remoteObject = array_slice($remoteObject, 0, $toNb);
+ foreach ($remoteObject as $id) {
+ if (($pos = strpos($id, '|')) !== false) {
+ $variation_id = substr($id,$pos+1);
+ $id = substr($id,0,$pos);
+ if (!isset($remoteVariationObject[$id])) $remoteVariationObject[$id] = [];
+ $remoteVariationObject[$id][] = $variation_id;
+ }
+ $newRemoteObject[$id] = $id;
+ }
+ $requestGroups = $this->getRequestGroups($newRemoteObject, $nb_max_by_request);
+ foreach ($requestGroups as $request) {
+ dol_syslog(__METHOD__ . ": Get ".count($request)." partial remote products ID: " . implode(', ', $request), LOG_DEBUG);
+ try {
+ $results = $this->client->get('products',
+ [
+ 'per_page' => $nb_max_by_request,
+ 'include' => implode(',', $request),
+ ]
+ );
+ } catch (HttpClientException $fault) {
+ $this->errors[] = $langs->trans('ECommerceWoocommerceConvertRemoteObjectIntoDolibarrProduct', $this->site->name, $fault->getCode() . ': ' . $fault->getMessage());
+ dol_syslog(__METHOD__ .
+ ': Error:' . $langs->transnoentitiesnoconv('ECommerceWoocommerceConvertRemoteObjectIntoDolibarrProduct', $this->site->name, $fault->getCode() . ': ' . $fault->getMessage()) .
+ ' - Request:' . json_encode($fault->getRequest()) . ' - Response:' . json_encode($fault->getResponse()), LOG_ERR);
+ return false;
}
- if (count($calls)) $callsgroup[]=$calls; // Add new group for the remain lot of calls not yet added
- dol_syslog("convertRemoteObjectIntoDolibarrProduct Call WS to get detail for the ".count($remoteObject)." objects (".count($callsgroup)." calls with ".$maxsizeofmulticall." max of records each) then create a Dolibarr array for each object");
- //var_dump($callsgroup);exit;
+ if (is_array($results)) {
+ foreach ($results as $product) {
+ // Categories
+ $categories = [];
+ foreach ($product['categories'] as $category) {
+ $categories[] = $category['id'];
+ }
- $results=array();
- $nbcall=0;
- foreach ($callsgroup as $calls)
- {
- try {
- $nbcall++;
- dol_syslog("convertRemoteObjectIntoDolibarrProduct Call WS nb ".$nbcall." (".count($calls)." record)");
- $resulttmp = $this->client->get('products',
- [
- 'per_page' => $maxsizeofmulticall,
- 'include' => implode(',', $calls),
- ]
- );
- $results=array_merge($results, $resulttmp);
- } catch (HttpClientException $fault) {
- dol_syslog('convertRemoteObjectIntoDolibarrProduct :'.$fault->getMessage().'-'.$fault->getCode().'-'.$fault->getTraceAsString(), LOG_WARNING);
+ // Images
+ $images = [];
+ if (!empty($conf->global->ECOMMERCENG_ENABLE_SYNCHRO_IMAGES)) {
+ foreach ($product['images'] as $image) {
+ $last_update = $this->getDateTimeFromGMTDateTime(!empty($image['date_modified_gmt']) ? $image['date_modified_gmt'] : $image['date_created_gmt']);
+ $images[] = [
+ 'url' => $image['src'],
+ 'date_modified' => $last_update->format('Y-m-d H:i:s'),
+ ];
+ }
+ array_reverse($images);
+ }
- return false;
- }
- }
+ $last_update_product = $this->getDateTimeFromGMTDateTime(!empty($product['date_modified_gmt']) ? $product['date_modified_gmt'] : $product['date_created_gmt']);
+
+ $remote_id = $product['id']; // id product
+ $last_update = $last_update_product->format('Y-m-d H:i:s');
+
+ // Produit de base
+ if (in_array($remote_id, $remoteObject, true)) {
+ $products_last_update[$remote_id] = $last_update;
+ $products[$remote_id] = [
+ 'remote_id' => $remote_id,
+ 'last_update' => $last_update,
+ 'fk_product_type' => ($product['virtual'] ? 1 : 0), // 0 (product) or 1 (service)
+ 'ref' => $product['sku'],
+ 'label' => $product['name'],
+ 'weight' => $product['weight'],
+ 'price' => $product['price'],
+ 'envente' => empty($product['variations']) ? 1 : 0,
+ 'enachat' => empty($product['variations']) ? 1 : 0,
+ 'finished' => 1, // 1 = manufactured, 0 = raw material
+ 'canvas' => $canvas,
+ 'categories' => $categories,
+ 'tax_rate' => $this->getTaxRate($product['tax_class'], $product['tax_status']),
+ 'price_min' => $product['price'],
+ 'fk_country' => '',
+ 'url' => $product['permalink'],
+ // Stock
+ 'stock_qty' => $product['stock_quantity'],
+ 'is_in_stock' => $product['in_stock'], // not used
+ 'extrafields' => [
+ "ecommerceng_wc_status_{$this->site->id}_{$conf->entity}" => $product['status'],
+ "ecommerceng_description_{$conf->entity}" => $product['description'],
+ "ecommerceng_short_description_{$conf->entity}" => $product['short_description'],
+ "ecommerceng_tax_class_{$this->site->id}_{$conf->entity}" => $this->getTaxClass($product['tax_class'], $product['tax_status']),
+ ],
+ 'images' => $images,
+ ];
+ }
- if (count($results))
- {
- foreach ($results as $cursorproduct => $product)
- {
// Variations
- if (count($product['variations'])) {
- try {
- $variations = $this->client->get('products/' . $product['id'] . '/variations');
- } catch (HttpClientException $fault) {
- $this->errors[] = $fault->getMessage() . '-' . $fault->getCode();
- dol_syslog($fault->getRequest(), LOG_WARNING);
- dol_syslog($fault->getResponse(), LOG_WARNING);
- dol_syslog(__METHOD__ . ': ' . $fault->getMessage() . '-' . $fault->getCode() . '-' . $fault->getTraceAsString(), LOG_WARNING);
- return false;
- }
+ $requestGroupsVariations = $this->getRequestGroups($remoteVariationObject[$product['id']], $nb_max_by_request);
+ foreach ($requestGroupsVariations as $requestVariations) {
+ dol_syslog(__METHOD__ . ": Get ".count($requestVariations)." products variations of remote product (ID:{$product['id']}): " . implode(', ', $requestVariations), LOG_DEBUG);
+ try {
+ $results = $this->client->get('products/' . $product['id'] . '/variations',
+ [
+ 'per_page' => $nb_max_by_request,
+ 'include' => implode(',', $requestVariations),
+ ]
+ );
+ } catch (HttpClientException $fault) {
+ $this->errors[] = $langs->trans('ECommerceWoocommerceConvertRemoteObjectIntoDolibarrProductVariations', $this->site->name, $fault->getCode() . ': ' . $fault->getMessage());
+ dol_syslog(__METHOD__ .
+ ': Error:' . $langs->transnoentitiesnoconv('ECommerceWoocommerceConvertRemoteObjectIntoDolibarrProductVariations', $this->site->name, $fault->getCode() . ': ' . $fault->getMessage()) .
+ ' - Request:' . json_encode($fault->getRequest()) . ' - Response:' . json_encode($fault->getResponse()), LOG_ERR);
+ return false;
+ }
- foreach ($variations as $variation) {
+ if (is_array($results)) {
+ foreach ($results as $variation) {
$attributesLabel = '';
foreach ($variation['attributes'] as $attribute) {
- $attributesLabel .= ', '.$attribute['name'].':'.$attribute['option'];
+ $attributesLabel .= ', ' . $attribute['name'] . ':' . $attribute['option'];
+ }
+
+ // Images
+ $images = [];
+ if (!empty($conf->global->ECOMMERCENG_ENABLE_SYNCHRO_IMAGES)) {
+ if (!empty($variation['image'])) {
+ $last_update = $this->getDateTimeFromGMTDateTime(!empty($variation['image']['date_modified_gmt']) ? $variation['image']['date_modified_gmt'] : $variation['image']['date_created_gmt']);
+ $images[] = [
+ 'url' => $variation['image']['src'],
+ 'date_modified' => $last_update->format('Y-m-d H:i:s'),
+ ];
+ }
}
- $products[] = array(
- 'remote_id' => $product['id'].'|'.$variation['id'], // id product | id variation
- 'last_update' => isset($variation['date_modified'])?$variation['date_modified']:$variation['date_created'],
- 'fk_product_type' => ($variation['virtual'] ? 1 : 0), // 0 (product) or 1 (service)
- 'ref' => dol_string_nospecial($variation['sku']),
- 'label' => ($product['name']?$product['name']:dol_string_nospecial($variation['sku'])).$attributesLabel,
- 'description' => $variation['description'],
- 'weight' => $variation['weight'],
- 'price' => $variation['price'], //sale_price
- 'envente' => $variation['purchasable'] ? 1 : 0,
- 'finished' => 1, // 1 = manufactured, 0 = raw material
- 'canvas' => $canvas,
- 'categories' => '', //$product['categories'], // a check // Same as property $product['category_ids']
- 'tax_rate' => '', // $variation['tax_rate'], // a check
- 'price_min' => $variation['price'],
- 'fk_country' => '',
- 'url' => $variation['permalink'],
+ $last_update_product_variation = $this->getDateTimeFromGMTDateTime(!empty($variation['date_modified_gmt']) ? $variation['date_modified_gmt'] : $variation['date_created_gmt']);
+
+ $remote_id = $product['id'] . '|' . $variation['id']; // id product | id variation
+ $last_update = $last_update_product_variation->format('Y-m-d H:i:s');
+
+ // Variation
+ $products_last_update[$remote_id] = $last_update;
+ $products[$remote_id] = [
+ 'remote_id' => $remote_id,
+ 'last_update' => $last_update,
+ 'fk_product_type' => ($variation['virtual'] ? 1 : 0), // 0 (product) or 1 (service)
+ 'ref' => $variation['sku'],
+ 'label' => $product['name'] . $attributesLabel,
+ 'weight' => $variation['weight'],
+ 'price' => $variation['price'],
+ 'envente' => 1,
+ 'enachat' => 1,
+ 'finished' => 1, // 1 = manufactured, 0 = raw material
+ 'canvas' => $canvas,
+ 'categories' => $product['categories'],
+ 'tax_rate' => $this->getTaxRate($variation['tax_class'], $variation['tax_status']),
+ 'price_min' => $variation['price'],
+ 'fk_country' => '',
+ 'url' => $variation['permalink'],
// Stock
- 'stock_qty' => $variation['stock_quantity'],
- 'is_in_stock' => $variation['in_stock'], // not used
- );
+ 'stock_qty' => $variation['stock_quantity'],
+ 'is_in_stock' => $variation['in_stock'], // not used
+ 'extrafields' => [
+ "ecommerceng_description_{$conf->entity}" => $variation['description'],
+ "ecommerceng_tax_class_{$this->site->id}_{$conf->entity}" => $this->getTaxClass($variation['tax_class'], $variation['tax_status']),
+ ],
+ 'images' => $images,
+ ];
}
- } else {
- $products[] = array(
- 'remote_id' => $product['id'], // id product
- 'last_update' => isset($product['date_modified'])?$product['date_modified']:$product['date_created'],
- 'fk_product_type' => ($product['virtual'] ? 1 : 0), // 0 (product) or 1 (service)
- 'ref' => dol_string_nospecial($product['sku']),
- 'label' => ($product['name']?$product['name']:dol_string_nospecial($product['sku'])),
- 'description' => $product['description'],
- 'weight' => $product['weight'],
- 'price' => $product['price'], //sale_price
- 'envente' => $product['purchasable'] ? 1 : 0,
- 'finished' => 1, // 1 = manufactured, 0 = raw material
- 'canvas' => $canvas,
- 'categories' => '', // $product['categories'], // a check // Same as property $product['category_ids']
- 'tax_rate' => '', // $product['tax_rate'], // a check
- 'price_min' => $product['price'],
- 'fk_country' => '',
- 'url' => $product['permalink'],
- // Stock
- 'stock_qty' => $product['stock_quantity'],
- 'is_in_stock' => $product['in_stock'], // not used
- );
+ }
}
}
}
}
//important - order by last update
- if (count($products))
- {
- $last_update = array();
- foreach ($products as $key => $row)
- {
- $last_update[$key] = $row['last_update'];
- }
- array_multisort($last_update, SORT_ASC, $products);
+ if (count($products)) {
+ array_multisort($products_last_update, SORT_ASC, $products);
}
- dol_syslog("convertRemoteObjectIntoDolibarrProduct end (found ".count($products)." record)");
+ dol_syslog(__METHOD__ . ": end, converted " . count($products) . " remote products", LOG_DEBUG);
return $products;
}
/**
- * Put the remote data into commande dolibarr data from instantiated class in the constructor
- * Return array of orders by update time.
+ * Call Woocommerce API to get order datas and put into dolibarr order class.
*
- * @param array $remoteObject array of remote orders
- * @param int $toNb Max nb
- * @return array commande
+ * @param array $remoteObject List of id of remote orders to convert
+ * @param int $toNb Max nb
+ * @return array|boolean List of orders sorted by update time or false if error.
*/
public function convertRemoteObjectIntoDolibarrCommande($remoteObject, $toNb=0)
{
+ dol_syslog(__METHOD__ . ": Get " . count($remoteObject) . " remote orders ID: " . implode(', ', $remoteObject) . " for site ID {$this->site->id}", LOG_DEBUG);
global $conf, $langs;
- $commandes = array();
-
- $maxsizeofmulticall = (empty($conf->global->ECOMMERCENG_MAXSIZE_MULTICALL)?100:$conf->global->ECOMMERCENG_MAXSIZE_MULTICALL); // 1000 seems ok for multicall.
- $nbsynchro = 0;
- $nbremote = count($remoteObject);
- if ($nbremote)
- {
- // Create n groups of $maxsizeofmulticall records max to call the multiCall
- $callsgroup = array();
- $calls=array();
- foreach ($remoteObject as $rcommande)
- {
- if (($nbsynchro % $maxsizeofmulticall) == 0)
- {
- if (count($calls)) $callsgroup[]=$calls; // Add new group for lot of 1000 call arrays
- $calls=array();
- }
+ $orders = [];
+ $nb_max_by_request = empty($conf->global->ECOMMERCENG_MAXSIZE_MULTICALL) ? 100 : min($conf->global->ECOMMERCENG_MAXSIZE_MULTICALL, 100);
+ $requestGroups = $this->getRequestGroups($remoteObject, $nb_max_by_request, $toNb);
- $calls[] = $rcommande;
-
- $nbsynchro++; // nbsynchro is now number of calls to do
+ foreach ($requestGroups as $request) {
+ dol_syslog(__METHOD__ . ": Get partial remote orders ID: " . implode(', ', $request), LOG_DEBUG);
+ try {
+ $results = $this->client->get('orders',
+ [
+ 'per_page' => $nb_max_by_request,
+ 'include' => implode(',', $request),
+ ]
+ );
+ } catch (HttpClientException $fault) {
+ $this->errors[] = $langs->trans('ECommerceWoocommerceConvertRemoteObjectIntoDolibarrCommande', $this->site->name, $fault->getCode() . ': ' . $fault->getMessage());
+ dol_syslog(__METHOD__ .
+ ': Error:' . $langs->transnoentitiesnoconv('ECommerceWoocommerceConvertRemoteObjectIntoDolibarrCommande', $this->site->name, $fault->getCode() . ': ' . $fault->getMessage()) .
+ ' - Request:' . json_encode($fault->getRequest()) . ' - Response:' . json_encode($fault->getResponse()), LOG_ERR);
+ return false;
}
- if (count($calls)) $callsgroup[]=$calls; // Add new group for the remain lot of calls not yet added
- dol_syslog("convertRemoteObjectIntoDolibarrCommande Call WS to get detail for the ".count($remoteObject)." objects (".count($callsgroup)." calls with ".$maxsizeofmulticall." max of records each) then create a Dolibarr array for each object");
- //var_dump($callsgroup);exit;
-
- $results=array();
- $nbcall=0;
- foreach ($callsgroup as $calls)
- {
- try {
- $nbcall++;
- dol_syslog("convertRemoteObjectIntoDolibarrCommande Call WS nb ".$nbcall." (".count($calls)." record)");
- $resulttmp = $this->client->get('orders',
- [
- 'per_page' => $maxsizeofmulticall,
- 'include' => implode(',', $calls),
- ]
- );
- $results=array_merge($results, $resulttmp);
- } catch (HttpClientException $fault) {
- dol_syslog('convertRemoteObjectIntoDolibarrCommande :'.$fault->getMessage().'-'.$fault->getCode().'-'.$fault->getTraceAsString(), LOG_WARNING);
- return false;
- }
- }
+ if (is_array($results)) {
+ foreach ($results as $order) {
+ // Set items
+ $items = [];
+ foreach ($order['line_items'] as $item) {
+ $items[] = [
+ 'item_id' => $item['id'],
+ 'id_remote_product' => !empty($item['variation_id']) ? $item['product_id'] . '|' . $item['variation_id'] : $item['product_id'],
+ 'description' => $item['name'],
+ 'product_type' => 'simple',
+ 'price' => $item['price'],
+ 'qty' => $item['quantity'],
+ 'tva_tx' => $this->getClosestDolibarrTaxRate($item['total'], $item['total_tax']),
+ ];
+ }
- if (count($results))
- {
- foreach ($results as $commande)
- {
- // Process order
- dol_syslog("- Process order remote_id=".$commande['order_id']." last_update=".$commande['updated_at']." societe remote_id=".$commande['customer_id']);
-
- //set each items
- $items = array();
- $configurableItems = array();
- if (count($commande['line_items']))
- {
- foreach ($commande['line_items'] as $item)
- {
- $items[] = array(
- 'item_id' => $item['id'],
- 'id_remote_product' => !empty($item['variation_id']) ? $item['product_id'].'|'.$item['variation_id'] : $item['product_id'],
- 'description' => $item['name'],
- 'product_type' => 'simple',
- 'price' => $item['price'],
- 'qty' => $item['quantity'],
- 'tva_tx' => $this->getTaxRate($commande['total'], $commande['total_tax']) // tax_class > requete taxes rates
- );
- }
+ // Set remote id company : 0 for anonymous
+ $eCommerceTempSoc = new eCommerceSociete($this->db);
+ if (empty($order['customer_id']) || $eCommerceTempSoc->fetchByRemoteId($order['customer_id'], $this->site->id) < 0) {
+ dol_syslog(__METHOD__ . ": The customer of the remote order ID " . $order['id'] . " was not found into companies table link", LOG_WARNING);
+ $remoteCompanyID = 0; // If company was not found into companies table link
+ } else {
+ $remoteCompanyID = $order['customer_id'];
+ }
- //define remote id societe : 0 for anonymous
- $eCommerceTempSoc = new eCommerceSociete($this->db);
- if ($commande['customer_id'] == null || $eCommerceTempSoc->fetchByRemoteId($commande['customer_id'], $this->site->id) < 0)
- {
- dol_syslog("The customer of this order was not found into table link", LOG_WARNING);
- $remoteIdSociete = 0; // If thirdparty was not found into thirdparty table link
- }
- else
- {
- $remoteIdSociete = $commande['customer_id'];
- }
+ $last_update = $this->getDateTimeFromGMTDateTime(!empty($order['date_modified_gmt']) ? $order['date_modified_gmt'] : $order['date_created_gmt']);
- //set order's address
- $billingName = (empty($conf->global->ECOMMERCENG_BILLING_CONTACT_NAME)?'Billing':$conf->global->ECOMMERCENG_BILLING_CONTACT_NAME); // Contact name treated as billing address.
- $commandeSocpeople = $commande['billing'];
- $socpeopleCommande = array(
- 'remote_id' => $remoteIdSociete.'|1',
- 'type' => eCommerceSocpeople::CONTACT_TYPE_ORDER,
- 'last_update' => isset($commande['date_modified'])?$commande['date_modified']:$commande['date_created'],
- 'name' => $billingName, // $commandeSocpeople['last_name'],
- 'lastname' => $billingName, // $commandeSocpeople['last_name'],
- 'firstname' => '', // $commandeSocpeople['first_name'],
- 'town' => $commandeSocpeople['city'],
- //'fk_pays' => getCountry($commandeSocpeople['country'], 3),
- 'fax' => '',
- 'zip' => $commandeSocpeople['postcode'],
- //add wrap
- 'address' => (!empty(trim($commandeSocpeople['company'])) ? trim($commandeSocpeople['company']) . ", " : "") .
- $commandeSocpeople['address_1'] . (!empty($commandeSocpeople['address_1']) && !empty($commandeSocpeople['address_2']) ? "\n" : "") . $commandeSocpeople['address_2'],
- 'phone' => $commandeSocpeople['phone'],
- );
-
- //set billing's address
- $socpeopleFacture = $socpeopleCommande;
- $socpeopleFacture['type'] = eCommerceSocpeople::CONTACT_TYPE_INVOICE;
-
- //set shipping's address
- $livraisonSocpeople = $commande['shipping'];
- if ((!empty($livraisonSocpeople['address_1']) || !empty($livraisonSocpeople['address_1'])) && !empty($livraisonSocpeople['city']) && !empty($livraisonSocpeople['postcode']) && !empty($livraisonSocpeople['country'])) {
- $shippingName = (empty($conf->global->ECOMMERCENG_SHIPPING_CONTACT_NAME) ? 'Shipping' : $conf->global->ECOMMERCENG_SHIPPING_CONTACT_NAME); // Contact name treated as shipping address.
- $socpeopleLivraison = array(
- 'remote_id' => $remoteIdSociete . '|2',
- 'type' => eCommerceSocpeople::CONTACT_TYPE_DELIVERY,
- 'last_update' => isset($commande['date_modified'])?$commande['date_modified']:$commande['date_created'],
- 'name' => $shippingName, // $livraisonSocpeople['last_name'],
- 'lastname' => $shippingName, // $livraisonSocpeople['last_name'],
- 'firstname' => '', // $livraisonSocpeople['first_name'],
- 'town' => $livraisonSocpeople['city'],
- //'fk_pays' => getCountry($commandeSocpeople['country'], 3),
- 'fax' => '',
- 'zip' => $livraisonSocpeople['postcode'],
- //add wrap
- 'address' => (!empty(trim($livraisonSocpeople['company'])) ? addslashes(trim($livraisonSocpeople['company'])) . ", " : "") .
- $livraisonSocpeople['address_1'] . (!empty($livraisonSocpeople['address_1']) && !empty($livraisonSocpeople['address_2']) ? "\n" : "") .
- $livraisonSocpeople['address_2'],
- 'phone' => '',
- );
+ // Set billing's address
+ $bContact = $order['billing'];
+ $firstname = $bContact['first_name'];
+ $lastname = $bContact['last_name'];
+ if (!empty($firstname) && empty($lastname)) {
+ $lastname = $langs->trans("ECommercengWoocommerceLastnameNotInformed");
+ } elseif (empty($firstname) && empty($lastname)) {
+ $lastname = $langs->trans('ECommercengWoocommerceWithoutFirstnameLastname');
+ }
+ $contactBilling = [
+ 'remote_id' => "",
+ 'type' => 1, //eCommerceSocpeople::CONTACT_TYPE_ORDER,
+ 'last_update' => $last_update->format('Y-m-d H:i:s'),
+ 'firstname' => $firstname,
+ 'lastname' => $lastname,
+ 'address' => $bContact['address_1'] . (!empty($bContact['address_1']) && !empty($bContact['address_2']) ? "\n" : "") . $bContact['address_2'],
+ 'zip' => $bContact['postcode'],
+ 'town' => $bContact['city'],
+ 'country_id' => getCountry($bContact['country'], 3),
+ 'email' => $bContact['email'],
+ 'phone' => $bContact['phone'],
+ 'fax' => null,
+ ];
+
+ // Set invoice's address
+ $contactInvoice = $contactBilling;
+ $contactInvoice['type'] = 1; //eCommerceSocpeople::CONTACT_TYPE_INVOICE;
+
+ // Set shipping's address
+ $sContact = $order['shipping'];
+ if (!empty($sContact['address_1']) || !empty($sContact['address_2']) ||
+ !empty($sContact['postcode']) || !empty($sContact['city']) ||
+ !empty($sContact['country'])
+ ) {
+ if ($bContact['first_name'] != $sContact['first_name'] || $bContact['last_name'] != $sContact['last_name'] ||
+ $bContact['address_1'] != $sContact['address_1'] || $bContact['address_2'] != $sContact['address_2'] ||
+ $bContact['postcode'] != $sContact['postcode'] || $bContact['city'] != $sContact['city'] ||
+ $bContact['country'] != $sContact['country']
+ ) {
+ $firstname = $sContact['first_name'];
+ $lastname = $sContact['last_name'];
+ if (!empty($firstname) && empty($lastname)) {
+ $lastname = $langs->trans("ECommercengWoocommerceLastnameNotInformed");
+ } elseif (empty($firstname) && empty($lastname)) {
+ $lastname = $langs->trans('ECommercengWoocommerceWithoutFirstnameLastname');
+ }
+ $contactShipping = [
+ 'remote_id' => "",
+ 'type' => 1, //eCommerceSocpeople::CONTACT_TYPE_DELIVERY,
+ 'last_update' => $last_update->format('Y-m-d H:i:s'),
+ 'firstname' => $firstname,
+ 'lastname' => $lastname,
+ 'address' => $sContact['address_1'] . (!empty($sContact['address_1']) && !empty($sContact['address_2']) ? "\n" : "") . $sContact['address_2'],
+ 'zip' => $sContact['postcode'],
+ 'town' => $sContact['city'],
+ 'country_id' => getCountry($sContact['country'], 3),
+ 'email' => null,
+ 'phone' => null,
+ 'fax' => null,
+ ];
} else {
- $socpeopleLivraison = $socpeopleCommande;
- $socpeopleLivraison['type'] = eCommerceSocpeople::CONTACT_TYPE_DELIVERY;
+ $contactShipping = $contactBilling;
+ $contactShipping['type'] = 1; //eCommerceSocpeople::CONTACT_TYPE_DELIVERY;
}
+ } else {
+ $contactShipping = $contactBilling;
+ $contactShipping['type'] = 1; //eCommerceSocpeople::CONTACT_TYPE_DELIVERY;
+ }
- //set delivery as service
- $langs->load("ecommerce@ecommerceng");
- $shippingDisplayIfNull = (empty($conf->global->ECOMMERCENG_SHIPPING_NOT_DISPLAY_IF_NULL)?true:false); // Contact name treated as shipping address.
- $delivery = array(
- 'description' => $langs->trans('ECommerceShipping') . (isset($commande['shipping_lines'][0]) ? ' - '.$commande['shipping_lines'][0]['method_title'] : ''), // $commande['customer_note']
- 'price' => $commande['shipping_total'],
- 'qty' => $shippingDisplayIfNull || isset($commande['shipping_lines'][0]) ? 1 : 0, //0 to not show
- 'tva_tx' => $this->getTaxRate($commande['shipping_total'], $commande['shipping_tax'])
- );
-
- //define delivery date
- if (isset($commande['date_completed']) && $commande['date_completed'] != null)
- $deliveryDate = $commande['date_completed'];
- else
- $deliveryDate = $commande['date_created'];
-
- // define status of order
- // $commande['status'] is: 'pending', 'processing', 'on-hold', 'completed', 'cancelled', 'refunded', 'failed'
- $tmp = $commande['status'];
-
- // try to match dolibarr status
- $status = '';
- if (preg_match('/^pending/', $tmp)) $status = Commande::STATUS_VALIDATED; // manage 'pending', 'pending_payment', 'pending_paypal', 'pending_ogone', 'pending_...'
- elseif ($tmp == 'processing') $status = Commande::STATUS_ACCEPTED; // shipment in process or invoice done = processing // Should be constant Commande::STATUS_SHIPMENTONPROCESS but not defined in dolibarr 3.9
- elseif ($tmp == 'on-hold') $status = Commande::STATUS_ACCEPTED;
- elseif (preg_match('/^cancelled/', $tmp)) $status = Commande::STATUS_CANCELED; // manage 'canceled', 'canceled_bnpmercanetcw', 'canceled_...'
- elseif ($tmp == 'completed') $status = Commande::STATUS_CLOSED;
- elseif ($tmp == 'refunded') $status = Commande::STATUS_CLOSED;
- elseif ($tmp == 'failed') $status = Commande::STATUS_CANCELED;
- if ($status == '')
- {
- dol_syslog("Status: We found an order id ".$commande['increment_id']." with ecommerce status '".$tmp."' that is unknown, not supported. We will use '0' for Dolibarr", LOG_WARNING);
- $status = Commande::STATUS_DRAFT; // draft by default (draft does not exists with magento, so next line will set correct status)
- }
- else
- {
- dol_syslog("Status: We found an order id ".$commande['increment_id']." with ecommerce status '".$tmp."'. We convert it into Dolibarr status '".$status."'");
- }
-
- // try to match dolibarr billed status (payed or not)
- $billed = -1; // unknown
- if ($commande['status'] == 'pending') $billed = 0;
- if ($commande['status'] == 'processing') $billed = 0; //
- if ($commande['status'] == 'on-hold') $billed = 0; //
- if ($commande['status'] == 'completed') $billed = 1; // We are sure for complete that order is payed
- if ($commande['status'] == 'cancelled') $billed = 0; // We are sure for canceled that order was not payed
- if ($commande['status'] == 'refunded') $billed = 1; //
- if ($commande['status'] == 'failed') $billed = 0; //
- // Note: with processing, billed can be 0 or 1, so we keep -1
-
-
- // Add order content to array or orders
- $commandes[] = array(
- 'last_update' => isset($commande['date_modified'])?$commande['date_modified']:$commande['date_created'],
- 'remote_id' => $commande['id'],
- 'remote_increment_id' => $commande['id'],
- 'remote_id_societe' => $remoteIdSociete,
- 'ref_client' => $commande['id'],
- 'date_commande' => $commande['date_created'],
- 'date_livraison' => $commande['date_completed'], // $deliveryDate,
- 'items' => $items,
- 'delivery' => $delivery,
- 'note' => $commande['customer_note'],
- 'socpeopleCommande' => $socpeopleCommande,
- 'socpeopleFacture' => $socpeopleFacture,
- 'socpeopleLivraison' => $socpeopleLivraison,
- 'status' => $status, // dolibarr status
- 'billed' => $billed,
- 'remote_state' => $commande['status'], // remote state, for information only (less accurate than status)
- 'remote_status' => $commande['status'], // remote status, for information only (more accurate than state)
- 'remote_order' => $commande
- );
+ // Set delivery as service
+ $shippingDisplayIfNull = (empty($conf->global->ECOMMERCENG_SHIPPING_NOT_DISPLAY_IF_NULL) ? true : false);
+ $delivery = [
+ 'description' => $langs->trans('ECommerceShipping') . (isset($order['shipping_lines'][0]) ? ' - ' .
+ $order['shipping_lines'][0]['method_title'] : ''), // $order['customer_note']
+ 'price' => $order['shipping_total'],
+ 'qty' => $shippingDisplayIfNull || isset($order['shipping_lines'][0]) ? 1 : 0, //0 to not show
+ 'tva_tx' => $this->getClosestDolibarrTaxRate($order['shipping_total'], $order['shipping_tax'])
+ ];
+
+ // Set status of order
+ // $order['status'] is: 'pending', 'processing', 'on-hold', 'completed', 'cancelled', 'refunded', 'failed'
+ $orderStatus = $order['status'];
+
+ $status = '';
+ switch ($orderStatus) {
+ case 'on-hold': $status = Commande::STATUS_DRAFT; break;
+ case 'pending': $status = Commande::STATUS_DRAFT; break;
+ case 'processing': $status = !empty($conf->global->ECOMMERCENG_WOOCOMMERCE_ORDER_PROCESSING_STATUS_TO_DRAFT)?Commande::STATUS_DRAFT:Commande::STATUS_VALIDATED; break;
+ case 'completed': $status = Commande::STATUS_CLOSED; break;
+ case 'refunded': $status = Commande::STATUS_CANCELED; break;
+ case 'cancelled': $status = Commande::STATUS_CANCELED; break;
+ case 'failed': $status = Commande::STATUS_CANCELED; break;
}
- else
- {
- dol_syslog("No items in this order", LOG_WARNING);
+ if (!empty($conf->global->ECOMMERCENG_WOOCOMMERCE_FORCE_ORDER_STATUS_TO_DRAFT)) $status = Commande::STATUS_DRAFT;
+ if ($status == '') {
+ dol_syslog(__METHOD__ . ": Status \"$orderStatus\" was not found for remote order ID {$order['id']} and set in draft", LOG_WARNING);
+ $status = Commande::STATUS_DRAFT; // draft by default
}
+
+ // Set dolibarr billed status (payed or not)
+ $billed = -1; // unknown
+ if ($order['status'] == 'pending') $billed = 0;
+ if ($order['status'] == 'processing') $billed = 0; //
+ if ($order['status'] == 'on-hold') $billed = 0; //
+ if ($order['status'] == 'completed') $billed = 1; // We are sure for complete that order is payed
+ if ($order['status'] == 'cancelled') $billed = 0; // We are sure for canceled that order was not payed
+ if ($order['status'] == 'refunded') $billed = 1; //
+ if ($order['status'] == 'failed') $billed = 0; //
+ // Note: with processing, billed can be 0 or 1, so we keep -1
+
+ // Add order content to array or orders
+ $orders[] = [
+ 'last_update' => $last_update->format('Y-m-d H:i:s'),
+ 'remote_id' => $order['id'],
+ 'remote_increment_id' => $order['id'],
+ 'remote_id_societe' => $remoteCompanyID,
+ 'ref_client' => $order['id'],
+ 'date_commande' => $order['date_created'],
+ 'date_livraison' => $order['date_completed'],
+ 'items' => $items,
+ 'delivery' => $delivery,
+ 'note' => $order['customer_note'],
+ 'socpeopleCommande' => $contactBilling,
+ 'socpeopleFacture' => $contactInvoice,
+ 'socpeopleLivraison' => $contactShipping,
+ 'status' => $status, // dolibarr status
+ 'billed' => $billed,
+ 'remote_state' => $order['status'], // remote state, for information only (less accurate than status)
+ 'remote_status' => $order['status'], // remote status, for information only (more accurate than state)
+ 'remote_order' => $order,
+ 'payment_method' => $order['payment_method_title'],
+ 'extrafields' => [
+ "ecommerceng_online_payment_{$conf->entity}" => empty($order['date_paid']) ? 0 : 1,
+ ],
+ ];
}
}
}
//important - order by last update
- if (count($commandes))
- {
- $last_update = array();
- foreach ($commandes as $key => $row)
- {
+ if (count($orders)) {
+ $last_update = [];
+ foreach ($orders as $key => $row) {
$last_update[$key] = $row['last_update'];
}
- array_multisort($last_update, SORT_ASC, $commandes);
+ array_multisort($last_update, SORT_ASC, $orders);
}
- dol_syslog("convertRemoteObjectIntoDolibarrCommande end (found ".count($commandes)." array of orders filled with complete data from eCommerce)");
- return $commandes;
+ dol_syslog(__METHOD__ . ": end, converted " . count($orders) . " remote orders", LOG_DEBUG);
+ return $orders;
}
/**
- * Put the remote data into facture dolibarr data from instantiated class
- * Return array of invoices by update time.
+ * Desactivated because is not supported by woocommerce.
*
- * @param array $remoteObject array of remote invoices
- * @param int $toNb Max nb
- * @return array facture
+ * @param array $remoteObject List of id of remote orders to convert
+ * @param int $toNb Max nb
+ * @return array Empty list
*/
public function convertRemoteObjectIntoDolibarrFacture($remoteObject, $toNb=0)
{
- global $conf;
-
- $factures = array();
+ dol_syslog(__METHOD__ . ": Desactivated for site ID {$this->site->id}", LOG_DEBUG);
+ return [];
+ }
-/* $maxsizeofmulticall = (empty($conf->global->ECOMMERCENG_MAXSIZE_MULTICALL)?100:$conf->global->ECOMMERCENG_MAXSIZE_MULTICALL); // 1000 seems ok for multicall.
- $nbsynchro = 0;
- $nbremote = count($remoteObject);
- if ($nbremote)
- {
- // Create n groups of $maxsizeofmulticall records max to call the multiCall
- $callsgroup = array();
- $calls=array();
- foreach ($remoteObject as $rfacture)
- {
- if (($nbsynchro % $maxsizeofmulticall) == 0)
- {
- if (count($calls)) $callsgroup[]=$calls; // Add new group for lot of 1000 call arrays
- $calls=array();
- }
+ /**
+ * Get remote category tree
+ *
+ * @return array|boolean Array with categories or false if error
+ */
+ public function getRemoteCategoryTree()
+ {
+ dol_syslog(__METHOD__ . ": Get remote category tree for site ID {$this->site->id}", LOG_DEBUG);
+ global $conf, $langs;
- $calls[] = $rfacture;
+ $categories = [];
+ $idxPage = 1;
+ $per_page = empty($conf->global->ECOMMERCENG_MAXSIZE_MULTICALL) ? 100 : min($conf->global->ECOMMERCENG_MAXSIZE_MULTICALL, 100);
- $nbsynchro++; // nbsynchro is now number of calls to do
+ while (true) {
+ try {
+ $results = $this->client->get('products/categories',
+ [
+ 'page' => $idxPage++,
+ 'per_page' => $per_page,
+ ]
+ );
+ } catch (HttpClientException $fault) {
+ $this->errors[] = $langs->trans('ECommerceWoocommerceGetRemoteCategoryTree', $this->site->name, $fault->getCode() . ': ' . $fault->getMessage());
+ dol_syslog(__METHOD__ .
+ ': Error:' . $langs->transnoentitiesnoconv('ECommerceWoocommerceGetRemoteCategoryTree', $this->site->name, $fault->getCode() . ': ' . $fault->getMessage()) .
+ ' - Request:' . json_encode($fault->getRequest()) . ' - Response:' . json_encode($fault->getResponse()), LOG_ERR);
+ return false;
+ }
+ if (count($results) == 0) break;
+
+ foreach ($results as $category) {
+ $categories[$category['id']] = [
+ 'category_id' => $category['id'], // id category
+ 'parent_id' => $category['parent'],
+ 'label' => $category['name'],
+ 'name' => $category['name'],
+ 'description' => $category['description'],
+ 'updated_at' => '',
+ ];
}
- if (count($calls)) $callsgroup[]=$calls; // Add new group for the remain lot of calls not yet added
+ }
- dol_syslog("convertRemoteObjectIntoDolibarrFacture Call WS to get detail for the ".count($remoteObject)." objects (".count($callsgroup)." calls with ".$maxsizeofmulticall." max of records each) then create a Dolibarr array for each object");
- //var_dump($callsgroup);exit;
+ // Set tree
+ foreach ($categories as $category) {
+ $parent_id = $category['parent_id'];
- $results=array();
- $nbcall=0;
- foreach ($callsgroup as $calls)
- {
- try {
- $nbcall++;
- dol_syslog("convertRemoteObjectIntoDolibarrFacture Call WS nb ".$nbcall." (".count($calls)." record)");
- $resulttmp = $this->client->get('orders',
- [
- 'include' => implode(',', $calls),
- ]
- );
- $results=array_merge($results, $resulttmp);
- } catch (HttpClientException $fault) {
- dol_syslog('convertRemoteObjectIntoDolibarrFacture :'.$fault->getMessage().'-'.$fault->getCode().'-'.$fault->getTraceAsString(), LOG_WARNING);
+ if (!empty($parent_id)) {
+ if (!isset($categories[$parent_id]['children'])) {
+ $categories[$parent_id]['level'] = 0;
+ $categories[$parent_id]['children'] = [];
}
- }
-
- if (count($results))
- {
- $i=0;
- foreach ($results as $facture)
- {
- // Process invoice
- dol_syslog("- Process invoice remote_id=".$facture['order_id']." last_update=".$facture['updated_at']." societe order_id=".$facture['order_id']);
-
- $i++;
-
- $configurableItems = array();
- //retrive remote order from invoice
- $commande = $this->getRemoteCommande($facture['order_id']);
- //set each invoice items
- $items = array();
- if (count($facture['items']))
- {
- foreach ($facture['items'] as $item)
- {
- //var_dump($item); // show invoice item as it is from magento
-
- $product_type = $this->getProductTypeOfItem($item, $commande, $facture);
- $parent_item_id = $this->getParentItemOfItem($item, $commande, $facture);
-
- // If item is configurable, localMemCache it, to use its price and tax rate instead of the one of its child
- if ($product_type == 'configurable') {
- $configurableItems[$item['item_id']] = array(
- 'item_id' => $item['item_id'],
- 'id_remote_product' => $item['product_id'],
- 'description' => $item['name'],
- 'product_type' => $product_type,
- 'price' => $item['price'],
- 'qty' => $item['qty'],
- 'tva_tx' => $this->getTaxRate($item['row_total'], $item['tax_amount'])
- );
- } else {
- // If item has a parent item id defined in $configurableItems, it's a child simple item so we get it's price and tax values instead of 0
- if (!array_key_exists($parent_item_id, $configurableItems)) {
- $items[] = array(
- 'item_id' => $item['item_id'],
- 'id_remote_product' => $item['product_id'],
- 'description' => $item['name'],
- 'product_type' => $product_type,
- 'price' => $item['price'],
- 'qty' => $item['qty'],
- 'tva_tx' => $this->getTaxRate($item['row_total'], $item['tax_amount'])
- );
- } else {
- $items[] = array(
- 'item_id' => $item['item_id'],
- 'id_remote_product' => $item['product_id'],
- 'description' => $item['name'],
- 'product_type' => $product_type,
- 'price' => $configurableItems[$parent_item_id]['price'],
- 'qty' => $item['qty'],
- 'tva_tx' => $configurableItems[$parent_item_id]['tva_tx']
- );
- }
- }
- }
-
- //set shipping address
- $shippingAddress = $commande["shipping_address"];
- $billingAddress = $commande["billing_address"];
- $socpeopleLivraison = array(
- 'remote_id' => $shippingAddress['address_id'],
- 'type' => eCommerceSocpeople::CONTACT_TYPE_DELIVERY,
- 'last_update' => $shippingAddress['updated_at'],
- 'name' => $shippingAddress['lastname'],
- 'firstname' => $shippingAddress['firstname'],
- 'ville' => $shippingAddress['city'],
- //'fk_pays' => $commandeSocpeople['country_id'],
- 'fax' => $shippingAddress['fax'],
- 'cp' => $shippingAddress['postcode'],
- //add wrap
- 'address' => (trim($shippingAddress['company']) != '' ? trim($shippingAddress['company']) . '
- ' : '') . $shippingAddress['street'],
- 'phone' => $shippingAddress['telephone']
- );
- //set invoice address
- $socpeopleFacture = array(
- 'remote_id' => $billingAddress['address_id'],
- 'type' => eCommerceSocpeople::CONTACT_TYPE_INVOICE,
- 'last_update' => $billingAddress['updated_at'],
- 'name' => $billingAddress['lastname'],
- 'firstname' => $billingAddress['firstname'],
- 'ville' => $billingAddress['city'],
- //'fk_pays' => $commandeSocpeople['country_id'],
- 'fax' => $billingAddress['fax'],
- 'cp' => $billingAddress['postcode'],
- //add wrap
- 'address' => (trim($billingAddress['company']) != '' ? trim($billingAddress['company']) . '
- ' : '') . $billingAddress['street'],
- 'phone' => $billingAddress['telephone']
- );
- //set delivery as service
- $delivery = array(
- 'description' => $commande['shipping_description'],
- 'price' => $facture['shipping_amount'],
- 'qty' => 1, //0 to not show
- 'tva_tx' => $this->getTaxRate($facture['shipping_amount'], $facture['shipping_tax_amount'])
- );
-
- $eCommerceTempSoc = new eCommerceSociete($this->db);
- if ($commande['customer_id'] == null || $eCommerceTempSoc->fetchByRemoteId($commande['customer_id'], $this->site->id) < 0)
- {
- $remoteIdSociete = 0;
- }
- else
- {
- $remoteIdSociete = $commande['customer_id'];
- }
-
- // load local order to be used to retreive some data for invoice
- $eCommerceTempCommande = new eCommerceCommande($this->db);
- $eCommerceTempCommande->fetchByRemoteId($commande['order_id'], $this->site->id);
- $dbCommande = new Commande($this->db);
- $dbCommande->fetch($eCommerceTempCommande->fk_commande);
-
-
- // define status of invoice
- $tmp = $facture['state']; // state from is 1, 2, 3
-
- // try to match dolibarr status
- $status = '';
- if ($tmp == 1) $status = Facture::STATUS_VALIDATED; // validated = pending
- if ($tmp == 2) $status = Facture::STATUS_CLOSED; // complete
- if ($tmp == 3) $status = Facture::STATUS_ABANDONED; // canceled = holded
- if ($status == '')
- {
- dol_syslog("Status: We found an invoice id ".$commande['increment_id']." with ecommerce status '".$tmp."' that is unknown, not supported. We will use '0' for Dolibarr", LOG_WARNING);
- $status = Facture::STATUS_DRAFT; // draft by default (draft does not exists with magento, so next line will set correct status)
- }
- else
- {
- dol_syslog("Status: We found an invoice id ".$commande['increment_id']." with ecommerce status '".$tmp."'. We convert it into Dolibarr status '".$status."'");
- }
-
- $close_code = '';
- $close_note = '';
- if ($tmp == 3)
- {
- $close_code = Facture::CLOSECODE_ABANDONED;
- $close_note = 'Holded on ECommerce';
- }
-
- //add invoice to invoices
- $factures[] = array(
- 'last_update' => $facture['updated_at'],
- 'remote_id' => $facture['invoice_id'],
- 'remote_increment_id' => $facture['increment_id'],
- 'ref_client' => $facture['increment_id'],
- 'remote_order_id' => $facture['order_id'],
- 'remote_order_increment_id' => $facture['order_increment_id'],
- 'remote_id_societe' => $remoteIdSociete,
- 'socpeopleLivraison' => $socpeopleLivraison,
- 'socpeopleFacture' => $socpeopleFacture,
- 'date' => $facture['created_at'],
- 'code_cond_reglement' => $dbCommande->cond_reglement_code, // Take for local order
- 'delivery' => $delivery,
- 'items' => $items,
- 'status' => $tmp,
- 'close_code' => $close_code,
- 'close_note' => $close_note,
- 'remote_state' => $facture['state'],
- 'remote_order' => $commande,
- 'remote_invoice' => $facture
- );
- }
- else
- {
- dol_syslog("No items in this invoice", LOG_WARNING);
- }
- }
+ $categories[$parent_id]['children'][] = &$categories[$category['category_id']];
}
}
- //important - order by last update
- if (count($factures))
- {
- $last_update=array();
- foreach ($factures as $key => $row)
- {
- $last_update[$key] = $row['last_update'];
+ // Make tree
+ $categories_tree = ['level' => 0, 'children' => []];
+ foreach ($categories as $category) {
+ if (empty($category['parent_id'])) {
+ $categories_tree['children'][] = $category;
}
- array_multisort($last_update, SORT_ASC, $factures);
}
- //var_dump($factures);exit;
- */
-
- dol_syslog("convertRemoteObjectIntoDolibarrFacture end (found ".count($products)." record)");
- return $factures;
+ dol_syslog(__METHOD__ . ": end, " . count($categories) . " remote category recovered", LOG_DEBUG);
+ return $categories_tree;
}
-
/**
- * Return if type of an item of invoice (information comue from item of order)
+ * Desactivated because is not supported by woocommerce.
*
- * @param array $item Item of invoice
- * @param array $commande Commande with items
- * @param array $facture Facture with items
- * @return string
+ * @param int $remote_company_id Id of company
+ *
+ * @return array Array with address id
*/
- function getProductTypeOfItem($item, $commande, $facture)
+ public function getRemoteAddressIdForSociete($remote_company_id)
{
- $product_type = 'notfound'; // By default
+ dol_syslog(__METHOD__ . ": Desactivated for site ID {$this->site->id}", LOG_DEBUG);
+ return [$remote_company_id];
+ }
- //print "Try to find product type of invoice item_id=".$item['item_id']." (invoice ".$facture['increment_id'].") and order_item_id=".$item['order_item_id']." (order ".$commande['increment_id'].")\n";
+ /**
+ * Return content of one category
+ *
+ * @param int $category_id Remote category id
+ *
+ * @return array|boolean Return category data
+ */
+ public function getCategoryData($category_id)
+ {
+ dol_syslog(__METHOD__ . ": Get remote category for site ID {$this->site->id}", LOG_DEBUG);
+ global $langs;
- $order_item_id = $item['order_item_id'];
+ $category = [];
- // We scan item of order to find this order item id
- foreach($commande['items'] as $itemorder)
- {
- if ($itemorder['item_id'] == $order_item_id)
- {
- // We've got it
- $product_type = $itemorder['product_type'];
- break;
- }
+ try {
+ $result = $this->client->get('products/categories/' . $category_id);
+ } catch (HttpClientException $fault) {
+ $this->errors[] = $langs->trans('ECommerceWoocommerceGetCategoryData', $this->site->name, $fault->getCode() . ': ' . $fault->getMessage());
+ dol_syslog(__METHOD__ .
+ ': Error:' . $langs->transnoentitiesnoconv('ECommerceWoocommerceGetCategoryData', $this->site->name, $fault->getCode() . ': ' . $fault->getMessage()) .
+ ' - Request:' . json_encode($fault->getRequest()) . ' - Response:' . json_encode($fault->getResponse()), LOG_ERR);
+ return false;
}
- //print "Found product type = ".$product_type."\n";
-
- if ($product_type == 'notfound') $product_type = 'simple';
+ if (isset($result)) {
+ $category = [
+ 'category_id' => $result['id'], // id category
+ 'parent_id' => $result['parent'],
+ 'label' => $result['name'],
+ 'name' => $result['name'],
+ 'description' => $result['description'],
+ 'updated_at' => '',
+ ];
+ }
- return $product_type;
+ dol_syslog(__METHOD__ . ": end", LOG_DEBUG);
+ return $category;
}
/**
- * Return if type of an item of invoice (information comue from item of order)
+ * Return content of one order
*
- * @param array $item Item of invoice
- * @param array $commande Commande with items
- * @param array $facture Facture with items
- * @return string
+ * @param int $remoteOrderId Remote order id
+ *
+ * @return array Empty
*/
- function getParentItemOfItem($item, $commande, $facture)
+ public function getRemoteCommande($remoteOrderId)
{
- //print "Try to find invoice parent item id of invoice item_id=".$item['item_id']." (invoice ".$facture['increment_id'].") and order_item_id=".$item['order_item_id']." (order ".$commande['increment_id'].")\n";
+ dol_syslog(__METHOD__ . ": Desactivated for site ID {$this->site->id}", LOG_DEBUG);
+ return [];
+ }
- $parent_item_id = 0; // By default
- $parent_item_id_in_order = 0;
+ /**
+ * Update the remote product
+ *
+ * @param int $remote_id Id of product on remote ecommerce
+ * @param Product $object Product object
+ *
+ * @return boolean True or false
+ */
+ public function updateRemoteProduct($remote_id, $object)
+ {
+ dol_syslog(__METHOD__ . ": Update the remote product ID $remote_id for Dolibarr product ID {$object->id} for site ID {$this->site->id}", LOG_DEBUG);
+ global $conf, $langs;
- $order_item_id = $item['order_item_id'];
+ $isProductVariation = false;
+ $remote_product_id = $remote_id;
+ $remote_product_variation_id = 0;
+ if (preg_match('/^(\d+)\|(\d+)$/', $remote_id, $idsProduct) == 1) { // Variations
+ $isProductVariation = true;
+ $remote_product_id = $idsProduct[1];
+ $remote_product_variation_id = $idsProduct[2];
+ }
- // We scan item of order to find this order item id
- foreach($commande['items'] as $itemorder)
+ // Set Weight
+ $totalWeight = $object->weight;
+ if ($object->weight_units < 50) // >50 means a standard unit (power of 10 of official unit), > 50 means an exotic unit (like inch)
{
- if ($itemorder['item_id'] == $order_item_id)
- {
- // We've got it
- $product_type = $itemorder['product_type'];
+ $trueWeightUnit = pow(10, $object->weight_units);
+ $totalWeight = sprintf("%f", $object->weight * $trueWeightUnit);
+ }
- $parent_item_id_in_order = $itemorder['parent_item_id'];
- break;
+ try {
+ if ($isProductVariation) { // Variations
+ $results = $this->client->get("products/$remote_product_id/variations/$remote_product_variation_id");
+ } else {
+ $results = $this->client->get("products/$remote_product_id");
}
+ } catch (HttpClientException $fault) {
+ $this->errors[] = $langs->trans('ECommerceWoocommerceUpdateRemoteProductGetRemoteProduct', $this->site->name, $fault->getCode() . ': ' . $fault->getMessage());
+ dol_syslog(__METHOD__ .
+ ': Error:' . $langs->transnoentitiesnoconv('ECommerceWoocommerceUpdateRemoteProductGetRemoteProduct', $this->site->name, $fault->getCode() . ': ' . $fault->getMessage()) .
+ ' - Request:' . json_encode($fault->getRequest()) . ' - Response:' . json_encode($fault->getResponse()), LOG_ERR);
+ return false;
}
- // If the item is linked to an order item id that has a parent order item id
- if ($parent_item_id_in_order)
- {
- // We scan now invoice items to find the item that is linked to order item id $parent_item_id_in_order
- foreach($facture['items'] as $itemfacture)
- {
- if ($itemfacture['order_item_id'] == $parent_item_id_in_order)
- {
- // We've got it
- $parent_item_id = $itemfacture['item_id'];
+ // images
+ $images = [];
+ if (!empty($conf->global->ECOMMERCENG_ENABLE_SYNCHRO_IMAGES)) {
+ // Get current images
+ $current_images = [];
+ if (!empty($results) && isset($results['images']) && is_array($results['images'])) {
+ foreach ($results['images'] as $image) {
+ $current_images[$image['name']] = $image['id'];
+ }
+ }
+
+ // Product - Images properties
+ $entity = isset($object->entity) ? $object->entity : $conf->entity;
+ if (!empty($conf->global->PRODUCT_USE_OLD_PATH_FOR_PHOTO)) { // For backward compatiblity, we scan also old dirs
+ if ($object->type == Product::TYPE_PRODUCT) {
+ $dir = $conf->product->multidir_output[$entity] . '/' . substr(substr("000" . $object->id, -2), 1, 1) . '/' . substr(substr("000" . $object->id, -2), 0, 1) . '/' . $object->id . "/photos/";
+ } else {
+ $dir = $conf->service->multidir_output[$entity] . '/' . substr(substr("000" . $object->id, -2), 1, 1) . '/' . substr(substr("000" . $object->id, -2), 0, 1) . '/' . $object->id . "/photos/";
+ }
+ } else {
+ if ($object->type == Product::TYPE_PRODUCT) {
+ $dir = $conf->product->multidir_output[$entity] . '/' . get_exdir(0, 0, 0, 0, $object, 'product') . dol_sanitizeFileName($object->ref) . '/';
+ } else {
+ $dir = $conf->service->multidir_output[$entity] . '/' . get_exdir(0, 0, 0, 0, $object, 'product') . dol_sanitizeFileName($object->ref) . '/';
+ }
+ }
+ $photos = $object->liste_photos($dir);
+ foreach ($photos as $index => $photo) {
+ $img = [];
+
+ $filename = ecommerceng_wordpress_sanitize_file_name($photo['photo']);
+ if (!isset($current_images[$filename])) {
+ $result = $this->worpressclient->postmedia("media", $dir . $photo['photo'], [
+ 'slug' => $object->id . '_' . $filename,
+ 'ping_status' => 'closed',
+ 'comment_status' => 'closed',
+ ]);
+
+ if ($result === null) {
+ $this->errors[] = $langs->trans('ECommerceWoocommerceUpdateRemoteProductSendImage', $remote_id, $this->site->name, implode('; ', $this->worpressclient->errors));
+ dol_syslog(__METHOD__ . ': Error:' . $langs->transnoentitiesnoconv('ECommerceWoocommerceUpdateRemoteProductSendImage', $remote_id, $this->site->name, implode('; ', $this->worpressclient->errors)), LOG_ERR);
+ return false;
+ }
+
+ $img['id'] = $result['id'];
+ } else {
+ $img['id'] = $current_images[$filename];
+ }
+
+ $img['name'] = $filename;
+ $img['position'] = $index;
+ $images[] = $img;
+
+ if ($isProductVariation) { // Get only one image for variation
break;
}
}
}
- //print "Found invoice parent_item_id=".$parent_item_id." and order parent_item_id=".$parent_item_id_in_order."\n";
+ // Product - Meta data properties
+ $object->fetch_optionals();
- return $parent_item_id;
- }
+ // Price
+ if (!empty($conf->global->PRODUIT_MULTIPRICES)) {
+ $price_level = !empty($this->site->price_level) ? $this->site->price_level : 1;
+ $price = $object->multiprices[$price_level];
+ } else {
+ $price = $object->price;
+ }
+ if ($isProductVariation) { // Variations
+ /*
+ // Product variation - Downloads properties
+ $downloads = [
+ [
+ 'name' => '', // string File name.
+ 'file' => '', // string File URL.
+ ],
+ ];
+
+ // Product variation - Dimensions properties
+ $dimensions = [
+ 'length' => '', // string Product length (cm).
+ 'width' => '', // string Product width (cm).
+ 'height' => '', // string Product height (cm).
+ ];
+
+ // Product variation - Image properties
+ $images = [
+ [
+ 'id' => 0, // integer Image ID. Not required
+ 'src' => '', // string Image URL.
+ 'name' => '', // string Image name.
+ 'alt' => '', // string Image alternative text.
+ 'position' => 0, // integer Image position. 0 means that the image is featured.
+ ],
+ ];
+
+ // Product variation - Attributes properties
+ $attributes = [
+ [
+ 'id' => 0, // integer Attribute ID.
+ 'name' => '', // string Attribute name.
+ 'option' => '', // string Selected attribute term name.
+ ],
+ ];
+
+ // Product variation - Meta data properties
+ $meta_data = [
+ 'key' => '', // string Meta key.
+ 'value' => '', // string Meta value.
+ ];
+ */
+
+ $variationData = [
+ 'description' => nl2br($object->array_options["options_ecommerceng_description_{$conf->entity}"]), // string Variation description.
+ 'sku' => $object->ref, // string Unique identifier.
+ 'regular_price' => $price, // string Variation regular price.
+ //'sale_price' => '', // string Variation sale price.
+ //'date_on_sale_from' => '', // date-time Start date of sale price, in the site’s timezone.
+ //'date_on_sale_from_gmt' => '', // date-time Start date of sale price, as GMT.
+ //'date_on_sale_to' => '', // date-time End date of sale price, in the site’s timezone.
+ //'date_on_sale_to_gmt' => '', // date-time End date of sale price, in the site’s timezone.
+ //'visible' => '', // boolean Define if the attribute is visible on the “Additional information” tab in the product’s page. Default is true.
+ //'virtual' => $object->type == Product::TYPE_SERVICE, // boolean If the variation is virtual. Default is false.
+ //'downloadable' => '', // boolean If the variation is downloadable. Default is false.
+ //'downloads' => $downloads, // array List of downloadable files. See Product variation - Downloads properties
+ //'download_limit' => '', // integer Number of times downloadable files can be downloaded after purchase. Default is -1.
+ //'download_expiry' => '', // integer Number of days until access to downloadable files expires. Default is -1.
+ 'tax_status' => 'none', // string Tax status. Options: taxable, shipping and none. Default is taxable.
+ //'tax_class' => '', // string Tax class.
+ //'manage_stock' => '', // boolean Stock management at variation level. Default is false.
+ //'stock_quantity' => '', // integer Stock quantity.
+ //'in_stock' => '', // boolean Controls whether or not the variation is listed as “in stock” or “out of stock” on the frontend. Default is true.
+ //'backorders' => '', // string If managing stock, this controls if backorders are allowed. Options: no, notify and yes. Default is no.
+ 'weight' => (!empty($totalWeight) ? $totalWeight : ''), // string Variation weight (kg).
+ //'dimensions' => $dimensions, // object Variation dimensions. See Product variation - Dimensions properties
+ //'shipping_class' => '', // string Shipping class slug.
+ 'image' => (!empty($images) ? $images[0] : ''), // object Variation image data. See Product variation - Image properties
+ //'attributes' => $attributes, // array List of attributes. See Product variation - Attributes properties
+ //'menu_order' => '', // integer Menu order, used to custom sort products.
+ //'meta_data' => $meta_data, // array Meta data. See Product variation - Meta data properties
+ ];
+
+ // Set tax
+ if (!empty($object->array_options["options_ecommerceng_tax_class_{$this->site->id}_{$conf->entity}"])) {
+ $variationData['tax_status'] = 'taxable';
+ $variationData['tax_class'] = $object->array_options["options_ecommerceng_tax_class_{$this->site->id}_{$conf->entity}"];
+ }
+ // Product
+ // 'name' => $object->label, // string Product name.
+ // 'status' => $object->status ? 'publish' : 'pending', // string Product status (post status). Options: draft, pending, private and publish. Default is publish.
+ try {
+ $result = $this->client->put("products/$remote_product_id/variations/$remote_product_variation_id", $variationData);
+ } catch (HttpClientException $fault) {
+ $this->errors[] = $langs->trans('ECommerceWoocommerceUpdateRemoteProductVariation', $this->site->name, $fault->getCode() . ': ' . $fault->getMessage());
+ dol_syslog(__METHOD__ .
+ ': Error:' . $langs->transnoentitiesnoconv('ECommerceWoocommerceUpdateRemoteProductVariation', $this->site->name, $fault->getCode() . ': ' . $fault->getMessage()) .
+ ' - Request:' . json_encode($fault->getRequest()) . ' - Response:' . json_encode($fault->getResponse()), LOG_ERR);
+ return false;
+ }
+ } else { // Product
+ /*
+ // Product - Downloads properties
+ $downloads = [
+ [
+ 'name' => '', // string File name.
+ 'file' => '', // string File URL.
+ ],
+ ];
+
+ // Product - Dimensions properties
+ $dimensions = [
+ 'length' => '', // string Product length (cm).
+ 'width' => '', // string Product width (cm).
+ 'height' => '', // string Product height (cm).
+ ];
+
+ // Product - Categories properties
+ $categories = [
+ [
+ 'id' => 0, // integer Category ID.
+ ],
+ ];
- // Now functions to get data on remote shop, from the remote id.
+ // Product - Tags properties
+ $tags = [
+ [
+ 'id' => 0, // integer Tag ID.
+ ],
+ ];
+ // Product - Images properties
+ $images = [
+ [
+ 'id' => 0, // integer Image ID. Not required
+ 'src' => '', // string Image URL.
+ 'name' => '', // string Image name.
+ 'alt' => '', // string Image alternative text.
+ 'position' => 0, // integer Image position. 0 means that the image is featured.
+ ],
+ ];
+
+ // Product - Attributes properties
+ $attributes = [
+ [
+ 'id' => 0, // integer Attribute ID. Not required
+ 'name' => '', // string Attribute name.
+ 'position' => 0, // integer Attribute position.
+ 'visible' => false, // boolean Define if the attribute is visible on the “Additional information” tab in the product’s page. Default is false.
+ 'variation' => false, // boolean Define if the attribute can be used as variation. Default is false.
+ 'options' => [], // array List of available term names of the attribute.
+ ],
+ ];
+
+ // Product - Default attributes properties
+ $default_attributes = [
+ 'id' => 0, // integer Attribute ID. Not required
+ 'name' => '', // string Attribute name.
+ 'option' => '', // string Selected attribute term name.
+ ];
+
+ // Product - Meta data properties
+ $meta_data = [
+ 'key' => '', // string Meta key.
+ 'value' => '', // string Meta value.
+ ];
+ */
+
+ // Get categories
+ $eCommerceCategory = new eCommerceCategory($this->db);
+ $cat = new Categorie($this->db);
+ $categories_list = $cat->containing($object->id, 'product');
+ $categories = [];
+ foreach ($categories_list as $category) {
+ if ($this->site->fk_cat_product != $category->id) {
+ $ret = $eCommerceCategory->fetchByFKCategory($category->id, $this->site->id);
+ if ($ret > 0) {
+ $categories[] = ['id' => $eCommerceCategory->remote_id];
+ }
+ }
+ }
+
+ $status = $object->array_options["options_ecommerceng_wc_status_{$this->site->id}_{$conf->entity}"];
+
+ $productData = [
+ 'name' => $object->label, // string Product name.
+ //'slug' => '', // string Product slug.
+ //'type' => '', // string Product type. Options: simple, grouped, external and variable. Default is simple.
+ 'status' => (!empty($status) ? $status : ''), //$object->status ? 'publish' : 'pending', // string Product status (post status). Options: draft, pending, private and publish. Default is publish.
+ //'featured' => false, // boolean Featured product. Default is false.
+ //'catalog_visibility' => '', // string Catalog visibility. Options: visible, catalog, search and hidden. Default is visible.
+ 'description' => nl2br($object->array_options["options_ecommerceng_description_{$conf->entity}"]), // string Product description.
+ 'short_description' => nl2br($object->array_options["options_ecommerceng_short_description_{$conf->entity}"]), // string Product short description.
+ 'sku' => $object->ref, // string Unique identifier.
+ 'regular_price' => $price, // string Product regular price.
+ //'sale_price' => '', // string Product sale price.
+ //'date_on_sale_from' => '', // date-time Start date of sale price, in the site’s timezone.
+ //'date_on_sale_from_gmt' => '', // date-time Start date of sale price, as GMT.
+ //'date_on_sale_to' => '', // date-time End date of sale price, in the site’s timezone.
+ //'date_on_sale_to_gmt' => '', // date-time End date of sale price, in the site’s timezone.
+ //'virtual' => $object->type == Product::TYPE_SERVICE, // boolean If the product is virtual. Default is false.
+ //'downloadable' => false, // boolean If the product is downloadable. Default is false.
+ //'downloads' => $downloads, // array List of downloadable files. See Product - Downloads properties
+ //'download_limit' => -1, // integer Number of times downloadable files can be downloaded after purchase. Default is -1.
+ //'download_expiry' => -1, // integer Number of days until access to downloadable files expires. Default is -1.
+ //'external_url' => '', // string Product external URL. Only for external products.
+ //'button_text' => '', // string Product external button text. Only for external products.
+ 'tax_status' => 'none', // string Tax status. Options: taxable, shipping and none. Default is taxable.
+ //'tax_class' => '', // string Tax class.
+ //'manage_stock' => false, // boolean Stock management at product level. Default is false.
+ //'stock_quantity' => $object->stock_reel, // integer Stock quantity.
+ //'in_stock' => $object->stock_reel > 0, // boolean Controls whether or not the product is listed as “in stock” or “out of stock” on the frontend. Default is true.
+ //'backorders' => '', // string If managing stock, this controls if backorders are allowed. Options: no, notify and yes. Default is no.
+ //'sold_individually' => false, // boolean Allow one item to be bought in a single order. Default is false.
+ 'weight' => (!empty($totalWeight) ? $totalWeight : ''), // string Product weight (kg).
+ //'dimensions' => $dimensions, // object Product dimensions. See Product - Dimensions properties
+ //'shipping_class' => '', // string Shipping class slug.
+ //'reviews_allowed' => true, // boolean Allow reviews. Default is true.
+ //'upsell_ids' => [], // array List of up-sell products IDs.
+ //'cross_sell_ids' => [], // array List of cross-sell products IDs.
+ //'parent_id' => 0, // integer Product parent ID.
+ //'purchase_note' => '', // string Optional note to send the customer after purchase.
+ 'categories' => $categories, // array List of categories. See Product - Categories properties
+ //'tags' => $tags, // array List of tags. See Product - Tags properties
+ 'images' => (!empty($images) ? $images : ''), // object List of images. See Product - Images properties
+ //'attributes' => $attributes, // array List of attributes. See Product - Attributes properties
+ //'default_attributes' => $default_attributes, // array Defaults variation attributes. See Product - Default attributes properties
+ //'menu_order' => 0, // integer Menu order, used to custom sort products.
+ //'meta_data' => $meta_data, // array Meta data. See Product - Meta data properties
+ ];
+
+ // Set tax
+ if (!empty($object->array_options["options_ecommerceng_tax_class_{$this->site->id}_{$conf->entity}"])) {
+ $productData['tax_status'] = 'taxable';
+ $productData['tax_class'] = $object->array_options["options_ecommerceng_tax_class_{$this->site->id}_{$conf->entity}"];
+ }
+
+ try {
+ $result = $this->client->put("products/$remote_product_id", $productData);
+ } catch (HttpClientException $fault) {
+ $this->errors[] = $langs->trans('ECommerceWoocommerceUpdateRemoteProduct', $this->site->name, $fault->getCode() . ': ' . $fault->getMessage());
+ dol_syslog(__METHOD__ .
+ ': Error:' . $langs->transnoentitiesnoconv('ECommerceWoocommerceUpdateRemoteProduct', $this->site->name, $fault->getCode() . ': ' . $fault->getMessage()) .
+ ' - Request:' . json_encode($fault->getRequest()) . ' - Response:' . json_encode($fault->getResponse()), LOG_ERR);
+ return false;
+ }
+ }
+
+ dol_syslog(__METHOD__ . ": end", LOG_DEBUG);
+ return true;
+ }
/**
- * Return the magento's category tree
+ * Update the remote stock of product
*
- * @return array|boolean Array with categories or false if error
+ * @param int $remote_id Id of product on remote ecommerce
+ * @param MouvementStock $object MouvementStock object, enhanced with property qty_after be the trigger STOCK_MOVEMENT.
+ *
+ * @return boolean True or false
*/
- public function getRemoteCategoryTree()
+ public function updateRemoteStockProduct($remote_id, $object)
{
- dol_syslog("eCommerceRemoteAccessWoocommerce getRemoteCategoryTree session=".$this->session);
- /* try {
- //$result = $this->client->call($this->session, 'auguria_dolibarrapi_catalog_category.tree');
- $result = $this->client->call($this->session, 'catalog_category.tree');
- return $result;
- //dol_syslog($this->client->__getLastRequest());
- } catch (SoapFault $fault) {
- $this->errors[]=$this->site->name.': '.$fault->getMessage().'-'.$fault->getCode();
- dol_syslog(__METHOD__.': '.$fault->getMessage().'-'.$fault->getCode().'-'.$fault->getTraceAsString(), LOG_WARNING);
- return false;
- }*/
- return array();
- //var_dump($result);
- dol_syslog("eCommerceRemoteAccessWoocommerce getRemoteCategoryTree end. Nb of record of result = ".count($result));
+ dol_syslog(__METHOD__ . ": Update stock of the remote product ID $remote_id for MouvementStock ID {$object->id}, new qty: {$object->qty_after} for site ID {$this->site->id}", LOG_DEBUG);
+ global $langs;
+
+ if (preg_match('/^(\d+)\|(\d+)$/', $remote_id, $idsProduct) == 1) {
+ // Variations
+ $variationData = [
+ //'manage_stock' => '', // boolean Stock management at variation level. Default is false.
+ 'stock_quantity' => $object->qty_after, // integer Stock quantity.
+ 'in_stock' => $object->qty_after > 0, // boolean Controls whether or not the variation is listed as “in stock” or “out of stock” on the frontend. Default is true.
+ //'backorders' => '', // string If managing stock, this controls if backorders are allowed. Options: no, notify and yes. Default is no.
+ ];
+
+ try {
+ $result = $this->client->put("products/$idsProduct[1]/variations/$idsProduct[2]", $variationData);
+ } catch (HttpClientException $fault) {
+ $this->errors[] = $langs->trans('ECommerceWoocommerceUpdateRemoteStockProductVariation', $this->site->name, $fault->getCode() . ': ' . $fault->getMessage());
+ dol_syslog(__METHOD__ .
+ ': Error:' . $langs->transnoentitiesnoconv('ECommerceWoocommerceUpdateRemoteStockProductVariation', $this->site->name, $fault->getCode() . ': ' . $fault->getMessage()) .
+ ' - Request:' . json_encode($fault->getRequest()) . ' - Response:' . json_encode($fault->getResponse()), LOG_ERR);
+ return false;
+ }
+ } else {
+ $productData = [
+ //'manage_stock' => false, // boolean Stock management at product level. Default is false.
+ 'stock_quantity' => $object->qty_after, // integer Stock quantity.
+ 'in_stock' => $object->qty_after > 0, // boolean Controls whether or not the product is listed as “in stock” or “out of stock” on the frontend. Default is true.
+ //'backorders' => '', // string If managing stock, this controls if backorders are allowed. Options: no, notify and yes. Default is no.
+ ];
+
+ try {
+ $result = $this->client->put("products/$remote_id", $productData);
+ } catch (HttpClientException $fault) {
+ $this->errors[] = $langs->trans('ECommerceWoocommerceUpdateRemoteStockProduct', $this->site->name, $fault->getCode() . ': ' . $fault->getMessage());
+ dol_syslog(__METHOD__ .
+ ': Error:' . $langs->transnoentitiesnoconv('ECommerceWoocommerceUpdateRemoteStockProduct', $this->site->name, $fault->getCode() . ': ' . $fault->getMessage()) .
+ ' - Request:' . json_encode($fault->getRequest()) . ' - Response:' . json_encode($fault->getResponse()), LOG_ERR);
+ return false;
+ }
+ }
+
+ dol_syslog(__METHOD__ . ": end", LOG_DEBUG);
+ return true;
}
/**
- * Return the magento's category att
+ * Update the remote company
*
- * @return array|boolean Array with categories or false if error
+ * @param int $remote_id Id of company on remote ecommerce
+ * @param Societe $object Societe object
+ *
+ * @return boolean True or false
*/
- /*public function getRemoteCategoryAtt()
+ public function updateRemoteSociete($remote_id, $object)
{
- dol_syslog("eCommerceRemoteAccessWoocommerce getRemoteCategoryAtt session=".$this->session);
+ dol_syslog(__METHOD__ . ": Update the remote company ID $remote_id for Dolibarr company ID {$object->id} for site ID {$this->site->id}", LOG_DEBUG);
+ global $langs;
+
+ /*
+ // Customer - Meta data properties
+ $meta_data = [
+ 'key' => '', // string Meta key.
+ 'value' => '', // string Meta value.
+ ];
+ */
+ $companyData = [
+ 'email' => $object->email, // string The email address for the customer. MANDATORY
+ //'first_name' => '', // string Customer first name.
+ //'last_name' => $object->name, // string Customer last name.
+ //'username' => '', // string Customer login name.
+ //'password' => '', // string Customer password.
+ //'meta_data' => $meta_data, // array Meta data. See Customer - Meta data properties
+ ];
+
try {
- //$result = $this->client->call($this->session, 'auguria_dolibarrapi_catalog_category.tree');
- $result = $this->client->call($this->session, 'catalog_category_attribute.list');
- } catch (SoapFault $fault) {
- $this->errors[]=$this->site->name.': '.$fault->getMessage().'-'.$fault->getCode();
- dol_syslog(__METHOD__.': '.$fault->getMessage().'-'.$fault->getCode().'-'.$fault->getTraceAsString(), LOG_WARNING);
+ $result = $this->client->put("customers/$remote_id", $companyData);
+ } catch (HttpClientException $fault) {
+ $this->errors[] = $langs->trans('ECommerceWoocommerceUpdateRemoteSociete', $this->site->name, $fault->getCode() . ': ' . $fault->getMessage());
+ dol_syslog(__METHOD__ .
+ ': Error:' . $langs->transnoentitiesnoconv('ECommerceWoocommerceUpdateRemoteSociete', $this->site->name, $fault->getCode() . ': ' . $fault->getMessage()) .
+ ' - Request:' . json_encode($fault->getRequest()) . ' - Response:' . json_encode($fault->getResponse()), LOG_ERR);
return false;
}
- dol_syslog("eCommerceRemoteAccessWoocommerce getRemoteCategoryAtt end");
- return $result;
- }*/
+
+ dol_syslog(__METHOD__ . ": end", LOG_DEBUG);
+ return true;
+ }
/**
- * Return the magento's address id
+ * Update the remote contact
*
- * @param int $remote_thirdparty_id Id of thirdparty
- * @return array|boolean Array with address id
+ * @param int $remote_id Id of contact on remote ecommerce
+ * @param Contact $object Contact object
+ *
+ * @return boolean True or false
*/
- public function getRemoteAddressIdForSociete($remote_thirdparty_id)
+ public function updateRemoteSocpeople($remote_id, $object)
{
- dol_syslog("eCommerceRemoteAccessWoocommerce getRemoteAddressIdForSociete session=".$this->session);
- $result = array($remote_thirdparty_id);
- dol_syslog("eCommerceRemoteAccessWoocommerce getRemoteAddressIdForSociete end");
- return $result;
- }
+ dol_syslog(__METHOD__ . ": Update the remote contact ID $remote_id for Dolibarr contact ID {$object->id} for site ID {$this->site->id}", LOG_DEBUG);
+ global $conf, $langs;
+ // Get societe
+ //require_once DOL_DOCUMENT_ROOT . '/societe/class/societe.class.php';
+ //$societe = new Societe($this->db);
+ //$societe->fetch($object->socid);
+
+ $billingName = (empty($conf->global->ECOMMERCENG_BILLING_CONTACT_NAME) ? 'Billing' : $conf->global->ECOMMERCENG_BILLING_CONTACT_NAME); // Contact name treated as billing address.
+ $shippingName = (empty($conf->global->ECOMMERCENG_SHIPPING_CONTACT_NAME) ? 'Shipping' : $conf->global->ECOMMERCENG_SHIPPING_CONTACT_NAME); // Contact name treated as shipping address.
+
+ if ($object->lastname == $billingName) {
+ $address = explode("\n", $object->address);
+ // Billing
+ $contactData = [
+ 'billing' => [
+ //'first_name' => '', // string First name.
+ //'last_name' => '', // string Last name.
+ //'company' => $societe->name, // string Company name.
+ 'address_1' => isset($address[0]) ? $address[0] : '', // string Address line 1
+ 'address_2' => isset($address[1]) ? implode(" ", array_slice($address, 1)) : '', // string Address line 2
+ 'city' => $object->town, // string City name.
+ //'state' => '', // string ISO code or name of the state, province or district.
+ 'postcode' => $object->zip, // string Postal code.
+ 'country' => getCountry($object->country_id, 2), // string ISO code of the country.
+ 'email' => $object->email, // string Email address.
+ 'phone' => $object->phone_pro, // string Phone number.
+ ],
+ ];
+ } elseif ($object->lastname == $shippingName) {
+ $address = explode("\n", $object->address);
+ // Shipping
+ $contactData = [
+ 'shipping' => [
+ //'first_name' => '', // string First name.
+ //'last_name' => '', // string Last name.
+ //'company' => $societe->name, // string Company name.
+ 'address_1' => isset($address[0]) ? $address[0] : '', // string Address line 1
+ 'address_2' => isset($address[1]) ? implode(" ", array_slice($address, 1)) : '', // string Address line 2
+ 'city' => $object->town, // string City name.
+ //'state' => '', // string ISO code or name of the state, province or district.
+ 'postcode' => $object->zip, // string Postal code.
+ 'country' => getCountry($object->country_id, 2), // string ISO code of the country.
+ ],
+ ];
+ }
+
+ if (isset($contactData)) {
+ if (preg_match('/^(\d+)\|(\d+)$/', $remote_id, $idsCustomer) == 1) {
+ try {
+ $result = $this->client->put("customers/$idsCustomer[1]", $contactData);
+ } catch (HttpClientException $fault) {
+ $this->errors[] = $langs->trans('ECommerceWoocommerceUpdateRemoteSocpeople', $this->site->name, $fault->getCode() . ': ' . $fault->getMessage());
+ dol_syslog(__METHOD__ .
+ ': Error:' . $langs->transnoentitiesnoconv('ECommerceWoocommerceUpdateRemoteSocpeople', $this->site->name, $fault->getCode() . ': ' . $fault->getMessage()) .
+ ' - Request:' . json_encode($fault->getRequest()) . ' - Response:' . json_encode($fault->getResponse()), LOG_ERR);
+ return false;
+ }
+ }
+ }
+
+ dol_syslog(__METHOD__ . ": end", LOG_DEBUG);
+ return true;
+ }
/**
- * Return content of one category
+ * Update the remote order
*
- * @param int $category_id Remote category id
- * @return boolean|unknown Return
+ * @param int $remote_id Id of order on remote ecommerce
+ * @param Commande $object Commande object
+ *
+ * @return boolean True or false
*/
- public function getCategoryData($category_id)
+ public function updateRemoteCommande($remote_id, $object)
{
- $result = array();
- dol_syslog("eCommerceRemoteAccessWoocommerce getCategoryData session=".$this->session);
-/* try {
- //$result = $this->client->call($this->session, 'auguria_dolibarrapi_catalog_category.tree');
- $result = $this->client->call($this->session, 'catalog_category.info', array('categoryId'=>$category_id));
- //dol_syslog($this->client->__getLastRequest());
- } catch (SoapFault $fault) {
- $this->errors[]=$this->site->name.': '.$fault->getMessage().'-'.$fault->getCode();
- dol_syslog($this->client->__getLastRequestHeaders(), LOG_WARNING);
- dol_syslog($this->client->__getLastRequest(), LOG_WARNING);
- dol_syslog(__METHOD__.': '.$fault->getMessage().'-'.$fault->getCode().'-'.$fault->getTraceAsString(), LOG_WARNING);
- return false;
- }*/
- dol_syslog("eCommerceRemoteAccessWoocommerce getCategoryData end");
- return $result;
+ dol_syslog(__METHOD__ . ": Update the remote order ID $remote_id for Dolibarr order ID {$object->id} for site ID {$this->site->id}", LOG_DEBUG);
+ global $langs;
+
+ $status = '';
+ switch ($object->statut) {
+ //case Commande::STOCK_NOT_ENOUGH_FOR_ORDER: $status = ''; break;
+ case Commande::STATUS_CANCELED: $status = 'cancelled'; break;
+ case Commande::STATUS_DRAFT: $status = 'on-hold'; break;
+ case Commande::STATUS_VALIDATED: $status = 'processing'; break;
+ //case Commande::STATUS_ACCEPTED: $status = 'processing'; break;
+ case Commande::STATUS_SHIPMENTONPROCESS: $status = 'processing'; break;
+ case Commande::STATUS_CLOSED: $status = 'completed'; break;
+ }
+
+ if (!empty($status)) {
+ $orderData = [
+ 'status' => $status, // string Order status. Options: pending, processing, on-hold, completed, cancelled, refunded and failed.
+ ];
+
+ try {
+ $result = $this->client->put("orders/$remote_id", $orderData);
+ } catch (HttpClientException $fault) {
+ $this->errors[] = $langs->trans('ECommerceWoocommerceUpdateRemoteCommande', $this->site->name, $fault->getCode() . ': ' . $fault->getMessage());
+ dol_syslog(__METHOD__ .
+ ': Error:' . $langs->transnoentitiesnoconv('ECommerceWoocommerceUpdateRemoteCommande', $this->site->name, $fault->getCode() . ': ' . $fault->getMessage()) .
+ ' - Request:' . json_encode($fault->getRequest()) . ' - Response:' . json_encode($fault->getResponse()), LOG_ERR);
+ return false;
+ }
+ }
+
+ dol_syslog(__METHOD__ . ": end", LOG_DEBUG);
+ return true;
}
/**
- * Return the magento's order
+ * Desactivated because is not supported by woocommerce.
*
- * @param int $remoteCommandeId Id of remote order
- * @return object Order
+ * @param int $remote_id Id of invoice on remote ecommerce
+ * @param Facture $object Invoice object
+ *
+ * @return boolean True or false
*/
- public function getRemoteCommande($remoteCommandeId)
+ public function updateRemoteFacture($remote_id, $object)
{
- $commande = array();
- try {
- dol_syslog("getCommande begin");
- $commande = $this->client->get("orders/$remoteCommandeId");
- dol_syslog("getCommande end");
- } catch (HttpClientException $fault) {
- if ($fault->getCode() != 404) {
- $this->errors[]=$fault->getMessage().'-'.$fault->getCode();
- dol_syslog(__METHOD__.': '.$fault->getMessage().'-'.$fault->getCode().'-'.$fault->getTraceAsString(), LOG_WARNING);
- }
- }
- return $commande;
+ dol_syslog(__METHOD__ . ": Desactivated for site ID {$this->site->id}", LOG_DEBUG);
+ return true;
}
-
+ /**
+ * Desactivated because is not supported by woocommerce.
+ *
+ * @param int $livraison Object shipment ?
+ * @param int $remote_order_id Id of remote order
+ *
+ * @return boolean True or false
+ */
+ public function createRemoteLivraison($livraison, $remote_order_id)
+ {
+ dol_syslog(__METHOD__ . ": Desactivated for site ID {$this->site->id}", LOG_DEBUG);
+ return $remote_order_id;
+ }
/**
- * Update the remote product
+ * Create product
+ *
+ * @param Product $object Object product
*
- * @param int $remote_id Id of product on remote ecommerce
- * @param Product $object Product object
* @return boolean True or false
*/
- public function updateRemoteProduct($remote_id, $object)
+ public function createRemoteProduct($object)
{
- dol_syslog("eCommerceRemoteAccessWoocommerce updateRemoteProduct session=".$this->session." remote_id=".$remote_id." object->id=".$object->id);
+ dol_syslog(__METHOD__ . ": Create product from Dolibarr product ID {$object->id} for site ID {$this->site->id}", LOG_DEBUG);
+ global $conf, $langs, $user;
+ // Set weight
$totalWeight = $object->weight;
if ($object->weight_units < 50) // >50 means a standard unit (power of 10 of official unit), > 50 means an exotic unit (like inch)
{
- $trueWeightUnit=pow(10, $object->weight_units);
+ $trueWeightUnit = pow(10, $object->weight_units);
$totalWeight = sprintf("%f", $object->weight * $trueWeightUnit);
}
+ // Product - Meta data properties
+ $object->fetch_optionals();
- try {
- if (preg_match('/^(\d+)\|(\d+)$/', $remote_id, $idsProduct) == 1) {
- // Variations
-/*
- // Product variation - Downloads properties
- $downloads = [
- [
- 'name' => '', // string File name.
- 'file' => '', // string File URL.
- ],
- ];
-*/
-/*
- // Product variation - Dimensions properties
- $dimensions = [
- 'length' => '', // string Product length (cm).
- 'width' => '', // string Product width (cm).
- 'height' => '', // string Product height (cm).
- ];
-*/
-/*
- // Product variation - Image properties
- $images = [
- [
- 'id' => 0, // integer Image ID. Not required
- 'src' => '', // string Image URL.
- 'name' => '', // string Image name.
- 'alt' => '', // string Image alternative text.
- 'position' => 0, // integer Image position. 0 means that the image is featured.
- ],
- ];
-*/
-/*
- // Product variation - Attributes properties
- $attributes = [
- [
- 'id' => 0, // integer Attribute ID.
- 'name' => '', // string Attribute name.
- 'option' => '', // string Selected attribute term name.
- ],
- ];
-*/
-/*
- // Product variation - Meta data properties
- $meta_data = [
- 'key' => '', // string Meta key.
- 'value' => '', // string Meta value.
- ];
-*/
- $variationData = array(
- 'description' => $object->description, // string Variation description.
- 'sku' => $object->ref, // string Unique identifier.
- 'regular_price' => $object->price, // string Variation regular price.
- //'sale_price' => '', // string Variation sale price.
- //'date_on_sale_from' => '', // date-time Start date of sale price, in the site’s timezone.
- //'date_on_sale_from_gmt' => '', // date-time Start date of sale price, as GMT.
- //'date_on_sale_to' => '', // date-time End date of sale price, in the site’s timezone.
- //'date_on_sale_to_gmt' => '', // date-time End date of sale price, in the site’s timezone.
- //'visible' => '', // boolean Define if the attribute is visible on the “Additional information” tab in the product’s page. Default is true.
- //'virtual' => $object->type == Product::TYPE_SERVICE, // boolean If the variation is virtual. Default is false.
- //'downloadable' => '', // boolean If the variation is downloadable. Default is false.
- //'downloads' => $downloads, // array List of downloadable files. See Product variation - Downloads properties
- //'download_limit' => '', // integer Number of times downloadable files can be downloaded after purchase. Default is -1.
- //'download_expiry' => '', // integer Number of days until access to downloadable files expires. Default is -1.
- //'tax_status' => '', // string Tax status. Options: taxable, shipping and none. Default is taxable.
- //'tax_class' => '', // string Tax class.
- //'manage_stock' => '', // boolean Stock management at variation level. Default is false.
- //'stock_quantity' => '', // integer Stock quantity.
- //'in_stock' => '', // boolean Controls whether or not the variation is listed as “in stock” or “out of stock” on the frontend. Default is true.
- //'backorders' => '', // string If managing stock, this controls if backorders are allowed. Options: no, notify and yes. Default is no.
- 'weight' => $totalWeight, // string Variation weight (kg).
- //'dimensions' => $dimensions, // object Variation dimensions. See Product variation - Dimensions properties
- //'shipping_class' => '', // string Shipping class slug.
- //'image' => $images, // object Variation image data. See Product variation - Image properties
- //'attributes' => $attributes, // array List of attributes. See Product variation - Attributes properties
- //'menu_order' => '', // integer Menu order, used to custom sort products.
- //'meta_data' => $meta_data, // array Meta data. See Product variation - Meta data properties
- );
+ // Price
+ if (!empty($conf->global->PRODUIT_MULTIPRICES)) {
+ $price_level = !empty($this->site->price_level) ? $this->site->price_level : 1;
+ $price = $object->multiprices[$price_level];
+ } else {
+ $price = $object->price;
+ }
- // Product
- // 'name' => $object->label, // string Product name.
- // 'status' => $object->status ? 'publish' : 'pending', // string Product status (post status). Options: draft, pending, private and publish. Default is publish.
+ /*
+ // Product - Downloads properties
+ $downloads = [
+ [
+ 'name' => '', // string File name.
+ 'file' => '', // string File URL.
+ ],
+ ];
- $result = $this->client->put("products/$idsProduct[1]/variations/$idsProduct[2]", $variationData);
- } else {
- // Product
-/*
- // Product - Downloads properties
- $downloads = [
- [
- 'name' => '', // string File name.
- 'file' => '', // string File URL.
- ],
- ];
-*/
-/*
- // Product - Dimensions properties
- $dimensions = [
- 'length' => '', // string Product length (cm).
- 'width' => '', // string Product width (cm).
- 'height' => '', // string Product height (cm).
- ];
-*/
-/*
- // Product - Categories properties
- $categories = [
- [
- 'id' => 0, // integer Category ID.
- ],
- ];
-*/
-/*
- // Product - Tags properties
- $tags = [
- [
- 'id' => 0, // integer Tag ID.
- ],
- ];
-*/
-/*
- // Product - Images properties
- $images = [
- [
- 'id' => 0, // integer Image ID. Not required
- 'src' => '', // string Image URL.
- 'name' => '', // string Image name.
- 'alt' => '', // string Image alternative text.
- 'position' => 0, // integer Image position. 0 means that the image is featured.
- ],
- ];
-*/
-/*
- // Product - Attributes properties
- $attributes = [
- [
- 'id' => 0, // integer Attribute ID. Not required
- 'name' => '', // string Attribute name.
- 'position' => 0, // integer Attribute position.
- 'visible' => false, // boolean Define if the attribute is visible on the “Additional information” tab in the product’s page. Default is false.
- 'variation' => false, // boolean Define if the attribute can be used as variation. Default is false.
- 'options' => [], // array List of available term names of the attribute.
- ],
- ];
-*/
-/*
- // Product - Default attributes properties
- $default_attributes = [
- 'id' => 0, // integer Attribute ID. Not required
- 'name' => '', // string Attribute name.
- 'option' => '', // string Selected attribute term name.
- ];
-*/
-/*
- // Product - Meta data properties
- $meta_data = [
- 'key' => '', // string Meta key.
- 'value' => '', // string Meta value.
- ];
-*/
- $productData = array(
- 'name' => $object->label, // string Product name.
- //'slug' => '', // string Product slug.
- //'type' => '', // string Product type. Options: simple, grouped, external and variable. Default is simple.
- 'status' => $object->status ? 'publish' : 'pending', // string Product status (post status). Options: draft, pending, private and publish. Default is publish.
- //'featured' => false, // boolean Featured product. Default is false.
- //'catalog_visibility' => '', // string Catalog visibility. Options: visible, catalog, search and hidden. Default is visible.
- 'description' => $object->description, // string Product description.
- //'short_description' => '', // string Product short description.
- 'sku' => $object->ref, // string Unique identifier.
- 'regular_price' => $object->price, // string Product regular price.
- //'sale_price' => '', // string Product sale price.
- //'date_on_sale_from' => '', // date-time Start date of sale price, in the site’s timezone.
- //'date_on_sale_from_gmt' => '', // date-time Start date of sale price, as GMT.
- //'date_on_sale_to' => '', // date-time End date of sale price, in the site’s timezone.
- //'date_on_sale_to_gmt' => '', // date-time End date of sale price, in the site’s timezone.
- //'virtual' => $object->type == Product::TYPE_SERVICE, // boolean If the product is virtual. Default is false.
- //'downloadable' => false, // boolean If the product is downloadable. Default is false.
- //'downloads' => $downloads, // array List of downloadable files. See Product - Downloads properties
- //'download_limit' => -1, // integer Number of times downloadable files can be downloaded after purchase. Default is -1.
- //'download_expiry' => -1, // integer Number of days until access to downloadable files expires. Default is -1.
- //'external_url' => '', // string Product external URL. Only for external products.
- //'button_text' => '', // string Product external button text. Only for external products.
- //'tax_status' => '', // string Tax status. Options: taxable, shipping and none. Default is taxable.
- //'tax_class' => '', // string Tax class.
- //'manage_stock' => false, // boolean Stock management at product level. Default is false.
- //'stock_quantity' => $object->stock_reel, // integer Stock quantity.
- //'in_stock' => $object->stock_reel > 0, // boolean Controls whether or not the product is listed as “in stock” or “out of stock” on the frontend. Default is true.
- //'backorders' => '', // string If managing stock, this controls if backorders are allowed. Options: no, notify and yes. Default is no.
- //'sold_individually' => false, // boolean Allow one item to be bought in a single order. Default is false.
- 'weight' => $totalWeight, // string Product weight (kg).
- //'dimensions' => $dimensions, // object Product dimensions. See Product - Dimensions properties
- //'shipping_class' => '', // string Shipping class slug.
- //'reviews_allowed' => true, // boolean Allow reviews. Default is true.
- //'upsell_ids' => [], // array List of up-sell products IDs.
- //'cross_sell_ids' => [], // array List of cross-sell products IDs.
- //'parent_id' => 0, // integer Product parent ID.
- //'purchase_note' => '', // string Optional note to send the customer after purchase.
- //'categories' => $categories, // array List of categories. See Product - Categories properties
- //'tags' => $tags, // array List of tags. See Product - Tags properties
- //'images' => $images, // object List of images. See Product - Images properties
- //'attributes' => $attributes, // array List of attributes. See Product - Attributes properties
- //'default_attributes' => $default_attributes, // array Defaults variation attributes. See Product - Default attributes properties
- //'menu_order' => 0, // integer Menu order, used to custom sort products.
- //'meta_data' => $meta_data, // array Meta data. See Product - Meta data properties
- );
+ // Product - Dimensions properties
+ $dimensions = [
+ 'length' => '', // string Product length (cm).
+ 'width' => '', // string Product width (cm).
+ 'height' => '', // string Product height (cm).
+ ];
- $result = $this->client->put("products/$remote_id", $productData);
+ // Product - Categories properties
+ $categories = [
+ [
+ 'id' => 0, // integer Category ID.
+ ],
+ ];
+
+ // Product - Tags properties
+ $tags = [
+ [
+ 'id' => 0, // integer Tag ID.
+ ],
+ ];
+
+ // Product - Images properties
+ $images = [
+ [
+ 'id' => 0, // integer Image ID. Not required
+ 'src' => '', // string Image URL.
+ 'name' => '', // string Image name.
+ 'alt' => '', // string Image alternative text.
+ 'position' => 0, // integer Image position. 0 means that the image is featured.
+ ],
+ ];
+
+ // Product - Attributes properties
+ $attributes = [
+ [
+ 'id' => 0, // integer Attribute ID. Not required
+ 'name' => '', // string Attribute name.
+ 'position' => 0, // integer Attribute position.
+ 'visible' => false, // boolean Define if the attribute is visible on the “Additional information” tab in the product’s page. Default is false.
+ 'variation' => false, // boolean Define if the attribute can be used as variation. Default is false.
+ 'options' => [], // array List of available term names of the attribute.
+ ],
+ ];
+
+ // Product - Default attributes properties
+ $default_attributes = [
+ 'id' => 0, // integer Attribute ID. Not required
+ 'name' => '', // string Attribute name.
+ 'option' => '', // string Selected attribute term name.
+ ];
+
+ // Product - Meta data properties
+ $meta_data = [
+ 'key' => '', // string Meta key.
+ 'value' => '', // string Meta value.
+ ];
+ */
+
+ // Get categories
+ $eCommerceCategory = new eCommerceCategory($this->db);
+ $cat = new Categorie($this->db);
+ $categories_list = $cat->containing($object->id, 'product');
+ $categories = [];
+ foreach ($categories_list as $category) {
+ if ($this->site->fk_cat_product != $category->id) {
+ $ret = $eCommerceCategory->fetchByFKCategory($category->id, $this->site->id);
+ if ($ret > 0) {
+ $categories[] = ['id' => $eCommerceCategory->remote_id];
+ }
}
+ }
+
+ $status = $object->array_options["options_ecommerceng_wc_status_{$this->site->id}_{$conf->entity}"];
+
+ // Product
+ $productData = [
+ 'name' => $object->label, // string Product name.
+ //'slug' => '', // string Product slug.
+ //'type' => '', // string Product type. Options: simple, grouped, external and variable. Default is simple.
+ 'status' => (!empty($status) ? $status : ''), //$object->status ? 'publish' : 'pending', // string Product status (post status). Options: draft, pending, private and publish. Default is publish.
+ //'featured' => false, // boolean Featured product. Default is false.
+ //'catalog_visibility' => '', // string Catalog visibility. Options: visible, catalog, search and hidden. Default is visible.
+ 'description' => $object->array_options["options_ecommerceng_description_{$conf->entity}"], // string Product description.
+ 'short_description' => $object->array_options["options_ecommerceng_short_description_{$conf->entity}"], // string Product short description.
+ 'sku' => $object->ref, // string Unique identifier.
+ 'regular_price' => $price, // string Product regular price.
+ //'sale_price' => '', // string Product sale price.
+ //'date_on_sale_from' => '', // date-time Start date of sale price, in the site’s timezone.
+ //'date_on_sale_from_gmt' => '', // date-time Start date of sale price, as GMT.
+ //'date_on_sale_to' => '', // date-time End date of sale price, in the site’s timezone.
+ //'date_on_sale_to_gmt' => '', // date-time End date of sale price, in the site’s timezone.
+ //'virtual' => $object->type == Product::TYPE_SERVICE, // boolean If the product is virtual. Default is false.
+ //'downloadable' => false, // boolean If the product is downloadable. Default is false.
+ //'downloads' => $downloads, // array List of downloadable files. See Product - Downloads properties
+ //'download_limit' => -1, // integer Number of times downloadable files can be downloaded after purchase. Default is -1.
+ //'download_expiry' => -1, // integer Number of days until access to downloadable files expires. Default is -1.
+ //'external_url' => '', // string Product external URL. Only for external products.
+ //'button_text' => '', // string Product external button text. Only for external products.
+ 'tax_status' => 'none', // string Tax status. Options: taxable, shipping and none. Default is taxable.
+ //'tax_class' => '', // string Tax class.
+ //'manage_stock' => false, // boolean Stock management at product level. Default is false.
+ //'stock_quantity' => $object->stock_reel, // integer Stock quantity.
+ //'in_stock' => $object->stock_reel > 0, // boolean Controls whether or not the product is listed as “in stock” or “out of stock” on the frontend. Default is true.
+ //'backorders' => '', // string If managing stock, this controls if backorders are allowed. Options: no, notify and yes. Default is no.
+ //'sold_individually' => false, // boolean Allow one item to be bought in a single order. Default is false.
+ 'weight' => (!empty($totalWeight)?$totalWeight:''), // string Product weight (kg).
+ //'dimensions' => $dimensions, // object Product dimensions. See Product - Dimensions properties
+ //'shipping_class' => '', // string Shipping class slug.
+ //'reviews_allowed' => true, // boolean Allow reviews. Default is true.
+ //'upsell_ids' => [], // array List of up-sell products IDs.
+ //'cross_sell_ids' => [], // array List of cross-sell products IDs.
+ //'parent_id' => 0, // integer Product parent ID.
+ //'purchase_note' => '', // string Optional note to send the customer after purchase.
+ 'categories' => $categories, // array List of categories. See Product - Categories properties
+ //'tags' => $tags, // array List of tags. See Product - Tags properties
+ //'images' => $images, // object List of images. See Product - Images properties
+ //'attributes' => $attributes, // array List of attributes. See Product - Attributes properties
+ //'default_attributes' => $default_attributes, // array Defaults variation attributes. See Product - Default attributes properties
+ //'menu_order' => 0, // integer Menu order, used to custom sort products.
+ //'meta_data' => $meta_data, // array Meta data. See Product - Meta data properties
+ ];
+
+ // Set tax
+ if (!empty($object->array_options["options_ecommerceng_tax_class_{$this->site->id}_{$conf->entity}"])) {
+ $productData['tax_status'] = 'taxable';
+ $productData['tax_class'] = $object->array_options["options_ecommerceng_tax_class_{$this->site->id}_{$conf->entity}"];
+ }
- dol_syslog("eCommerceRemoteAccessWoocommerce updateRemoteProduct end");
- return true;
+ try {
+ $res = $this->client->post("products", $productData);
} catch (HttpClientException $fault) {
- $this->errors[]=$fault->getMessage().'-'.$fault->getCode();
- dol_syslog(__METHOD__.': '.$fault->getMessage().'-'.$fault->getCode().'-'.$fault->getTraceAsString(), LOG_WARNING);
+ $this->errors[] = $langs->trans('ECommerceWoocommerceCreateRemoteProduct', $this->site->name, $fault->getCode() . ': ' . $fault->getMessage());
+ dol_syslog(__METHOD__ .
+ ': Error:' . $langs->transnoentitiesnoconv('ECommerceWoocommerceCreateRemoteProduct', $this->site->name, $fault->getCode() . ': ' . $fault->getMessage()) .
+ ' - Request:' . json_encode($fault->getRequest()) . ' - Response:' . json_encode($fault->getResponse()), LOG_ERR);
return false;
}
+
+ // Create remote link
+ $eCommerceProduct = new eCommerceProduct($this->db);
+ $eCommerceProduct->fk_product = $object->id;
+ $eCommerceProduct->fk_site = $this->site->id;
+ $eCommerceProduct->remote_id = $res['id'];
+ $res = $eCommerceProduct->create($user);
+ if ($res < 0) {
+ $this->errors[] = $langs->trans('ECommerceWoocommerceCreateRemoteProductLink', $object->id, $this->site->name, $eCommerceProduct->error);
+ dol_syslog(__METHOD__ . ': Error:' . $langs->transnoentitiesnoconv('ECommerceWoocommerceCreateRemoteProductLink', $object->id, $this->site->name, $eCommerceProduct->error), LOG_ERR);
+ return false;
+ }
+
+ dol_syslog(__METHOD__ . ": end", LOG_DEBUG);
+ return true;
}
/**
- * Update the remote stock of product
+ * Send a file for remote order
*
- * @param int $remote_id Id of product on remote ecommerce
- * @param Movement $object Movement object, enhanced with property qty_after be the trigger STOCK_MOVEMENT.
- * @return boolean True or false
+ * @param int $order_remote_id Id of order on remote ecommerce
+ * @param int $company_remote_id Id of company on remote ecommerce
+ * @param Object $object Object (invoice or shipping)
+ * @param string $file File path
+ * @param Translate $outputlangs Lang output object
+ *
+ * @return bool
*/
- public function updateRemoteStockProduct($remote_id, $object)
+ public function sendFileForCommande($order_remote_id, $company_remote_id, $object, $file, $outputlangs)
{
- dol_syslog("eCommerceRemoteAccessWoocommerce updateRemoteStockProduct session=".$this->session." product remote_id=".$remote_id." movement object->id=".$object->id.", new qty=".$object->qty_after);
+ dol_syslog(__METHOD__ . ": Send file '$file' for remote order ID $order_remote_id for site ID {$this->site->id}", LOG_DEBUG);
+ global $langs;
+
+ // Send file to WordPress
+ $result = $this->worpressclient->postmedia("media", $file, [
+ 'slug' => $order_remote_id . '_' . $object->element,
+ 'author' => $company_remote_id,
+ 'post' => $order_remote_id,
+ 'ping_status' => 'closed',
+ 'comment_status' => 'closed',
+ ]);
+ if ($result === null) {
+ $this->errors[] = $langs->trans('ECommerceWoocommerceSendFileForCommandeInWordpress', $order_remote_id, $this->site->name, implode('; ', $this->worpressclient->errors));
+ dol_syslog(__METHOD__ . ': Error:' . $langs->transnoentitiesnoconv('ECommerceWoocommerceSendFileForCommandeInWordpress', $order_remote_id, $this->site->name, implode('; ', $this->worpressclient->errors)), LOG_ERR);
+ return false;
+ }
- // $object->qty is the qty of movement
+ // Set meta data in remote commande
+ $commandeData = [
+ 'meta_data' => [
+ [
+ 'key' => 'file_for_' . $object->element,
+ 'value' => [
+ 'id' => $result['id'],
+ 'link' => $result['link'],
+ 'source_url' => $result['source_url'],
+ ],
+ ],
+ ]
+ ];
try {
- if (preg_match('/^(\d+)\|(\d+)$/', $remote_id, $idsProduct) == 1) {
- // Variations
- $variationData = array(
- //'manage_stock' => '', // boolean Stock management at variation level. Default is false.
- 'stock_quantity' => $object->qty_after, // integer Stock quantity.
- 'in_stock' => $object->qty_after > 0, // boolean Controls whether or not the variation is listed as “in stock” or “out of stock” on the frontend. Default is true.
- //'backorders' => '', // string If managing stock, this controls if backorders are allowed. Options: no, notify and yes. Default is no.
- );
+ $result = $this->client->put("orders/$order_remote_id", $commandeData);
+ } catch (HttpClientException $fault) {
+ $this->errors[] = $langs->trans('ECommerceWoocommerceSendFileForCommande', $this->site->name, $fault->getCode() . ': ' . $fault->getMessage());
+ dol_syslog(__METHOD__ .
+ ': Error:' . $langs->transnoentitiesnoconv('ECommerceWoocommerceSendFileForCommande', $this->site->name, $fault->getCode() . ': ' . $fault->getMessage()) .
+ ' - Request:' . json_encode($fault->getRequest()) . ' - Response:' . json_encode($fault->getResponse()), LOG_ERR);
+ return false;
+ }
- // Product
- // 'name' => $object->label, // string Product name.
- // 'status' => $object->status ? 'publish' : 'pending', // string Product status (post status). Options: draft, pending, private and publish. Default is publish.
+ dol_syslog(__METHOD__ . ": end", LOG_DEBUG);
+ return true;
+ }
- $result = $this->client->put("products/$idsProduct[1]/variations/$idsProduct[2]", $variationData);
- } else {
- $productData = array(
- //'manage_stock' => false, // boolean Stock management at product level. Default is false.
- 'stock_quantity' => $object->qty_after, // integer Stock quantity.
- 'in_stock' => $object->qty_after > 0, // boolean Controls whether or not the product is listed as “in stock” or “out of stock” on the frontend. Default is true.
- //'backorders' => '', // string If managing stock, this controls if backorders are allowed. Options: no, notify and yes. Default is no.
- );
+ /**
+ * Get tax rate from tax class name
+ *
+ * @param string $tax_class Tax class name
+ * @param string $tax_status Tax status
+ *
+ * @return float Tax rate
+ */
+ private function getTaxRate($tax_class, $tax_status = 'taxable')
+ {
+ //dol_syslog(__METHOD__ . ": Get tax rate, tax_classe: $tax_class, tax_status: $tax_status", LOG_DEBUG);
+ global $conf, $mysoc;
- $result = $this->client->put("products/$remote_id", $productData);
+ $tax_rate = 0;
+
+ // $tax_status => Tax status. Options: taxable, shipping and none. Default is taxable
+ if ($tax_status != 'none') {
+ $tax_class = !empty($tax_class) ? $tax_class : 'standard';
+ $tax_rate = '';
+
+ // Retrieve all woocommerce tax classes
+ if (!isset($this->woocommerceTaxes) || !isset($this->woocommerceTaxes['classes'][$tax_class])) {
+ $this->setWoocommerceTaxes();
}
- dol_syslog("eCommerceRemoteAccessWoocommerce updateRemoteStockProduct end");
- return true;
- } catch (HttpClientException $fault) {
- $this->errors[]=$fault->getMessage().'-'.$fault->getCode();
- dol_syslog(__METHOD__.': '.$fault->getMessage().'-'.$fault->getCode().'-'.$fault->getTraceAsString(), LOG_WARNING);
- return false;
+ // Get woocommerce tax if one only
+ if (isset($this->woocommerceTaxes['classes'][$tax_class]) && count($this->woocommerceTaxes['classes'][$tax_class]) == 1) {
+ $tax_rate = $this->woocommerceTaxes['classes'][$tax_class];
+ $tax_rate = array_values($tax_rate);
+ $tax_rate = doubleval($tax_rate[0]['rate']);
+
+ // Get near dolibarr tax for woocommerce tax rate
+ $tax = $this->_getClosestDolibarrTaxRate($tax_rate);
+ if (isset($tax)) {
+ $tax_rate = $tax;
+ }
+ }
+
+ if ($tax_rate == '') {
+ $tax_rate = $conf->global->ECOMMERCE_WOOCOMMERCE_DEFAULT_TVA;
+ }
}
+
+ //dol_syslog(__METHOD__ . ": end, return $tax_rate", LOG_DEBUG);
+ return $tax_rate;
}
/**
- * Update the remote societe
+ * Get tax class for show in extrafields
*
- * @param int $remote_id Id of societe on remote ecommerce
- * @param Societe $object Societe object
- * @return boolean True or false
+ * @param string $tax_class Tax class name
+ * @param string $tax_status Tax status
+ *
+ * @return string Tax class name
*/
- public function updateRemoteSociete($remote_id, $object)
+ private function getTaxClass($tax_class, $tax_status = 'taxable')
{
- dol_syslog("eCommerceRemoteAccessWoocommerce updateRemoteSociete session=".$this->session." remote_id=".$remote_id." object->id=".$object->id);
-/*
- // Customer - Meta data properties
- $meta_data = [
- 'key' => '', // string Meta key.
- 'value' => '', // string Meta value.
- ];
-*/
- try {
- $societeData = array(
- 'email' => $object->email, // string The email address for the customer. MANDATORY
- //'first_name' => '', // string Customer first name.
- //'last_name' => $object->name, // string Customer last name.
- //'username' => '', // string Customer login name.
- //'password' => '', // string Customer password.
- //'meta_data' => $meta_data, // array Meta data. See Customer - Meta data properties
- );
-
- $result = $this->client->put("customers/$remote_id", $societeData);
+ //dol_syslog(__METHOD__ . ": Get tax class name, tax_class: $tax_class, tax_status: $tax_status", LOG_DEBUG);
- dol_syslog("eCommerceRemoteAccessWoocommerce updateRemoteSociete end");
- return true;
- } catch (HttpClientException $fault) {
- $this->errors[]=$fault->getMessage().'-'.$fault->getCode();
- dol_syslog(__METHOD__.': '.$fault->getMessage().'-'.$fault->getCode().'-'.$fault->getTraceAsString(), LOG_WARNING);
- return false;
+ // $tax_status => Tax status. Options: taxable, shipping and none. Default is taxable
+ if ($tax_status != 'none') {
+ $tax_class = !empty($tax_class) ? $tax_class : 'standard';
+ } else {
+ $tax_class = '';
}
+
+ //dol_syslog(__METHOD__ . ": end, return $tax_class", LOG_DEBUG);
+ return $tax_class;
}
/**
- * Update the remote contact
+ * Calcul tax rate and return the closest dolibarr tax rate.
*
- * @param int $remote_id Id of contact on remote ecommerce
- * @param Contact $object Contact object
- * @return boolean True or false
+ * @param float $priceHT Price HT
+ * @param float $taxAmount Tax amount
+ *
+ * @return float Tax rate
*/
- public function updateRemoteSocpeople($remote_id, $object)
+ private function getClosestDolibarrTaxRate($priceHT, $taxAmount)
{
- global $conf;
+ //dol_syslog(__METHOD__ . ": Get closest dolibarr tax rate, priceHT: $priceHT, priceHT: $taxAmount", LOG_DEBUG);
+ $tax_rate = 0;
+ if ($taxAmount != 0) {
+ //calcul tax rate from remote site
+ $shipping_tax_rate = ($taxAmount / $priceHT) * 100;
- dol_syslog("eCommerceRemoteAccessWoocommerce updateRemoteSocpeople session=".$this->session." remote_id=".$remote_id." object->id=".$object->id);
+ // Get near dolibarr tax for woocommerce tax rate
+ $tax = $this->_getClosestDolibarrTaxRate($shipping_tax_rate);
+ if (isset($tax)) {
+ $tax_rate = $tax;
+ }
+ }
- // Get societe
- require_once DOL_DOCUMENT_ROOT . '/societe/class/societe.class.php';
- $societe = new Societe($this->db);
- $societe->fetch($object->socid);
+ //dol_syslog(__METHOD__ . ": end, return $tax_rate", LOG_DEBUG);
+ return $tax_rate;
+ }
- $billingName = (empty($conf->global->ECOMMERCENG_BILLING_CONTACT_NAME)?'Billing':$conf->global->ECOMMERCENG_BILLING_CONTACT_NAME); // Contact name treated as billing address.
- $shippingName = (empty($conf->global->ECOMMERCENG_SHIPPING_CONTACT_NAME)?'Shipping':$conf->global->ECOMMERCENG_SHIPPING_CONTACT_NAME); // Contact name treated as shipping address.
+ /**
+ * Retrieve all Dolibarr tax rates
+ *
+ * @return void
+ */
+ private function setDolibarrTaxes()
+ {
+ //dol_syslog(__METHOD__ . ": Retrieve all Dolibarr tax rates", LOG_DEBUG);
- try {
- if ($object->lastname == $billingName) {
- $address = explode("\n", $object->address);
- // Billing
- $contactData = [
- 'billing' => [
- //'first_name' => '', // string First name.
- //'last_name' => '', // string Last name.
- //'company' => $societe->name, // string Company name.
- 'address_1' => isset($address[0])?$address[0]:'', // string Address line 1
- 'address_2' => isset($address[1])?implode(" ", array_slice($address, 1)):'', // string Address line 2
- 'city' => $object->town, // string City name.
- //'state' => '', // string ISO code or name of the state, province or district.
- 'postcode' => $object->zip, // string Postal code.
- 'country' => getCountry($object->country_id, 2), // string ISO code of the country.
- 'email' => $object->email, // string Email address.
- 'phone' => $object->phone_pro, // string Phone number.
- ],
- ];
- } elseif ($object->lastname == $shippingName) {
- $address = explode("\n", $object->address);
- // Shipping
- $contactData = [
- 'shipping' => [
- //'first_name' => '', // string First name.
- //'last_name' => '', // string Last name.
- //'company' => $societe->name, // string Company name.
- 'address_1' => isset($address[0])?$address[0]:'', // string Address line 1
- 'address_2' => isset($address[1])?implode(" ", array_slice($address, 1)):'', // string Address line 2
- 'city' => $object->town, // string City name.
- //'state' => '', // string ISO code or name of the state, province or district.
- 'postcode' => $object->zip, // string Postal code.
- 'country' => getCountry($object->country_id, 2), // string ISO code of the country.
- ],
- ];
- }
+ $resql = $this->db->query("SELECT DISTINCT taux FROM ".MAIN_DB_PREFIX."c_tva ORDER BY taux DESC");
+ if ($resql) {
+ $taxesTable = [];
- if (isset($contactData)) {
- if (preg_match('/^(\d+)\|(\d+)$/', $remote_id, $idsCustomer) == 1) {
- $result = $this->client->put("customers/$idsCustomer[1]", $contactData);
- }
+ while ($tax = $this->db->fetch_object($resql)) {
+ $taxesTable[] = $tax->taux;
}
- dol_syslog("eCommerceRemoteAccessWoocommerce updateRemoteSocpeople end");
- return true;
- } catch (HttpClientException $fault) {
- $this->errors[]=$fault->getMessage().'-'.$fault->getCode();
- dol_syslog(__METHOD__.': '.$fault->getMessage().'-'.$fault->getCode().'-'.$fault->getTraceAsString(), LOG_WARNING);
- return false;
+ $this->dolibarrTaxes = $taxesTable;
}
+
+ //dol_syslog(__METHOD__ . ": end", LOG_DEBUG);
}
/**
- * Update the remote order
+ * Retrieve all Dolibarr tax rates
*
- * @param int $remote_id Id of order on remote ecommerce
- * @param Commande $object Commande object
- * @return boolean True or false
+ * @return void
*/
- public function updateRemoteCommande($remote_id, $object)
+ /* private function setDolibarrTaxes()
{
- dol_syslog("eCommerceRemoteAccessWoocommerce updateRemoteCommande session=".$this->session." remote_id=".$remote_id." object->id=".$object->id);
+ dol_syslog(__METHOD__ . ": Retrieve all Dolibarr tax rates", LOG_DEBUG);
- try {
- switch ($object->statut) {
- //case Commande::STOCK_NOT_ENOUGH_FOR_ORDER: $status = ''; break;
- case Commande::STATUS_CANCELED: $status = 'cancelled'; break;
- //case Commande::STATUS_DRAFT: $status = ''; break;
- case Commande::STATUS_VALIDATED: $status = 'pending'; break;
- case Commande::STATUS_ACCEPTED: $status = 'processing'; break;
- case Commande::STATUS_SHIPMENTONPROCESS: $status = 'processing'; break;
- case Commande::STATUS_CLOSED: $status = 'completed'; break;
+ $resql = $this->db->query("SELECT t.*, c.code AS country FROM ".MAIN_DB_PREFIX."c_tva AS t LEFT JOIN ".MAIN_DB_PREFIX."c_country AS c ON t.fk_pays = c.rowid");
+ if ($resql) {
+ $taxesTable = [ 'taxes' => [], 'countries' => [] ];
+
+ while ($tax = $this->db->fetch_array($resql)) {
+ $taxesTable['taxes'][] = $tax;
+ if (!empty($tax['country'])) {
+ $taxesTable['countries'][$tax['country']][] = $tax;
+ }
}
- if (isset($status)) {
- $commandeData = array(
- 'status' => $status, // string Order status. Options: pending, processing, on-hold, completed, cancelled, refunded and failed.
- );
+ $this->dolibarrTaxes = $taxesTable;
+ }
- $result = $this->client->put("orders/$remote_id", $commandeData);
- }
+ dol_syslog(__METHOD__ . ": end", LOG_DEBUG);
+ }*/
- dol_syslog("eCommerceRemoteAccessWoocommerce updateRemoteCommande end");
+ /**
+ * Update all Woocommerce tax classes in dict
+ *
+ * @return array|false List of woocommerce tax class or false if error
+ */
+ public function getAllWoocommerceTaxClass()
+ {
+ dol_syslog(__METHOD__ . ": Retrieve all Woocommerce tax classes", LOG_DEBUG);
+ global $langs;
- return true;
+ try {
+ $tax_classes = $this->client->get('taxes/classes');
} catch (HttpClientException $fault) {
- $this->errors[]=$fault->getMessage().'-'.$fault->getCode();
- dol_syslog(__METHOD__.': '.$fault->getMessage().'-'.$fault->getCode().'-'.$fault->getTraceAsString(), LOG_WARNING);
+ $this->errors[] = $langs->trans('ECommerceWoocommerceGetAllWoocommerceTaxClass', $this->site->name, $fault->getCode() . ': ' . $fault->getMessage());
+ dol_syslog(__METHOD__ .
+ ': Error:' . $langs->transnoentitiesnoconv('ECommerceWoocommerceGetAllWoocommerceTaxClass', $this->site->name, $fault->getCode() . ': ' . $fault->getMessage()) .
+ ' - Request:' . json_encode($fault->getRequest()) . ' - Response:' . json_encode($fault->getResponse()), LOG_ERR);
return false;
}
+
+ $taxClassesTable = [];
+ foreach ($tax_classes as $tax_class) {
+ unset($tax_class['_links']);
+ $taxClassesTable[$tax_class['slug']] = $tax_class;
+ }
+
+ dol_syslog(__METHOD__ . ": end, return: ".json_encode($taxClassesTable), LOG_DEBUG);
+ return $taxClassesTable;
}
/**
- * Update the remote invoice
+ * Retrieve all Woocommerce tax rates
*
- * @param int $remote_id Id of invoice on remote ecommerce
- * @param Facture $object Invoice object
- * @return boolean True or false
+ * @return boolean
*/
- public function updateRemoteFacture($remote_id, $object)
+ private function setWoocommerceTaxes()
{
- dol_syslog("eCommerceRemoteAccessWoocommerce updateRemoteFacture session=".$this->session." remote_id=".$remote_id." object->id=".$object->id);
+ dol_syslog(__METHOD__ . ": Retrieve all Woocommerce tax rates", LOG_DEBUG);
+ global $conf, $langs;
- $result = false;
- /*
- try {
- $factureData = array(
- 'status' => $object->status,
- );
+ $nb_max_by_request = empty($conf->global->ECOMMERCENG_MAXSIZE_MULTICALL) ? 100 : min($conf->global->ECOMMERCENG_MAXSIZE_MULTICALL, 100);
- $result = $this->client->call($this->session, 'invoice.update', array($remote_id, $factureData, null, 'order_id'));
- //dol_syslog($this->client->__getLastRequest());
- } catch (SoapFault $fault) {
- $this->errors[]=$fault->getMessage().'-'.$fault->getCode();
- dol_syslog(__METHOD__.': '.$fault->getMessage().'-'.$fault->getCode().'-'.$fault->getTraceAsString(), LOG_WARNING);
- return false;
- }*/
- dol_syslog("eCommerceRemoteAccessWoocommerce updateRemoteFacture end");
- return $result;
+ $taxesTable = [ 'taxes' => [], 'classes' => [], 'countries' => [], 'states' => [], 'postcodes' => [], 'cities' => []];
+ $idxPage = 0;
+ do {
+ $idxPage++;
+ try {
+ $taxes = $this->client->get('taxes',
+ [
+ 'page' => $idxPage,
+ 'per_page' => $nb_max_by_request,
+ ]
+ );
+ } catch (HttpClientException $fault) {
+ $this->errors[] = $langs->trans('ECommerceWoocommerceGetWoocommerceTaxes', $this->site->name, $fault->getCode() . ': ' . $fault->getMessage());
+ dol_syslog(__METHOD__ .
+ ': Error:' . $langs->transnoentitiesnoconv('ECommerceWoocommerceGetWoocommerceTaxes', $this->site->name, $fault->getCode() . ': ' . $fault->getMessage()) .
+ ' - Request:' . json_encode($fault->getRequest()) . ' - Response:' . json_encode($fault->getResponse()), LOG_ERR);
+ return false;
+ }
+
+ foreach ($taxes as $tax) {
+ $id = $tax['id'];
+ unset($tax['_links']);
+
+ $taxesTable['taxes'][$id] = $tax;
+ if (!empty($tax['class'])) {
+ $taxesTable['classes'][$tax['class']][$id] = $tax;
+ }
+ if (!empty($tax['country'])) {
+ $taxesTable['countries'][$tax['country']][$id] = $tax;
+ }
+ if (!empty($tax['state'])) {
+ $taxesTable['states'][$tax['state']][$id] = $tax;
+ }
+ if (!empty($tax['postcode'])) {
+ $taxesTable['postcodes'][$tax['postcode']][$id] = $tax;
+ }
+ if (!empty($tax['city'])) {
+ $taxesTable['cities'][$tax['city']][$id] = $tax;
+ }
+ }
+ } while (!empty($taxes));
+
+ $this->woocommerceTaxes = $taxesTable;
+
+ dol_syslog(__METHOD__ . ": end", LOG_DEBUG);
+ return true;
}
/**
- * Create shipment
+ * Get closest dolibarr tax rate
*
- * @param int $livraison Object shipment ?
- * @param int $remote_order_id Id of order
- * @return boolean True or false
+ * @param string $tax_rate Tax rate
+ *
+ * @return float Closest dolibarr tax rate
*/
- public function createRemoteLivraison($livraison, $remote_order_id)
+ private function _getClosestDolibarrTaxRate($tax_rate)
{
- $result = false;
+ //dol_syslog(__METHOD__ . ": Get closest dolibarr tax rate, tax_rate: $tax_rate", LOG_DEBUG);
- dol_syslog("eCommerceRemoteAccessWoocommerce createRemoteLivraison session=" . $this->session . " dolibarr shipment id = " . $livraison->id . ", ref = " . $livraison->ref . ", order remote id = " . $remote_order_id);
-/* $remoteCommande = $this->getRemoteCommande($remote_order_id); // SOAP request to get data
- $livraisonArray = get_object_vars($livraison);
- try {
- $orderItemQty = array();
- foreach ($remoteCommande['items'] as $productWoocommerce) {
- foreach ($livraisonArray['lines'] as $lines) {
- if ($lines->product_ref == $productWoocommerce['sku']) {
- $orderItemQty[$productWoocommerce['item_id']] = $lines->qty_shipped;
- }
+ $tax = null;
+
+ // Retrieve all dolibarr tax
+ if (!isset($this->dolibarrTaxes)) {
+ $this->setDolibarrTaxes();
+ }
+
+ // Get closest dolibarr tax for woocommerce tax
+ if (is_array($this->dolibarrTaxes) && count($this->dolibarrTaxes) > 0) {
+ $closestTax = 0;
+ foreach ($this->dolibarrTaxes as $tax) {
+ if (abs($tax - $tax_rate) < abs($tax_rate - $closestTax)) {
+ $closestTax = $tax;
}
}
- $result = $this->client->call($this->session, 'sales_order_shipment.create', array(
- $remoteCommande['increment_id'],
- $orderItemQty,
- 'Shipment Created from ' . ($livraison->newref ? $livraison->newref : $livraison->ref),
- true,
- true
- ));
- //dol_syslog($this->client->__getLastResponse());
- } catch (SoapFault $fault) {
- $this->errors[] = $this->site->name . ': ' . $fault->getMessage() . ' - ' . $fault->getCode();
- dol_syslog(__METHOD__ . ': ' . $fault->getMessage() . '-' . $fault->getCode() . '-' . $fault->getTraceAsString(), LOG_WARNING);
- return false;
- }*/
- dol_syslog("eCommerceRemoteAccessWoocommerce createRemoteLivraison end");
- return $result;
+ $tax = $closestTax;
+ }
+
+ //dol_syslog(__METHOD__ . ": end, return ".(isset($tax)?json_encode($tax):'null'), LOG_DEBUG);
+ return $tax;
}
+ /**
+ * Get closest dolibarr tax
+ *
+ * @param string $country_code Country code
+ * @param string $tax_rate Tax rate
+ *
+ * @return float Near dolibarr tax
+ */
+ /*private function getClosestDolibarCountryTax($country_code, $tax_rate)
+ {
+ dol_syslog(__METHOD__ . ": Get closest dolibarr tax rate, country_code: $country_code, tax_rate: $tax_rate", LOG_DEBUG);
+ global $langs;
+
+ $tax = null;
+ // Get country code from default language if empty
+ if (empty($country_code)) $country_code = substr($langs->defaultlang, -2);
+
+ // Retrieve all dolibarr tax
+ if (!isset($this->dolibarrTaxes) || !isset($this->dolibarrTaxes['countries'][$country_code])) {
+ $this->setDolibarrTaxes();
+ }
+
+ // Get closest dolibarr tax for woocommerce tax
+ $dolibarrTaxes = $this->dolibarrTaxes['countries'][$country_code];
+ if (is_array($dolibarrTaxes)) {
+ $closestTaxes = [];
+ foreach ($dolibarrTaxes as $tax) {
+ $near = $tax['taux'] - $tax_rate;
+ if (!isset($closestTaxes[$near]) || $closestTaxes[$near]['taux'] < $tax['taux']) {
+ $nearTaxes[$near] = $tax;
+ }
+ }
+ ksort($closestTaxes);
+ reset($closestTaxes);
+ $tax = $closestTaxes[0];
+ }
+ dol_syslog(__METHOD__ . ": end, return ".(isset($tax)?json_encode($tax):'null'), LOG_DEBUG);
+ return $tax;
+ }*/
/**
- * Calcul tax rate and return the closest dolibarr tax rate.
+ * Get request groups of ID for get datas of remotes objects.
*
- * @param float $priceHT Price HT
- * @param float $taxAmount Tax amount
+ * @param array $remoteObject List of ids of remote objects
+ * @param int $nb_max_by_request Nb remote ID by request
+ * @param int $toNb Max nb
+ * @return array List of request groups of ID
*/
- private function getTaxRate($priceHT, $taxAmount)
+ private function getRequestGroups($remoteObject, $nb_max_by_request, $toNb=0)
{
- $taxRate = 0;
- if ($taxAmount != 0)
- {
- //calcul tax rate from remote site
- $tempTaxRate = ($taxAmount / $priceHT) * 100;
- //get all dolibarr tax rates
- if (!isset($this->taxRates))
- $this->setTaxRates();
- if (count($this->taxRates))
- {
- $min = 1;
- $rate = 0;
- foreach ($this->taxRates as $dolibarrTaxRate)
- {
- $diff = $tempTaxRate - $dolibarrTaxRate['taux'];
- if ($diff < 0)
- $diff = (-1 * $diff);
- if ($diff < $min)
- {
- $min = $diff;
- $rate = $dolibarrTaxRate['taux'];
- }
- }
- if ($rate > 0)
- $taxRate = $rate;
+ //dol_syslog(__METHOD__ . ": Get request groups of ID: " . implode(', ', $remoteObject), LOG_DEBUG);
+
+ $idx = 0;
+ $request = [];
+ $request_groups = [];
+
+ foreach ($remoteObject as $remote_object_id) {
+ if ($toNb > 0 && $idx > $toNb) break;
+
+ if (($idx++ % $nb_max_by_request) == 0) {
+ if (count($request)) $request_groups[] = $request;
+ $request = [];
}
+
+ $request[] = $remote_object_id;
}
- return $taxRate;
+ if (count($request)) $request_groups[] = $request;
+
+ //dol_syslog(__METHOD__ . ": end", LOG_DEBUG);
+ return $request_groups;
}
/**
- * Retrieve all Dolibarr tax rates
+ * Get DateTime object in current timezone from gmt date time.
+ *
+ * @param string $datetime GMT date time
+ *
+ * @return DateTime DateTime in current Time Zone
*/
- private function setTaxRates()
+ private function getDateTimeFromGMTDateTime($datetime)
{
- $taxTable = new eCommerceDict($this->db, MAIN_DB_PREFIX . "c_tva");
- $this->taxRates = $taxTable->getAll();
+ //dol_syslog(__METHOD__ . ": Get DateTime object in current timezone from gmt date time: $datetime", LOG_DEBUG);
+
+ $dt = new DateTime($datetime, $this->gmtTimeZone);
+ $dt->setTimezone($this->currentTimeZone);
+
+ //dol_syslog(__METHOD__ . ": end", LOG_DEBUG);
+ return $dt;
}
public function __destruct()
{
- //ini_set("memory_limit", "528M");
+ ini_set("memory_limit", "528M");
}
-
}
-
diff --git a/htdocs/ecommerceng/core/modules/modECommerceNg.class.php b/htdocs/ecommerceng/core/modules/modECommerceNg.class.php
index 9982f98..1da64e0 100644
--- a/htdocs/ecommerceng/core/modules/modECommerceNg.class.php
+++ b/htdocs/ecommerceng/core/modules/modECommerceNg.class.php
@@ -19,10 +19,12 @@
require_once(DOL_DOCUMENT_ROOT.'/core/modules/DolibarrModules.class.php');
+require_once(DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php');
require_once(DOL_DOCUMENT_ROOT.'/societe/class/societe.class.php');
dol_include_once('/ecommerceng/admin/class/gui/eCommerceMenu.class.php');
dol_include_once('/ecommerceng/admin/class/data/eCommerceDict.class.php');
+dol_include_once('/ecommerceng/class/data/eCommerceSite.class.php');
/**
@@ -55,11 +57,11 @@ function __construct($db)
// Module description, used if translation string 'ModuleXXXDesc' not found (where XXX is value of numeric property 'numero' of module)
$this->description = "Module to synchronise Dolibarr with ECommerce platform (currently ecommerce supported: Magento, WooCommerce)";
$this->descriptionlong = "See page https://wiki.dolibarr.org/index.php/Module_Magento_EN for more information";
- $this->editor_name = 'TecLib';
+ $this->editor_name = 'TecLib, Open-Dsi';
$this->editor_url = 'http://www.teclib.com';
// Possible values for version are: 'development', 'experimental', 'dolibarr' or version
- $this->version = '4.0.0';
+ $this->version = '4.0.3';
// Key used in llx_const table to save module status enabled/disabled (where MYMODULE is value of property name of module in uppercase)
$this->const_name = 'MAIN_MODULE_'.strtoupper($this->name);
// Where to store the module in setup page (0=common,1=interface,2=others,3=very specific)
@@ -85,8 +87,9 @@ function __construct($db)
// 'workflow' => array('order' => array('WORKFLOW_ORDER_AUTOCREATE_INVOICE')) // Set here all workflow context managed by module
// );
$this->module_parts = array(
- 'triggers' => 1
- );
+ 'triggers' => 1,
+ 'hooks' => array('expeditioncard','invoicecard','productdocuments'),
+ );
// Data directories to create when module is enabled.
// Example: this->dirs = array("/mymodule/temp");
@@ -102,9 +105,9 @@ function __construct($db)
// Dependencies
$this->depends = array("modSociete","modProduct","modCategorie","modWebServices"); // List of modules id that must be enabled if this module is enabled
$this->requiredby = array(); // List of modules id to disable if this one is disabled
- $this->phpmin = array(4,3); // Minimum version of PHP required by module
+ $this->phpmin = array(5,3); // Minimum version of PHP required by module
$this->need_dolibarr_version = array(3,9); // Minimum version of Dolibarr required by module
- $this->langfiles = array("ecommerce@ecommerceng");
+ $this->langfiles = array("ecommerce@ecommerceng", "woocommerce@ecommerceng");
// Constants
// List of particular constants to add when module is enabled
@@ -130,6 +133,42 @@ function __construct($db)
// 'member' to add a tab in fundation member view
// 'contract' to add a tab in contract view
+ if (! isset($conf->ecommerceng) || ! isset($conf->ecommerceng->enabled))
+ {
+ $conf->ecommerceng=new stdClass();
+ $conf->ecommerceng->enabled=0;
+ }
+
+ $eCommerceSite = new eCommerceSite($this->db);
+
+ // Dictionaries
+ $this->dictionaries=array(
+ 'langs'=>'woocommerce@ecommerceng',
+ 'tabname'=>array(MAIN_DB_PREFIX."c_ecommerceng_tax_class"),
+ 'tablib'=>array("ECommercengWoocommerceDictTaxClass"),
+ 'tabsql'=>array('SELECT f.rowid as rowid, f.site_id, f.code, f.label, f.entity, f.active FROM '.MAIN_DB_PREFIX.'c_ecommerceng_tax_class as f WHERE f.entity='.$conf->entity),
+ 'tabsqlsort'=>array("site_id ASC, label ASC"),
+ 'tabfield'=>array("code,label,site_id"),
+ 'tabfieldvalue'=>array("code,label,site_id"),
+ 'tabfieldinsert'=>array("code,label,site_id"),
+ 'tabrowid'=>array("rowid"),
+ 'tabcond'=>array($conf->ecommerceng->enabled && $eCommerceSite->hasTypeSite(2))
+ );
+
+ /* Example:
+ $this->dictionaries=array(
+ 'langs'=>'mylangfile@mymodule',
+ 'tabname'=>array(MAIN_DB_PREFIX."table1",MAIN_DB_PREFIX."table2",MAIN_DB_PREFIX."table3"), // List of tables we want to see into dictonnary editor
+ 'tablib'=>array("Table1","Table2","Table3"), // Label of tables
+ 'tabsql'=>array('SELECT f.rowid as rowid, f.code, f.label, f.active FROM '.MAIN_DB_PREFIX.'table1 as f','SELECT f.rowid as rowid, f.code, f.label, f.active FROM '.MAIN_DB_PREFIX.'table2 as f','SELECT f.rowid as rowid, f.code, f.label, f.active FROM '.MAIN_DB_PREFIX.'table3 as f'), // Request to select fields
+ 'tabsqlsort'=>array("label ASC","label ASC","label ASC"), // Sort order
+ 'tabfield'=>array("code,label","code,label","code,label"), // List of fields (result of select to show dictionary)
+ 'tabfieldvalue'=>array("code,label","code,label","code,label"), // List of fields (list of fields to edit a record)
+ 'tabfieldinsert'=>array("code,label","code,label","code,label"), // List of fields (list of fields for insert)
+ 'tabrowid'=>array("rowid","rowid","rowid"), // Name of columns with primary key (try to always name it 'rowid')
+ 'tabcond'=>array($conf->mymodule->enabled,$conf->mymodule->enabled,$conf->mymodule->enabled) // Condition to show each dictionary
+ );
+ */
// Boxes
$this->boxes = array(); // List of boxes
@@ -226,6 +265,7 @@ function init($options = '')
$result=$this->load_tables($options);
$this->addSettlementTerms();
$this->addAnonymousCompany();
+ $this->addFiles();
return $this->_init($sql, $options);
}
@@ -338,5 +378,18 @@ private function AddSettlementTerms()
}
}
}
+
+ /**
+ * Add files need for dolibarr
+ */
+ private function addFiles()
+ {
+ $srcFile = dol_buildpath('/ecommerceng/patchs/dolibarr/includes/OAuth/OAuth2/Service/WordPress.php');
+ $destFile = DOL_DOCUMENT_ROOT . '/includes/OAuth/OAuth2/Service/WordPress.php';
+
+ if (dol_copy($srcFile, $destFile) < 0) {
+ setEventMessages("Error copy file '$srcFile' to '$destFile'", null, 'errors');
+ }
+ }
}
diff --git a/htdocs/ecommerceng/core/modules/oauth/wordpress_oauthcallback.php b/htdocs/ecommerceng/core/modules/oauth/wordpress_oauthcallback.php
new file mode 100644
index 0000000..3e1fcbb
--- /dev/null
+++ b/htdocs/ecommerceng/core/modules/oauth/wordpress_oauthcallback.php
@@ -0,0 +1,194 @@
+
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+/**
+ * \file htdocs/core/modules/oauth/wordpress_oauthcallback.php
+ * \ingroup oauth
+ * \brief Page to get oauth callback
+ */
+
+$res=0;
+if (! $res && ! empty($_SERVER["CONTEXT_DOCUMENT_ROOT"])) $res=@include($_SERVER["CONTEXT_DOCUMENT_ROOT"]."/main.inc.php");
+if (! $res && file_exists("../main.inc.php")) $res=@include("../main.inc.php");
+if (! $res && file_exists("../../main.inc.php")) $res=@include("../../main.inc.php");
+if (! $res && file_exists("../../../main.inc.php")) $res=@include("../../../main.inc.php");
+if (! $res && file_exists("../../../../main.inc.php")) $res=@include("../../../../main.inc.php");
+if (! $res && file_exists("../../../../../main.inc.php")) $res=@include("../../../../../main.inc.php");
+if (! $res && preg_match('/\/nltechno([^\/]*)\//',$_SERVER["PHP_SELF"],$reg)) $res=@include("../../../dolibarr".$reg[1]."/htdocs/main.inc.php"); // Used on dev env only
+if (! $res && preg_match('/\/teclib([^\/]*)\//',$_SERVER["PHP_SELF"],$reg)) $res=@include("../../../dolibarr".$reg[1]."/htdocs/main.inc.php"); // Used on dev env only
+if (! $res) die("Include of main fails");
+require_once DOL_DOCUMENT_ROOT.'/includes/OAuth/bootstrap.php';
+dol_include_once('/ecommerceng/includes/CurlClientEx.php');
+dol_include_once('/ecommerceng/class/data/eCommerceSite.class.php');
+use OAuth\Common\Storage\DoliStorage;
+use OAuth\Common\Consumer\Credentials;
+use OAuth\Common\Http\Uri\Uri;
+use OAuth\Common\Http\Client\CurlClient;
+use OAuth\OAuth2\Service\WordPress;
+
+// Define $urlwithroot
+$urlwithouturlroot=preg_replace('/'.preg_quote(DOL_URL_ROOT,'/').'$/i','',trim($dolibarr_main_url_root));
+$urlwithroot=$urlwithouturlroot.DOL_URL_ROOT; // This is to use external domain name found into config file
+//$urlwithroot=DOL_MAIN_URL_ROOT; // This is to use same domain name than current
+
+
+
+$action = GETPOST('action', 'alpha');
+$backtourl = GETPOST('backtourl', 'alpha');
+$siteId = GETPOST('ecommerce_id', 'int');
+
+//LOAD SELECTED SITE
+$siteDb = new eCommerceSite($db);
+$res = $siteDb->fetch($siteId);
+if ($res < 0) {
+ setEventMessage("Error: site ecommerce not found", 'errors');
+ header('Location: ' . $backtourl);
+ exit();
+}
+
+/**
+ * Create a new instance of the URI class with the current URI, stripping the query string
+ */
+$uriFactory = new \OAuth\Common\Http\Uri\UriFactory();
+//$currentUri = $uriFactory->createFromSuperGlobalArray($_SERVER);
+//$currentUri->setQuery('');
+$currentUri = $uriFactory->createFromAbsolute($urlwithroot.'/custom/ecommerceng/core/modules/oauth/wordpress_oauthcallback.php?ecommerce_id='.$siteId);
+
+
+/**
+ * Load the credential for the service
+ */
+
+/** @var $serviceFactory \OAuth\ServiceFactory An OAuth service factory. */
+$serviceFactory = new \OAuth\ServiceFactory();
+$httpClient = new CurlClient();
+// TODO Set options for proxy and timeout
+// $params=array('CURLXXX'=>value, ...)
+//$httpClient->setCurlParameters($params);
+$serviceFactory->setHttpClient($httpClient);
+
+// Dolibarr storage
+$storage = new DoliStorage($db, $conf);
+
+// Setup the credentials for the requests
+$credentials = new Credentials(
+ $siteDb->oauth_id,
+ $siteDb->oauth_secret,
+ $currentUri->getAbsoluteUri()
+);
+
+$requestedpermissionsarray=array();
+if (GETPOST('state')) $requestedpermissionsarray=explode(',', GETPOST('state')); // Example: 'userinfo_email,userinfo_profile,cloud_print'. 'state' parameter is standard to retrieve some parameters back
+/*if ($action != 'delete' && empty($requestedpermissionsarray))
+{
+ print 'Error, parameter state is not defined';
+ exit;
+}*/
+//var_dump($requestedpermissionsarray);exit;
+
+// Instantiate the Api service using the credentials, http client and storage mechanism for the token
+/** @var $apiService Service */
+$apiService = $serviceFactory->createService('WordPress', $credentials, $storage, array(), new Uri($siteDb->webservice_address));
+
+// access type needed to have oauth provider refreshing token
+// alos note that a refresh token is sent only after a prompt
+//$apiService->setAccessType('offline');
+
+//$apiService->setApprouvalPrompt('force');
+
+$langs->load("oauth");
+
+
+/*
+ * Actions
+ */
+
+
+if ($action == 'delete')
+{
+ $storage->clearToken('ECommerce_'.$siteId);
+
+ setEventMessages($langs->trans('TokenDeleted'), null, 'mesgs');
+
+ header('Location: ' . $backtourl);
+ exit();
+}
+
+if (! empty($_GET['code'])) // We are coming from oauth provider page
+{
+ $backtourl = $_SESSION["backtourlsavedbeforeoauthjump"];
+ unset($_SESSION["backtourlsavedbeforeoauthjump"]);
+
+ //llxHeader('',$langs->trans("OAuthSetup"));
+
+ //$linkback=''.$langs->trans("BackToModuleList").'';
+ //print load_fiche_titre($langs->trans("OAuthSetup"),$linkback,'title_setup');
+
+ //dol_fiche_head();
+ // retrieve the CSRF state parameter
+ $state = isset($_GET['state']) ? $_GET['state'] : null;
+ //print '
';
+
+ // This was a callback request from service, get the token
+ try {
+ //var_dump($_GET['code']);
+ //var_dump($state);
+ //var_dump($apiService); // OAuth\OAuth2\Service\WordPress
+
+ $token = $apiService->requestAccessToken($_GET['code'], $state);
+ $storage->storeAccessToken('ECommerce_'.$siteId, $token);
+
+// $token = $apiService->refreshAccessToken($token);
+
+ setEventMessages($langs->trans('NewTokenStored'), null, 'mesgs'); // Stored into object managed by class DoliStorage so into table oauth_token
+ } catch (Exception $e) {
+ setEventMessage($e->getMessage(), 'errors');
+ }
+
+ header('Location: ' . $backtourl);
+ exit();
+}
+else // If entry on page with no parameter, we arrive here
+{
+ $_SESSION["backtourlsavedbeforeoauthjump"]=$backtourl;
+
+ // This may create record into oauth_state before the header redirect.
+ // Creation of record with state in this tables depend on the Provider used (see its constructor).
+ if (GETPOST('state'))
+ {
+ $url = $apiService->getAuthorizationUri(array('state'=>GETPOST('state')));
+ }
+ else
+ {
+ $url = $apiService->getAuthorizationUri(); // Parameter state will be randomly generated
+ }
+
+ // we go on oauth provider authorization page
+ header('Location: ' . $url);
+ exit();
+}
+
+
+/*
+ * View
+ */
+
+// No view at all, just actions
+
+$db->close();
+
diff --git a/htdocs/ecommerceng/core/triggers/interface_90_modECommerceng_ECommerceng.class.php b/htdocs/ecommerceng/core/triggers/interface_90_modECommerceng_ECommerceng.class.php
old mode 100755
new mode 100644
index 3702cdc..f39a912
--- a/htdocs/ecommerceng/core/triggers/interface_90_modECommerceng_ECommerceng.class.php
+++ b/htdocs/ecommerceng/core/triggers/interface_90_modECommerceng_ECommerceng.class.php
@@ -98,6 +98,19 @@ function run_trigger($action,$object,$user,$langs,$conf)
{
$error=0;
+ if ($action == 'CATEGORY_LINK') {
+ if (isset($object->linkto->element)) {
+ switch ($object->linkto->element) {
+ case 'product':
+ //$cat_link_action_old = $action;
+ //$cat_link_object_old = $object;
+ $action = 'PRODUCT_MODIFY';
+ $object = $object->linkto;
+ break;
+ }
+ }
+ }
+
if ($action == 'COMPANY_CREATE')
{
@@ -274,11 +287,18 @@ function run_trigger($action,$object,$user,$langs,$conf)
{
$this->db->begin();
+ $categories = GETPOST('categories');
+
$eCommerceSite = new eCommerceSite($this->db);
$sites = $eCommerceSite->listSites('object');
foreach($sites as $site)
{
+ if (!in_array($site->fk_cat_product, $categories)) {
+ dol_syslog("Product not in categorie now, so we won't run code to sync from dolibarr to ecommerce");
+ continue;
+ }
+
if ($object->context['fromsyncofecommerceid'] && $object->context['fromsyncofecommerceid'] == $site->id)
{
dol_syslog("Triggers was ran from a create/update to sync from ecommerce to dolibarr, so we won't run code to sync from dolibarr to ecommerce");
@@ -317,21 +337,35 @@ function run_trigger($action,$object,$user,$langs,$conf)
}
else
{
- // Get current categories
- require_once DOL_DOCUMENT_ROOT . '/categories/class/categorie.class.php';
- $c = new Categorie($this->db);
- $catids = $c->containing($object->id, Categorie::TYPE_PRODUCT, 'id');
+ // Get current categories
+ require_once DOL_DOCUMENT_ROOT . '/categories/class/categorie.class.php';
+ $c = new Categorie($this->db);
+ $catids = $c->containing($object->id, Categorie::TYPE_PRODUCT, 'id');
- if (in_array($site->fk_cat_product, $catids))
- {
- dol_syslog("Product with id ".$object->id." is not linked to an ecommerce record but has category flag to push on eCommerce. So we push it");
- // TODO
- //$result = $eCommerceSynchro->eCommerceRemoteAccess->updateRemoteProduct($eCommerceProduct->remote_id);
- }
- else
- {
- dol_syslog("Product with id ".$object->id." is not linked to an ecommerce record and does not has category flag to push on eCommerce.");
- }
+ if (in_array($site->fk_cat_product, $catids)) {
+ dol_syslog("Product with id ".$object->id." is not linked to an ecommerce record but has category flag to push on eCommerce. So we push it");
+
+ $eCommerceSynchro = new eCommerceSynchro($this->db, $site);
+ dol_syslog("Trigger " . $action . " try to connect to eCommerce site " . $site->name);
+ $eCommerceSynchro->connect();
+ if (count($eCommerceSynchro->errors)) {
+ $error++;
+ setEventMessages($eCommerceSynchro->error, $eCommerceSynchro->errors, 'errors');
+ }
+
+ if (!empty($conf->global->PRODUIT_MULTIPRICES)) {
+ $object->price = $object->multiprices[$site->price_level];
+ }
+
+ $result = $eCommerceSynchro->eCommerceRemoteAccess->createRemoteProduct($object);
+ if (!$result) {
+ $error++;
+ $this->error = $eCommerceSynchro->eCommerceRemoteAccess->error;
+ $this->errors = $eCommerceSynchro->eCommerceRemoteAccess->errors;
+ }
+ } else {
+ dol_syslog("Product with id ".$object->id." is not linked to an ecommerce record and does not has category flag to push on eCommerce.");
+ }
}
}
}
@@ -350,10 +384,20 @@ function run_trigger($action,$object,$user,$langs,$conf)
- if ($action == 'ORDER_MODIFY' || $action == 'ORDER_CLOSE' || $action == 'ORDER_CLASSIFY_BILLED')
+ if ($action == 'ORDER_MODIFY' || $action == 'ORDER_CLOSE' || $action == 'ORDER_CLASSIFY_BILLED' ||
+ $action == 'ORDER_VALIDATE' || $action == 'ORDER_UNVALIDATE' || $action == 'ORDER_REOPEN' ||
+ $action == 'ORDER_CANCEL' || $action == 'ORDER_CLASSIFY_UNBILLED')
{
$this->db->begin();
+ switch ($action) {
+ case 'ORDER_VALIDATE': $object->statut = Commande::STATUS_VALIDATED; break;
+ case 'ORDER_UNVALIDATE': $object->statut = Commande::STATUS_DRAFT; break;
+ case 'ORDER_REOPEN': $object->statut = Commande::STATUS_DRAFT; break;
+ case 'ORDER_CLOSE': $object->statut = Commande::STATUS_CLOSED; break;
+ case 'ORDER_CANCEL': $object->statut = Commande::STATUS_CANCELED; break;
+ }
+
$eCommerceSite = new eCommerceSite($this->db);
$sites = $eCommerceSite->listSites('object');
diff --git a/htdocs/ecommerceng/doc/Interface Dolibarr-Woocommerce.odt b/htdocs/ecommerceng/doc/Interface Dolibarr-Woocommerce.odt
deleted file mode 100644
index e17f32a..0000000
Binary files a/htdocs/ecommerceng/doc/Interface Dolibarr-Woocommerce.odt and /dev/null differ
diff --git a/htdocs/ecommerceng/doc/Interface Dolibarr-Woocommerce.pdf b/htdocs/ecommerceng/doc/Interface Dolibarr-Woocommerce.pdf
deleted file mode 100644
index 336be59..0000000
Binary files a/htdocs/ecommerceng/doc/Interface Dolibarr-Woocommerce.pdf and /dev/null differ
diff --git a/htdocs/ecommerceng/doc/hack_wordpress/readme.txt b/htdocs/ecommerceng/doc/hack_wordpress/readme.txt
deleted file mode 100644
index 9a77c7d..0000000
--- a/htdocs/ecommerceng/doc/hack_wordpress/readme.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-# Hack for woocommerce.
-For authentification with api legacy v3 for the url with index.php in it.
-
-Override the file in the wordpress folder.
\ No newline at end of file
diff --git a/htdocs/ecommerceng/doc/hack_wordpress/wordpress/wp-content/plugins/woocommerce/includes/api/legacy/v3/class-wc-api-authentication.php b/htdocs/ecommerceng/doc/hack_wordpress/wordpress/wp-content/plugins/woocommerce/includes/api/legacy/v3/class-wc-api-authentication.php
deleted file mode 100755
index c5d486d..0000000
--- a/htdocs/ecommerceng/doc/hack_wordpress/wordpress/wp-content/plugins/woocommerce/includes/api/legacy/v3/class-wc-api-authentication.php
+++ /dev/null
@@ -1,421 +0,0 @@
-api->server->path ) {
- return new WP_User( 0 );
- }
-
- try {
- if ( is_ssl() ) {
- $keys = $this->perform_ssl_authentication();
- } else {
- $keys = $this->perform_oauth_authentication();
- }
-
- // Check API key-specific permission
- $this->check_api_key_permissions( $keys['permissions'] );
-
- $user = $this->get_user_by_id( $keys['user_id'] );
-
- $this->update_api_key_last_access( $keys['key_id'] );
-
- } catch ( Exception $e ) {
- $user = new WP_Error( 'woocommerce_api_authentication_error', $e->getMessage(), array( 'status' => $e->getCode() ) );
- }
-
- return $user;
- }
-
- /**
- * SSL-encrypted requests are not subject to sniffing or man-in-the-middle
- * attacks, so the request can be authenticated by simply looking up the user
- * associated with the given consumer key and confirming the consumer secret
- * provided is valid
- *
- * @since 2.1
- * @return array
- * @throws Exception
- */
- private function perform_ssl_authentication() {
- $params = WC()->api->server->params['GET'];
-
- // if the $_GET parameters are present, use those first
- if ( ! empty( $params['consumer_key'] ) && ! empty( $params['consumer_secret'] ) ) {
- $keys = $this->get_keys_by_consumer_key( $params['consumer_key'] );
-
- if ( ! $this->is_consumer_secret_valid( $keys['consumer_secret'], $params['consumer_secret'] ) ) {
- throw new Exception( __( 'Consumer secret is invalid.', 'woocommerce' ), 401 );
- }
-
- return $keys;
- }
-
- // if the above is not present, we will do full basic auth
- if ( empty( $_SERVER['PHP_AUTH_USER'] ) || empty( $_SERVER['PHP_AUTH_PW'] ) ) {
- $this->exit_with_unauthorized_headers();
- }
-
- $keys = $this->get_keys_by_consumer_key( $_SERVER['PHP_AUTH_USER'] );
-
- if ( ! $this->is_consumer_secret_valid( $keys['consumer_secret'], $_SERVER['PHP_AUTH_PW'] ) ) {
- $this->exit_with_unauthorized_headers();
- }
-
- return $keys;
- }
-
- /**
- * If the consumer_key and consumer_secret $_GET parameters are NOT provided
- * and the Basic auth headers are either not present or the consumer secret does not match the consumer
- * key provided, then return the correct Basic headers and an error message.
- *
- * @since 2.4
- */
- private function exit_with_unauthorized_headers() {
- $auth_message = __( 'WooCommerce API. Use a consumer key in the username field and a consumer secret in the password field.', 'woocommerce' );
- header( 'WWW-Authenticate: Basic realm="' . $auth_message . '"' );
- header( 'HTTP/1.0 401 Unauthorized' );
- throw new Exception( __( 'Consumer Secret is invalid.', 'woocommerce' ), 401 );
- }
-
- /**
- * Perform OAuth 1.0a "one-legged" (http://oauthbible.com/#oauth-10a-one-legged) authentication for non-SSL requests
- *
- * This is required so API credentials cannot be sniffed or intercepted when making API requests over plain HTTP
- *
- * This follows the spec for simple OAuth 1.0a authentication (RFC 5849) as closely as possible, with two exceptions:
- *
- * 1) There is no token associated with request/responses, only consumer keys/secrets are used
- *
- * 2) The OAuth parameters are included as part of the request query string instead of part of the Authorization header,
- * This is because there is no cross-OS function within PHP to get the raw Authorization header
- *
- * @link http://tools.ietf.org/html/rfc5849 for the full spec
- * @since 2.1
- * @return array
- * @throws Exception
- */
- private function perform_oauth_authentication() {
-
- $params = WC()->api->server->params['GET'];
-
- $param_names = array( 'oauth_consumer_key', 'oauth_timestamp', 'oauth_nonce', 'oauth_signature', 'oauth_signature_method' );
-
- // Check for required OAuth parameters
- foreach ( $param_names as $param_name ) {
-
- if ( empty( $params[ $param_name ] ) ) {
- throw new Exception( sprintf( __( '%s parameter is missing', 'woocommerce' ), $param_name ), 404 );
- }
- }
-
- // Fetch WP user by consumer key
- $keys = $this->get_keys_by_consumer_key( $params['oauth_consumer_key'] );
-
- // Perform OAuth validation
- $this->check_oauth_signature( $keys, $params );
- $this->check_oauth_timestamp_and_nonce( $keys, $params['oauth_timestamp'], $params['oauth_nonce'] );
-
- // Authentication successful, return user
- return $keys;
- }
-
- /**
- * Return the keys for the given consumer key
- *
- * @since 2.4.0
- * @param string $consumer_key
- * @return array
- * @throws Exception
- */
- private function get_keys_by_consumer_key( $consumer_key ) {
- global $wpdb;
-
- $consumer_key = wc_api_hash( sanitize_text_field( $consumer_key ) );
-
- $keys = $wpdb->get_row( $wpdb->prepare( "
- SELECT key_id, user_id, permissions, consumer_key, consumer_secret, nonces
- FROM {$wpdb->prefix}woocommerce_api_keys
- WHERE consumer_key = '%s'
- ", $consumer_key ), ARRAY_A );
-
- if ( empty( $keys ) ) {
- throw new Exception( __( 'Consumer key is invalid.', 'woocommerce' ), 401 );
- }
-
- return $keys;
- }
-
- /**
- * Get user by ID
- *
- * @since 2.4.0
- * @param int $user_id
- * @return WC_User
- * @throws Exception
- */
- private function get_user_by_id( $user_id ) {
- $user = get_user_by( 'id', $user_id );
-
- if ( ! $user ) {
- throw new Exception( __( 'API user is invalid', 'woocommerce' ), 401 );
- }
-
- return $user;
- }
-
- /**
- * Check if the consumer secret provided for the given user is valid
- *
- * @since 2.1
- * @param string $keys_consumer_secret
- * @param string $consumer_secret
- * @return bool
- */
- private function is_consumer_secret_valid( $keys_consumer_secret, $consumer_secret ) {
- return hash_equals( $keys_consumer_secret, $consumer_secret );
- }
-
- /**
- * Verify that the consumer-provided request signature matches our generated signature, this ensures the consumer
- * has a valid key/secret
- *
- * @param array $keys
- * @param array $params the request parameters
- * @throws Exception
- */
- private function check_oauth_signature( $keys, $params ) {
- /*$http_method = strtoupper( WC()->api->server->method );
-
- $server_path = WC()->api->server->path;
-
- // if the requested URL has a trailingslash, make sure our base URL does as well
- if ( isset( $_SERVER['REDIRECT_URL'] ) && '/' === substr( $_SERVER['REDIRECT_URL'], -1 ) ) {
- $server_path .= '/';
- }
-
- $base_request_uri = rawurlencode( untrailingslashit( get_woocommerce_api_url( '' ) ) . $server_path );*/
- // Hack for url // url pretty permalinks error for localhost/index.php/wc-api/v3/... for check signature
- $http_method = strtoupper( $_SERVER['REQUEST_METHOD'] );
- $request_path = parse_url( $_SERVER['REQUEST_URI'], PHP_URL_PATH );
- $wp_base = get_home_url( null, '/', 'relative' );
- if ( substr( $request_path, 0, strlen( $wp_base ) ) === $wp_base ) {
- $request_path = substr( $request_path, strlen( $wp_base ) );
- }
- $base_request_uri = rawurlencode( get_home_url( null, $request_path ) );
-
- // Get the signature provided by the consumer and remove it from the parameters prior to checking the signature
- $consumer_signature = rawurldecode( str_replace( ' ', '+', $params['oauth_signature'] ) );
- unset( $params['oauth_signature'] );
-
- // Sort parameters
- if ( ! uksort( $params, 'strcmp' ) ) {
- throw new Exception( __( 'Invalid signature - failed to sort parameters.', 'woocommerce' ), 401 );
- }
-
- // Normalize parameter key/values
- $params = $this->normalize_parameters( $params );
- $query_parameters = array();
- foreach ( $params as $param_key => $param_value ) {
- if ( is_array( $param_value ) ) {
- foreach ( $param_value as $param_key_inner => $param_value_inner ) {
- $query_parameters[] = $param_key . '%255B' . $param_key_inner . '%255D%3D' . $param_value_inner;
- }
- } else {
- $query_parameters[] = $param_key . '%3D' . $param_value; // join with equals sign
- }
- }
- $query_string = implode( '%26', $query_parameters ); // join with ampersand
-
- $string_to_sign = $http_method . '&' . $base_request_uri . '&' . $query_string;
-
- if ( 'HMAC-SHA1' !== $params['oauth_signature_method'] && 'HMAC-SHA256' !== $params['oauth_signature_method'] ) {
- throw new Exception( __( 'Invalid signature - signature method is invalid.', 'woocommerce' ), 401 );
- }
-
- $hash_algorithm = strtolower( str_replace( 'HMAC-', '', $params['oauth_signature_method'] ) );
-
- $secret = $keys['consumer_secret'] . '&';
- $signature = base64_encode( hash_hmac( $hash_algorithm, $string_to_sign, $secret, true ) );
-
- if ( ! hash_equals( $signature, $consumer_signature ) ) {
- throw new Exception( __( 'Invalid signature - provided signature does not match.', 'woocommerce' ), 401 );
- }
- }
-
- /**
- * Normalize each parameter by assuming each parameter may have already been
- * encoded, so attempt to decode, and then re-encode according to RFC 3986
- *
- * Note both the key and value is normalized so a filter param like:
- *
- * 'filter[period]' => 'week'
- *
- * is encoded to:
- *
- * 'filter%5Bperiod%5D' => 'week'
- *
- * This conforms to the OAuth 1.0a spec which indicates the entire query string
- * should be URL encoded
- *
- * @since 2.1
- * @see rawurlencode()
- * @param array $parameters un-normalized pararmeters
- * @return array normalized parameters
- */
- private function normalize_parameters( $parameters ) {
- $keys = WC_API_Authentication::urlencode_rfc3986( array_keys( $parameters ) );
- $values = WC_API_Authentication::urlencode_rfc3986( array_values( $parameters ) );
- $parameters = array_combine( $keys, $values );
- return $parameters;
- }
-
- /**
- * Encodes a value according to RFC 3986. Supports multidimensional arrays.
- *
- * @since 2.4
- * @param string|array $value The value to encode
- * @return string|array Encoded values
- */
- public static function urlencode_rfc3986( $value ) {
- if ( is_array( $value ) ) {
- return array_map( array( 'WC_API_Authentication', 'urlencode_rfc3986' ), $value );
- } else {
- // Percent symbols (%) must be double-encoded
- return str_replace( '%', '%25', rawurlencode( rawurldecode( $value ) ) );
- }
- }
-
- /**
- * Verify that the timestamp and nonce provided with the request are valid. This prevents replay attacks where
- * an attacker could attempt to re-send an intercepted request at a later time.
- *
- * - A timestamp is valid if it is within 15 minutes of now
- * - A nonce is valid if it has not been used within the last 15 minutes
- *
- * @param array $keys
- * @param int $timestamp the unix timestamp for when the request was made
- * @param string $nonce a unique (for the given user) 32 alphanumeric string, consumer-generated
- * @throws Exception
- */
- private function check_oauth_timestamp_and_nonce( $keys, $timestamp, $nonce ) {
- global $wpdb;
-
- $valid_window = 15 * 60; // 15 minute window
-
- if ( ( $timestamp < time() - $valid_window ) || ( $timestamp > time() + $valid_window ) ) {
- throw new Exception( __( 'Invalid timestamp.', 'woocommerce' ), 401 );
- }
-
- $used_nonces = maybe_unserialize( $keys['nonces'] );
-
- if ( empty( $used_nonces ) ) {
- $used_nonces = array();
- }
-
- if ( in_array( $nonce, $used_nonces ) ) {
- throw new Exception( __( 'Invalid nonce - nonce has already been used.', 'woocommerce' ), 401 );
- }
-
- $used_nonces[ $timestamp ] = $nonce;
-
- // Remove expired nonces
- foreach ( $used_nonces as $nonce_timestamp => $nonce ) {
- if ( $nonce_timestamp < ( time() - $valid_window ) ) {
- unset( $used_nonces[ $nonce_timestamp ] );
- }
- }
-
- $used_nonces = maybe_serialize( $used_nonces );
-
- $wpdb->update(
- $wpdb->prefix . 'woocommerce_api_keys',
- array( 'nonces' => $used_nonces ),
- array( 'key_id' => $keys['key_id'] ),
- array( '%s' ),
- array( '%d' )
- );
- }
-
- /**
- * Check that the API keys provided have the proper key-specific permissions to either read or write API resources
- *
- * @param string $key_permissions
- * @throws Exception if the permission check fails
- */
- public function check_api_key_permissions( $key_permissions ) {
- switch ( WC()->api->server->method ) {
-
- case 'HEAD':
- case 'GET':
- if ( 'read' !== $key_permissions && 'read_write' !== $key_permissions ) {
- throw new Exception( __( 'The API key provided does not have read permissions.', 'woocommerce' ), 401 );
- }
- break;
-
- case 'POST':
- case 'PUT':
- case 'PATCH':
- case 'DELETE':
- if ( 'write' !== $key_permissions && 'read_write' !== $key_permissions ) {
- throw new Exception( __( 'The API key provided does not have write permissions.', 'woocommerce' ), 401 );
- }
- break;
- }
- }
-
- /**
- * Updated API Key last access datetime
- *
- * @since 2.4.0
- *
- * @param int $key_id
- */
- private function update_api_key_last_access( $key_id ) {
- global $wpdb;
-
- $wpdb->update(
- $wpdb->prefix . 'woocommerce_api_keys',
- array( 'last_access' => current_time( 'mysql' ) ),
- array( 'key_id' => $key_id ),
- array( '%s' ),
- array( '%d' )
- );
- }
-}
diff --git a/htdocs/ecommerceng/includes/CurlClientEx.php b/htdocs/ecommerceng/includes/CurlClientEx.php
new file mode 100644
index 0000000..a216fc7
--- /dev/null
+++ b/htdocs/ecommerceng/includes/CurlClientEx.php
@@ -0,0 +1,157 @@
+ value` pairs) to be passed to `curl_setopt`
+ *
+ * @var array
+ */
+ private $parameters = array();
+
+ /**
+ * Additional `curl_setopt` parameters
+ *
+ * @param array $parameters
+ */
+ public function setCurlParameters(array $parameters)
+ {
+ $this->parameters = $parameters;
+ }
+
+ /**
+ * @param bool $buildHttpQuery
+ */
+ public function setHttpPostBuildQuery($buildHttpQuery)
+ {
+ $this->httpPostBuildQuery = $buildHttpQuery;
+ }
+
+ /**
+ * @param bool $force
+ *
+ * @return CurlClientEx
+ */
+ public function setForceSSL3($force)
+ {
+ $this->forceSSL3 = $force;
+
+ return $this;
+ }
+
+ /**
+ * Any implementing HTTP providers should send a request to the provided endpoint with the parameters.
+ * They should return, in string form, the response body and throw an exception on error.
+ *
+ * @param UriInterface $endpoint
+ * @param mixed $requestBody
+ * @param array $extraHeaders
+ * @param string $method
+ *
+ * @return string
+ *
+ * @throws TokenResponseException
+ * @throws \InvalidArgumentException
+ */
+ public function retrieveResponse(
+ UriInterface $endpoint,
+ $requestBody,
+ array $extraHeaders = array(),
+ $method = 'POST'
+ ) {
+ // Normalize method name
+ $method = strtoupper($method);
+
+ $this->normalizeHeaders($extraHeaders);
+
+ if ($method === 'GET' && !empty($requestBody)) {
+ throw new \InvalidArgumentException('No body expected for "GET" request.');
+ }
+
+ if (!isset($extraHeaders['Content-Type']) && $method === 'POST' && is_array($requestBody)) {
+ $extraHeaders['Content-Type'] = 'Content-Type: application/x-www-form-urlencoded';
+ }
+
+ $extraHeaders['Host'] = 'Host: '.$endpoint->getHost();
+ $extraHeaders['Connection'] = 'Connection: close';
+
+ $ch = curl_init();
+
+ curl_setopt($ch, CURLOPT_URL, $endpoint->getAbsoluteUri());
+
+ if ($method === 'POST' || $method === 'PUT') {
+ if ($requestBody && is_array($requestBody) && $this->httpPostBuildQuery) {
+ $requestBody = http_build_query($requestBody, '', '&');
+ }
+
+ if ($method === 'PUT') {
+ curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
+ } else {
+ curl_setopt($ch, CURLOPT_POST, true);
+ }
+
+ curl_setopt($ch, CURLOPT_POSTFIELDS, $requestBody);
+ } else {
+ curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
+ }
+
+ if ($this->maxRedirects > 0) {
+ curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
+ curl_setopt($ch, CURLOPT_MAXREDIRS, $this->maxRedirects);
+ }
+
+ curl_setopt($ch, CURLOPT_TIMEOUT, $this->timeout);
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
+ curl_setopt($ch, CURLOPT_HEADER, false);
+ curl_setopt($ch, CURLOPT_HTTPHEADER, $extraHeaders);
+ curl_setopt($ch, CURLOPT_USERAGENT, $this->userAgent);
+
+ foreach ($this->parameters as $key => $value) {
+ curl_setopt($ch, $key, $value);
+ }
+
+ if ($this->forceSSL3) {
+ curl_setopt($ch, CURLOPT_SSLVERSION, 3);
+ }
+
+ $response = curl_exec($ch);
+ $responseCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
+
+ if (false === $response) {
+ $errNo = curl_errno($ch);
+ $errStr = curl_error($ch);
+ curl_close($ch);
+ if (empty($errStr)) {
+ throw new TokenResponseException('Failed to request resource.', $responseCode);
+ }
+ throw new TokenResponseException('cURL Error # '.$errNo.': '.$errStr, $responseCode);
+ }
+
+ curl_close($ch);
+
+ return $response;
+ }
+}
diff --git a/htdocs/ecommerceng/includes/WooCommerce/Client.php b/htdocs/ecommerceng/includes/WooCommerce/Client.php
old mode 100755
new mode 100644
diff --git a/htdocs/ecommerceng/includes/WooCommerce/HttpClient/BasicAuth.php b/htdocs/ecommerceng/includes/WooCommerce/HttpClient/BasicAuth.php
old mode 100755
new mode 100644
diff --git a/htdocs/ecommerceng/includes/WooCommerce/HttpClient/HttpClient.php b/htdocs/ecommerceng/includes/WooCommerce/HttpClient/HttpClient.php
old mode 100755
new mode 100644
index b6754e4..48d8f5a
--- a/htdocs/ecommerceng/includes/WooCommerce/HttpClient/HttpClient.php
+++ b/htdocs/ecommerceng/includes/WooCommerce/HttpClient/HttpClient.php
@@ -313,12 +313,17 @@ protected function lookForErrors($parsedResponse)
if (!\in_array($this->response->getCode(), ['200', '201', '202'])) {
$errors = !empty($parsedResponse['errors']) ? $parsedResponse['errors'] : $parsedResponse;
- if (!empty($errors[0])) {
- $errorMessage = $errors[0]['message'];
- $errorCode = $errors[0]['code'];
+ if (is_array($errors)) {
+ if (!empty($errors[0])) {
+ $errorMessage = $errors[0]['message'];
+ $errorCode = $errors[0]['code'];
+ } else {
+ $errorMessage = $errors['message'];
+ $errorCode = $errors['code'];
+ }
} else {
- $errorMessage = $errors['message'];
- $errorCode = $errors['code'];
+ $errorMessage = 'N/A';
+ $errorCode = 'N/A';
}
throw new HttpClientException(\sprintf('Error: %s [%s]', $errorMessage, $errorCode), $this->response->getCode(), $this->request, $this->response);
@@ -335,7 +340,7 @@ protected function processResponse()
$parsedResponse = \json_decode($this->response->getBody(), true);
// Test if return a valid JSON.
- if (JSON_ERROR_NONE !== json_last_error()) {
+ if ($parsedResponse === null || (function_exists('json_last_error') && JSON_ERROR_NONE !== json_last_error())) {
$message = function_exists('json_last_error_msg') ? json_last_error_msg() : 'Invalid JSON returned';
throw new HttpClientException($message, $this->response->getCode(), $this->request, $this->response);
}
diff --git a/htdocs/ecommerceng/includes/WooCommerce/HttpClient/HttpClientException.php b/htdocs/ecommerceng/includes/WooCommerce/HttpClient/HttpClientException.php
old mode 100755
new mode 100644
diff --git a/htdocs/ecommerceng/includes/WooCommerce/HttpClient/OAuth.php b/htdocs/ecommerceng/includes/WooCommerce/HttpClient/OAuth.php
old mode 100755
new mode 100644
diff --git a/htdocs/ecommerceng/includes/WooCommerce/HttpClient/Options.php b/htdocs/ecommerceng/includes/WooCommerce/HttpClient/Options.php
old mode 100755
new mode 100644
diff --git a/htdocs/ecommerceng/includes/WooCommerce/HttpClient/Request.php b/htdocs/ecommerceng/includes/WooCommerce/HttpClient/Request.php
old mode 100755
new mode 100644
diff --git a/htdocs/ecommerceng/includes/WooCommerce/HttpClient/Response.php b/htdocs/ecommerceng/includes/WooCommerce/HttpClient/Response.php
old mode 100755
new mode 100644
diff --git a/htdocs/ecommerceng/includes/WordPressClient.php b/htdocs/ecommerceng/includes/WordPressClient.php
new file mode 100644
index 0000000..212a703
--- /dev/null
+++ b/htdocs/ecommerceng/includes/WordPressClient.php
@@ -0,0 +1,251 @@
+errors = array();
+
+ // Token storage
+ $this->storage = new DoliStorage($db, $conf);
+
+ // Setup the credentials for the requests
+ $this->credentials = new Credentials(
+ $oauth_id,
+ $oauth_secret,
+ $callbackUrl
+ );
+
+ // Setup the api service
+ $this->baseApiUri = $baseApiUri.(substr($baseApiUri, -1, 1)!='/'?'/':'').'wp-json/wp/v2';
+ $serviceFactory = new \OAuth\ServiceFactory();
+ $this->httpClient = new CurlClientEx();
+ $serviceFactory->setHttpClient($this->httpClient);
+ $this->apiService = $serviceFactory->createService(self::OAUTH_SERVICENAME_WORDPRESS, $this->credentials, $this->storage, array(), new Uri($baseApiUri));
+ }
+
+ /**
+ * POST method.
+ *
+ * @param string $endpoint API endpoint.
+ * @param array $data Request data.
+ *
+ * @return array
+ */
+ public function post($endpoint, $data)
+ {
+ $this->errors = array();
+ return $this->request($endpoint, 'POST', $data);
+ }
+
+ /**
+ * POST media method.
+ *
+ * @param string $endpoint API endpoint.
+ * @param string $filepath File path.
+ * @param array $data Request data.
+ *
+ * @return array
+ */
+ public function postmedia($endpoint, $filepath, $data)
+ {
+ $responseData = null;
+ $this->errors = array();
+
+ // Set File
+ if (file_exists($filepath)) {
+ if (function_exists('curl_file_create')) { // php 5.5+
+ $cFile = curl_file_create($filepath);
+ } else {
+ $cFile = '@' . realpath($filepath);
+ }
+ $data['file'] = $cFile;
+ } else {
+ $this->errors[] = array('File not found ("'.$filepath.'").');
+ return $responseData;
+ }
+
+ $extraHeaders = array("Content-Type" => "multipart/form-data");
+
+ return $this->request($endpoint, 'POST', $data, $extraHeaders);
+ }
+
+ /**
+ * PUT method.
+ *
+ * @param string $endpoint API endpoint.
+ * @param array $data Request data.
+ *
+ * @return array
+ */
+ public function put($endpoint, $data)
+ {
+ $this->errors = array();
+ return $this->request($endpoint, 'PUT', $data);
+ }
+
+ /**
+ * GET method.
+ *
+ * @param string $endpoint API endpoint.
+ * @param array $parameters Request parameters.
+ *
+ * @return array
+ */
+ public function get($endpoint, $parameters = [])
+ {
+ $this->errors = array();
+ return $this->request($endpoint, 'GET', $parameters);
+ }
+
+ /**
+ * DELETE method.
+ *
+ * @param string $endpoint API endpoint.
+ * @param array $parameters Request parameters.
+ *
+ * @return array
+ */
+ public function delete($endpoint, $parameters = [])
+ {
+ $this->errors = array();
+ return $this->request($endpoint, 'DELETE', $parameters);
+ }
+
+ /**
+ * OPTIONS method.
+ *
+ * @param string $endpoint API endpoint.
+ *
+ * @return array
+ */
+ public function options($endpoint)
+ {
+ $this->errors = array();
+ return $this->request($endpoint, 'OPTIONS');
+ }
+
+ /**
+ * Request.
+ *
+ * @param string $endpoint API endpoint.
+ * @param string $method HTTP method
+ * @param array $body Request body if applicable (an associative array will
+ * automatically be converted into a urlencoded body)
+ * @param array $extraHeaders Extra headers if applicable. These will override service-specific
+ * any defaults.
+ * @return array
+ */
+ public function request($endpoint, $method, $body = [], $extraHeaders = [])
+ {
+ $responseData = null;
+
+ // Check if we have auth token
+ try {
+ $token = $this->storage->retrieveAccessToken(self::OAUTH_SERVICENAME_WORDPRESS);
+ } catch (Exception $e) {
+ $this->errors[] = $e->getMessage();
+ return $responseData;
+ }
+
+ // Is token expired or will token expire in the next 30 seconds
+ $expire = ($token->getEndOfLife() !== -9002 && $token->getEndOfLife() !== -9001 && time() > ($token->getEndOfLife() - 30));
+
+ // Token expired so we refresh it
+ if ($expire) {
+ try {
+ $this->httpClient->setHttpPostBuildQuery(true);
+ $token = $this->apiService->refreshAccessToken($token);
+ } catch (Exception $e) {
+ $this->errors[] = $e->getMessage();
+ return $responseData;
+ }
+ }
+
+ // Send a request with api
+ try {
+ $this->httpClient->setHttpPostBuildQuery(false);
+ $response = $this->apiService->request($this->baseApiUri.(substr($this->baseApiUri, -1, 1)!='/'?'/':'').$endpoint, $method, $body, $extraHeaders);
+ $responseData = json_decode($response, true);
+ } catch (Exception $e) {
+ $this->errors[] = $e->getMessage();
+ }
+
+ return $responseData;
+ }
+}
diff --git a/htdocs/ecommerceng/js/form.js b/htdocs/ecommerceng/js/form.js
old mode 100755
new mode 100644
index e63cc24..ab864bf
--- a/htdocs/ecommerceng/js/form.js
+++ b/htdocs/ecommerceng/js/form.js
@@ -12,6 +12,15 @@ function eCommerceConfirmDelete(id_form, confirmation)
}
}
+function eCommerceConfirmWoocommerceUpdateDictTaxClass(id_form, confirmation)
+{
+ if (confirm(confirmation))
+ {
+ document.getElementById(id_form+'_action').value = 'update_woocommerce_tax_class';
+ eCommerceSubmitForm(id_form);
+ }
+}
+
function eCommerceConfirmUpdatePriceLevel(id_form, confirmation, price_level)
{
jQuery('#'+id_form).on('submit', function(e) {
diff --git a/htdocs/ecommerceng/langs/en_US/ecommerce.lang b/htdocs/ecommerceng/langs/en_US/ecommerce.lang
old mode 100755
new mode 100644
index ee47849..75b8595
--- a/htdocs/ecommerceng/langs/en_US/ecommerce.lang
+++ b/htdocs/ecommerceng/langs/en_US/ecommerce.lang
@@ -1,9 +1,9 @@
# Dolibarr language file - en_Us - magento
CHARSET=UTF-8
-ECommerceMagentoPriceType=Imported prices' types
-ECommerceMagentoPriceTypeHT=Tax excluded
-ECommerceMagentoPriceTypeTTC=Tax included
-ECommerceMagentoPriceTypeDescription=Define the VAT application on Magento's imported products' prices (TE or TI)
+ECommercePriceType=Imported prices' types
+ECommercePriceTypeHT=Tax excluded
+ECommercePriceTypeTTC=Tax included
+ECommercePriceTypeDescription=Define the VAT application on E-Commerce's imported products' prices (TE or TI)
ECommerceMagentoUseSpecialPriceDescription=Check to import Magento's special prices instead of public prices (public price will be imported only if special price is not defined)
ECommerceMagentoUseSpecialPrice=Use Magento's special price
ECommerceDashboard=ECommerce synchronization management dashboard
@@ -33,15 +33,15 @@ ECommerceCatProductDescription=Select a product category to use to tags products
ECommerceCatSocieteDescription=Select a customer category to use to tags thirparties in Doliarr to mark them as customers presents in Ecommerce too Note: Module Tags/Categories must be activated.
ECommerceFilterLabelDescription=Indicate a filter (exemple : store_id)
ECommerceFilterValueDescription=Indicate a value du filtre (exemple : *)
-ECommerceSiteTypeDescription =Select a site type
+ECommerceSiteTypeDescription=Select a site type
ECommerceSiteAddressDescription=Check before into your eCommerce admin that services are enabled. Exemple : http://www.localhost.com/api/?wsdl, http://mymagentoserver/index.php/api/?wsdl
ECommerceUserNameDescription=Exemple : soapuser
ECommerceUserPasswordDescription=Exemple : myapikey
ECommerceSite=Site
ECommerceLastUpdate=Last Ecommerce->Dolibarr sync
ECommerceNoUpdateSite=This site has never been synchronized
-ECommerceUpdateSite=Synchronization detail of this site
-ECommerceUpdateAll=Synchronize all objects
+ECommerceUpdateSite=Detailed update of this site
+ECommerceUpdateAll=Update all for this site
ECommerceReset=Delete all links and Dolibarr linked record
ECommerceResetLink=Delete all link records between Dolibarr and Ecommerce
ECommerceMenu=ECommerce Sync
@@ -86,11 +86,11 @@ ECommerceSynchSocieteSuccess=companies have been synchronized.
ECommerceSynchProductSuccess=products have been synchronized.
ECommerceSynchCommandeSuccess=orders have been synchronized.
ECommerceSynchFactureSuccess=bills have been synchronized.
-ECommerceSynchCommandeError=Error during synchronization of orders
+ECommerceSynchCommandeError=Error during synchronization of orders
ECommerceCheckIfCategoryDoesNotExistsTwice=Try to make name of your categories unique on your eCommerce platform
ECommerceSynchSocieteErrorCreateUpdateSociete=Failed to synchronize thirdparty
-ECommerceSyncheCommerceSocpeopleCreateError=An error occured while saving contact.
+ECommerceSyncheCommerceSocpeopleCreateError=An error occured while saving contact (company ID: %s; first name: %s; last name: %s).
ECommerceSyncheCommerceProductCreateError=Error creating the link between Dolibarr product and eCommerce product
ECommerceSyncheCommerceCommandeCreateError=Error creating the link between Dolibarr order and eCommerce order
ECommerceSyncheCommerceCategoryUpdateError=Error while updating a category.
@@ -159,3 +159,44 @@ RestrictNbInSync=Restrict number of record of same object to synchronize in same
SynchUnkownCustomersOnThirdParty=Use the following thirdparty for orders done on unknown customers (non logged customers)
ThirdPartyForNonLoggedUsers=Third party for anonymous/non logged users
+## OAuth Setup ##
+ECommerceOAuthWordpressSetup=Connexion OAuth2 sur WordPress ( Allez sur cette page , puis "Ajouter un nouveau client" pour créer les informations d'identification OAuth2 )
+ECommerceSiteOAuthRedirectUri=Url de redirection
+ECommerceSiteOAuthRedirectUriDescription=Utilisez l'URL suivante comme URI de redirection (Callback) quand vous créez une nouvelle application (ou un nouveau client)
+ECommerceSiteOAuthId=OAuth ID
+ECommerceSiteOAuthIdDescription=Id de connexion au service OAuth
+ECommerceSiteOAuthSecret=OAuth secret
+ECommerceSiteOAuthSecretDescription=Secret de connexion au service OAuth
+ECommerceOAuthCheckToken=Allez sur cette page pour vérifier/effacer les autorisations sauvées par le fournisseur OAuth2.
+
+ECommerceSynchronizeProductImages=Synchronize images
+ECommerceProductImagesSynchronized=Images synchronized.
+
+ECommerceRemoteAccessConnect=Erreur de connection au site '%s': %s
+ECommerceRemoteAccessConvertRemoteObjectIntoDolibarrCommande=Erreur de recuperation des commandes sur le site '%s': %s
+ECommerceRemoteAccessConvertRemoteObjectIntoDolibarrProduct=Erreur de recuperation des produits sur le site '%s': %s
+ECommerceRemoteAccessConvertRemoteObjectIntoDolibarrProductVariations=Erreur de recuperation des variations du produit distant 'id:%s' sur le site '%s': %s
+ECommerceRemoteAccessConvertRemoteObjectIntoDolibarrSociete=Erreur de recuperation des sociétés sur le site '%s': %s
+ECommerceRemoteAccessConvertRemoteObjectIntoDolibarrSocpeople=Erreur de recuperation des sociétés (pour les contacts/adresses) sur le site '%s': %s
+ECommerceRemoteAccessCreateRemoteProduct=Erreur de creation du produit 'id:%s' sur le site '%s': %s
+ECommerceRemoteAccessCreateRemoteProductLink=Erreur de creation du lien pour le produit 'id:%s' pour le site '%s': %s
+ECommerceRemoteAccessGetCategoryData=Erreur de récupération des données de la catégorie distante 'id:%s' sur le site '%s': %s
+ECommerceRemoteAccessGetCommandeToUpdate=Erreur de récupération de la liste des commandes à mettre à jour sur le site '%s': %s
+ECommerceRemoteAccessGetProductToUpdate=Erreur de récupération de la liste des produits à mettre à jour sur le site '%s': %s
+ECommerceRemoteAccessGetRemoteCategoryTree=Erreur de récupération de la liste des catégories à mettre à jour sur le site '%s': %s
+ECommerceRemoteAccessGetSocieteToUpdate=Erreur de récupération de la liste des sociétés à mettre à jour sur le site '%s': %s
+ECommerceRemoteAccessSendFileForCommande=Erreur pour lier le fichier avec la commande distante 'id:%s' sur le site '%s': %s
+ECommerceRemoteAccessSendFileForCommandeInWordpress=Erreur de l'envoi du fichier pour la commande distante 'id:%s' dans les média de Wordpress sur le site '%s': %s
+ECommerceRemoteAccessUpdateRemoteCommande=Erreur de mise à jour de la commande distante 'id:%s' sur le site '%s': %s
+ECommerceRemoteAccessUpdateRemoteProduct=Erreur de mise à jour du produit distant 'id:%s' sur le site '%s': %s
+ECommerceRemoteAccessUpdateRemoteProductGetRemoteProduct=Erreur de récupération du produit distant 'id:%s' sur le site '%s': %s
+ECommerceRemoteAccessUpdateRemoteProductSendImage=Erreur de l'envoi d'une image pour le produit distante 'id:%s' dans les média de Wordpress sur le site '%s': %s
+ECommerceRemoteAccessUpdateRemoteProductVariation=Erreur de mise à jour de la variation 'id:%s' du produit distant 'id:%s' sur le site '%s': %s
+ECommerceRemoteAccessUpdateRemoteSociete=Erreur de mise à jour de la société distante 'id:%s' sur le site '%s': %s
+ECommerceRemoteAccessUpdateRemoteSocpeople=Erreur de mise à jour des contacts/adresses de la société distante 'id:%s' sur le site '%s': %s
+ECommerceRemoteAccessUpdateRemoteStockProduct=Erreur de mise à jour des stocks de la variation 'id:%s' du produit distant 'id:%s' sur le site '%s': %s
+ECommerceRemoteAccessUpdateRemoteStockProductVariation=Erreur de mise à jour des stocks du produit distant 'id:%s' sur le site '%s': %s
+
+ECommerceSyncheCommerceProductDownloadImageError=Erreur de récupération de l'image (%s) pour le produit 'id:%s' du produit distant 'id:%s' sur le site '%s'
+
+ECommerceNoDescForProductLine=L'api n'a pas pu récupérer la description du produit
diff --git a/htdocs/ecommerceng/langs/en_US/woocommerce.lang b/htdocs/ecommerceng/langs/en_US/woocommerce.lang
new file mode 100644
index 0000000..a4ea380
--- /dev/null
+++ b/htdocs/ecommerceng/langs/en_US/woocommerce.lang
@@ -0,0 +1,50 @@
+# Dolibarr language file - en_Us - woocommerce
+CHARSET=UTF-8
+
+ECommerceWoocommerceConnect=Erreur de connection au site '%s': %s
+ECommerceWoocommerceConvertRemoteObjectIntoDolibarrCommande=Erreur de recuperation des commandes sur le site '%s': %s
+ECommerceWoocommerceConvertRemoteObjectIntoDolibarrProduct=Erreur de recuperation des produits sur le site '%s': %s
+ECommerceWoocommerceConvertRemoteObjectIntoDolibarrProductVariations=Erreur de recuperation des variations du produit distant 'id:%s' sur le site '%s': %s
+ECommerceWoocommerceConvertRemoteObjectIntoDolibarrSociete=Erreur de recuperation des sociétés sur le site '%s': %s
+ECommerceWoocommerceConvertRemoteObjectIntoDolibarrSocpeople=Erreur de recuperation des sociétés (pour les contacts/adresses) sur le site '%s': %s
+ECommerceWoocommerceCreateRemoteProduct=Erreur de creation du produit 'id:%s' sur le site '%s': %s
+ECommerceWoocommerceCreateRemoteProductLink=Erreur de creation du lien pour le produit 'id:%s' pour le site '%s': %s
+ECommerceWoocommerceGetCategoryData=Erreur de récupération des données de la catégorie distante 'id:%s' sur le site '%s': %s
+ECommerceWoocommerceGetCommandeToUpdate=Erreur de récupération de la liste des commandes à mettre à jour sur le site '%s': %s
+ECommerceWoocommerceGetProductToUpdate=Erreur de récupération de la liste des produits à mettre à jour sur le site '%s': %s
+ECommerceWoocommerceGetRemoteCategoryTree=Erreur de récupération de la liste des catégories à mettre à jour sur le site '%s': %s
+ECommerceWoocommerceGetSocieteToUpdate=Erreur de récupération de la liste des sociétés à mettre à jour sur le site '%s': %s
+ECommerceWoocommerceSendFileForCommande=Erreur pour lier le fichier avec la commande distante 'id:%s' sur le site '%s': %s
+ECommerceWoocommerceSendFileForCommandeInWordpress=Erreur de l'envoi du fichier pour la commande distante 'id:%s' dans les média de Wordpress sur le site '%s': %s
+ECommerceWoocommerceUpdateRemoteCommande=Erreur de mise à jour de la commande distante 'id:%s' sur le site '%s': %s
+ECommerceWoocommerceUpdateRemoteProduct=Erreur de mise à jour du produit distant 'id:%s' sur le site '%s': %s
+ECommerceWoocommerceUpdateRemoteProductGetRemoteProduct=Erreur de récupération du produit distant 'id:%s' sur le site '%s': %s
+ECommerceWoocommerceUpdateRemoteProductSendImage=Erreur de l'envoi d'une image pour le produit distante 'id:%s' dans les média de Wordpress sur le site '%s': %s
+ECommerceWoocommerceUpdateRemoteProductVariation=Erreur de mise à jour de la variation 'id:%s' du produit distant 'id:%s' sur le site '%s': %s
+ECommerceWoocommerceUpdateRemoteSociete=Erreur de mise à jour de la société distante 'id:%s' sur le site '%s': %s
+ECommerceWoocommerceUpdateRemoteSocpeople=Erreur de mise à jour des contacts/adresses de la société distante 'id:%s' sur le site '%s': %s
+ECommerceWoocommerceUpdateRemoteStockProduct=Erreur de mise à jour des stocks de la variation 'id:%s' du produit distant 'id:%s' sur le site '%s': %s
+ECommerceWoocommerceUpdateRemoteStockProductVariation=Erreur de mise à jour des stocks du produit distant 'id:%s' sur le site '%s': %s
+ECommerceWoocommerceGetAllWoocommerceTaxClass=Erreur de récupération des données des classes de taxes sur le site '%s': %s
+ECommerceWoocommerceGetWoocommerceTaxes=Erreur de récupération des données des taxes sur le site '%s': %s
+
+ECommercengWoocommerceStatus=Statut pour le site "%s"
+ECommercengWoocommerceDescription=Description boutique
+ECommercengWoocommerceShortDescription=Description courte boutique
+ECommercengWoocommerceOnlinePayment=Paiement en ligne
+ECommercengWoocommerceTaxClass=Classe de TVA pour le site "%s"
+
+ECommercengWoocommerceDictTaxClass=Liste des classes de TVA sur Woocommerce
+ECommercengWoocommerceDictTaxClassUpdated=Dictionnaire des classes de TVA sur Woocommerce mise à jour.
+ECommerceWoocommerceConfirmUpdateDictTaxClasses=Confirmer la mise à jour du dictionnaire des classes de TVA pour ce site ?
+ECommerceWoocommerceUpdateDictTaxClasses=Mise à jour du dictionnaire des classes de TVA
+ECommerceWoocommerceErrorDisableDictTaxClass=Erreur de déactivation d'une classe de TVA, code:"%s", erreur:"%s"
+ECommerceWoocommerceErrorAddDictTaxClass=Erreur d'ajout d'une classe de TVA, code:"%s", name:"%s", erreur:"%s"
+
+ECommercengWoocommerceStatusDraft=Draft
+ECommercengWoocommerceStatusPending=Pending
+ECommercengWoocommerceStatusPrivate=Private
+ECommercengWoocommerceStatusPublish=Publish
+
+ECommercengWoocommerceWithoutFirstnameLastname=No firstname/lastname informed
+ECommercengWoocommerceLastnameNotInformed=[Lastname not informed]
diff --git a/htdocs/ecommerceng/langs/fr_FR/ecommerce.lang b/htdocs/ecommerceng/langs/fr_FR/ecommerce.lang
old mode 100755
new mode 100644
index a7a8fd1..e78e49d
--- a/htdocs/ecommerceng/langs/fr_FR/ecommerce.lang
+++ b/htdocs/ecommerceng/langs/fr_FR/ecommerce.lang
@@ -1,20 +1,38 @@
# Dolibarr language file - fr_FR - ECommerce
CHARSET=UTF-8
-ECommerceMagentoPriceType=Type de prix importés
-ECommerceMagentoPriceTypeHT=Hors Taxes
-ECommerceMagentoPriceTypeTTC=Toutes Taxes Comprises
-ECommerceMagentoPriceTypeDescription=Définit l'application de la TVA sur les prix des produits Magento importés (HT ou TTC)
+
+##PERMISSIONS##
+Permission107101=Lire les statuts de synchronisation des sites e-commerce
+Permission107102=Synchroniser les sites e-commerce
+Permission107103=Configurer les sites e-commerce
+
+##ADMIN##
+Module107100Name=EcommerceNG
+Module107100Desc=Module de synchronisation entre Dolibarr et les plateformes e-commerce Magento et WooCommerce
+BackToListOfSites=Retour à la liste des sites
+NothingToSetup=Activez le module pour accéder à sa configuration
+
+##SETUP##
+magento=Magento
+woocommerce=WooCommerce
+ECommercetoDolibarr=De E-Commerce vers Dolibarr
+DolibarrToeCommerce=De Dolibarr vers E-Commerce
+ECommercePriceType=Type de prix importés
+ECommercePriceTypeHT=Hors Taxes
+ECommercePriceTypeTTC=Toutes Taxes Comprises
+ECommercePriceTypeDescription=Définit l'application de la TVA sur les prix des produits E-Commerce importés (HT ou TTC)
ECommerceMagentoUseSpecialPriceDescription=Cocher pour importer en priorité les prix spéciaux Magento des produits au lieu des prix publics (le prix public ne sera importé que si le prix spécial n'est pas renseigné)
+WarningStockProductNotFilled=L'entrepôt n'est pas renseigné
ECommerceMagentoUseSpecialPrice=Utiliser le prix spécial Magento
-ECommerceDashboard=Gestion des synchronisations ECommerce
-ECommerceSetup=Configuration du module Ecommerce
+ECommerceDashboard=Gestion des synchronisations E-Commerce
+ECommerceSetup=Configuration du module E-Commerce
ECommerceAddNewSite=Ajouter un nouveau site
ECommerceCreateSite=Création d'un nouveau site
ECommerceSetupSite=Configuration du site
ECommerceSiteName=Nom du site
ECommerceCatProduct=Catégorie des produits
ECommerceCatSociete=Catégorie des clients
-ECommerceFilterLabel=Label du filtre
+ECommerceFilterLabel=Libellé du filtre
ECommerceFilterValue=Valeur du filtre
ECommerceSiteType=Type de site
ECommerceSiteAddress=Adresse du site
@@ -22,29 +40,31 @@ ECommerceUserName=Nom d'utilisateur
ECommerceUserPassword=Mot de passe - API key
ECommerceUserPasswordRetype=Retapez le mot de passe - API key
ECommerceConfirmDelete=Êtes vous sûre de vouloir supprimer ce site ?
-ECommerceConfirmReset=Êtes vous sûre de vouloir purger les données synchronisées liées à ce site? (Attention, cette action est irréversible, toute les données synchronisées seront perdues)
+ECommerceConfirmReset=Êtes vous sûre de vouloir purger les données synchronisées liées à ce site? (Attention : cette action est irréversible, toute les données synchronisées seront perdues)
ECommerceSetupSaved=La configuration a bien été enregistrée.
ECommerceSetupErrorDb=Une erreur est survenue lors de l'enregistrement dans la base de données.
ECommerceDeleteOk=Le site a bien été supprimé.
ECommerceSetupPasswordNotSame=Le mot de passe doit être identique dans les 2 champs.
ECommerceSetupNameEmpty=Le nom du site est obligatoire.
-ECommerceSiteNameDescription=Indiquez le nom qui sera affiché dans Dolibarr (exemple : Mon Site)
-ECommerceCatProductDescription=Sélectionnez la catégorie Produit mère Dolibarr qui accueille les catégories Produit à synchroniser avec Magento (à créer une fois le module Catégories Dolibarr activé). Exemple: "Catégories Produits Magento"
-ECommerceCatSocieteDescription=Sélectionnez la catégorie Tiers client Dolibarr pour marquer les clients Magento (à créer une fois le module Catégories Dolibarr activé). Exemple: "Clients Eboutique Magento"
+ECommerceSiteNameDescription=Indiquez le nom qui sera affiché dans la liste des site e-commerce dans Dolibarr (exemple : Mon Site)
+ECommerceCatProductDescription=Sélectionnez la catégorie Produit mère Dolibarr qui accueille les catégories Produit à synchroniser avec la plateforme e-commerce (à créer une fois le module Catégories de Dolibarr activé). Exemple: "Catégories Produits Magento"
+ECommerceCatSocieteDescription=Sélectionnez la catégorie Tiers client Dolibarr pour marquer les clients e-commerce (à créer une fois le module Catégories Dolibarr activé). Exemple: "Clients Eboutique Magento"
ECommerceFilterLabelDescription=Indiquez un filtre (exemple : store_id)
ECommerceFilterValueDescription=Indiquez la valeur du filtre (exemple : *)
ECommerceSiteTypeDescription =Sélectionnez un type de site
-ECommerceSiteAddressDescription=URL des API v1 Magento. Exemple : http://localhost/api/?wsdl, http://www.example.com/magento/index.php/api/?wsdl, http://www.example.com/magento/index.php/api/soap/?wsdl (Note: L'accès par localhost peut ne pas fonctionner)
-ECommerceUserNameDescription=Compte à créer dans Magento via le menu SOAP/XML-RPC users. Ce compte doit aussi être placé dans un role créé dans magento via le menu SOAP/XML-RPC roles (donnez de préférence tous les droits à ce role). Exemple : soapuser
-ECommerceUserPasswordDescription=Compte à créer dans magento via le menu SOAP/XML-RPC users. Ce compte doit aussi être placé dans un role créé dans magento via le menu SOAP/XML-RPC roles (donnez de préférence tous les droits à ce role). Exemple : myapikey
+ECommerceSiteAddressDescription=URL des API v1 Magento. Exemples : http://localhost/api/?wsdl, http://www.example.com/magento/index.php/api/?wsdl ou encore http://www.example.com/magento/index.php/api/soap/?wsdl (Note: L'accès par localhost peut ne pas fonctionner)
+ECommerceUserNameDescription=Compte à créer dans Magento via le menu SOAP/XML-RPC users. Ce compte doit aussi être placé dans un rôle créé dans magento via le menu SOAP/XML-RPC roles (donnez de préférence tous les droits à ce role). Exemple : soapuser. Dans WooCommerce, Clé API Client
+ECommerceUserPasswordDescription=Compte à créer dans magento via le menu SOAP/XML-RPC users. Ce compte doit aussi être placé dans un role créé dans magento via le menu SOAP/XML-RPC roles (donnez de préférence tous les droits à ce rôle). Exemple : myapikey. Dans WooCommerce, Clé API Secret Client
ECommerceSite=Site
ECommerceLastUpdate=Dernière mise à jour
-ECommerceNoUpdateSite=Ce site n'a jamais été synchronisé ENTIEREMENT (Entierement = plus aucun élément à synchroniser)
+ECommerceNoUpdateSite=Ce site n'a jamais été synchronisé ENTIÈREMENT (Entièrement = plus aucun élément à synchroniser)
ECommerceUpdateSite=Synchronisation détaillée du site
ECommerceUpdateAll=Tout synchroniser pour ce site
+ECommerceStockProduct=Entrepôt
+ECommerceStockProductDescription=Si vous définissez l'option précédente de %s à E-Commerce vers Dolibarr, les produits créés ou modifiés depuis la plateforme e-commerce seront synchronisés dans Dolibarr dans cet entrepôt. Attention : Les stocks de Dolibarr sont modifiés lors de la synchronisation des produits et non pas pendant la synchronisation de commandes ou des factures.
ECommerceReset=Supprimer de Dolibarr toutes les données issues de synchronisation de la boutique Ecommerce
ECommerceResetLink=Supprimer les enregistrements liens entre Dolibarr et la boutique Ecommerce
-ECommerceMenu=ECommerce synchro.
+ECommerceMenu=Synchro. E-Commerce
ECommerceSetupCatProductEmpty=Une catégorie produit est obligatoire.
ECommerceSetupCatSocieteEmpty=Une catégorie client est obligatoire.
ECommerceSetupTypeEmpty=Le type de site est obligatoire.
@@ -55,7 +75,7 @@ ECommerceSiteSynchro=Synchronisation du site
ECommerceProducts=Produits
ECommerceCommande=Commandes
ECommerceFacture=Factures
-ECommerceObjectToUpdate=Eléments à synchroniser
+ECommerceObjectToUpdate=Éléments à synchroniser
ECommerceCountToUpdate=Nombre d'éléments à synchroniser (modifié côté Ecommerce et non à jour dans Dolibarr)
ECommerceSiteErrorConnect=Un problème de connection est survenue. Merci de réessayer.
ECommerceSynchronizeSociete = Synchroniser les tiers clients et contacts de tiers
@@ -63,13 +83,13 @@ ECommerceSynchronizeProduct = Synchroniser les produits
ECommerceSynchronizeCommande = Synchroniser les commandes
ECommerceSynchronizeFacture = Synchroniser les factures
ECommerceSynchSocieteErrorCreateUpdateSociete=Erreur dans le synchronisation du client
-ECommerceErrorGetSocieteToUpdate=Un problème de connection est survenue lors de la récupération des sociétés. Merci de réessayer.
+ECommerceErrorGetSocieteToUpdate=Un problème de connection est survenue lors de la récupération des clients. Merci de réessayer.
ECommerceErrorGetProduitsToUpdate=Un problème de connection est survenue lors de la récupération des produits. Merci de réessayer.
ECommerceErrorGetCategoryToUpdate=Un problème de connection est survenue lors de la récupération des catégories. Merci de réessayer.
ECommerceErrorGetCommandeToUpdate=Un problème de connection est survenue lors de la récupération des commandes. Merci de réessayer.
ECommerceErrorGetFactureToUpdate=Un problème de connection est survenue lors de la récupération des factures. Merci de réessayer.
ECommerceReboot=Veuillez désactiver le module et le réactiver avant de réessayer.
-ECommerceAnonymousCreateFailed=Echec de création de l'objet de synchronisation correspondant au tiers anonyme.
+ECommerceAnonymousCreateFailed=Échec de création de l'objet de synchronisation correspondant au tiers anonyme.
ECommerceNoDbAnonymous=Le tiers anonyme n'existe pas dans la base de donnée.
ECommerceResetDolFactureSuccess=factures importées ont bien été supprimées.
ECommerceResetSynchFactureSuccess=références de synchronisation de factures ont bien été supprimées.
@@ -79,8 +99,8 @@ ECommerceResetDolProductSuccess=produits importées ont bien été supprimées.
ECommerceResetSynchProductSuccess=références de synchronisation de produits ont bien été supprimées.
ECommerceResetDolSocpeopleSuccess=contacts importées ont bien été supprimées.
ECommerceResetSynchSocpeopleSuccess=références de synchronisation de contacts ont bien été supprimées.
-ECommerceResetDolSocieteSuccess=sociétés importées ont bien été supprimées.
-ECommerceResetSynchSocieteSuccess=références de synchronisation de sociétés ont bien été supprimées.
+ECommerceResetDolSocieteSuccess=tiers clients importés ont bien été supprimées.
+ECommerceResetSynchSocieteSuccess=références de synchronisation de tiers clients ont bien été supprimées.
ECommerceResetDolCategorySuccess=catégories importées ont bien été supprimées (ce nombre peut-être supérieur à celui indiqué en incluant les enfants des catégories supprimées).
ECommerceResetSynchCategorySuccess=références de synchronisation de catégories ont bien été supprimées (ce nombre peut-être supérieur à celui indiqué en incluant les enfants des références supprimées).
ECommerceSyncheCommerceCategoryUpdateError=Erreur dans la mise à jour d'une catégorie.
@@ -88,53 +108,96 @@ ECommerceSyncheCommerceCategoryCreateError=Erreur lors de la création d'une cat
ECommerceSynchronizeCategoryProduct=Synchroniser les catégories de produits
ECommerceSynchCategoryError=Erreur lors de la synchronisation des catégories.
ECommerceSynchCategorySuccess=catégories ont bien été synchronisées.
-ECommerceSynchCategoryNoImportRoot=La synchronization des catégories a été annulée car la catégorie d'import de Dolibarr n'est pas définies. Veuillez la définir dans la configuration de synchronisation avant de réessayer.
+ECommerceSynchCategoryNoImportRoot=La synchronisation des catégories a été annulée car la catégorie d'import de Dolibarr n'est pas définie. Veuillez la définir dans la configuration de synchronisation avant de réessayer.
ECommerceSynchCategoryConnectError=Une erreur de connexion est survenue durant la synchronisation des catégories. Veuillez réessayer.
-ECommerceSynchSocieteSuccess=sociétés ont bien été synchronisées.
+ECommerceSynchSocieteSuccess=clients ont bien été synchronisées.
ECommerceSynchProductSuccess=produits ont bien été synchronisés.
ECommerceSynchCommandeSuccess=commandes ont bien été synchronisées.
ECommerceSynchFactureSuccess=factures ont bien été synchronisées.
-ECommerceSynchECommerceSocpeopleCreateError=Une erreur est survenue lors de l'enregistrement du contact.
+ECommerceSynchECommerceSocpeopleCreateError=Une erreur est survenue lors de l'enregistrement du contact (societe ID: %s; prénom: %s; nom: %s).
ECommerceSetupSites=Configuration des sites
ECommerceTimeout=Timeout des accès APIS
+ECommerceClickUrlToTestUrl=Cliquez ici pour tester l'URL (un fichier XML ou JSON doit s'afficher)
ECommerceTimeoutDescription=Timeout pour les accès aux APIs, en secondes
ECommerceSetupTimeoutEmpty=Durée de connexion vide
ECommerceSetupTimeoutMustBeInt=La durée de connexion doit-être un entier
ECommerceCategoriesProducts=Catégories de produits
-SyncCategFirst=Synchroniser les catégories d'abord
+SyncCategFirst=Synchroniser d'abord les catégories
ECommerceSynchCommandeError=Erreur durant la synchronisation des commandes
-OnlyThirdPartyWithTags=Nb de tiers ayant le tag '%s' (donc sensé être commun avec la boutique en ligne)
+OnlyThirdPartyWithTags=Nb de tiers rattachés à la catégorie %s (donc sensé être commun avec la boutique en ligne)
NbInDolibarr=Nb dans l'ERP
-NbInDolibarrLinkedToE=Nb dans l'ERP lié à la boutique
+NbInDolibarrLinkedToE=Nb dans l'ERP liés à la boutique
ModuleCustomerOrderDisabled=Non géré (module Commande Client désactivé)
-ECommerceLastCompleteSync=Date de la dernière synchro de %s vers Dolibarr réalisée ENTIEREMENT (=plus aucun élément à synchroniser)
-WithMagentoThirdIsModifiedIfAddressModified=Avec Magento, un tiers sera vue modifié aussi si un de ces contacts/address a été modifié
+ECommerceLastCompleteSync=Date de la dernière synchronisation de %s vers Dolibarr réalisée ENTIÈREMENT (Entièrement = plus aucun élément à synchroniser)
+WithMagentoThirdIsModifiedIfAddressModified=Avec Magento et WooCommerce, un tiers sera aussi considéré comme modifié si un de ces contacts/adresses a été modifié.
SyncSocieteFirst=Synchroniser d'abord les tiers
SyncCommandeFirst=Synchroniser d'abord les commandes
-OnlyProductsIn=Only products with category %s or sub-categories of '%s' are synchronized from Dolibarr to Magento
-NbInDolibarr=Nb into ERP
-NbInDolibarrLinkedToE=Nb into ERP linked to ecommerce
-RefreshCount=Raffraichir le comptage
+OnlyProductsIn=Seuls les produits de la catégorie %s et de ses sous-catégories sont synchronisées de Dolibarr vers Magento ou WooCommerce.
+NbInDolibarr=Nb dans l'ERP
+NbInDolibarrLinkedToE=NB dans l'ERP liés à la boutique
+RefreshCount=Rafraîchir le comptage
ModuleCustomerOrderDisabled=Not supported (module Customer Order disabled)
ECommerceLastCompleteSync=Last synchronize from %s to Dolibarr done completely (no more elements to synchronize)
-SyncIsAutomaticInRealTime=Synchronization from Dolibarr to %s is done automatically in real time.
+SyncIsAutomaticInRealTime=La synchronisation De Dolibarr vers %s est effectuée en temps réel.
WithMagentoThirdIsModifiedIfAddressModified=With Magento, a third party is also flagged as modified if one of its contact/address is modified
-OnlyProductCategIn=Only sub-categories of product category '%s' are synchronized from Dolibarr to Magento
-OnlyThirdPartyIn=Only thirdparties with thirdparty category '%s' are synchronized from Dolibarr to Magento
+OnlyProductCategIn=Seule la catégorie %s et ses sous-catégories sont synchronisée de Dolibarr vers Magento ou WooCommerce.
+OnlyThirdPartyIn=Seuls les tiers de la catégorie %s et de ses sous-catégories sont synchronisées de Dolibarr vers Magento ou WooCommerce.²
OnlyThirdPartyWithTags=Nb of thirdparties with tag '%s' (so that should be common with the online ecommerce shop)
-WarningSoapCacheIsOn=Warning: WSDL cache is on into directory '%s'.
+WarningSoapCacheIsOn=Attention : WSDL cache is on into directory %s.
WarningSoapCacheIsOn2=Changer %s ou son contenu peut ne pas être vu par le PHP.
SoapCacheIsOff=Votre cache PHP WSDL est inactif.
SetupOfWarehouseNotDefinedForThisSite=A new or modified product were found on eCommerce shop with a different stock level than into Dolibarr. To be able to create/update them in Dolibarr, you must setup the warehouse to initialize.
-ECommerceStockSyncDirection=Stock synchronisation direction
-ECommerceStockSyncDirectionDescription=Define if you want to see stock decrease in Dolibarr when stock decrease on Magento (rare), or overwrite Magento stock when stock in Dolibarr is modified (common choice)
-MainSyncSetup=Configuration synchronisation générale
-StockSyncSetup=Configuration synchronisation stock
-ErrorModuleSoapRequired=Error: PHP module SOAP is required to have this module working.
+ECommerceStockSyncDirection=Synchronisation des stocks
+ECommerceStockSyncDirectionDescription=Ce paramètre détermine : - Si le stock doit être décrémenté dans Dolibarr suite à une décrémentation du stock e-commerce (rare) ou - Si le stock e-commerce doit être remplacé par le stock Dolibarr suite à sa modification (choix commun)
+MainSyncSetup=Synchronisation générale
+StockSyncSetup=Synchronisation des stocks
+ErrorModuleSoapRequired=Erreur: Le module PHP SOAP est requis pour le bon fonctionnement du module.
SyncAll=Synchroniser tout
-DangerZone=Zone dangeureuse
+DangerZone=Zone dangereuse
ShowDebugTools=Afficher les outils d'init/purge/debug
ECommerceShipping=Frais de port
ECommercePriceLevel=Niveau de prix
-ECommercePriceLevelDescription=Seulement ce niveau de prix sera shynchronisé entre Dolibarr et Ecommerce
-ECommerceConfirmUpdatePriceLevel=Vous avez modifié le niveau de prix et les produits sur le eCommerce vont être mises à jour.\nCette opération peut être longue, merci de confirmer.
+ECommercePriceLevelDescription=Seul ce niveau de prix sera synchronisé entre Dolibarr et Ecommerce
+ECommerceConfirmUpdatePriceLevel=Vous avez modifié le niveau de prix. Les produits sur le site e-commerce vont être mis à jour.\nCette opération peut être longue, merci de confirmer.
+
+## OAuth Setup ##
+ECommerceOAuthWordpressSetup=Connexion OAuth2 sur WordPress ( Allez sur cette page , puis "Ajouter un nouveau client" pour créer les informations d'identification OAuth2 )
+ECommerceSiteOAuthRedirectUri=Url de redirection
+ECommerceSiteOAuthRedirectUriDescription=Utilisez l'URL suivante comme URI de redirection (Callback) quand vous créez une nouvelle application (ou un nouveau client)
+ECommerceSiteOAuthId=OAuth ID
+ECommerceSiteOAuthIdDescription=Id de connexion au service OAuth
+ECommerceSiteOAuthSecret=OAuth secret
+ECommerceSiteOAuthSecretDescription=Secret de connexion au service OAuth
+ECommerceOAuthCheckToken=Allez sur cette page pour vérifier/effacer les autorisations sauvées par le fournisseur OAuth2.
+
+ECommerceSynchronizeProductImages=Synchroniser les images
+ECommerceProductImagesSynchronized=Les images ont été synchronisées.
+
+ECommerceRemoteAccessConnect=Erreur de connection au site '%s': %s
+ECommerceRemoteAccessConvertRemoteObjectIntoDolibarrCommande=Erreur de recuperation des commandes sur le site '%s': %s
+ECommerceRemoteAccessConvertRemoteObjectIntoDolibarrProduct=Erreur de recuperation des produits sur le site '%s': %s
+ECommerceRemoteAccessConvertRemoteObjectIntoDolibarrProductVariations=Erreur de recuperation des variations du produit distant 'id:%s' sur le site '%s': %s
+ECommerceRemoteAccessConvertRemoteObjectIntoDolibarrSociete=Erreur de recuperation des sociétés sur le site '%s': %s
+ECommerceRemoteAccessConvertRemoteObjectIntoDolibarrSocpeople=Erreur de recuperation des sociétés (pour les contacts/adresses) sur le site '%s': %s
+ECommerceRemoteAccessCreateRemoteProduct=Erreur de creation du produit 'id:%s' sur le site '%s': %s
+ECommerceRemoteAccessCreateRemoteProductLink=Erreur de creation du lien pour le produit 'id:%s' pour le site '%s': %s
+ECommerceRemoteAccessGetCategoryData=Erreur de récupération des données de la catégorie distante 'id:%s' sur le site '%s': %s
+ECommerceRemoteAccessGetCommandeToUpdate=Erreur de récupération de la liste des commandes à mettre à jour sur le site '%s': %s
+ECommerceRemoteAccessGetProductToUpdate=Erreur de récupération de la liste des produits à mettre à jour sur le site '%s': %s
+ECommerceRemoteAccessGetRemoteCategoryTree=Erreur de récupération de la liste des catégories à mettre à jour sur le site '%s': %s
+ECommerceRemoteAccessGetSocieteToUpdate=Erreur de récupération de la liste des sociétés à mettre à jour sur le site '%s': %s
+ECommerceRemoteAccessSendFileForCommande=Erreur pour lier le fichier avec la commande distante 'id:%s' sur le site '%s': %s
+ECommerceRemoteAccessSendFileForCommandeInWordpress=Erreur de l'envoi du fichier pour la commande distante 'id:%s' dans les média de Wordpress sur le site '%s': %s
+ECommerceRemoteAccessUpdateRemoteCommande=Erreur de mise à jour de la commande distante 'id:%s' sur le site '%s': %s
+ECommerceRemoteAccessUpdateRemoteProduct=Erreur de mise à jour du produit distant 'id:%s' sur le site '%s': %s
+ECommerceRemoteAccessUpdateRemoteProductGetRemoteProduct=Erreur de récupération du produit distant 'id:%s' sur le site '%s': %s
+ECommerceRemoteAccessUpdateRemoteProductSendImage=Erreur de l'envoi d'une image pour le produit distante 'id:%s' dans les média de Wordpress sur le site '%s': %s
+ECommerceRemoteAccessUpdateRemoteProductVariation=Erreur de mise à jour de la variation 'id:%s' du produit distant 'id:%s' sur le site '%s': %s
+ECommerceRemoteAccessUpdateRemoteSociete=Erreur de mise à jour de la société distante 'id:%s' sur le site '%s': %s
+ECommerceRemoteAccessUpdateRemoteSocpeople=Erreur de mise à jour des contacts/adresses de la société distante 'id:%s' sur le site '%s': %s
+ECommerceRemoteAccessUpdateRemoteStockProduct=Erreur de mise à jour des stocks de la variation 'id:%s' du produit distant 'id:%s' sur le site '%s': %s
+ECommerceRemoteAccessUpdateRemoteStockProductVariation=Erreur de mise à jour des stocks du produit distant 'id:%s' sur le site '%s': %s
+
+ECommerceSyncheCommerceProductDownloadImageError=Erreur de récupération de l'image (%s) pour le produit 'id:%s' du produit distant 'id:%s' sur le site '%s'
+
+ECommerceNoDescForProductLine=L'api n'a pas pu récupérer la description du produit
diff --git a/htdocs/ecommerceng/langs/fr_FR/woocommerce.lang b/htdocs/ecommerceng/langs/fr_FR/woocommerce.lang
new file mode 100644
index 0000000..6eb493c
--- /dev/null
+++ b/htdocs/ecommerceng/langs/fr_FR/woocommerce.lang
@@ -0,0 +1,50 @@
+# Dolibarr language file - fr_FR - ECommerce
+CHARSET=UTF-8
+
+ECommerceWoocommerceConnect=Erreur de connection au site '%s': %s
+ECommerceWoocommerceConvertRemoteObjectIntoDolibarrCommande=Erreur de recuperation des commandes sur le site '%s': %s
+ECommerceWoocommerceConvertRemoteObjectIntoDolibarrProduct=Erreur de recuperation des produits sur le site '%s': %s
+ECommerceWoocommerceConvertRemoteObjectIntoDolibarrProductVariations=Erreur de recuperation des variations du produit distant 'id:%s' sur le site '%s': %s
+ECommerceWoocommerceConvertRemoteObjectIntoDolibarrSociete=Erreur de recuperation des sociétés sur le site '%s': %s
+ECommerceWoocommerceConvertRemoteObjectIntoDolibarrSocpeople=Erreur de recuperation des sociétés (pour les contacts/adresses) sur le site '%s': %s
+ECommerceWoocommerceCreateRemoteProduct=Erreur de creation du produit 'id:%s' sur le site '%s': %s
+ECommerceWoocommerceCreateRemoteProductLink=Erreur de creation du lien pour le produit 'id:%s' pour le site '%s': %s
+ECommerceWoocommerceGetCategoryData=Erreur de récupération des données de la catégorie distante 'id:%s' sur le site '%s': %s
+ECommerceWoocommerceGetCommandeToUpdate=Erreur de récupération de la liste des commandes à mettre à jour sur le site '%s': %s
+ECommerceWoocommerceGetProductToUpdate=Erreur de récupération de la liste des produits à mettre à jour sur le site '%s': %s
+ECommerceWoocommerceGetRemoteCategoryTree=Erreur de récupération de la liste des catégories à mettre à jour sur le site '%s': %s
+ECommerceWoocommerceGetSocieteToUpdate=Erreur de récupération de la liste des sociétés à mettre à jour sur le site '%s': %s
+ECommerceWoocommerceSendFileForCommande=Erreur pour lier le fichier avec la commande distante 'id:%s' sur le site '%s': %s
+ECommerceWoocommerceSendFileForCommandeInWordpress=Erreur de l'envoi du fichier pour la commande distante 'id:%s' dans les média de Wordpress sur le site '%s': %s
+ECommerceWoocommerceUpdateRemoteCommande=Erreur de mise à jour de la commande distante 'id:%s' sur le site '%s': %s
+ECommerceWoocommerceUpdateRemoteProduct=Erreur de mise à jour du produit distant 'id:%s' sur le site '%s': %s
+ECommerceWoocommerceUpdateRemoteProductGetRemoteProduct=Erreur de récupération du produit distant 'id:%s' sur le site '%s': %s
+ECommerceWoocommerceUpdateRemoteProductSendImage=Erreur de l'envoi d'une image pour le produit distante 'id:%s' dans les média de Wordpress sur le site '%s': %s
+ECommerceWoocommerceUpdateRemoteProductVariation=Erreur de mise à jour de la variation 'id:%s' du produit distant 'id:%s' sur le site '%s': %s
+ECommerceWoocommerceUpdateRemoteSociete=Erreur de mise à jour de la société distante 'id:%s' sur le site '%s': %s
+ECommerceWoocommerceUpdateRemoteSocpeople=Erreur de mise à jour des contacts/adresses de la société distante 'id:%s' sur le site '%s': %s
+ECommerceWoocommerceUpdateRemoteStockProduct=Erreur de mise à jour des stocks de la variation 'id:%s' du produit distant 'id:%s' sur le site '%s': %s
+ECommerceWoocommerceUpdateRemoteStockProductVariation=Erreur de mise à jour des stocks du produit distant 'id:%s' sur le site '%s': %s
+ECommerceWoocommerceGetAllWoocommerceTaxClass=Erreur de récupération des données des classes de taxes sur le site '%s': %s
+ECommerceWoocommerceGetWoocommerceTaxes=Erreur de récupération des données des taxes sur le site '%s': %s
+
+ECommercengWoocommerceStatus=Statut pour le site "%s"
+ECommercengWoocommerceDescription=Description boutique
+ECommercengWoocommerceShortDescription=Description courte boutique
+ECommercengWoocommerceOnlinePayment=Paiement en ligne
+ECommercengWoocommerceTaxClass=Classe de TVA pour le site "%s"
+
+ECommercengWoocommerceDictTaxClass=Liste des classes de TVA sur Woocommerce
+ECommercengWoocommerceDictTaxClassUpdated=Dictionnaire des classes de TVA sur Woocommerce mise à jour.
+ECommerceWoocommerceConfirmUpdateDictTaxClasses=Confirmer la mise à jour du dictionnaire des classes de TVA pour ce site ?
+ECommerceWoocommerceUpdateDictTaxClasses=Mise à jour du dictionnaire des classes de TVA
+ECommerceWoocommerceErrorDisableDictTaxClass=Erreur de déactivation d'une classe de TVA, code:"%s", erreur:"%s"
+ECommerceWoocommerceErrorAddDictTaxClass=Erreur d'ajout d'une classe de TVA, code:"%s", name:"%s", erreur:"%s"
+
+ECommercengWoocommerceStatusDraft=Brouillon
+ECommercengWoocommerceStatusPending=En attente de relecture
+ECommercengWoocommerceStatusPrivate=Privé
+ECommercengWoocommerceStatusPublish=Publié
+
+ECommercengWoocommerceWithoutFirstnameLastname=Pas de nom/prénom renseigné
+ECommercengWoocommerceLastnameNotInformed=[Nom non renseigné]
diff --git a/htdocs/ecommerceng/lib/eCommerce.lib.php b/htdocs/ecommerceng/lib/eCommerce.lib.php
index 7131da7..7f194fb 100644
--- a/htdocs/ecommerceng/lib/eCommerce.lib.php
+++ b/htdocs/ecommerceng/lib/eCommerce.lib.php
@@ -17,8 +17,10 @@
*/
+include_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
dol_include_once('/ecommerceng/class/data/eCommerceProduct.class.php');
dol_include_once('/ecommerceng/class/business/eCommerceSynchro.class.php');
+dol_include_once('/ecommerceng/class/data/woocommerce/eCommerceRemoteAccessWoocommerce.class.php');
/**
* Update the price for all product in the ecommerce product category for this site price level
@@ -85,3 +87,399 @@ function updatePriceLevel($siteDb)
return 1;
}
+function ecommerceng_wordpress_sanitize_file_name( $filename ) {
+ //$filename_raw = $filename;
+ $special_chars = array("?", "[", "]", "/", "\\", "=", "<", ">", ":", ";", ",", "'", "\"", "&", "$", "#", "*", "(", ")", "|", "~", "`", "!", "{", "}", "%", "+", chr(0));
+ /**
+ * Filters the list of characters to remove from a filename.
+ *
+ * @since 2.8.0
+ *
+ * @param array $special_chars Characters to remove.
+ * @param string $filename_raw Filename as it was passed into sanitize_file_name().
+ */
+ $filename = preg_replace( "#\x{00a0}#siu", ' ', $filename );
+ $filename = str_replace( $special_chars, '', $filename );
+ $filename = str_replace( array( '%20', '+' ), '-', $filename );
+ $filename = preg_replace( '/[\r\n\t -]+/', '-', $filename );
+ $filename = trim( $filename, '.-_' );
+
+ /*if ( false === strpos( $filename, '.' ) ) {
+ $mime_types = wp_get_mime_types();
+ $filetype = wp_check_filetype( 'test.' . $filename, $mime_types );
+ if ( $filetype['ext'] === $filename ) {
+ $filename = 'unnamed-file.' . $filetype['ext'];
+ }
+ }*/
+
+ // Split the filename into a base and extension[s]
+ //$parts = explode('.', $filename);
+
+ // Return if only one extension
+ /*if ( count( $parts ) <= 2 ) {
+ /**
+ * Filters a sanitized filename string.
+ *
+ * @since 2.8.0
+ *
+ * @param string $filename Sanitized filename.
+ * @param string $filename_raw The filename prior to sanitization.
+ */
+ /* return apply_filters( 'sanitize_file_name', $filename, $filename_raw );
+ }*/
+
+ // Process multiple extensions
+ /*$filename = array_shift($parts);
+ $extension = array_pop($parts);
+ $mimes = get_allowed_mime_types();
+
+ /*
+ * Loop over any intermediate extensions. Postfix them with a trailing underscore
+ * if they are a 2 - 5 character long alpha string not in the extension whitelist.
+ */
+ /*foreach ( (array) $parts as $part) {
+ $filename .= '.' . $part;
+
+ if ( preg_match("/^[a-zA-Z]{2,5}\d?$/", $part) ) {
+ $allowed = false;
+ foreach ( $mimes as $ext_preg => $mime_match ) {
+ $ext_preg = '!^(' . $ext_preg . ')$!i';
+ if ( preg_match( $ext_preg, $part ) ) {
+ $allowed = true;
+ break;
+ }
+ }
+ if ( !$allowed )
+ $filename .= '_';
+ }
+ }
+ $filename .= '.' . $extension;
+ /** This filter is documented in wp-includes/formatting.php */
+ //return apply_filters('sanitize_file_name', $filename, $filename_raw);
+ return $filename;
+}
+
+function ecommerceng_download_image($image, $product, &$error_message)
+{
+ dol_syslog(__METHOD__.': image=' . implode(',',$image) . ' product_id=' . $product->id, LOG_DEBUG);
+ global $db, $conf, $maxwidthsmall, $maxheightsmall, $maxwidthmini, $maxheightmini;
+
+ if ($product->type != Product::TYPE_PRODUCT && $product->type != Product::TYPE_SERVICE) {
+ $error_message = "Error the product is not a product or service type";
+ dol_syslog(__METHOD__.': '.$error_message, LOG_ERR);
+ return false;
+ }
+
+ $entity = isset($product->entity) ? $product->entity : $conf->entity;
+
+ // Set upload directory
+ if (!empty($conf->global->PRODUCT_USE_OLD_PATH_FOR_PHOTO)) { // For backward compatiblity, we scan also old dirs
+ if ($product->type == Product::TYPE_PRODUCT) {
+ $upload_dir = $conf->product->multidir_output[$entity] . '/' . substr(substr("000" . $product->id, -2), 1, 1) . '/' . substr(substr("000" . $product->id, -2), 0, 1) . '/' . $product->id . "/photos";
+ } else {
+ $upload_dir = $conf->service->multidir_output[$entity] . '/' . substr(substr("000" . $product->id, -2), 1, 1) . '/' . substr(substr("000" . $product->id, -2), 0, 1) . '/' . $product->id . "/photos";
+ }
+ } else {
+ if ($product->type == Product::TYPE_PRODUCT) {
+ $upload_dir = $conf->product->multidir_output[$entity] . '/' . get_exdir(0, 0, 0, 0, $product, 'product') . dol_sanitizeFileName($product->ref);
+ } else {
+ $upload_dir = $conf->service->multidir_output[$entity] . '/' . get_exdir(0, 0, 0, 0, $product, 'product') . dol_sanitizeFileName($product->ref);
+ }
+ }
+
+ // Define $destpath (path to file including filename) and $destfile (only filename)
+ $file_name = basename(parse_url($image['url'], PHP_URL_PATH));
+ $destpath = $upload_dir . "/" . $file_name;
+ $destfile = $file_name;
+
+ // lowercase extension
+ $info = pathinfo($destpath);
+ $destpath = $info['dirname'] . '/' . $info['filename'] . '.' . strtolower($info['extension']);
+ $info = pathinfo($destfile);
+ $destfile = $info['filename'] . '.' . strtolower($info['extension']);
+
+ // Security:
+ // Disallow file with some extensions. We rename them.
+ // Because if we put the documents directory into a directory inside web root (very bad), this allows to execute on demand arbitrary code.
+ if (preg_match('/\.htm|\.html|\.php|\.pl|\.cgi|\.exe$/i', $destfile) && empty($conf->global->MAIN_DOCUMENT_IS_OUTSIDE_WEBROOT_SO_NOEXE_NOT_REQUIRED)) {
+ $destfile .= '.noexe';
+ $destpath .= '.noexe';
+ }
+
+ // Check if image is modified
+ if (file_exists($destpath)) {
+ $local_image_date = new DateTime();
+ $local_image_date->setTimestamp(filectime($destpath));
+ $remote_image_date = new DateTime($image['date_modified']);
+
+ if ($local_image_date >= $remote_image_date) {
+ return true;
+ }
+ }
+
+ dol_syslog(__METHOD__.': upload_dir=' . $upload_dir . ' image=' . implode(',',$image) . ' product_id=' . $product->id . ' dest_path=' . $destpath, LOG_DEBUG);
+
+ if (dol_mkdir($upload_dir) < 0) {
+ $error_message = "Error create product images directory ($upload_dir)";
+ dol_syslog(__METHOD__.': '.$error_message, LOG_ERR);
+ return false;
+ }
+
+ // Get file
+ $timeout = 5;
+ $ch = curl_init();
+ curl_setopt($ch, CURLOPT_URL, $image['url']);
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+ curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
+ $data = curl_exec($ch);
+ curl_close($ch);
+ if ($data === false) {
+ $error_message = curl_error($ch);
+ dol_syslog(__METHOD__.': '.$error_message, LOG_ERR);
+ return false;
+ }
+
+ // Get in temporary file name
+ if (version_compare(phpversion(), '5.2.1', '<')) {
+ if ($conf->global->ECOMMERCE_DOWNLOAD_TMP_DIRECTORY_PATH) {
+ $tmp_path = $conf->global->ECOMMERCE_DOWNLOAD_TMP_DIRECTORY_PATH;
+ } else {
+ $error_message = "Error ECOMMERCE_DOWNLOAD_TMP_DIRECTORY_PATH not defined";
+ dol_syslog(__METHOD__.': '.$error_message, LOG_ERR);
+ return false;
+ }
+ } else {
+ $tmp_path = sys_get_temp_dir();
+ }
+
+ if (dol_mkdir($tmp_path) < 0) {
+ $error_message = "Error create download temporary directory ($tmp_path)";
+ dol_syslog(__METHOD__.': '.$error_message, LOG_ERR);
+ return false;
+ }
+
+ // Save temporary file
+ $temp_file = tempnam($tmp_path, $destfile);
+ $fh = @fopen($temp_file, "w");
+ if ($fh === false) {
+ $error_message = "Error open temporary file ($temp_file)";
+ dol_syslog(__METHOD__.': '.$error_message, LOG_ERR);
+ return false;
+ }
+ $ret = fwrite($fh, $data);
+ if ($ret === false) {
+ $error_message = "Error write data in temporary file ($temp_file)";
+ dol_syslog(__METHOD__.': '.$error_message, LOG_ERR);
+ return false;
+ }
+ $ret = fclose($fh);
+ if ($ret === false) {
+ $error_message = "Error close temporary file ($temp_file)";
+ dol_syslog(__METHOD__.': '.$error_message, LOG_ERR);
+ return false;
+ }
+
+ // If we need to make a virus scan
+ if (empty($disablevirusscan) && file_exists($temp_file) && !empty($conf->global->MAIN_ANTIVIRUS_COMMAND)) {
+ if (!class_exists('AntiVir')) {
+ require_once DOL_DOCUMENT_ROOT . '/core/class/antivir.class.php';
+ }
+ $antivir = new AntiVir($db);
+ $result = $antivir->dol_avscan_file($temp_file);
+ if ($result < 0) // If virus or error, we stop here
+ {
+ $error_message = 'Error file is infected with a virus: ' . join(',', $antivir->errors);
+ dol_syslog('Files.lib::dol_move_uploaded_file File "' . $temp_file . '" (target name "' . $temp_file . '") KO with antivirus: result=' . $result . ' errors=' . join(',', $antivir->errors), LOG_ERR);
+ return false;
+ }
+ }
+
+ if (!dol_move($temp_file, $destpath)) {
+ unlink($temp_file);
+ $error_message = "Error move temporary file ($temp_file) in product image directory ($destpath)";
+ dol_syslog(__METHOD__.': '.$error_message, LOG_ERR);
+ return false;
+ }
+
+ include_once DOL_DOCUMENT_ROOT . '/core/lib/images.lib.php';
+ if (image_format_supported($destpath) == 1) {
+ // Create thumbs
+ // We can't use $object->addThumbs here because there is no $object known
+
+ // Used on logon for example
+ $imgThumbSmall = vignette($destpath, $maxwidthsmall, $maxheightsmall, '_small', 50, "thumbs");
+ // Create mini thumbs for image (Ratio is near 16/9)
+ // Used on menu or for setup page for example
+ $imgThumbMini = vignette($destpath, $maxwidthmini, $maxheightmini, '_mini', 50, "thumbs");
+ }
+
+ return true;
+}
+
+function ecommerceng_remove_obsolete_image($product, $images, &$error_message)
+{
+ dol_syslog(__METHOD__.': product_id=' . $product->id . ' images=' . implode(',', $images), LOG_DEBUG);
+ global $db, $conf;
+
+ if ($product->type != Product::TYPE_PRODUCT && $product->type != Product::TYPE_SERVICE) {
+ $error_message = "Error the product is not a product or service type";
+ dol_syslog(__METHOD__.': '.$error_message, LOG_ERR);
+ return false;
+ }
+
+ $entity = isset($product->entity) ? $product->entity : $conf->entity;
+
+ // Set upload directory
+ if (!empty($conf->global->PRODUCT_USE_OLD_PATH_FOR_PHOTO)) { // For backward compatiblity, we scan also old dirs
+ if ($product->type == Product::TYPE_PRODUCT) {
+ $upload_dir = $conf->product->multidir_output[$entity] . '/' . substr(substr("000" . $product->id, -2), 1, 1) . '/' . substr(substr("000" . $product->id, -2), 0, 1) . '/' . $product->id . "/photos/";
+ } else {
+ $upload_dir = $conf->service->multidir_output[$entity] . '/' . substr(substr("000" . $product->id, -2), 1, 1) . '/' . substr(substr("000" . $product->id, -2), 0, 1) . '/' . $product->id . "/photos/";
+ }
+ } else {
+ if ($product->type == Product::TYPE_PRODUCT) {
+ $upload_dir = $conf->product->multidir_output[$entity] . '/' . get_exdir(0, 0, 0, 0, $product, 'product') . dol_sanitizeFileName($product->ref) . '/';
+ } else {
+ $upload_dir = $conf->service->multidir_output[$entity] . '/' . get_exdir(0, 0, 0, 0, $product, 'product') . dol_sanitizeFileName($product->ref) . '/';
+ }
+ }
+
+ $images_name = [];
+ foreach ($images as $image) {
+ // Define $destpath (path to file including filename) and $destfile (only filename)
+ $file_name = basename(parse_url($image['url'], PHP_URL_PATH));
+ $destfile = $file_name;
+
+ // lowercase extension
+ $info = pathinfo($destfile);
+ $destfile = $info['filename'] . '.' . strtolower($info['extension']);
+
+ // Security:
+ // Disallow file with some extensions. We rename them.
+ // Because if we put the documents directory into a directory inside web root (very bad), this allows to execute on demand arbitrary code.
+ if (preg_match('/\.htm|\.html|\.php|\.pl|\.cgi|\.exe$/i', $destfile) && empty($conf->global->MAIN_DOCUMENT_IS_OUTSIDE_WEBROOT_SO_NOEXE_NOT_REQUIRED)) {
+ $destfile .= '.noexe';
+ }
+
+ $images_name[] = $destfile;
+ }
+
+ dol_syslog(__METHOD__.': upload_dir=' . $upload_dir . ' images=' . implode(',',$images_name) . ' product_id=' . $product->id, LOG_DEBUG);
+
+ $photos = $product->liste_photos($upload_dir);
+ foreach ($photos as $index => $photo) {
+ if (! in_array($photo['photo'], $images_name, true)) {
+ unlink($upload_dir . $photo['photo']);
+ }
+ }
+
+ return true;
+}
+
+function ecommerceng_add_extrafields($db, $langs, $extrafields, &$error) {
+ $efields = new ExtraFields($db);
+ foreach ($extrafields as $extrafield) {
+ $result = $efields->addExtraField(
+ $extrafield['attrname'],
+ $langs->trans($extrafield['label']),
+ $extrafield['type'],
+ $extrafield['pos'],
+ $extrafield['size'],
+ $extrafield['elementtype'],
+ $extrafield['unique'],
+ $extrafield['required'],
+ $extrafield['default_value'],
+ $extrafield['param'],
+ $extrafield['alwayseditable'],
+ $extrafield['perms'],
+ $extrafield['list']
+ );
+ if ($result <= 0) {
+ $error = $efields->error;
+ return -1;
+ }
+ }
+}
+
+function ecommerceng_update_woocommerce_dict_tax_class($db, $site)
+{
+ global $conf, $langs;
+ $langs->load('woocommerce@ecommerceng');
+
+ $eCommerceRemoteAccessWoocommerce = new eCommerceRemoteAccessWoocommerce($db, $site);
+
+ if (!$eCommerceRemoteAccessWoocommerce->connect()) {
+ setEventMessages('', $this->errors, 'errors');
+ return false;
+ }
+
+ $taxClasses = $eCommerceRemoteAccessWoocommerce->getAllWoocommerceTaxClass();
+ if ($taxClasses === false) {
+ setEventMessages('', $this->errors, 'errors');
+ return false;
+ }
+
+ $eCommerceDict = new eCommerceDict($db, MAIN_DB_PREFIX.'c_ecommerceng_tax_class');
+
+ // Get all tax class in dictionary for this entity and site
+ $dict_tax_classes = $eCommerceDict->search(['entity'=>['value'=>$conf->entity],'site_id'=>['value'=>$site->id]]);
+
+ // Desactive code not found in woocommerce
+ foreach ($dict_tax_classes as $line) {
+ if (!isset($taxClasses[$line['code']])) {
+ // Desactive code
+ $result = $eCommerceDict->update(['active' => ['value' => 0]], ['rowid' => ['value' => $line['rowid']]]);
+ if ($result == false) {
+ setEventMessage($langs->trans('ECommerceWoocommerceErrorDisableDictTaxClass', $line['code'], $db->error()), 'errors');
+ return false;
+ }
+ } else {
+ $taxClasses[$line['code']]['founded'] = true;
+ }
+ }
+
+ // Add new code from woocommerce
+ foreach ($taxClasses as $taxClass) {
+ if (!isset($taxClass['founded'])) {
+ // Add new tax class code
+ $result = $eCommerceDict->insert(['site_id','code','label','entity','active'], ['site_id'=>['value'=>$site->id],'code'=>['value'=>$taxClass['slug'],'type'=>'string'],'label'=>['value'=>$taxClass['name'],'type'=>'string'],'entity'=>['value'=>$conf->entity],'active'=>['value'=>1]]);
+ if ($result == false) {
+ setEventMessage($langs->trans('ECommerceWoocommerceErrorAddDictTaxClass', $taxClass['slug'], $taxClass['name'], $db->error()), 'errors');
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+function get_company_by_email($db, $email, $site=0)
+{
+ $email = $db->escape($email);
+
+ $sql = "SELECT s.rowid FROM " . MAIN_DB_PREFIX . "societe AS s";
+ $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "socpeople AS sp ON sp.fk_soc = s.rowid";
+ if ($site > 0) $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "ecommerce_societe AS es ON es.fk_societe = s.rowid";
+ $sql .= " WHERE (s.email = '$email' OR sp.email = '$email')";
+ if ($site > 0) $sql .= " AND es.fk_site = $site";
+ $sql .= " GROUP BY s.rowid";
+
+ $resql = $db->query($sql);
+ if ($resql) {
+ $num = $db->num_rows($resql);
+ if ($num > 1) {
+ $result = -2;
+ } elseif ($num) {
+ $obj = $db->fetch_object($resql);
+ $result = $obj->rowid;
+ } else {
+ $result = 0;
+ }
+
+ $db->free($resql);
+ } else {
+ $result = -1;
+ }
+
+ return $result;
+}
\ No newline at end of file
diff --git a/htdocs/ecommerceng/patchs/dolibarr/includes/OAuth/OAuth2/Service/WordPress.php b/htdocs/ecommerceng/patchs/dolibarr/includes/OAuth/OAuth2/Service/WordPress.php
new file mode 100755
index 0000000..f4fc920
--- /dev/null
+++ b/htdocs/ecommerceng/patchs/dolibarr/includes/OAuth/OAuth2/Service/WordPress.php
@@ -0,0 +1,96 @@
+baseApiUri = new Uri('https://addresse_de_votre_site_wordpress');
+ }
+ }
+/*
+ // LDR CHANGE Add approval_prompt to force the prompt if value is set to 'force' so it force return of a "refresh token" in addition to "standard token"
+ public $approvalPrompt='auto';
+ public function setApprouvalPrompt($prompt)
+ {
+ if (!in_array($prompt, array('auto', 'force'), true)) {
+ // @todo Maybe could we rename this exception
+ throw new InvalidAccessTypeException('Invalid approuvalPrompt, expected either auto or force.');
+ }
+ $this->approvalPrompt = $prompt;
+ }*/
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getAuthorizationEndpoint()
+ {
+ return new Uri(sprintf('%s/oauth/authorize', $this->baseApiUri));
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getAccessTokenEndpoint()
+ {
+ return new Uri(sprintf('%s/oauth/token', $this->baseApiUri));
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function getAuthorizationMethod()
+ {
+ return static::AUTHORIZATION_METHOD_HEADER_BEARER;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function parseAccessTokenResponse($responseBody)
+ {
+ $data = json_decode($responseBody, true);
+
+ if (null === $data || !is_array($data)) {
+ throw new TokenResponseException('Unable to parse response: "'.(isset($responseBody)?$responseBody:'NULL').'"');
+ } elseif (isset($data['error'])) {
+ throw new TokenResponseException('Error in retrieving token: "' . $data['error'] . '" : "'.$data['error_description'].'"');
+ }
+
+ $token = new StdOAuth2Token();
+ $token->setAccessToken($data['access_token']);
+ $token->setLifetime($data['expires_in']);
+
+ if (isset($data['refresh_token'])) {
+ $token->setRefreshToken($data['refresh_token']);
+ unset($data['refresh_token']);
+ }
+
+ unset($data['access_token']);
+ unset($data['expires_in']);
+
+ $token->setExtraParams($data);
+
+ return $token;
+ }
+}
diff --git a/htdocs/ecommerceng/site.php b/htdocs/ecommerceng/site.php
index 4d439d3..19f555a 100644
--- a/htdocs/ecommerceng/site.php
+++ b/htdocs/ecommerceng/site.php
@@ -214,19 +214,19 @@
// Count into Magento
if (! GETPOST('test_with_no_categ_count'))
{
- if (! $error) $nbCategoriesToUpdate = $synchro->getNbCategoriesToUpdate(true);
+ if (! $error && empty($conf->global->ECOMMERCENG_NO_COUNT_UPDATE)) $nbCategoriesToUpdate = $synchro->getNbCategoriesToUpdate(true);
else $nbCategoriesToUpdate='?';
if ($nbCategoriesToUpdate < 0) $error++;
}
if (! GETPOST('test_with_no_product_count'))
{
- if (! $error) $nbProductToUpdate = $synchro->getNbProductToUpdate(true);
+ if (! $error && empty($conf->global->ECOMMERCENG_NO_COUNT_UPDATE)) $nbProductToUpdate = $synchro->getNbProductToUpdate(true);
else $nbProductToUpdate='?';
if ($nbProductToUpdate < 0) $error++;
}
if (! GETPOST('test_with_no_thirdparty_count'))
{
- if (! $error) $nbSocieteToUpdate = $synchro->getNbSocieteToUpdate(true);
+ if (! $error && empty($conf->global->ECOMMERCENG_NO_COUNT_UPDATE)) $nbSocieteToUpdate = $synchro->getNbSocieteToUpdate(true);
else $nbSocieteToUpdate='?';
if ($nbSocieteToUpdate < 0) $error++;
}
@@ -234,7 +234,7 @@
{
if (! empty($conf->commande->enabled))
{
- if (! $error) $nbCommandeToUpdate = $synchro->getNbCommandeToUpdate(true);
+ if (! $error && empty($conf->global->ECOMMERCENG_NO_COUNT_UPDATE)) $nbCommandeToUpdate = $synchro->getNbCommandeToUpdate(true);
else $nbCommandeToUpdate='?';
if ($nbCommandeToUpdate < 0) $error++;
}
@@ -243,7 +243,7 @@
{
if (! empty($conf->facture->enabled))
{
- if (! $error) $nbFactureToUpdate = $synchro->getNbFactureToUpdate(true);
+ if (! $error && empty($conf->global->ECOMMERCENG_NO_COUNT_UPDATE)) $nbFactureToUpdate = $synchro->getNbFactureToUpdate(true);
else $nbFactureToUpdate='?';
if ($nbFactureToUpdate < 0) $error++;
}
diff --git a/htdocs/ecommerceng/sql/llx_c_ecommerceng_tax_class.key.sql b/htdocs/ecommerceng/sql/llx_c_ecommerceng_tax_class.key.sql
new file mode 100644
index 0000000..ecfdfa6
--- /dev/null
+++ b/htdocs/ecommerceng/sql/llx_c_ecommerceng_tax_class.key.sql
@@ -0,0 +1,19 @@
+-- ===================================================================
+-- Copyright (C) 2011 Auguria
+-- This program is free software; you can redistribute it and/or modify
+-- it under the terms of the GNU General Public License as published by
+-- the Free Software Foundation; either version 2 of the License, or
+-- (at your option) any later version.
+--
+-- This program is distributed in the hope that it will be useful,
+-- but WITHOUT ANY WARRANTY; without even the implied warranty of
+-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+-- GNU General Public License for more details.
+--
+-- You should have received a copy of the GNU General Public License
+-- along with this program; if not, write to the Free Software
+-- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+--
+-- ===================================================================
+
+ALTER TABLE llx_c_ecommerceng_tax_class ADD UNIQUE INDEX uk_c_ecommerceng_tax_class_site_id_code_entity(site_id,code,entity);
diff --git a/htdocs/ecommerceng/sql/llx_c_ecommerceng_tax_class.sql b/htdocs/ecommerceng/sql/llx_c_ecommerceng_tax_class.sql
new file mode 100644
index 0000000..845d266
--- /dev/null
+++ b/htdocs/ecommerceng/sql/llx_c_ecommerceng_tax_class.sql
@@ -0,0 +1,27 @@
+-- ===================================================================
+-- Copyright (C) 2011 Auguria
+-- This program is free software; you can redistribute it and/or modify
+-- it under the terms of the GNU General Public License as published by
+-- the Free Software Foundation; either version 2 of the License, or
+-- (at your option) any later version.
+--
+-- This program is distributed in the hope that it will be useful,
+-- but WITHOUT ANY WARRANTY; without even the implied warranty of
+-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+-- GNU General Public License for more details.
+--
+-- You should have received a copy of the GNU General Public License
+-- along with this program; if not, write to the Free Software
+-- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+--
+-- ===================================================================
+
+create table llx_c_ecommerceng_tax_class
+(
+ rowid integer AUTO_INCREMENT PRIMARY KEY,
+ site_id integer NOT NULL,
+ code varchar(255) NOT NULL,
+ label varchar(255) NOT NULL,
+ entity integer DEFAULT 1,
+ active tinyint DEFAULT 1 NOT NULL
+) ENGINE=InnoDB;
diff --git a/htdocs/ecommerceng/sql/llx_ecommerce_site.sql b/htdocs/ecommerceng/sql/llx_ecommerce_site.sql
index 6aaddfd..2b5ac7e 100644
--- a/htdocs/ecommerceng/sql/llx_ecommerce_site.sql
+++ b/htdocs/ecommerceng/sql/llx_ecommerce_site.sql
@@ -29,7 +29,6 @@ CREATE TABLE llx_ecommerce_site (
fk_cat_societe integer NOT NULL,
fk_cat_product integer NOT NULL,
fk_warehouse integer NULL,
- fk_thirdparty integer NULL, -- thirdparty for non logged users
stock_sync_direction varchar(24) DEFAULT 'none',
last_update datetime DEFAULT NULL,
timeout integer NOT NULL DEFAULT 300,
diff --git a/htdocs/ecommerceng/sql/update_anonymous_thirdparty.sql b/htdocs/ecommerceng/sql/update_anonymous_thirdparty.sql
new file mode 100644
index 0000000..bb34979
--- /dev/null
+++ b/htdocs/ecommerceng/sql/update_anonymous_thirdparty.sql
@@ -0,0 +1 @@
+ALTER TABLE llx_ecommerce_site ADD COLUMN fk_anonymous_thirdparty integer NULL;
diff --git a/htdocs/ecommerceng/sql/update_oauth.sql b/htdocs/ecommerceng/sql/update_oauth.sql
new file mode 100644
index 0000000..c88ab46
--- /dev/null
+++ b/htdocs/ecommerceng/sql/update_oauth.sql
@@ -0,0 +1,2 @@
+ALTER TABLE llx_ecommerce_site ADD COLUMN oauth_id varchar(255) NULL after user_password;
+ALTER TABLE llx_ecommerce_site ADD COLUMN oauth_secret varchar(255) NULL after oauth_id;
diff --git a/htdocs/ecommerceng/sql/update_pricetype.sql b/htdocs/ecommerceng/sql/update_pricetype.sql
new file mode 100644
index 0000000..e297379
--- /dev/null
+++ b/htdocs/ecommerceng/sql/update_pricetype.sql
@@ -0,0 +1 @@
+ALTER TABLE llx_ecommerce_site CHANGE COLUMN magento_price_type ecommerce_price_type VARCHAR(3) NOT NULL DEFAULT 'HT';
diff --git a/htdocs/ecommerceng/tpl/site.tpl.php b/htdocs/ecommerceng/tpl/site.tpl.php
index 2ef182c..683a62b 100644
--- a/htdocs/ecommerceng/tpl/site.tpl.php
+++ b/htdocs/ecommerceng/tpl/site.tpl.php
@@ -63,13 +63,13 @@
print '
';
print '
';
- if (! empty($conf->global->ECOMMERCENG_USE_THIS_THIRDPARTY_FOR_NONLOGGED_CUSTOMER))
+ if (! empty($site->fk_anonymous_thirdparty))
{
print '