Browse Source

Merge remote-tracking branch 'origin/3.8' into develop

Conflicts:
	htdocs/core/class/html.form.class.php
	htdocs/core/lib/pdf.lib.php
	htdocs/langs/en_US/main.lang
	htdocs/product/list.php
	htdocs/product/stock/mouvement.php
Laurent Destailleur 9 years ago
parent
commit
da0aa2f937
42 changed files with 377 additions and 86 deletions
  1. 10 5
      htdocs/admin/security.php
  2. 1 1
      htdocs/comm/action/listactions.php
  3. 2 8
      htdocs/commande/class/commande.class.php
  4. 7 4
      htdocs/compta/facture.php
  5. 3 1
      htdocs/contrat/card.php
  6. 6 3
      htdocs/contrat/index.php
  7. 2 1
      htdocs/contrat/services.php
  8. 2 1
      htdocs/core/boxes/box_produits.php
  9. 2 1
      htdocs/core/boxes/box_produits_alerte_stock.php
  10. 1 0
      htdocs/core/class/commondocgenerator.class.php
  11. 4 4
      htdocs/core/class/extrafields.class.php
  12. 6 1
      htdocs/core/class/html.formfile.class.php
  13. 64 0
      htdocs/core/js/select2_locale.js.php
  14. 9 11
      htdocs/core/lib/functions.lib.php
  15. 174 6
      htdocs/core/lib/pdf.lib.php
  16. 1 1
      htdocs/core/modules/facture/doc/pdf_crabe.modules.php
  17. 2 2
      htdocs/core/modules/mailings/modules_mailings.php
  18. 2 2
      htdocs/core/modules/modProjet.class.php
  19. 2 2
      htdocs/core/modules/propale/doc/pdf_azur.modules.php
  20. 6 3
      htdocs/core/tpl/document_actions_pre_headers.tpl.php
  21. 2 1
      htdocs/fourn/card.php
  22. 1 1
      htdocs/fourn/commande/orderstoinvoice.php
  23. 2 1
      htdocs/fourn/product/list.php
  24. 4 0
      htdocs/langs/en_US/admin.lang
  25. 7 1
      htdocs/langs/en_US/main.lang
  26. 1 0
      htdocs/langs/en_US/projects.lang
  27. 1 0
      htdocs/main.inc.php
  28. 2 1
      htdocs/margin/productMargins.php
  29. 2 1
      htdocs/product/canvas/product/actions_card_product.class.php
  30. 8 6
      htdocs/product/class/product.class.php
  31. 4 1
      htdocs/product/composition/card.php
  32. 16 3
      htdocs/product/document.php
  33. 3 2
      htdocs/product/list.php
  34. 2 1
      htdocs/product/reassort.php
  35. 3 2
      htdocs/product/reassortlot.php
  36. 1 1
      htdocs/product/stats/commande.php
  37. 2 1
      htdocs/product/stats/commande_fournisseur.php
  38. 2 1
      htdocs/product/stats/propal.php
  39. 2 1
      htdocs/product/stock/card.php
  40. 2 1
      htdocs/product/stock/mouvement.php
  41. 2 2
      htdocs/public/emailing/mailing-read.php
  42. 2 1
      htdocs/societe/consumption.php

+ 10 - 5
htdocs/admin/security.php

@@ -292,6 +292,7 @@ $var=!$var;
 	$this->NbRepeat = $tabConf[4];
 	$this->WithoutAmbi = $tabConf[5];
 	*/
+	print '<br>';
 	print '<table class="noborder" width="100%">';
 	print '<tr class="liste_titre">';
 	print '<td colspan="3"> '.$langs->trans("PasswordPatternDesc").'</td>';
@@ -332,12 +333,16 @@ $var=!$var;
 	print '<td>' . $langs->trans("NoAmbiCaracAutoGeneration")."</td>";
 	print '<td colspan="2"><input type="checkbox" id="NoAmbiCaracAutoGeneration" '.($tabConf[5] ? "checked" : "").' min="0"> <span id="textcheckbox">'.($tabConf[5] ? $langs->trans("Activated") : $langs->trans("Disabled")).'</span></td>';
 	print '</tr>';
+	
+	print '</table>';
 
-	$var=!$var;
-	print "<tr ".$bc[$var].">";
-	print '<td colspan="2"></td><td width="103" align="center"><a id="linkChangePattern">'.$langs->trans("Save").'</a></td>';
-	print '</tr>';
+	print '<br>';
+	print '<table align="right">';
+	print '<tr><td>';
+	print '<a class="button" id="linkChangePattern">'.$langs->trans("Save").'</a>';
+	print '</td></tr>';
 	print '</table>';
+	print '<br><br>';
 
 	print '<script type="text/javascript">';
 	print '	function getStringArg(){';
@@ -389,7 +394,7 @@ $var=!$var;
 // Cryptage mot de passe
 print '<br>';
 $var=true;
-print "<form method=\"post\" action=\"security.php\">";
+print "<form method=\"post\" action=\"" . $_SERVER["PHP_SELF"] . "\">";
 print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
 print "<input type=\"hidden\" name=\"action\" value=\"encrypt\">";
 

+ 1 - 1
htdocs/comm/action/listactions.php

@@ -202,7 +202,7 @@ if ($status == 'todo') { $sql.= " AND ((a.percent >= 0 AND a.percent < 100) OR (
 if ($filtert > 0 || $usergroup > 0)
 {
     $sql.= " AND (";
-    if ($filtert > 0) $sql.= "ar.fk_element = ".$filtert;
+    if ($filtert > 0) $sql.= "(ar.fk_element = ".$filtert." OR a.fk_user_action=".$filtert.")";
     if ($usergroup > 0) $sql.= ($filtert>0?" OR ":"")." ugu.fk_usergroup = ".$usergroup;
     $sql.= ")";
 }

+ 2 - 8
htdocs/commande/class/commande.class.php

@@ -944,6 +944,7 @@ class Commande extends CommonOrder
         }
 
         $this->id=0;
+		$this->ref = '';
         $this->statut=self::STATUS_DRAFT;
 
         // Clear fields
@@ -952,14 +953,7 @@ class Commande extends CommonOrder
         $this->date_creation      = '';
         $this->date_validation    = '';
         $this->ref_client         = '';
-
-        // Set ref
-        require_once DOL_DOCUMENT_ROOT ."/core/modules/commande/".$conf->global->COMMANDE_ADDON.'.php';
-        $obj = $conf->global->COMMANDE_ADDON;
-        $modCommande = new $obj;
-        $this->ref = $modCommande->getNextValue($objsoc,$this);
-
-
+		
         // Create clone
         $result=$this->create($user);
         if ($result < 0) $error++;

+ 7 - 4
htdocs/compta/facture.php

@@ -2541,7 +2541,8 @@ else if ($id > 0 || ! empty($ref))
 			$qualified_for_stock_change = $object->hasProductsOrServices(1);
 		}
 
-		if ($object->type != Facture::TYPE_DEPOSIT && ! empty($conf->global->STOCK_CALCULATE_ON_BILL) && $qualified_for_stock_change && $object->statut >= 1) {
+		if ($object->type != Facture::TYPE_DEPOSIT && ! empty($conf->global->STOCK_CALCULATE_ON_BILL) && $qualified_for_stock_change && $object->statut >= 1) 
+		{
 			$langs->load("stocks");
 			require_once DOL_DOCUMENT_ROOT . '/product/class/html.formproduct.class.php';
 			$formproduct = new FormProduct($db);
@@ -2731,17 +2732,19 @@ else if ($id > 0 || ! empty($ref))
 	}
 
 	// Clone confirmation
-	if ($action == 'clone') {
+	if ($action == 'clone') 
+	{
 		// Create an array for form
 		$formquestion = array(
 							// 'text' => $langs->trans("ConfirmClone"),
 							// array('type' => 'checkbox', 'name' => 'clone_content', 'label' => $langs->trans("CloneMainAttributes"), 'value' => 1)
-							array('type' => 'other','name' => 'socid','label' => $langs->trans("SelectThirdParty"),'value' => $form->select_company('', 'socid', '(s.client=1 OR s.client=2 OR s.client=3)', 1)));
+							array('type' => 'other','name' => 'socid','label' => $langs->trans("SelectThirdParty"),'value' => $form->select_company($object->socid, 'socid', '(s.client=1 OR s.client=2 OR s.client=3)', 1)));
 		// Paiement incomplet. On demande si motif = escompte ou autre
 		$formconfirm = $form->formconfirm($_SERVER["PHP_SELF"] . '?facid=' . $object->id, $langs->trans('CloneInvoice'), $langs->trans('ConfirmCloneInvoice', $object->ref), 'confirm_clone', $formquestion, 'yes', 1);
 	}
 
-	if (! $formconfirm) {
+	if (! $formconfirm) 
+	{
 		$parameters = array('lineid' => $lineid);
 		$reshook = $hookmanager->executeHooks('formConfirm', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
 		if (empty($reshook)) $formconfirm.=$hookmanager->resPrint;

+ 3 - 1
htdocs/contrat/card.php

@@ -1366,7 +1366,7 @@ else
             $sql.= " cd.date_fin_validite as date_fin, cd.date_cloture as date_fin_reelle,";
             $sql.= " cd.commentaire as comment, cd.fk_product_fournisseur_price as fk_fournprice, cd.buy_price_ht as pa_ht,";
 	        $sql.= " cd.fk_unit,";
-            $sql.= " p.rowid as pid, p.ref as pref, p.label as label, p.fk_product_type as ptype";
+            $sql.= " p.rowid as pid, p.ref as pref, p.label as label, p.fk_product_type as ptype, p.entity as pentity";
             $sql.= " FROM ".MAIN_DB_PREFIX."contratdet as cd";
             $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."product as p ON cd.fk_product = p.rowid";
             $sql.= " WHERE cd.rowid = ".$object->lines[$cursorline-1]->id;
@@ -1401,6 +1401,7 @@ else
                         $productstatic->id=$objp->fk_product;
                         $productstatic->type=$objp->ptype;
                         $productstatic->ref=$objp->pref;
+						$productstatic->entity=$objp->pentity;
                         $text = $productstatic->getNomUrl(1,'',20);
                         if ($objp->label)
                         {
@@ -1527,6 +1528,7 @@ else
                         $productstatic->id=$objp->fk_product;
                         $productstatic->type=$objp->ptype;
                         $productstatic->ref=$objp->pref;
+						$productstatic->entity=$objp->pentity;
                         print $productstatic->getNomUrl(1,'',20);
                         print $objp->label?' - '.dol_trunc($objp->label,16):'';
                         print '<br>';

+ 6 - 3
htdocs/contrat/index.php

@@ -369,7 +369,7 @@ print '<br>';
 $sql = "SELECT c.ref, c.fk_soc, ";
 $sql.= " cd.rowid as cid, cd.statut, cd.label, cd.fk_product, cd.description as note, cd.fk_contrat, cd.date_fin_validite,";
 $sql.= " s.nom as name,";
-$sql.= " p.rowid as pid, p.ref as pref, p.label as plabel, p.fk_product_type as ptype";
+$sql.= " p.rowid as pid, p.ref as pref, p.label as plabel, p.fk_product_type as ptype, p.entity as pentity";
 $sql.= " FROM (".MAIN_DB_PREFIX."contrat as c";
 $sql.= ", ".MAIN_DB_PREFIX."societe as s";
 if (!$user->rights->societe->client->voir && !$socid) $sql.= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc";
@@ -411,6 +411,7 @@ if ($resql)
     		$productstatic->id=$obj->fk_product;
             $productstatic->type=$obj->ptype;
             $productstatic->ref=$obj->pref;
+			$productstatic->entity=$obj->pentity;
             print $productstatic->getNomUrl(1,'',20);
 		}
 		else
@@ -447,7 +448,7 @@ print '<br>';
 // Not activated services
 $sql = "SELECT c.ref, c.fk_soc, cd.rowid as cid, cd.statut, cd.label, cd.fk_product, cd.description as note, cd.fk_contrat,";
 $sql.= " s.nom as name,";
-$sql.= " p.rowid as pid, p.ref as pref, p.label as plabel, p.fk_product_type as ptype";
+$sql.= " p.rowid as pid, p.ref as pref, p.label as plabel, p.fk_product_type as ptype, p.entity as pentity";
 $sql.= " FROM (".MAIN_DB_PREFIX."contrat as c";
 $sql.= ", ".MAIN_DB_PREFIX."societe as s";
 if (!$user->rights->societe->client->voir && !$socid) $sql.= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc";
@@ -491,6 +492,7 @@ if ($resql)
     		$productstatic->id=$obj->fk_product;
             $productstatic->type=$obj->ptype;
             $productstatic->ref=$obj->pref;
+			$productstatic->entity=$obj->pentity;
             print $productstatic->getNomUrl(1,'',20);
 		}
 		else
@@ -526,7 +528,7 @@ print '<br>';
 // Expired services
 $sql = "SELECT c.ref, c.fk_soc, cd.rowid as cid, cd.statut, cd.label, cd.fk_product, cd.description as note, cd.fk_contrat,";
 $sql.= " s.nom as name,";
-$sql.= " p.rowid as pid, p.ref as pref, p.label as plabel, p.fk_product_type as ptype";
+$sql.= " p.rowid as pid, p.ref as pref, p.label as plabel, p.fk_product_type as ptype, p.entity as pentity";
 $sql.= " FROM (".MAIN_DB_PREFIX."contrat as c";
 $sql.= ", ".MAIN_DB_PREFIX."societe as s";
 if (!$user->rights->societe->client->voir && !$socid) $sql.= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc";
@@ -571,6 +573,7 @@ if ($resql)
     		$productstatic->id=$obj->fk_product;
             $productstatic->type=$obj->ptype;
             $productstatic->ref=$obj->pref;
+			$productstatic->entity=$obj->pentity;
             print $productstatic->getNomUrl(1,'',20);
 		}
 		else

+ 2 - 1
htdocs/contrat/services.php

@@ -98,7 +98,7 @@ llxHeader();
 $sql = "SELECT c.rowid as cid, c.ref, c.statut as cstatut,";
 $sql.= " s.rowid as socid, s.nom as name,";
 $sql.= " cd.rowid, cd.description, cd.statut,";
-$sql.= " p.rowid as pid, p.ref as pref, p.label as label, p.fk_product_type as ptype,";
+$sql.= " p.rowid as pid, p.ref as pref, p.label as label, p.fk_product_type as ptype, p.entity as pentity,";
 if (!$user->rights->societe->client->voir && !$socid) $sql .= " sc.fk_soc, sc.fk_user,";
 $sql.= " cd.date_ouverture_prevue,";
 $sql.= " cd.date_ouverture,";
@@ -225,6 +225,7 @@ if ($resql)
 			$productstatic->id=$obj->pid;
 			$productstatic->type=$obj->ptype;
 			$productstatic->ref=$obj->pref;
+			$productstatic->entity=$obj->pentity;
 			print $productstatic->getNomUrl(1,'',20);
             print $obj->label?' - '.dol_trunc($obj->label,16):'';
             if (! empty($obj->description) && ! empty($conf->global->PRODUCT_DESC_IN_LIST)) print '<br>'.dol_nl2br($obj->description);

+ 2 - 1
htdocs/core/boxes/box_produits.php

@@ -64,7 +64,7 @@ class box_produits extends ModeleBoxes
 
 		if ($user->rights->produit->lire || $user->rights->service->lire)
 		{
-			$sql = "SELECT p.rowid, p.label, p.ref, p.price, p.price_base_type, p.price_ttc, p.fk_product_type, p.tms, p.tosell, p.tobuy, p.fk_price_expression";
+			$sql = "SELECT p.rowid, p.label, p.ref, p.price, p.price_base_type, p.price_ttc, p.fk_product_type, p.tms, p.tosell, p.tobuy, p.fk_price_expression, p.entity";
 			$sql.= " FROM ".MAIN_DB_PREFIX."product as p";
 			$sql.= ' WHERE p.entity IN ('.getEntity($productstatic->element, 1).')';
 			if (empty($user->rights->produit->lire)) $sql.=' AND p.fk_product_type != 0';
@@ -103,6 +103,7 @@ class box_produits extends ModeleBoxes
                     $productstatic->ref = $objp->ref;
                     $productstatic->type = $objp->fk_product_type;
                     $productstatic->label = $objp->label;
+					$productstatic->entity = $objp->entity;
 
 					$this->info_box_contents[$line][] = array(
                         'td' => 'align="left"',

+ 2 - 1
htdocs/core/boxes/box_produits_alerte_stock.php

@@ -66,7 +66,7 @@ class box_produits_alerte_stock extends ModeleBoxes
 
 		if ($user->rights->produit->lire || $user->rights->service->lire)
 		{
-			$sql = "SELECT p.rowid, p.label, p.price, p.ref, p.price_base_type, p.price_ttc, p.fk_product_type, p.tms, p.tosell, p.tobuy, p.seuil_stock_alerte,";
+			$sql = "SELECT p.rowid, p.label, p.price, p.ref, p.price_base_type, p.price_ttc, p.fk_product_type, p.tms, p.tosell, p.tobuy, p.seuil_stock_alerte,p.entity,";
 			$sql.= " SUM(".$db->ifsql("s.reel IS NULL","0","s.reel").") as total_stock";
 			$sql.= " FROM ".MAIN_DB_PREFIX."product as p";
 			$sql.= " LEFT JOIN ".MAIN_DB_PREFIX."product_stock as s on p.rowid = s.fk_product";
@@ -110,6 +110,7 @@ class box_produits_alerte_stock extends ModeleBoxes
                     $productstatic->ref = $objp->ref;
                     $productstatic->type = $objp->fk_product_type;
                     $productstatic->label = $objp->label;
+					$productstatic->entity = $objp->entity;
 
                     $this->info_box_contents[$line][] = array(
                         'td' => 'align="left"',

+ 1 - 0
htdocs/core/class/commondocgenerator.class.php

@@ -75,6 +75,7 @@ abstract class CommonDocGenerator
             'myuser_mobile'=>$user->user_mobile,
             'myuser_email'=>$user->email,
         	'myuser_logo'=>$user->photo,
+        	'myuser_job'=>$user->job,
             'myuser_web'=>''	// url not exist in $user object
         );
     }

+ 4 - 4
htdocs/core/class/extrafields.class.php

@@ -739,10 +739,10 @@ class ExtraFields
 		elseif ($type == 'select')
 		{
 			$out = '';
-			if (! empty($conf->use_javascript_ajax) && ! empty($conf->global->COMPANY_USE_SEARCH_TO_SELECT) && ! $forcecombo)
+			if (! empty($conf->use_javascript_ajax) && ! empty($conf->global->MAIN_EXTRAFIELDS_USE_SELECT2))
 			{
 				include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
-				$out.= ajax_combobox($keysuffix.'options_'.$key.$keyprefix, array(), $conf->global->COMPANY_USE_SEARCH_TO_SELECT);
+				$out.= ajax_combobox($keysuffix.'options_'.$key.$keyprefix, array(), 0);
 			}
 
 			$out.='<select class="flat" name="'.$keysuffix.'options_'.$key.$keyprefix.'" id="options_'.$key.$keyprefix.'" '.($moreparam?$moreparam:'').'>';
@@ -760,10 +760,10 @@ class ExtraFields
 		elseif ($type == 'sellist')
 		{
 			$out = '';
-			if ($conf->use_javascript_ajax && $conf->global->COMPANY_USE_SEARCH_TO_SELECT && ! $forcecombo)
+			if (! empty($conf->use_javascript_ajax) && ! empty($conf->global->MAIN_EXTRAFIELDS_USE_SELECT2))
 			{
 				include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
-				$out.= ajax_combobox($keysuffix.'options_'.$key.$keyprefix, array(), $conf->global->COMPANY_USE_SEARCH_TO_SELECT);
+				$out.= ajax_combobox($keysuffix.'options_'.$key.$keyprefix, array(), 0);
 			}
 
 			$out.='<select class="flat" name="'.$keysuffix.'options_'.$key.$keyprefix.'" id="options_'.$key.$keyprefix.'" '.($moreparam?$moreparam:'').'>';

+ 6 - 1
htdocs/core/class/html.formfile.class.php

@@ -822,7 +822,12 @@ class FormFile
 						if ($object->element == 'member') $relativepath=get_exdir($object->id,2,0,0,$object,'member').$relativepath;				// TODO Call using a defined value for $relativepath
 						if ($object->element == 'project_task') $relativepath='Call_not_supported_._Call_function_using_a_defined_relative_path_.';
 					}
-
+					// For backward compatiblity, we detect file is stored into an old path
+					if (! empty($conf->global->PRODUCT_USE_OLD_PATH_FOR_PHOTO) && $file['level1name'] == 'photos')
+	                {
+	                    $relativepath=preg_replace('/^.*\/produit\//','',$file['path']).'/';
+	                }
+					
 					$var=!$var;
 					print '<tr '.$bc[$var].'>';
 					print '<td>';

+ 64 - 0
htdocs/core/js/select2_locale.js.php

@@ -0,0 +1,64 @@
+<?php
+/* Copyright (C) 2012	Regis Houssin		<regis.houssin@capnetworks.com>
+ * Copyright (C) 2012	Laurent Destailleur	<eldy@users.sourceforge.net>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file       htdocs/core/js/timepicker.js.php
+ * \brief      File that include javascript functions for timepicker
+ */
+
+//if (! defined('NOREQUIREUSER')) define('NOREQUIREUSER','1');	// Not disabled cause need to load personalized language
+//if (! defined('NOREQUIREDB'))   define('NOREQUIREDB','1');
+if (! defined('NOREQUIRESOC'))    define('NOREQUIRESOC','1');
+//if (! defined('NOREQUIRETRAN')) define('NOREQUIRETRAN','1');	// Not disabled cause need to do translations
+if (! defined('NOCSRFCHECK'))     define('NOCSRFCHECK',1);
+if (! defined('NOTOKENRENEWAL'))  define('NOTOKENRENEWAL',1);
+if (! defined('NOLOGIN'))         define('NOLOGIN',1);
+if (! defined('NOREQUIREMENU'))   define('NOREQUIREMENU',1);
+if (! defined('NOREQUIREHTML'))   define('NOREQUIREHTML',1);
+if (! defined('NOREQUIREAJAX'))   define('NOREQUIREAJAX','1');
+
+session_cache_limiter(FALSE);
+
+require_once '../../main.inc.php';
+
+// Define javascript type
+header('Content-type: text/javascript; charset=UTF-8');
+// Important: Following code is to avoid page request by browser and PHP CPU at each Dolibarr page access.
+if (empty($dolibarr_nocache)) header('Cache-Control: max-age=3600, public, must-revalidate');
+else header('Cache-Control: no-cache');
+?>
+
+/**
+ * Select2 French translation
+ */
+(function ($) {
+    "use strict";
+
+    $.fn.select2.locales['xx'] = {
+        formatMatches: function (matches) { return matches + " <?php echo dol_escape_js($langs->trans("Select2ResultFoundUseArrows")); ?>"; },
+        formatNoMatches: function () { return "<?php echo dol_escape_js($langs->trans("Select2NotFound")); ?>"; },
+        formatInputTooShort: function (input, min) { var n = min - input.length; return "<?php echo dol_escape_js($langs->trans("Select2Enter")); ?> " + n + " <?php echo dol_escape_js($langs->trans("Select2MoreCharacters")); ?>"; },
+        formatLoadMore: function (pageNumber) { return "<?php echo dol_escape_js($langs->trans("Select2LoadingMoreResults")); ?>"; },
+        formatSearching: function () { return "<?php echo dol_escape_js($langs->trans("Select2SearchInProgress")); ?>"; }
+    };
+
+    $.extend($.fn.select2.defaults, $.fn.select2.locales['xx']);
+})(jQuery);
+
+<?php
+if (is_object($db)) $db->close();

+ 9 - 11
htdocs/core/lib/functions.lib.php

@@ -3842,13 +3842,14 @@ function yn($yesno, $case=1, $color=0)
 
 /**
  *	Return a path to have a directory according to object.
- *  Examples:       '001' with level 3->"0/0/1/", '015' with level 3->"0/1/5/"
- *  Examples:       'ABC-1' with level 3 ->"0/0/1/", '015' with level 1->"5/"
- *
- *	@param	string	$num            Id of object
- *	@param  int		$level		    Level of subdirs to return (1, 2 or 3 levels)
- * 	@param	int		$alpha		    0=Keep number only to forge path, 1=Use alpha part afer the - (By default, use 0).
- *  @param  int		$withoutslash   0=With slash at end, 1=without slash at end (except if '/', we return '')
+ *  New usage:       $conf->product->multidir_output[$object->entity].'/'.get_exdir(0, 0, 0, 1, $object, 'modulepart')
+ *  Old usage:       '001' with level 3->"0/0/1/", '015' with level 3->"0/1/5/"
+ *  Old usage:       'ABC-1' with level 3 ->"0/0/1/", '015' with level 1->"5/"
+ *
+ *	@param	string	$num            Id of object (deprecated, $object will be used in future)
+ *	@param  int		$level		    Level of subdirs to return (1, 2 or 3 levels). (deprecated, global option will be used in future)
+ * 	@param	int		$alpha		    0=Keep number only to forge path, 1=Use alpha part afer the - (By default, use 0). (deprecated, global option will be used in future)
+ *  @param  int		$withoutslash   0=With slash at end (except if '/', we return ''), 1=without slash at end
  *  @param	Object	$object			Object
  *  @param	string	$modulepart		Type of object ('invoice_supplier, 'donation', 'invoice', ...')
  *  @return	string					Dir to use ending. Example '' or '1/' or '1/2/'
@@ -3859,9 +3860,6 @@ function get_exdir($num,$level,$alpha,$withoutslash,$object,$modulepart)
 
 	$path = '';
 
-	// TODO if object is null, load it from id and modulepart.
-
-
 	if (! empty($level) && in_array($modulepart, array('cheque','user','category','holiday','shipment', 'member','don','donation','supplier_invoice','invoice_supplier')))
 	{
 		// This part should be removed once all code is using "get_exdir" to forge path, with all parameters provided
@@ -3876,7 +3874,7 @@ function get_exdir($num,$level,$alpha,$withoutslash,$object,$modulepart)
 	{
 		// TODO
 		// We will introduce here a common way of forging path for document storage
-		// Here, $num=id, ref and modulepart are required.
+		// Here, object->id, object->ref and object->modulepart are required.
 
 	}
 

+ 174 - 6
htdocs/core/lib/pdf.lib.php

@@ -1266,7 +1266,10 @@ function pdf_getlinenum($object,$i,$outputlangs,$hidedetails=0)
 	{
 		$special_code = $object->lines[$i]->special_code;
 		if (! empty($object->lines[$i]->fk_parent_line)) $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
-		// TODO add hook function
+		$parameters = array('i'=>$i,'outputlangs'=>$outputlangs,'hidedetails'=>$hidedetails,'special_code'=>$special_code);
+		$action='';
+		$reshook = $hookmanager->executeHooks('pdf_getlinenum',$parameters,$object,$action);    // Note that $action and $object may have been modified by some hooks
+		return $hookmanager->resPrint;
 	}
 	if (empty($reshook))
 	{
@@ -1295,7 +1298,10 @@ function pdf_getlineref($object,$i,$outputlangs,$hidedetails=0)
 	{
 		$special_code = $object->lines[$i]->special_code;
 		if (! empty($object->lines[$i]->fk_parent_line)) $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
-		// TODO add hook function
+		$parameters = array('i'=>$i,'outputlangs'=>$outputlangs,'hidedetails'=>$hidedetails,'special_code'=>$special_code);
+		$action='';
+		$reshook = $hookmanager->executeHooks('pdf_getlineref',$parameters,$object,$action);    // Note that $action and $object may have been modified by some hooks
+		return $hookmanager->resPrint;
 	}
 	if (empty($reshook))
 	{
@@ -1323,7 +1329,10 @@ function pdf_getlineref_supplier($object,$i,$outputlangs,$hidedetails=0)
 	{
 		$special_code = $object->lines[$i]->special_code;
 		if (! empty($object->lines[$i]->fk_parent_line)) $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
-		// TODO add hook function
+		$parameters = array('i'=>$i,'outputlangs'=>$outputlangs,'hidedetails'=>$hidedetails,'special_code'=>$special_code);
+		$action='';
+		$reshook = $hookmanager->executeHooks('pdf_getlineref_supplier',$parameters,$object,$action);    // Note that $action and $object may have been modified by some hooks
+		return $hookmanager->resPrint;
 	}
 	if (empty($reshook))
 	{
@@ -1347,7 +1356,7 @@ function pdf_getlinevatrate($object,$i,$outputlangs,$hidedetails=0)
 
 	$reshook=0;
 	//if (is_object($hookmanager) && ( (isset($object->lines[$i]->product_type) && $object->lines[$i]->product_type == 9 && ! empty($object->lines[$i]->special_code)) || ! empty($object->lines[$i]->fk_parent_line) ) )
-	if (is_object($hookmanager))   // Old code is commented on preceding line. Reproduct this test in the pdf_xxx function if you don't want your hook to run
+	if (is_object($hookmanager))   // Old code is commented on preceding line. Reproduce this test in the pdf_xxx function if you don't want your hook to run
 	{
 		$special_code = $object->lines[$i]->special_code;
 		if (! empty($object->lines[$i]->fk_parent_line)) $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
@@ -1389,8 +1398,12 @@ function pdf_getlineupexcltax($object,$i,$outputlangs,$hidedetails=0)
 		$parameters = array('i'=>$i,'outputlangs'=>$outputlangs,'hidedetails'=>$hidedetails,'special_code'=>$special_code);
 		$action='';
 		$reshook = $hookmanager->executeHooks('pdf_getlineupexcltax',$parameters,$object,$action);    // Note that $action and $object may have been modified by some hooks
+<<<<<<< HEAD
 		
 		if (!empty($hookmanager->resPrint)) print $hookmanager->resPrint;
+=======
+		return $hookmanager->resPrint;
+>>>>>>> refs/remotes/origin/3.8
 	}
 	if (empty($reshook))
 	{
@@ -1421,8 +1434,12 @@ function pdf_getlineupwithtax($object,$i,$outputlangs,$hidedetails=0)
 		$parameters = array('i'=>$i,'outputlangs'=>$outputlangs,'hidedetails'=>$hidedetails,'special_code'=>$special_code);
 		$action='';
 		$reshook = $hookmanager->executeHooks('pdf_getlineupwithtax',$parameters,$object,$action);    // Note that $action and $object may have been modified by some hooks
+<<<<<<< HEAD
 		
 		if (!empty($hookmanager->resPrint)) print $hookmanager->resPrint;
+=======
+		return $hookmanager->resPrint;
+>>>>>>> refs/remotes/origin/3.8
 	}
 	if (empty($reshook))
 	{
@@ -1448,6 +1465,7 @@ function pdf_getlineqty($object,$i,$outputlangs,$hidedetails=0)
 	//if (is_object($hookmanager) && ( (isset($object->lines[$i]->product_type) && $object->lines[$i]->product_type == 9 && ! empty($object->lines[$i]->special_code)) || ! empty($object->lines[$i]->fk_parent_line) ) )
 	if (is_object($hookmanager))   // Old code is commented on preceding line. Reproduct this test in the pdf_xxx function if you don't want your hook to run
 	{
+<<<<<<< HEAD
 		$special_code = $object->lines[$i]->special_code;
 		if (! empty($object->lines[$i]->fk_parent_line)) $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
 		$parameters = array('i'=>$i,'outputlangs'=>$outputlangs,'hidedetails'=>$hidedetails,'special_code'=>$special_code);
@@ -1456,6 +1474,21 @@ function pdf_getlineqty($object,$i,$outputlangs,$hidedetails=0)
 		
 		if(!empty($hookmanager->resPrint)) return $hookmanager->resPrint;
 		else return $reshook;
+=======
+		if (is_object($hookmanager) && (( $object->lines[$i]->product_type == 9 && !empty($object->lines[$i]->special_code) ) || ! empty($object->lines[$i]->fk_parent_line) ) )
+		{
+			$special_code = $object->lines[$i]->special_code;
+			if (! empty($object->lines[$i]->fk_parent_line)) $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
+			$parameters = array('i'=>$i,'outputlangs'=>$outputlangs,'hidedetails'=>$hidedetails,'special_code'=>$special_code);
+			$action='';
+			$reshook = $hookmanager->executeHooks('pdf_getlineqty',$parameters,$object,$action);    // Note that $action and $object may have been modified by some hooks
+			return $hookmanager->resPrint;
+		}
+		else
+		{
+			if (empty($hidedetails) || $hidedetails > 1) return $object->lines[$i]->qty;
+		}
+>>>>>>> refs/remotes/origin/3.8
 	}
     if (empty($reshook))
 	{
@@ -1482,6 +1515,7 @@ function pdf_getlineqty_asked($object,$i,$outputlangs,$hidedetails=0)
 	//if (is_object($hookmanager) && ( (isset($object->lines[$i]->product_type) && $object->lines[$i]->product_type == 9 && ! empty($object->lines[$i]->special_code)) || ! empty($object->lines[$i]->fk_parent_line) ) )
 	if (is_object($hookmanager))   // Old code is commented on preceding line. Reproduct this test in the pdf_xxx function if you don't want your hook to run
 	{
+<<<<<<< HEAD
 		$special_code = $object->lines[$i]->special_code;
 		if (! empty($object->lines[$i]->fk_parent_line)) $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
 		$parameters = array('i'=>$i,'outputlangs'=>$outputlangs,'hidedetails'=>$hidedetails,'special_code'=>$special_code);
@@ -1489,6 +1523,21 @@ function pdf_getlineqty_asked($object,$i,$outputlangs,$hidedetails=0)
 		$reshook = $hookmanager->executeHooks('pdf_getlineqty_asked',$parameters,$object,$action);    // Note that $action and $object may have been modified by some hooks
 	
 		if (!empty($hookmanager->resPrint)) return $hookmanager->resPrint;
+=======
+		if (is_object($hookmanager) && (( $object->lines[$i]->product_type == 9 && !empty($object->lines[$i]->special_code) ) || ! empty($object->lines[$i]->fk_parent_line) ) )
+		{
+			$special_code = $object->lines[$i]->special_code;
+			if (! empty($object->lines[$i]->fk_parent_line)) $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
+			$parameters = array('i'=>$i,'outputlangs'=>$outputlangs,'hidedetails'=>$hidedetails,'special_code'=>$special_code);
+			$action='';
+			$reshook = $hookmanager->executeHooks('pdf_getlineqty_asked',$parameters,$object,$action);    // Note that $action and $object may have been modified by some hooks
+			return $hookmanager->resPrint;
+		}
+		else
+		{
+			if (empty($hidedetails) || $hidedetails > 1) return $object->lines[$i]->qty_asked;
+		}
+>>>>>>> refs/remotes/origin/3.8
 	}
 	if (empty($reshook))
 	{
@@ -1515,6 +1564,7 @@ function pdf_getlineqty_shipped($object,$i,$outputlangs,$hidedetails=0)
 	//if (is_object($hookmanager) && ( (isset($object->lines[$i]->product_type) && $object->lines[$i]->product_type == 9 && ! empty($object->lines[$i]->special_code)) || ! empty($object->lines[$i]->fk_parent_line) ) )
 	if (is_object($hookmanager))   // Old code is commented on preceding line. Reproduct this test in the pdf_xxx function if you don't want your hook to run
 	{
+<<<<<<< HEAD
 		$special_code = $object->lines[$i]->special_code;
 		if (! empty($object->lines[$i]->fk_parent_line)) $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
 		$parameters = array('i'=>$i,'outputlangs'=>$outputlangs,'hidedetails'=>$hidedetails,'special_code'=>$special_code);
@@ -1522,6 +1572,21 @@ function pdf_getlineqty_shipped($object,$i,$outputlangs,$hidedetails=0)
 		$reshook = $hookmanager->executeHooks('pdf_getlineqty_shipped',$parameters,$object,$action);    // Note that $action and $object may have been modified by some hooks
 		
 		if(!empty($hookmanager->resPrint)) return $hookmanager->resPrint;
+=======
+		if (is_object($hookmanager) && (( $object->lines[$i]->product_type == 9 && !empty($object->lines[$i]->special_code) ) || ! empty($object->lines[$i]->fk_parent_line) ) )
+		{
+			$special_code = $object->lines[$i]->special_code;
+			if (! empty($object->lines[$i]->fk_parent_line)) $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
+			$parameters = array('i'=>$i,'outputlangs'=>$outputlangs,'hidedetails'=>$hidedetails,'special_code'=>$special_code);
+			$action='';
+			$reshook = $hookmanager->executeHooks('pdf_getlineqty_shipped',$parameters,$object,$action);    // Note that $action and $object may have been modified by some hooks
+			return $hookmanager->resPrint;
+		}
+		else
+		{
+			if (empty($hidedetails) || $hidedetails > 1) return $object->lines[$i]->qty_shipped;
+		}
+>>>>>>> refs/remotes/origin/3.8
 	}
 	if (empty($reshook))
 	{
@@ -1548,6 +1613,7 @@ function pdf_getlineqty_keeptoship($object,$i,$outputlangs,$hidedetails=0)
 	//if (is_object($hookmanager) && ( (isset($object->lines[$i]->product_type) && $object->lines[$i]->product_type == 9 && ! empty($object->lines[$i]->special_code)) || ! empty($object->lines[$i]->fk_parent_line) ) )
 	if (is_object($hookmanager))   // Old code is commented on preceding line. Reproduct this test in the pdf_xxx function if you don't want your hook to run
 	{
+<<<<<<< HEAD
 		$special_code = $object->lines[$i]->special_code;
 		if (! empty($object->lines[$i]->fk_parent_line)) $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
 		$parameters = array('i'=>$i,'outputlangs'=>$outputlangs,'hidedetails'=>$hidedetails,'special_code'=>$special_code);
@@ -1555,6 +1621,21 @@ function pdf_getlineqty_keeptoship($object,$i,$outputlangs,$hidedetails=0)
 		$reshook = $hookmanager->executeHooks('pdf_getlineqty_keeptoship',$parameters,$object,$action);    // Note that $action and $object may have been modified by some hooks
 		
 		if(!empty($hookmanager->resPrint)) return $hookmanager->resPrint;
+=======
+		if (is_object($hookmanager) && (( $object->lines[$i]->product_type == 9 && !empty($object->lines[$i]->special_code) ) || ! empty($object->lines[$i]->fk_parent_line) ) )
+		{
+			$special_code = $object->lines[$i]->special_code;
+			if (! empty($object->lines[$i]->fk_parent_line)) $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
+			$parameters = array('i'=>$i,'outputlangs'=>$outputlangs,'hidedetails'=>$hidedetails,'special_code'=>$special_code);
+			$action='';
+			$reshook = $hookmanager->executeHooks('pdf_getlineqty_keeptoship',$parameters,$object,$action);    // Note that $action and $object may have been modified by some hooks
+			return $hookmanager->resPrint;
+		}
+		else
+		{
+			if (empty($hidedetails) || $hidedetails > 1) return ($object->lines[$i]->qty_asked - $object->lines[$i]->qty_shipped);
+		}
+>>>>>>> refs/remotes/origin/3.8
 	}
 	if (empty($reshook))
 	{
@@ -1577,6 +1658,7 @@ function pdf_getlineqty_keeptoship($object,$i,$outputlangs,$hidedetails=0)
 function pdf_getlineunit($object, $i, $outputlangs, $hidedetails = 0, $hookmanager = false)
 {
 	global $langs;
+<<<<<<< HEAD
 	
 	$reshook=0;
 	//if (is_object($hookmanager) && ( (isset($object->lines[$i]->product_type) && $object->lines[$i]->product_type == 9 && ! empty($object->lines[$i]->special_code)) || ! empty($object->lines[$i]->fk_parent_line) ) )
@@ -1585,6 +1667,27 @@ function pdf_getlineunit($object, $i, $outputlangs, $hidedetails = 0, $hookmanag
 		$special_code = $object->lines[$i]->special_code;
 		if (!empty($object->lines[$i]->fk_parent_line)) {
 			$special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
+=======
+	if ($object->lines[$i]->special_code != 3) {
+		if (is_object($hookmanager) && (($object->lines[$i]->product_type == 9 && !empty($object->lines[$i]->special_code)) || !empty($object->lines[$i]->fk_parent_line))) {
+			$special_code = $object->lines[$i]->special_code;
+			if (!empty($object->lines[$i]->fk_parent_line)) {
+				$special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
+			}
+			$parameters = array(
+				'i' => $i,
+				'outputlangs' => $outputlangs,
+				'hidedetails' => $hidedetails,
+				'special_code' => $special_code
+			);
+			$action = '';
+			$reshook = $hookmanager->executeHooks('pdf_getlineunit', $parameters, $object, $action);    // Note that $action and $object may have been modified by some hooks
+			return $hookmanager->resPrint;
+		} else {
+			if (empty($hidedetails) || $hidedetails > 1) {
+				return $langs->transnoentitiesnoconv($object->lines[$i]->getLabelOfUnit('short'));
+			}
+>>>>>>> refs/remotes/origin/3.8
 		}
 		$parameters = array(
 			'i' => $i,
@@ -1625,6 +1728,7 @@ function pdf_getlineremisepercent($object,$i,$outputlangs,$hidedetails=0)
 	//if (is_object($hookmanager) && ( (isset($object->lines[$i]->product_type) && $object->lines[$i]->product_type == 9 && ! empty($object->lines[$i]->special_code)) || ! empty($object->lines[$i]->fk_parent_line) ) )
 	if (is_object($hookmanager))   // Old code is commented on preceding line. Reproduct this test in the pdf_xxx function if you don't want your hook to run
 	{
+<<<<<<< HEAD
 		$special_code = $object->lines[$i]->special_code;
 		if (! empty($object->lines[$i]->fk_parent_line)) $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
 		$parameters = array('i'=>$i,'outputlangs'=>$outputlangs,'hidedetails'=>$hidedetails,'special_code'=>$special_code);
@@ -1632,6 +1736,21 @@ function pdf_getlineremisepercent($object,$i,$outputlangs,$hidedetails=0)
 		$reshook = $hookmanager->executeHooks('pdf_getlineremisepercent',$parameters,$object,$action);    // Note that $action and $object may have been modified by some hooks
 		
 		if(!empty($hookmanager->resPrint)) return $hookmanager->resPrint;
+=======
+		if (is_object($hookmanager) && ( ($object->lines[$i]->product_type == 9 && !empty($object->lines[$i]->special_code) ) || ! empty($object->lines[$i]->fk_parent_line) ) )
+		{
+			$special_code = $object->lines[$i]->special_code;
+			if (! empty($object->lines[$i]->fk_parent_line)) $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
+			$parameters = array('i'=>$i,'outputlangs'=>$outputlangs,'hidedetails'=>$hidedetails,'special_code'=>$special_code);
+			$action='';
+			$reshook = $hookmanager->executeHooks('pdf_getlineremisepercent',$parameters,$object,$action);    // Note that $action and $object may have been modified by some hooks
+			return $hookmanager->resPrint;
+		}
+		else
+		{
+			if (empty($hidedetails) || $hidedetails > 1) return dol_print_reduction($object->lines[$i]->remise_percent,$outputlangs);
+		}
+>>>>>>> refs/remotes/origin/3.8
 	}
 	if (empty($reshook))
 	{
@@ -1653,6 +1772,7 @@ function pdf_getlineremisepercent($object,$i,$outputlangs,$hidedetails=0)
  */
 function pdf_getlineprogress($object, $i, $outputlangs, $hidedetails = 0, $hookmanager = null)
 {
+<<<<<<< HEAD
 	$reshook=0;
 	//if (is_object($hookmanager) && ( (isset($object->lines[$i]->product_type) && $object->lines[$i]->product_type == 9 && ! empty($object->lines[$i]->special_code)) || ! empty($object->lines[$i]->fk_parent_line) ) )
 	if (is_object($hookmanager))   // Old code is commented on preceding line. Reproduct this test in the pdf_xxx function if you don't want your hook to run
@@ -1664,6 +1784,19 @@ function pdf_getlineprogress($object, $i, $outputlangs, $hidedetails = 0, $hookm
 		$reshook = $hookmanager->executeHooks('pdf_getlineprogress', $parameters, $object, $action);    // Note that $action and $object may have been modified by some hooks
 		
 		if(!empty($hookmanager->resPrint)) return $hookmanager->resPrint;
+=======
+	if ($object->lines[$i]->special_code != 3) {
+		if (is_object($hookmanager) && (($object->lines[$i]->product_type == 9 && !empty($object->lines[$i]->special_code)) || !empty($object->lines[$i]->fk_parent_line))) {
+			$special_code = $object->lines[$i]->special_code;
+			if (!empty($object->lines[$i]->fk_parent_line)) $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
+			$parameters = array('i' => $i, 'outputlangs' => $outputlangs, 'hidedetails' => $hidedetails, 'special_code' => $special_code);
+			$action = '';
+			$reshook = $hookmanager->executeHooks('pdf_getlineprogress', $parameters, $object, $action);    // Note that $action and $object may have been modified by some hooks
+			return $hookmanager->resPrint;
+		} else {
+			if (empty($hidedetails) || $hidedetails > 1) return $object->lines[$i]->situation_percent . '%';
+		}
+>>>>>>> refs/remotes/origin/3.8
 	}
 	if (empty($reshook))
 	{
@@ -1703,11 +1836,27 @@ function pdf_getlinetotalexcltax($object,$i,$outputlangs,$hidedetails=0)
 	}
     if (empty($reshook))
 	{
+<<<<<<< HEAD
 	    if ($object->lines[$i]->special_code == 3)
     	{
     		return $outputlangs->transnoentities("Option");
     	}
         if (empty($hidedetails) || $hidedetails > 1) return price($sign * $object->lines[$i]->total_ht, 0, $outputlangs);
+=======
+		if (is_object($hookmanager) && (($object->lines[$i]->product_type == 9 && ! empty($object->lines[$i]->special_code)) || ! empty($object->lines[$i]->fk_parent_line)))
+		{
+			$special_code = $object->lines[$i]->special_code;
+			if (! empty($object->lines[$i]->fk_parent_line)) $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
+			$parameters = array('i'=>$i,'outputlangs'=>$outputlangs,'hidedetails'=>$hidedetails,'special_code'=>$special_code);
+			$action='';
+			$reshook = $hookmanager->executeHooks('pdf_getlinetotalexcltax',$parameters,$object,$action);    // Note that $action and $object may have been modified by some hooks
+			return $hookmanager->resPrint;
+		}
+		else
+		{
+			if (empty($hidedetails) || $hidedetails > 1) return price($sign * $object->lines[$i]->total_ht, 0, $outputlangs);
+		}
+>>>>>>> refs/remotes/origin/3.8
 	}
 	return '';
 }
@@ -1739,11 +1888,27 @@ function pdf_getlinetotalwithtax($object,$i,$outputlangs,$hidedetails=0)
 	}
 	if (empty($reshook))
 	{
+<<<<<<< HEAD
 		if ($object->lines[$i]->special_code == 3)
     	{
     		return $outputlangs->transnoentities("Option");
     	}
 		if (empty($hidedetails) || $hidedetails > 1) return price(($object->lines[$i]->total_ht) + ($object->lines[$i]->total_ht)*($object->lines[$i]->tva_tx)/100, 0, $outputlangs);
+=======
+		if (is_object($hookmanager) && (($object->lines[$i]->product_type == 9 && ! empty($object->lines[$i]->special_code)) || ! empty($object->lines[$i]->fk_parent_line)))
+		{
+			$special_code = $object->lines[$i]->special_code;
+			if (! empty($object->lines[$i]->fk_parent_line)) $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
+			$parameters = array('i'=>$i,'outputlangs'=>$outputlangs,'hidedetails'=>$hidedetails,'special_code'=>$special_code);
+			$action='';
+			$reshook = $hookmanager->executeHooks('pdf_getlinetotalwithtax',$parameters,$object,$action);    // Note that $action and $object may have been modified by some hooks
+			return $hookmanager->resPrint;
+		}
+		else
+		{
+			if (empty($hidedetails) || $hidedetails > 1) return price(($object->lines[$i]->total_ht) + ($object->lines[$i]->total_ht)*($object->lines[$i]->tva_tx)/100, 0, $outputlangs);
+		}
+>>>>>>> refs/remotes/origin/3.8
 	}
 	return '';
 }
@@ -1776,7 +1941,10 @@ function pdf_getTotalQty($object,$type,$outputlangs)
 			{
 				$special_code = $object->lines[$i]->special_code;
 				if (! empty($object->lines[$i]->fk_parent_line)) $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
-				// TODO add hook function
+				$parameters = array('i'=>$i,'outputlangs'=>$outputlangs,'hidedetails'=>$hidedetails,'special_code'=>$special_code);
+				$action='';
+				$reshook = $hookmanager->executeHooks('pdf_getTotalQty',$parameters,$object,$action);    // Note that $action and $object may have been modified by some hooks
+				return $hookmanager->resPrint;
 			}
 			else if ($type==0 && $object->lines[$i]->product_type == 0)
 			{
@@ -1812,7 +1980,7 @@ function pdf_getLinkedObjects($object,$outputlangs)
 		if ($objecttype == 'propal')
 		{
 			$outputlangs->load('propal');
-			
+
 			foreach($objects as $elementobject)
 			{
 				$linkedobjects[$objecttype]['ref_title'] = $outputlangs->transnoentities("RefProposal");

+ 1 - 1
htdocs/core/modules/facture/doc/pdf_crabe.modules.php

@@ -191,7 +191,7 @@ class pdf_crabe extends ModelePDFFactures
 				$objphoto = new Product($this->db);
 				$objphoto->fetch($object->lines[$i]->fk_product);
 
-				$pdir = get_exdir($object->lines[$i]->fk_product,2,0,0,'product') . $object->lines[$i]->fk_product ."/photos/";
+				$pdir = get_exdir($object->lines[$i]->fk_product,2,0,0,$objphoto,'product') . $object->lines[$i]->fk_product ."/photos/";
 				$dir = $conf->product->dir_output.'/'.$pdir;
 
 				$realpath='';

+ 2 - 2
htdocs/core/modules/mailings/modules_mailings.php

@@ -203,9 +203,9 @@ class MailingTargets    // This can't be abstract as it is used for some method
         //Update the status to show contact mail that don't want to be contacted anymore'
         $sql = "UPDATE ".MAIN_DB_PREFIX."mailing_cibles";
         $sql .= " SET statut=3";
-        $sql .= " WHERE fk_mailing=".$mailing_id." AND email in (SELECT sc.email FROM ".MAIN_DB_PREFIX."socpeople AS sc ";
+        $sql .= " WHERE fk_mailing=".$mailing_id." AND source_type='contact' AND (email in (SELECT sc.email FROM ".MAIN_DB_PREFIX."socpeople AS sc ";
         $sql .= " INNER JOIN ".MAIN_DB_PREFIX."societe s ON s.fk_stcomm=-1 AND s.rowid=sc.fk_soc)";
-        $sql .= " AND source_type='contact'";
+        $sql .= "  OR no_email=1)";
         $result=$this->db->query($sql);
 
         dol_syslog(get_class($this)."::add_to_target: mailing update status to display contact mail that do not want to be contacted sql:".$sql);

+ 2 - 2
htdocs/core/modules/modProjet.class.php

@@ -300,8 +300,8 @@ class modProjet extends DolibarrModules
         	}
         }
         // End add extra fields
-		$this->export_fields_array[$r]=array_merge($this->export_fields_array[$r], array('ptt.task_date'=>'TaskTimeDate','ptt.task_duration'=>"TimesSpent",'ptt.fk_user'=>"TaskTimeUser",'ptt.note'=>"TaskTimeNote"));
-        $this->export_entities_array[$r]=array_merge($this->export_entities_array[$r], array('ptt.task_date'=>'task_time','ptt.task_duration'=>"task_time",'ptt.fk_user'=>"task_time",'ptt.note'=>"task_time"));
+		$this->export_fields_array[$r]=array_merge($this->export_fields_array[$r], array('ptt.rowid'=>'IdTaskTime','ptt.task_date'=>'TaskTimeDate','ptt.task_duration'=>"TimesSpent",'ptt.fk_user'=>"TaskTimeUser",'ptt.note'=>"TaskTimeNote"));
+        $this->export_entities_array[$r]=array_merge($this->export_entities_array[$r], array('ptt.rowid'=>'task_time','ptt.task_date'=>'task_time','ptt.task_duration'=>"task_time",'ptt.fk_user'=>"task_time",'ptt.note'=>"task_time"));
 
         $this->export_sql_start[$r]='SELECT DISTINCT ';
 		$this->export_sql_end[$r]  =' FROM '.MAIN_DB_PREFIX.'projet as p';

+ 2 - 2
htdocs/core/modules/propale/doc/pdf_azur.modules.php

@@ -181,11 +181,11 @@ class pdf_azur extends ModelePDFPropales
 				if (! empty($conf->global->PRODUCT_USE_OLD_PATH_FOR_PHOTO))
 				{
 					$pdir[0] = get_exdir($objphoto->id,2,0,0,$objphoto,'product') . $objphoto->id ."/photos/";
-					$pdir[1] = dol_sanitizeFileName($objphoto->ref).'/';
+					$pdir[1] = get_exdir(0,0,0,0,$objphoto,'product') . dol_sanitizeFileName($objphoto->ref).'/';
 				}
 				else
 				{
-					$pdir[0] = dol_sanitizeFileName($objphoto->ref).'/';				// default
+					$pdir[0] = get_exdir(0,0,0,0,$objphoto,'product') . dol_sanitizeFileName($objphoto->ref).'/';				// default
 					$pdir[1] = get_exdir($objphoto->id,2,0,0,$objphoto,'product') . $objphoto->id ."/photos/";	// alternative
 				}
 

+ 6 - 3
htdocs/core/tpl/document_actions_pre_headers.tpl.php

@@ -23,6 +23,7 @@
 
 
 // Variable $upload_dir must be defined when entering here
+// Variable $upload_dirold may also exists.
 
 // Send file/link
 if (GETPOST('sendit') && ! empty($conf->global->MAIN_UPLOAD_DOC))
@@ -59,16 +60,18 @@ if ($action == 'confirm_deletefile' && $confirm == 'yes')
 		{
        		$urlfile=basename($urlfile);
 			$file = $upload_dir . "/" . $urlfile;
+			if (! empty($upload_dirold)) $fileold = $upload_dirold . "/" . $urlfile;
 		}
         $linkid = GETPOST('linkid', 'int');	// Do not use urldecode here ($_GET and $_REQUEST are already decoded by PHP).
 
         if ($urlfile)
         {
-	        $dir = dirname($file).'/'; // Chemin du dossier contenant l'image d'origine
-	        $dirthumb = $dir.'/thumbs/'; // Chemin du dossier contenant la vignette
+	        $dir = dirname($file).'/';     // Chemin du dossier contenant l'image d'origine
+	        $dirthumb = $dir.'/thumbs/';   // Chemin du dossier contenant la vignette
 
             $ret = dol_delete_file($file, 0, 0, 0, $object);
-
+            if (! empty($fileold)) dol_delete_file($fileold, 0, 0, 0, $object);     // Delete file using old path
+            
 	        // Si elle existe, on efface la vignette
 	        if (preg_match('/(\.jpg|\.jpeg|\.bmp|\.gif|\.png|\.tiff)$/i',$file,$regs))
 	        {

+ 2 - 1
htdocs/fourn/card.php

@@ -307,7 +307,7 @@ if ($object->id > 0)
 
 		//Query from product/liste.php
 		$sql = 'SELECT p.rowid, p.ref, p.label, pfp.tms,';
-		$sql.= ' p.fk_product_type';
+		$sql.= ' p.fk_product_type, p.entity';
 		$sql.= ' FROM '.MAIN_DB_PREFIX.'product_fournisseur_price as pfp';
 		$sql.= " LEFT JOIN ".MAIN_DB_PREFIX."product as p ON p.rowid = pfp.fk_product";
 		$sql.= ' WHERE p.entity IN ('.getEntity('product', 1).')';
@@ -331,6 +331,7 @@ if ($object->id > 0)
 				$productstatic->ref = $objp->ref;
 				$productstatic->label = $objp->label;
 				$productstatic->type = $objp->fk_product_type;
+				$productstatic->entity = $objp->entity;
 
 				print "<tr ".$bc[$var].">";
 				print '<td class="nowrap">';

+ 1 - 1
htdocs/fourn/commande/orderstoinvoice.php

@@ -44,7 +44,7 @@ $langs->load('orders');
 $langs->load('deliveries');
 $langs->load('companies');
 
-if (! $user->rights->facture->creer)
+if (! $user->rights->fournisseur->facture->creer)
 	accessforbidden();
 
 $id = (GETPOST('id') ? GETPOST('id', 'int') : GETPOST("facid")); // For backward compatibility

+ 2 - 1
htdocs/fourn/product/list.php

@@ -87,7 +87,7 @@ if ($fourn_id)
 	$supplier->fetch($fourn_id);
 }
 
-$sql = "SELECT p.rowid, p.label, p.ref, p.fk_product_type,";
+$sql = "SELECT p.rowid, p.label, p.ref, p.fk_product_type, p.entity,";
 $sql.= " ppf.fk_soc, ppf.ref_fourn, ppf.price as price, ppf.quantity as qty, ppf.unitprice,";
 $sql.= " s.rowid as socid, s.nom as name";
 $sql.= " FROM ".MAIN_DB_PREFIX."product as p";
@@ -215,6 +215,7 @@ if ($resql)
 		$productstatic->id=$objp->rowid;
 		$productstatic->ref=$objp->ref;
 		$productstatic->type=$objp->fk_product_type;
+		$productstatic->entity=$objp->entity;
 		print $productstatic->getNomUrl(1,'supplier');
 		print '</td>';
 

+ 4 - 0
htdocs/langs/en_US/admin.lang

@@ -980,6 +980,7 @@ Delays_MAIN_DELAY_CUSTOMER_BILLS_UNPAYED=Tolerence delay (in days) before alert
 Delays_MAIN_DELAY_TRANSACTIONS_TO_CONCILIATE=Tolerance delay (in days) before alert on pending bank reconciliation
 Delays_MAIN_DELAY_MEMBERS=Tolerance delay (in days) before alert on delayed membership fee
 Delays_MAIN_DELAY_CHEQUES_TO_DEPOSIT=Tolerance delay (in days) before alert for cheques deposit to do
+Delays_MAIN_DELAY_EXPENSEREPORTS=Tolerance delay (in days) before alert for expense reports to approve
 SetupDescription1=All parameters available in the setup area allow you to setup Dolibarr before starting using it.
 SetupDescription2=The 2 most important setup steps are the 2 first ones in the left setup menu, this means Company/foundation setup page and Modules setup page:
 SetupDescription3=Parameters in menu <a href="%s">Setup -> Company/foundation</a> are required because input information is used on Dolibarr displays and to modify Dolibarr behaviour (for example for features related to your country).
@@ -1117,6 +1118,9 @@ EmptyNumRefModelDesc=The code is free. This code can be modified at any time.
 ##### Module password generation
 PasswordGenerationStandard=Return a password generated according to internal Dolibarr algorithm: 8 characters containing shared numbers and characters in lowercase.
 PasswordGenerationNone=Do not suggest any generated password. Password must be type in manually.
+PasswordGenerationPerso=Return a password according to your personally defined configuration.
+SetupPerso=According to your configuration
+PasswordPatternDesc=Password pattern description
 ##### Users setup #####
 UserGroupSetup=Users and groups module setup
 GeneratePassword=Suggest a generated password

+ 7 - 1
htdocs/langs/en_US/main.lang

@@ -752,6 +752,12 @@ ShortSaturday=S
 ShortSunday=S
 SelectMailModel=Select email template
 SetRef=Set ref
+Select2ResultFoundUseArrows=
+Select2NotFound=No result found
+Select2Enter=Enter
+Select2MoreCharacters=or more characters
+Select2LoadingMoreResults=Loading more results...
+Select2SearchInProgress=Search in progress...
 SearchIntoThirdparties=Thirdparties
 SearchIntoContacts=Contacts
 SearchIntoMembers=Members
@@ -766,4 +772,4 @@ SearchIntoCustomerProposals=Customer proposals
 SearchIntoSupplierProposals=Supplier proposals
 SearchIntoInterventions=Interventions
 SearchIntoContracts=Contracts
-SearchIntoExpenseReports=Expense reports
+SearchIntoExpenseReports=Expense reports

+ 1 - 0
htdocs/langs/en_US/projects.lang

@@ -175,6 +175,7 @@ ProjectWeightedOppAmountOfProjectsByMonth=Weighted amount of opportunities by mo
 ProjectOpenedProjectByOppStatus=Opened project/lead by opportunity status
 ProjectsStatistics=Statistics on projects/leads
 TaskAssignedToEnterTime=Task assigned. Entering time on this task should be possible.
+IdTaskTime=Id task time
 OpenedProjectsByThirdparties=Opened projects by thirdparties
 OpportunityTotalAmount=Opportunities total amount
 OpportunityPonderatedAmount=Opportunities weighted amount

+ 1 - 0
htdocs/main.inc.php

@@ -1217,6 +1217,7 @@ function top_htmlhead($head, $title='', $disablejs=0, $disablehead=0, $arrayofjs
             {
             	$tmpplugin=empty($conf->global->MAIN_USE_JQUERY_MULTISELECT)?constant('REQUIRE_JQUERY_MULTISELECT'):$conf->global->MAIN_USE_JQUERY_MULTISELECT;
             	print '<script type="text/javascript" src="'.DOL_URL_ROOT.'/includes/jquery/plugins/'.$tmpplugin.'/'.$tmpplugin.'.min.js'.($ext?'?'.$ext:'').'"></script>'."\n";
+                print '<script type="text/javascript" src="'.DOL_URL_ROOT.'/core/js/select2_locale.js.php'.($ext?'?'.$ext:'').'"></script>'."\n";
             }
             // jQuery jMobile
             if (! empty($conf->global->MAIN_USE_JQUERY_JMOBILE) || defined('REQUIRE_JQUERY_JMOBILE') || (! empty($conf->dol_use_jmobile) && $conf->dol_use_jmobile > 0))

+ 2 - 1
htdocs/margin/productMargins.php

@@ -162,7 +162,7 @@ if (! empty($conf->global->DISPLAY_MARK_RATES)) {
 print "</table>";
 print '</form>';
 
-$sql = "SELECT p.label, p.rowid, p.fk_product_type, p.ref,";
+$sql = "SELECT p.label, p.rowid, p.fk_product_type, p.ref, p.entity as pentity,";
 if ($id > 0) $sql.= " d.fk_product,";
 if ($id > 0) $sql.= " f.rowid as facid, f.facnumber, f.total as total_ht, f.datef, f.paye, f.fk_statut as statut,";
 $sql.= " sum(d.total_ht) as selling_price,";
@@ -264,6 +264,7 @@ if ($result)
 				$product_static->id=$objp->rowid;
 				$product_static->ref=$objp->ref;
 				$product_static->label=$objp->label;
+				$product_static->entity=$objp->pentity;
 				$text=$product_static->getNomUrl(1);
 				print $text.= ' - '.$objp->label;
 				print "</td>\n";

+ 2 - 1
htdocs/product/canvas/product/actions_card_product.class.php

@@ -341,7 +341,7 @@ class ActionsCardProduct
 		$sql = 'SELECT DISTINCT ';
 
 		// Fields requiered
-		$sql.= 'p.rowid, p.price_base_type, p.fk_product_type, p.seuil_stock_alerte';
+		$sql.= 'p.rowid, p.price_base_type, p.fk_product_type, p.seuil_stock_alerte, p.entity';
 
 		// Fields not requiered
 		foreach($this->field_list as $field)
@@ -417,6 +417,7 @@ class ActionsCardProduct
 							$this->id 		= $obj->rowid;
 							$this->ref 		= $obj->$alias;
 							$this->type 	= $obj->fk_product_type;
+							$this->entity	= $obj->entity;
 							$datas[$alias] 	= $this->getNomUrl(1,'',24);
 						}
 						else if ($alias == 'stock')

+ 8 - 6
htdocs/product/class/product.class.php

@@ -2770,7 +2770,8 @@ class Product extends CommonObject
 					'type'=>$type,				// Nb of units that compose parent product
 					'desiredstock'=>$this->desiredstock,
 					'level'=>$level,
-					'incdec'=>$incdec
+					'incdec'=>$incdec,
+					'entity'=>$this->entity
 				);
 
 				// Recursive call if there is childs to child
@@ -2852,7 +2853,7 @@ class Product extends CommonObject
 	 */
 	function getFather()
 	{
-		$sql = "SELECT p.rowid, p.label as label, p.ref as ref, pa.fk_product_pere as id, p.fk_product_type, pa.qty, pa.incdec";
+		$sql = "SELECT p.rowid, p.label as label, p.ref as ref, pa.fk_product_pere as id, p.fk_product_type, pa.qty, pa.incdec, p.entity";
 		$sql.= " FROM ".MAIN_DB_PREFIX."product_association as pa,";
 		$sql.= " ".MAIN_DB_PREFIX."product as p";
 		$sql.= " WHERE p.rowid = pa.fk_product_pere";
@@ -2870,6 +2871,7 @@ class Product extends CommonObject
 				$prods[$record['id']]['qty'] = $record['qty'];
 				$prods[$record['id']]['incdec'] = $record['incdec'];
 				$prods[$record['id']]['fk_product_type'] =  $record['fk_product_type'];
+				$prods[$record['id']]['entity'] =  $record['entity'];
 			}
 			return $prods;
 		}
@@ -3412,7 +3414,7 @@ class Product extends CommonObject
 
 		$dir = $sdir;
 		if (! empty($conf->global->PRODUCT_USE_OLD_PATH_FOR_PHOTO)) $dir .= '/'. get_exdir($this->id,2,0,0,$this,'product') . $this->id ."/photos";
-		else $dir .= '/'.dol_sanitizeFileName($this->ref);
+		else $dir .= '/'.get_exdir(0,0,0,0,$this,'product').dol_sanitizeFileName($this->ref);
 
 		dol_mkdir($dir);
 
@@ -3450,7 +3452,7 @@ class Product extends CommonObject
 
 		$dir = $sdir;
 		if (! empty($conf->global->PRODUCT_USE_OLD_PATH_FOR_PHOTO)) $dir .= '/'. get_exdir($this->id,2,0,0,$this,'product') . $this->id ."/photos/";
-		else $dir .= '/'.dol_sanitizeFileName($this->ref).'/';
+		else $dir .= '/'.get_exdir(0,0,0,0,$this,'product').dol_sanitizeFileName($this->ref).'/';
 
 		$nbphoto=0;
 
@@ -3501,8 +3503,8 @@ class Product extends CommonObject
 		}
 		else
 		{
-			$dir .= $this->ref.'/';
-			$pdir .= $this->ref.'/';
+			$dir .= get_exdir(0,0,0,0,$this,'product').$this->ref.'/';
+			$pdir .= get_exdir(0,0,0,0,$this,'product').$this->ref.'/';
 		}
 
 		$dirthumb = $dir.'thumbs/';

+ 4 - 1
htdocs/product/composition/card.php

@@ -139,7 +139,7 @@ if ($action == 'search')
 {
 	$current_lang = $langs->getDefaultLang();
 
-    $sql = 'SELECT DISTINCT p.rowid, p.ref, p.label, p.barcode, p.price, p.price_ttc, p.price_base_type,';
+    $sql = 'SELECT DISTINCT p.rowid, p.ref, p.label, p.barcode, p.price, p.price_ttc, p.price_base_type, p.entity,';
     $sql.= ' p.fk_product_type, p.tms as datem';
 	if (! empty($conf->global->MAIN_MULTILANGS)) $sql.= ', pl.label as labelm, pl.description as descriptionm';
 	$sql.= ' FROM '.MAIN_DB_PREFIX.'product as p';
@@ -278,6 +278,7 @@ if ($id > 0 || ! empty($ref))
 					$productstatic->type=$value["fk_product_type"];
 					$productstatic->ref=$value['ref'];
 					$productstatic->label=$value['label'];
+					$productstatic->entity=$value['entity'];
 
 					$class=($class=='impair')?'pair':'impair';
 					print '<tr class="'.$class.'">';
@@ -334,6 +335,7 @@ if ($id > 0 || ! empty($ref))
 					$productstatic->id=$value['id'];
 					$productstatic->type=$value['type'];
 					$productstatic->label=$value['label'];
+					$productstatic->entity=$value['entity'];
 
 					if ($value['level'] <= 1)
 					{
@@ -542,6 +544,7 @@ if ($id > 0 || ! empty($ref))
 						$productstatic->ref=$objp->ref;
 						$productstatic->label=$objp->label;
 						$productstatic->type=$objp->type;
+						$productstatic->entity=$objp->entity;
 
 						print '<td>'.$productstatic->getNomUrl(1,'',24).'</td>';
 						$labeltoshow=$objp->label;

+ 16 - 3
htdocs/product/document.php

@@ -70,8 +70,14 @@ if ($id > 0 || ! empty($ref))
 {
     $result = $object->fetch($id, $ref);
 
-    if (! empty($conf->product->enabled)) $upload_dir = $conf->product->multidir_output[$object->entity].'/'.dol_sanitizeFileName($object->ref);
-    elseif (! empty($conf->service->enabled)) $upload_dir = $conf->service->multidir_output[$object->entity].'/'.dol_sanitizeFileName($object->ref);
+    if (! empty($conf->product->enabled)) $upload_dir = $conf->product->multidir_output[$object->entity].'/'.get_exdir(0, 0, 0, 1, $object, 'product').dol_sanitizeFileName($object->ref);
+    elseif (! empty($conf->service->enabled)) $upload_dir = $conf->service->multidir_output[$object->entity].'/'.get_exdir(0, 0, 0, 1, $object, 'product').dol_sanitizeFileName($object->ref);
+    
+	if (! empty($conf->global->PRODUCT_USE_OLD_PATH_FOR_PHOTO))    // For backward compatiblity, we scan also old dirs
+	{
+	    if (! empty($conf->product->enabled)) $upload_dirold = $conf->product->multidir_output[$object->entity].'/'.substr(substr("000".$object->id, -2),1,1).'/'.substr(substr("000".$object->id, -2),0,1).'/'.$object->id."/photos";
+	    else $upload_dirold = $conf->service->multidir_output[$object->entity].'/'.substr(substr("000".$object->id, -2),1,1).'/'.substr(substr("000".$object->id, -2),0,1).'/'.$object->id."/photos";
+	}
 }
 $modulepart='produit';
 
@@ -175,12 +181,19 @@ if ($object->id)
 
 	// Construit liste des fichiers
 	$filearray=dol_dir_list($upload_dir,"files",0,'','(\.meta|_preview\.png)$',$sortfield,(strtolower($sortorder)=='desc'?SORT_DESC:SORT_ASC),1);
+
+	if (! empty($conf->global->PRODUCT_USE_OLD_PATH_FOR_PHOTO))    // For backward compatiblity, we scan also old dirs
+	{
+		$filearrayold=dol_dir_list($upload_dirold,"files",0,'','(\.meta|_preview\.png)$',$sortfield,(strtolower($sortorder)=='desc'?SORT_DESC:SORT_ASC),1);
+		$filearray=array_merge($filearray, $filearrayold);
+	}
+	
 	$totalsize=0;
 	foreach($filearray as $key => $file)
 	{
 		$totalsize+=$file['size'];
 	}
-
+	
 
     print '<table class="border" width="100%">';
 

+ 3 - 2
htdocs/product/list.php

@@ -164,7 +164,7 @@ else
 		$texte = $langs->trans("ProductsAndServices");
 	}
 
-    $sql = 'SELECT DISTINCT p.rowid, p.ref, p.label, p.barcode, p.price, p.price_ttc, p.price_base_type,';
+    $sql = 'SELECT DISTINCT p.rowid, p.ref, p.label, p.barcode, p.price, p.price_ttc, p.price_base_type, p.entity,';
     $sql.= ' p.fk_product_type, p.duration, p.tosell, p.tobuy, p.seuil_stock_alerte, p.desiredstock,';
     $sql.= ' p.datec as date_creation, p.tms as date_update,';
     $sql.= ' MIN(pfp.unitprice) as minsellprice';
@@ -548,8 +548,9 @@ else
     			$product_static->ref = $objp->ref;
                 $product_static->label = $objp->label;
     			$product_static->type = $objp->fk_product_type;
-                $product_static->status_buy = $objp->tobuy;
+    			$product_static->status_buy = $objp->tobuy;
                 $product_static->status     = $objp->tosell;
+				$product_static->entity = $objp->entity;
 
     			$var=!$var;
     			print '<tr '.$bc[$var].'>';

+ 2 - 1
htdocs/product/reassort.php

@@ -101,7 +101,7 @@ $htmlother=new FormOther($db);
 
 $title=$langs->trans("ProductsAndServices");
 
-$sql = 'SELECT p.rowid, p.ref, p.label, p.barcode, p.price, p.price_ttc, p.price_base_type,';
+$sql = 'SELECT p.rowid, p.ref, p.label, p.barcode, p.price, p.price_ttc, p.price_base_type,p.entity,';
 $sql.= ' p.fk_product_type, p.tms as datem,';
 $sql.= ' p.duration, p.tosell as statut, p.tobuy, p.seuil_stock_alerte, p.desiredstock,';
 $sql.= ' SUM(s.reel) as stock_physique';
@@ -315,6 +315,7 @@ if ($resql)
 		$product_static->id=$objp->rowid;
         $product_static->label = $objp->label;
 		$product_static->type=$objp->fk_product_type;
+		$product_static->entity=$objp->entity;
 		print $product_static->getNomUrl(1,'',16);
 		//if ($objp->stock_theorique < $objp->seuil_stock_alerte) print ' '.img_warning($langs->trans("StockTooLow"));
 		print '</td>';

+ 3 - 2
htdocs/product/reassortlot.php

@@ -104,7 +104,7 @@ $htmlother=new FormOther($db);
 
 $title=$langs->trans("ProductsAndServices");
 
-$sql = 'SELECT p.rowid, p.ref, p.label, p.barcode, p.price, p.price_ttc, p.price_base_type,';
+$sql = 'SELECT p.rowid, p.ref, p.label, p.barcode, p.price, p.price_ttc, p.price_base_type,p.entity,';
 $sql.= ' p.fk_product_type, p.tms as datem,';
 $sql.= ' p.duration, p.tosell as statut, p.tobuy, p.seuil_stock_alerte, p.desiredstock,';
 $sql.= ' s.fk_entrepot,';
@@ -329,6 +329,7 @@ if ($resql)
 		$product_static->id=$objp->rowid;
         $product_static->label = $objp->label;
 		$product_static->type=$objp->fk_product_type;
+		$product_static->entity=$objp->entity;
 		print $product_static->getNomUrl(1,'',16);
 		//if ($objp->stock_theorique < $objp->seuil_stock_alerte) print ' '.img_warning($langs->trans("StockTooLow"));
 		print '</td>';
@@ -349,7 +350,7 @@ if ($resql)
 
 		// Warehouse
 		print '<td>';
-		$warehousetmp->fetch($obj->fk_entrepot);
+		$warehousetmp->fetch($objp->fk_entrepot);
 		print $warehousetmp->getNomUrl(1);
 		print '</td>';
 		print '<td align="center">'.$objp->batch.'</td>';

+ 1 - 1
htdocs/product/stats/commande.php

@@ -129,7 +129,7 @@ if ($id > 0 || ! empty($ref))
 		if ($user->rights->commande->lire)
 		{
 			$sql = "SELECT DISTINCT s.nom as name, s.rowid as socid, s.code_client, c.rowid, d.total_ht as total_ht, c.ref,";
-			$sql .= " c.ref_client,";
+			$sql.= " c.ref_client,";
 			$sql.= " c.date_commande, c.fk_statut as statut, c.facture, c.rowid as commandeid, d.rowid, d.qty";
 			if (!$user->rights->societe->client->voir && !$socid) $sql.= ", sc.fk_soc, sc.fk_user ";
 			$sql.= " FROM ".MAIN_DB_PREFIX."societe as s";

+ 2 - 1
htdocs/product/stats/commande_fournisseur.php

@@ -134,7 +134,8 @@ if ($id > 0 || ! empty($ref)) {
 
 		print '</div>';
 
-		if ($user->rights->fournisseur->commande->lire) {
+		if ($user->rights->fournisseur->commande->lire)
+		{
 			$sql = "SELECT DISTINCT s.nom as name, s.rowid as socid, s.code_client,";
 			$sql .= " c.rowid, d.total_ht as total_ht, c.ref,";
 			$sql .= " c.date_commande, c.fk_statut as statut, c.rowid as commandeid, d.rowid, d.qty";

+ 2 - 1
htdocs/product/stats/propal.php

@@ -126,7 +126,8 @@ if ($id > 0 || ! empty($ref))
 
 		print '</div>';
 
-		if ($user->rights->propale->lire) {
+		if ($user->rights->propale->lire) 
+		{
 			$sql = "SELECT DISTINCT s.nom as name, s.rowid as socid, p.rowid as propalid, p.ref, d.total_ht as amount,";
 			$sql .= " p.ref_client,";
 			$sql .= "p.datep, p.fk_statut as statut, d.rowid, d.qty";

+ 2 - 1
htdocs/product/stock/card.php

@@ -394,7 +394,7 @@ else
 			$totalunit=0;
 			$totalvalue=$totalvaluesell=0;
 
-			$sql = "SELECT p.rowid as rowid, p.ref, p.label as produit, p.fk_product_type as type, p.pmp as ppmp, p.price, p.price_ttc,";
+			$sql = "SELECT p.rowid as rowid, p.ref, p.label as produit, p.fk_product_type as type, p.pmp as ppmp, p.price, p.price_ttc, p.entity,";
 			$sql.= " ps.pmp, ps.reel as value";
 			$sql.= " FROM ".MAIN_DB_PREFIX."product_stock as ps, ".MAIN_DB_PREFIX."product as p";
 			$sql.= " WHERE ps.fk_product = p.rowid";
@@ -438,6 +438,7 @@ else
                     $productstatic->ref = $objp->ref;
                     $productstatic->label = $objp->produit;
 					$productstatic->type=$objp->type;
+					$productstatic->entity=$objp->entity;
 					print $productstatic->getNomUrl(1,'stock',16);
 					print '</td>';
 					print '<td>'.$objp->produit.'</td>';

+ 2 - 1
htdocs/product/stock/mouvement.php

@@ -164,7 +164,7 @@ $form=new Form($db);
 $formother=new FormOther($db);
 $formproduct=new FormProduct($db);
 
-$sql = "SELECT p.rowid, p.ref as product_ref, p.label as produit, p.fk_product_type as type,";
+$sql = "SELECT p.rowid, p.ref as product_ref, p.label as produit, p.fk_product_type as type, p.entity,";
 $sql.= " e.label as stock, e.rowid as entrepot_id, e.lieu,";
 $sql.= " m.rowid as mid, m.value, m.datem, m.fk_user_author, m.label, m.inventorycode, m.fk_origin, m.origintype,";
 $sql.= " m.batch,m.eatby,m.sellby,";
@@ -575,6 +575,7 @@ if ($resql)
         $productstatic->ref=$objp->product_ref;
         $productstatic->label=$objp->produit;
         $productstatic->type=$objp->type;
+        $productstatic->entity=$objp->entity;
         print $productstatic->getNomUrl(1,'stock',16);
         print "</td>\n";
         // Product label

+ 2 - 2
htdocs/public/emailing/mailing-read.php

@@ -72,13 +72,13 @@ if (! empty($tag))
 	$resql=$db->query($sql);
 
 	//Update status communication of thirdparty prospect
-	$sql = "UPDATE ".MAIN_DB_PREFIX."societe SET fk_stcomm=3 WHERE rowid IN (SELECT source_id FROM ".MAIN_DB_PREFIX."mailing_cibles WHERE tag='".$db->escape($tag)."' AND source_type='thirdparty' AND source_id is not null)";
+	$sql = "UPDATE ".MAIN_DB_PREFIX."societe SET fk_stcomm=3 WHERE fk_stcomm != -1 AND rowid IN (SELECT source_id FROM ".MAIN_DB_PREFIX."mailing_cibles WHERE tag='".$db->escape($tag)."' AND source_type='thirdparty' AND source_id is not null)";
 	dol_syslog("public/emailing/mailing-read.php : Mail read thirdparty : ".$sql, LOG_DEBUG);
 
 	$resql=$db->query($sql);
 
     //Update status communication of contact prospect
-	$sql = "UPDATE ".MAIN_DB_PREFIX."societe SET fk_stcomm=3 WHERE rowid IN (SELECT sc.fk_soc FROM ".MAIN_DB_PREFIX."socpeople AS sc INNER JOIN ".MAIN_DB_PREFIX."mailing_cibles AS mc ON mc.tag = '".$db->escape($tag)."' AND mc.source_type = 'contact' AND mc.source_id = sc.rowid)";
+	$sql = "UPDATE ".MAIN_DB_PREFIX."societe SET fk_stcomm=3 WHERE fk_stcomm != -1 AND rowid IN (SELECT sc.fk_soc FROM ".MAIN_DB_PREFIX."socpeople AS sc INNER JOIN ".MAIN_DB_PREFIX."mailing_cibles AS mc ON mc.tag = '".$db->escape($tag)."' AND mc.source_type = 'contact' AND mc.source_id = sc.rowid)";
 	dol_syslog("public/emailing/mailing-read.php : Mail read contact : ".$sql, LOG_DEBUG);
 
 	$resql=$db->query($sql);

+ 2 - 1
htdocs/societe/consumption.php

@@ -288,7 +288,7 @@ $sql = $sql_select;
 $sql.= ' d.description as description,';
 if ($type_element != 'fichinter' && $type_element != 'contract') $sql.= ' d.label, d.fk_product as product_id, d.fk_product as fk_product, d.info_bits, d.date_start, d.date_end, d.qty, d.qty as prod_qty,';
 if ($type_element == 'contract') $sql.= ' d.label, d.fk_product as product_id, d.fk_product as fk_product, d.info_bits, d.date_ouverture as date_start, d.date_cloture as date_end, d.qty, d.qty as prod_qty,';
-if ($type_element != 'fichinter') $sql.= ' p.ref as ref, p.rowid as prod_id, p.rowid as fk_product, p.fk_product_type as prod_type, p.fk_product_type as fk_product_type,';
+if ($type_element != 'fichinter') $sql.= ' p.ref as ref, p.rowid as prod_id, p.rowid as fk_product, p.fk_product_type as prod_type, p.fk_product_type as fk_product_type, p.entity as pentity,';
 $sql.= " s.rowid as socid ";
 if ($type_element != 'fichinter') $sql.= ", p.ref as prod_ref, p.label as product_label";
 $sql.= " FROM ".MAIN_DB_PREFIX."societe as s, ".$tables_from;
@@ -405,6 +405,7 @@ if ($sql_select)
 			$product_static->type=$objp->fk_product_type;
 			$product_static->id=$objp->fk_product;
 			$product_static->ref=$objp->ref;
+			$product_static->entity=$objp->pentity;
 			$text=$product_static->getNomUrl(1);
 		}