Selaa lähdekoodia

NEW: Enhancement of module 'Notification by Email'. Show nb of
notifications set. Can set several emails. Can set a threshold on
amount for notifications. Add notification on supplier order validation.

Laurent Destailleur 10 vuotta sitten
vanhempi
commit
6ceda02eaa

+ 21 - 1
htdocs/admin/commande.php

@@ -622,9 +622,29 @@ else
 }
 
 print '</table>';
-
 print '<br>';
 
+
+/*
+ * Notifications
+ */
+
+print_titre($langs->trans("Notifications"));
+print '<table class="noborder" width="100%">';
+print '<tr class="liste_titre">';
+print '<td>'.$langs->trans("Parameter").'</td>';
+print '<td align="center" width="60"></td>';
+print '<td width="80">&nbsp;</td>';
+print "</tr>\n";
+
+print '<tr '.$bc[$var].'><td colspan="2">';
+print $langs->trans("YouMayFindNotificationsFeaturesIntoModuleNotification").'<br>';
+print '</td><td align="right">';
+print "</td></tr>\n";
+
+print '</table>';
+
+
 llxFooter();
 
 $db->close();

+ 24 - 5
htdocs/admin/facture.php

@@ -171,7 +171,7 @@ else if ($action == 'setdoc')
 		// on passe donc par une variable pour avoir un affichage coherent
 		$conf->global->FACTURE_ADDON_PDF = $value;
 	}
-	
+
 	// On active le modele
 	$ret = delDocumentModel($value, $type);
 	if ($ret > 0)
@@ -341,7 +341,7 @@ foreach ($dirmodels as $reldir)
                     // Check if there is a filter on country
                     preg_match('/\-(.*)_(.*)$/',$classname,$reg);
                     if (! empty($reg[2]) && $reg[2] != strtoupper($mysoc->country_code)) continue;
-                    
+
                     $classname = preg_replace('/\-.*$/','',$classname);
                     if (! class_exists($classname) && is_readable($dir.$filebis) && (preg_match('/mod_/',$filebis) || preg_match('/mod_/',$classname)) && substr($filebis, dol_strlen($filebis)-3, 3) == 'php')
                     {
@@ -416,7 +416,7 @@ foreach ($dirmodels as $reldir)
                                     $htmltooltip.=$langs->trans($module->error).'<br>';
                                 }
                             }
-                            
+
                             // Example for credit invoice
                             $facture->type=2;
                             $nextval=$module->getNextValue($mysoc,$facture);
@@ -630,7 +630,6 @@ print '</table>';
 
 /*
  *  Modes de reglement
- *
  */
 print '<br>';
 print_titre($langs->trans("SuggestedPaymentModesIfNotDefinedInInvoice"));
@@ -811,7 +810,27 @@ print '</tr>'."\n";
 print "</table>\n";
 
 
-//dol_fiche_end();
+/*
+ * Notifications
+ */
+print '<br>';
+print_titre($langs->trans("Notifications"));
+print '<table class="noborder" width="100%">';
+print '<tr class="liste_titre">';
+print '<td>'.$langs->trans("Parameter").'</td>';
+print '<td align="center" width="60"></td>';
+print '<td width="80">&nbsp;</td>';
+print "</tr>\n";
+
+print '<tr '.$bc[$var].'><td colspan="2">';
+print $langs->trans("YouMayFindNotificationsFeaturesIntoModuleNotification").'<br>';
+print '</td><td align="right">';
+print "</td></tr>\n";
+
+print '</table>';
+
+dol_fiche_end();
+
 
 llxFooter();
 

+ 127 - 16
htdocs/admin/notification.php

@@ -24,6 +24,7 @@
  */
 
 require '../main.inc.php';
+require_once DOL_DOCUMENT_ROOT.'/core/class/notify.class.php';
 require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php';
 require_once DOL_DOCUMENT_ROOT.'/core/triggers/interface_50_modNotification_Notification.class.php';
 
@@ -48,25 +49,56 @@ $action = GETPOST("action");
 
 if ($action == 'setvalue' && $user->admin)
 {
+	$db->begin();
+
 	$result=dolibarr_set_const($db, "NOTIFICATION_EMAIL_FROM", $_POST["email_from"], 'chaine', 0, '', $conf->entity);
     if ($result < 0) $error++;
 
     if (! $error)
     {
+    	//var_dump($_POST);
 	    foreach($_POST as $key => $val)
 	    {
-	    	if (! preg_match('/^NOTIFICATION_FIXEDEMAIL_/',$key)) continue;
-	    	//print $key.' - '.$val.'<br>';
-			$result=dolibarr_set_const($db, $key, $val, 'chaine', 0, '', $conf->entity);
+	    	if (! preg_match('/^NOTIF_(.*)_key$/', $key, $reg)) continue;
+
+	    	$newval='';
+	    	$newkey='';
+
+	    	$shortkey=preg_replace('/_key$/','',$key);
+    		//print $shortkey.'<br>';
+
+	    	if (preg_match('/^NOTIF_(.*)_old_(.*)_key/',$key,$reg))
+	    	{
+				dolibarr_del_const($db, 'NOTIFICATION_FIXEDEMAIL_'.$reg[1].'_THRESHOLD_HIGHER_'.$reg[2], $conf->entity);
+
+				$newkey='NOTIFICATION_FIXEDEMAIL_'.$reg[1].'_THRESHOLD_HIGHER_'.((int) GETPOST($shortkey.'_amount'));
+				$newval=GETPOST($shortkey.'_key');
+				//print $newkey.' - '.$newval.'<br>';
+	    	}
+	    	else if (preg_match('/^NOTIF_(.*)_new_key/',$key,$reg))
+	    	{
+		    	// Add a new entry
+	    		$newkey='NOTIFICATION_FIXEDEMAIL_'.$reg[1].'_THRESHOLD_HIGHER_'.((int) GETPOST($shortkey.'_amount'));
+	    		$newval=GETPOST($shortkey.'_key');
+	    	}
+
+	    	if ($newkey && $newval)
+	    	{
+				$result=dolibarr_set_const($db, $newkey, $newval, 'chaine', 0, '', $conf->entity);
+	    	}
 	    }
     }
 
   	if (! $error)
     {
+    	$db->commit();
+
         setEventMessage($langs->trans("SetupSaved"));
     }
     else
 	{
+		$db->rollback();
+
         setEventMessage($langs->trans("Error"),'errors');
     }
 }
@@ -78,6 +110,7 @@ if ($action == 'setvalue' && $user->admin)
  */
 
 $form=new Form($db);
+$notify = new Notify($db);
 
 llxHeader('',$langs->trans("NotificationSetup"));
 
@@ -107,7 +140,53 @@ print '</table>';
 
 print '<br>';
 
-print_fiche_titre($langs->trans("ListOfAvailableNotifications"),'','');
+
+if ($conf->societe->enabled)
+{
+	print_fiche_titre($langs->trans("ListOfNotificationsPerContact"),'','');
+
+	print '<table class="noborder" width="100%">';
+	print '<tr class="liste_titre">';
+	print '<td>'.$langs->trans("Module").'</td>';
+	print '<td>'.$langs->trans("Code").'</td>';
+	print '<td>'.$langs->trans("Label").'</td>';
+	print '<td align="right">'.$langs->trans("NbOfTargetedContacts").'</td>';
+	print '<td>'.'</td>';
+	print "</tr>\n";
+
+	// Load array of available notifications
+	$notificationtrigger=new InterfaceNotification($db);
+	$listofnotifiedevents=$notificationtrigger->getListOfManagedEvents();
+
+	$var=true;
+	foreach($listofnotifiedevents as $notifiedevent)
+	{
+	    $var=!$var;
+	    $label=$langs->trans("Notify_".$notifiedevent['code']); //!=$langs->trans("Notify_".$notifiedevent['code'])?$langs->trans("Notify_".$notifiedevent['code']):$notifiedevent['label'];
+
+	    if ($notifiedevent['elementtype'] == 'order_supplier') $elementLabel = $langs->trans('SupplierOrder');
+	    elseif ($notifiedevent['elementtype'] == 'propal') $elementLabel = $langs->trans('Proposal');
+	    elseif ($notifiedevent['elementtype'] == 'facture') $elementLabel = $langs->trans('Bill');
+	    elseif ($notifiedevent['elementtype'] == 'commande') $elementLabel = $langs->trans('Order');
+
+	    print '<tr '.$bc[$var].'>';
+	    print '<td>'.$elementLabel.'</td>';
+	    print '<td>'.$notifiedevent['code'].'</td>';
+	    print '<td>'.$label.'</td>';
+	    print '<td align="right">';
+		$nb = $notify->countDefinedNotifications($notifiedevent['code'], 0);
+		print $nb;
+	    print '</td>';
+	    print '</tr>';
+	}
+
+	print '</table>';
+	print '* '.$langs->trans("GoOntoContactCardToAddMore").'<br>';
+	print '<br>';
+}
+
+
+print_fiche_titre($langs->trans("ListOfFixedNotifications"),'','');
 
 print '<table class="noborder" width="100%">';
 print '<tr class="liste_titre">';
@@ -115,12 +194,15 @@ print '<td>'.$langs->trans("Module").'</td>';
 print '<td>'.$langs->trans("Code").'</td>';
 print '<td>'.$langs->trans("Label").'</td>';
 print '<td>'.$langs->trans("FixedEmailTarget").'</td>';
+print '<td>'.$langs->trans("Threshold").'</td>';
+print '<td>'.'</td>';
 print "</tr>\n";
 
 // Load array of available notifications
 $notificationtrigger=new InterfaceNotification($db);
 $listofnotifiedevents=$notificationtrigger->getListOfManagedEvents();
 
+$var=true;
 foreach($listofnotifiedevents as $notifiedevent)
 {
     $var=!$var;
@@ -136,18 +218,47 @@ foreach($listofnotifiedevents as $notifiedevent)
     print '<td>'.$notifiedevent['code'].'</td>';
     print '<td>'.$label.'</td>';
     print '<td>';
-    $param='NOTIFICATION_FIXEDEMAIL_'.$notifiedevent['code'];
-    $value=GETPOST($param)?GETPOST($param,'alpha'):$conf->global->$param;
-    $s='<input type="text" size="32" name="'.$param.'" value="'.dol_escape_htmltag($value).'">';		// Do not use type="email" here, we must be able to enter a list of email with , separator.
-    $arrayemail=explode(',',$value);
-	$showwarning=0;
-	foreach($arrayemail as $key=>$valuedet)
-	{
-		$valuedet=trim($valuedet);
-		if (! empty($valuedet) && ! isValidEmail($valuedet)) $showwarning++;
-	}
-    if ((! empty($conf->global->$param)) && $showwarning) $s.=' '.img_warning($langs->trans("ErrorBadEMail"));
-    print $form->textwithpicto($s,$langs->trans("YouCanUseCommaSeparatorForSeveralRecipients"));
+    // Notification with threshold
+    foreach($conf->global as $key => $val)
+    {
+		if ($val == '' || ! preg_match('/^NOTIFICATION_FIXEDEMAIL_'.$notifiedevent['code'].'_THRESHOLD_HIGHER_(.*)/', $key, $reg)) continue;
+
+	    $param='NOTIFICATION_FIXEDEMAIL_'.$notifiedevent['code'].'_THRESHOLD_HIGHER_'.$reg[1];
+    	$value=GETPOST('NOTIF_'.$notifiedevent['code'].'_old_'.$reg[1].'_key')?GETPOST('NOTIF_'.$notifiedevent['code'].'_old_'.$reg[1].'_key','alpha'):$conf->global->$param;
+
+    	$s='<input type="text" size="32" name="NOTIF_'.$notifiedevent['code'].'_old_'.$reg[1].'_key" value="'.dol_escape_htmltag($value).'">';		// Do not use type="email" here, we must be able to enter a list of email with , separator.
+	    $arrayemail=explode(',',$value);
+		$showwarning=0;
+		foreach($arrayemail as $key=>$valuedet)
+		{
+			$valuedet=trim($valuedet);
+			if (! empty($valuedet) && ! isValidEmail($valuedet)) $showwarning++;
+		}
+	    if ((! empty($conf->global->$param)) && $showwarning) $s.=' '.img_warning($langs->trans("ErrorBadEMail"));
+	    print $form->textwithpicto($s,$langs->trans("YouCanUseCommaSeparatorForSeveralRecipients"),1,'help','',0,2);
+		print '<br>';
+    }
+    // New entry input fields
+    $s='<input type="text" size="32" name="NOTIF_'.$notifiedevent['code'].'_new_key" value="">';		// Do not use type="email" here, we must be able to enter a list of email with , separator.
+    print $form->textwithpicto($s,$langs->trans("YouCanUseCommaSeparatorForSeveralRecipients"),1,'help','',0,2);
+    print '</td>';
+
+    print '<td>';
+    // Notification with threshold
+    foreach($conf->global as $key => $val)
+    {
+		if ($val == '' || ! preg_match('/^NOTIFICATION_FIXEDEMAIL_'.$notifiedevent['code'].'_THRESHOLD_HIGHER_(.*)/', $key, $reg)) continue;
+
+    	print $langs->trans("AmountHT").' >= <input type="text" size="4" name="NOTIF_'.$notifiedevent['code'].'_old_'.$reg[1].'_amount" value="'.dol_escape_htmltag($reg[1]).'">';
+		print '<br>';
+    }
+    // New entry input fields
+	print $langs->trans("AmountHT").' >= <input type="text" size="4" name="NOTIF_'.$notifiedevent['code'].'_new_amount" value="">';
+	print '</td>';
+
+    print '<td>';
+	// TODO Add link to show message content
+
     print '</td>';
     print '</tr>';
 }

+ 22 - 1
htdocs/admin/propal.php

@@ -643,6 +643,27 @@ print "</tr>\n";
 print "<tr ".$bc[false].">\n  <td width=\"140\">".$langs->trans("PathDirectory")."</td>\n  <td>".$conf->propal->dir_output."</td>\n</tr>\n";
 print "</table>\n<br>";
 
-$db->close();
+
+/*
+ * Notifications
+ */
+
+print_titre($langs->trans("Notifications"));
+print '<table class="noborder" width="100%">';
+print '<tr class="liste_titre">';
+print '<td>'.$langs->trans("Parameter").'</td>';
+print '<td align="center" width="60"></td>';
+print '<td width="80">&nbsp;</td>';
+print "</tr>\n";
+
+print '<tr '.$bc[$var].'><td colspan="2">';
+print $langs->trans("YouMayFindNotificationsFeaturesIntoModuleNotification").'<br>';
+print '</td><td align="right">';
+print "</td></tr>\n";
+
+print '</table>';
+
 
 llxFooter();
+
+$db->close();

+ 31 - 7
htdocs/admin/supplier_invoice.php

@@ -443,14 +443,16 @@ foreach ($dirmodels as $reldir)
     }
 }
 
-print '</table><br/>';
-print '<br>';
+print '</table><br>';
 
 /*
  * Other options
- *
  */
 
+print '<form action="'.$_SERVER["PHP_SELF"].'" method="post">';
+print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
+print '<input type="hidden" name="action" value="set_SUPPLIER_INVOICE_FREE_TEXT">';
+
 print_titre($langs->trans("OtherOptions"));
 print '<table class="noborder" width="100%">';
 print '<tr class="liste_titre">';
@@ -459,16 +461,38 @@ print '<td align="center" width="60">'.$langs->trans("Value").'</td>';
 print '<td width="80">&nbsp;</td>';
 print "</tr>\n";
 
-print '<form action="'.$_SERVER["PHP_SELF"].'" method="post">';
-print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
-print '<input type="hidden" name="action" value="set_SUPPLIER_INVOICE_FREE_TEXT">';
 print '<tr '.$bc[$var].'><td colspan="2">';
 print $langs->trans("FreeLegalTextOnInvoices").' ('.$langs->trans("AddCRIfTooLong").')<br>';
 print '<textarea name="SUPPLIER_INVOICE_FREE_TEXT" class="flat" cols="120">'.$conf->global->SUPPLIER_INVOICE_FREE_TEXT.'</textarea>';
 print '</td><td align="right">';
 print '<input type="submit" class="button" value="'.$langs->trans("Modify").'">';
 print "</td></tr>\n";
+
+print '</table><br>';
+
 print '</form>';
 
-$db->close();
+
+/*
+ * Notifications
+ */
+
+print_titre($langs->trans("Notifications"));
+print '<table class="noborder" width="100%">';
+print '<tr class="liste_titre">';
+print '<td>'.$langs->trans("Parameter").'</td>';
+print '<td align="center" width="60"></td>';
+print '<td width="80">&nbsp;</td>';
+print "</tr>\n";
+
+print '<tr '.$bc[$var].'><td colspan="2">';
+print $langs->trans("YouMayFindNotificationsFeaturesIntoModuleNotification").'<br>';
+print '</td><td align="right">';
+print "</td></tr>\n";
+
+print '</table>';
+
+
 llxFooter();
+
+$db->close();

+ 32 - 7
htdocs/admin/supplier_order.php

@@ -439,14 +439,16 @@ foreach ($dirmodels as $reldir)
     }
 }
 
-print '</table><br/>';
-print '<br>';
+print '</table><br>';
 
 /*
  * Other options
- *
  */
 
+print '<form action="'.$_SERVER["PHP_SELF"].'" method="post">';
+print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
+print '<input type="hidden" name="action" value="set_SUPPLIER_ORDER_FREE_TEXT">';
+
 print_titre($langs->trans("OtherOptions"));
 print '<table class="noborder" width="100%">';
 print '<tr class="liste_titre">';
@@ -455,16 +457,39 @@ print '<td align="center" width="60">'.$langs->trans("Value").'</td>';
 print '<td width="80">&nbsp;</td>';
 print "</tr>\n";
 
-print '<form action="'.$_SERVER["PHP_SELF"].'" method="post">';
-print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
-print '<input type="hidden" name="action" value="set_SUPPLIER_ORDER_FREE_TEXT">';
 print '<tr '.$bc[$var].'><td colspan="2">';
 print $langs->trans("FreeLegalTextOnOrders").' ('.$langs->trans("AddCRIfTooLong").')<br>';
 print '<textarea name="SUPPLIER_ORDER_FREE_TEXT" class="flat" cols="120">'.$conf->global->SUPPLIER_ORDER_FREE_TEXT.'</textarea>';
 print '</td><td align="right">';
 print '<input type="submit" class="button" value="'.$langs->trans("Modify").'">';
 print "</td></tr>\n";
+
+print '</table><br>';
+
 print '</form>';
 
-$db->close();
+
+
+/*
+ * Notifications
+ */
+
+print_titre($langs->trans("Notifications"));
+print '<table class="noborder" width="100%">';
+print '<tr class="liste_titre">';
+print '<td>'.$langs->trans("Parameter").'</td>';
+print '<td align="center" width="60"></td>';
+print '<td width="80">&nbsp;</td>';
+print "</tr>\n";
+
+print '<tr '.$bc[$var].'><td colspan="2">';
+print $langs->trans("YouMayFindNotificationsFeaturesIntoModuleNotification").'<br>';
+print '</td><td align="right">';
+print "</td></tr>\n";
+
+print '</table>';
+
+
 llxFooter();
+
+$db->close();

+ 1 - 1
htdocs/comm/askpricesupplier/card.php

@@ -1337,7 +1337,7 @@ if ($action == 'create')
 			require_once DOL_DOCUMENT_ROOT . '/core/class/notify.class.php';
 			$notify = new Notify($db);
 			$text .= '<br>';
-			$text .= $notify->confirmMessage('ASKPRICESUPPLIER_VALIDATE', $object->socid);
+			$text .= $notify->confirmMessage('ASKPRICESUPPLIER_VALIDATE', $object->socid, $object);
 		}
 
 		if (! $error)

+ 1 - 1
htdocs/comm/propal.php

@@ -1671,7 +1671,7 @@ if ($action == 'create')
 			require_once DOL_DOCUMENT_ROOT . '/core/class/notify.class.php';
 			$notify = new Notify($db);
 			$text .= '<br>';
-			$text .= $notify->confirmMessage('PROPAL_VALIDATE', $object->socid);
+			$text .= $notify->confirmMessage('PROPAL_VALIDATE', $object->socid, $object);
 		}
 
 		if (! $error)

+ 7 - 7
htdocs/commande/card.php

@@ -1600,7 +1600,7 @@ if ($action == 'create' && $user->rights->commande->creer)
 				require_once DOL_DOCUMENT_ROOT . '/core/class/notify.class.php';
 				$notify = new Notify($db);
 				$text .= '<br>';
-				$text .= $notify->confirmMessage('ORDER_VALIDATE', $object->socid);
+				$text .= $notify->confirmMessage('ORDER_VALIDATE', $object->socid, $object);
 			}
 
 			$qualified_for_stock_change=0;
@@ -2045,7 +2045,7 @@ if ($action == 'create' && $user->rights->commande->creer)
 
 		// Total HT
 		print '<tr><td>' . $langs->trans('AmountHT') . '</td>';
-		print '<td align="right">' . price($object->total_ht, 1, '', 1, - 1, - 1, $conf->currency) . '</td>';
+		print '<td>' . price($object->total_ht, 1, '', 1, - 1, - 1, $conf->currency) . '</td>';
 
 		// Margin Infos
 		if (! empty($conf->margin->enabled)) {
@@ -2057,23 +2057,23 @@ if ($action == 'create' && $user->rights->commande->creer)
 
 		print '</tr>';
 
-		// Total TVA
-		print '<tr><td>' . $langs->trans('AmountVAT') . '</td><td align="right">' . price($object->total_tva, 1, '', 1, - 1, - 1, $conf->currency) . '</td></tr>';
+		// Total VAT
+		print '<tr><td>' . $langs->trans('AmountVAT') . '</td><td>' . price($object->total_tva, 1, '', 1, - 1, - 1, $conf->currency) . '</td></tr>';
 
 		// Amount Local Taxes
 		if ($mysoc->localtax1_assuj == "1" || $object->total_localtax1 != 0) 		// Localtax1
 		{
 			print '<tr><td>' . $langs->transcountry("AmountLT1", $mysoc->country_code) . '</td>';
-			print '<td align="right">' . price($object->total_localtax1, 1, '', 1, - 1, - 1, $conf->currency) . '</td></tr>';
+			print '<td>' . price($object->total_localtax1, 1, '', 1, - 1, - 1, $conf->currency) . '</td></tr>';
 		}
 		if ($mysoc->localtax2_assuj == "1" || $object->total_localtax2 != 0) 		// Localtax2 IRPF
 		{
 			print '<tr><td>' . $langs->transcountry("AmountLT2", $mysoc->country_code) . '</td>';
-			print '<td align="right">' . price($object->total_localtax2, 1, '', 1, - 1, - 1, $conf->currency) . '</td></tr>';
+			print '<td>' . price($object->total_localtax2, 1, '', 1, - 1, - 1, $conf->currency) . '</td></tr>';
 		}
 
 		// Total TTC
-		print '<tr><td>' . $langs->trans('AmountTTC') . '</td><td align="right">' . price($object->total_ttc, 1, '', 1, - 1, - 1, $conf->currency) . '</td></tr>';
+		print '<tr><td>' . $langs->trans('AmountTTC') . '</td><td>' . price($object->total_ttc, 1, '', 1, - 1, - 1, $conf->currency) . '</td></tr>';
 
 		// Statut
 		print '<tr><td>' . $langs->trans('Status') . '</td><td>' . $object->getLibStatut(4) . '</td></tr>';

+ 1 - 1
htdocs/compta/facture.php

@@ -2587,7 +2587,7 @@ if ($action == 'create')
 			require_once DOL_DOCUMENT_ROOT . '/core/class/notify.class.php';
 			$notify = new Notify($db);
 			$text .= '<br>';
-			$text .= $notify->confirmMessage('BILL_VALIDATE', $object->socid);
+			$text .= $notify->confirmMessage('BILL_VALIDATE', $object->socid, $object);
 		}
 		$formquestion = array();
 

+ 14 - 12
htdocs/core/class/html.form.class.php

@@ -395,12 +395,13 @@ class Form
         $htmltext=str_replace("\n","",$htmltext);
 
         $htmltext=str_replace('"',"&quot;",$htmltext);
-        if ($tooltipon == 2 || $tooltipon == 3) $paramfortooltipimg=' class="classfortooltip'.($extracss?' '.$extracss:'').'" title="'.($noencodehtmltext?$htmltext:dol_escape_htmltag($htmltext,1)).'"'; // Attribut to put on td img tag to store tooltip
+        if ($tooltipon == 2 || $tooltipon == 3) $paramfortooltipimg=' class="classfortooltip inline-block'.($extracss?' '.$extracss:'').'" title="'.($noencodehtmltext?$htmltext:dol_escape_htmltag($htmltext,1)).'"'; // Attribut to put on td img tag to store tooltip
         else $paramfortooltipimg =($extracss?' class="'.$extracss.'"':''); // Attribut to put on td text tag
-        if ($tooltipon == 1 || $tooltipon == 3) $paramfortooltiptd=' class="classfortooltip'.($extracss?' '.$extracss:'').'" title="'.($noencodehtmltext?$htmltext:dol_escape_htmltag($htmltext,1)).'"'; // Attribut to put on td tag to store tooltip
+        if ($tooltipon == 1 || $tooltipon == 3) $paramfortooltiptd=' class="classfortooltip inline-block'.($extracss?' '.$extracss:'').'" title="'.($noencodehtmltext?$htmltext:dol_escape_htmltag($htmltext,1)).'"'; // Attribut to put on td tag to store tooltip
         else $paramfortooltiptd =($extracss?' class="'.$extracss.'"':''); // Attribut to put on td text tag
         $s="";
         if (empty($notabs)) $s.='<table class="nobordernopadding" summary=""><tr>';
+        elseif ($notabs == 2) $s.='<div class="inline-block nowrap">';
         if ($direction < 0) {
             $s.='<'.$tag.$paramfortooltipimg;
             if ($tag == 'td') {
@@ -411,8 +412,8 @@ class Form
         // Use another method to help avoid having a space in value in order to use this value with jquery
         // TODO add this in css
         //if ($text != '') $s.='<'.$tag.$paramfortooltiptd.'>'.(($direction < 0)?'&nbsp;':'').$text.(($direction > 0)?'&nbsp;':'').'</'.$tag.'>';
-        $paramfortooltiptd.= (($direction < 0)?' style="padding-left: 3px !important;"':'');
-        $paramfortooltiptd.= (($direction > 0)?' style="padding-right: 3px !important;"':'');
+        $paramfortooltiptd.= (($direction < 0)?' class="inline-block" style="padding-left: 3px !important;"':'');
+        $paramfortooltiptd.= (($direction > 0)?' class="inline-block" style="padding-right: 3px !important;"':'');
         if ((string) $text != '') $s.='<'.$tag.$paramfortooltiptd.'>'.$text.'</'.$tag.'>';
         if ($direction > 0) {
             $s.='<'.$tag.$paramfortooltipimg;
@@ -422,6 +423,7 @@ class Form
             $s.= '>'.$img.'</'.$tag.'>';
         }
         if (empty($notabs)) $s.='</tr></table>';
+		elseif ($notabs == 2) $s.='</div>';
 
         return $s;
     }
@@ -583,7 +585,7 @@ class Form
         $sql.= " FROM ".MAIN_DB_PREFIX."c_incoterms";
         $sql.= " WHERE active = 1";
         $sql.= " ORDER BY code ASC";
-	
+
         dol_syslog(get_class($this)."::select_incoterm", LOG_DEBUG);
         $resql=$this->db->query($sql);
         if ($resql)
@@ -593,14 +595,14 @@ class Form
 				include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
 				$out .= ajax_combobox($htmlname, $events);
 			}
-			
+
 			if (!empty($page))
 			{
 				$out .= '<form method="post" action="'.$page.'">';
 	            $out .= '<input type="hidden" name="action" value="set_incoterms">';
 	            $out .= '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
 			}
-			
+
             $out.= '<select id="'.$htmlname.'" class="flat selectincoterm" name="'.$htmlname.'" '.$htmloption.'>';
 			$out.= '<option value=""></option>';
             $num = $this->db->num_rows($resql);
@@ -627,17 +629,17 @@ class Form
 					{
                         $out.= '<option value="'.$row['rowid'].'">';
                     }
-					
+
                     if ($row['code']) $out.= $row['code'];
-					
+
 					$out.= '</option>';
                 }
             }
             $out.= '</select>';
-			
+
 			$out .= '<input id="location_incoterms" name="location_incoterms" size="14" value="'.$location_incoterms.'">';
-			
-			if (!empty($page)) 
+
+			if (!empty($page))
 			{
 	            $out .= '<input type="submit" class="button" value="'.$langs->trans("Modify").'"></form>';
 			}

+ 187 - 134
htdocs/core/class/notify.class.php

@@ -61,14 +61,15 @@ class Notify
      *
      * 	@param	string	$action		Id of action in llx_c_action_trigger
      * 	@param	int		$socid		Id of third party
+     *  @param	Object	$object		Object the notification is about
      *	@return	string				Message
      */
-	function confirmMessage($action,$socid)
+	function confirmMessage($action,$socid,$object)
 	{
 		global $langs;
 		$langs->load("mails");
 
-		$nb=$this->countDefinedNotifications($action,$socid);
+		$nb=$this->countDefinedNotifications($action,$socid,$object);
 		if ($nb <= 0) $texte=img_object($langs->trans("Notifications"),'email').' '.$langs->trans("NoNotificationsWillBeSent");
 		if ($nb == 1) $texte=img_object($langs->trans("Notifications"),'email').' '.$langs->trans("ANotificationsWillBeSent");
 		if ($nb >= 2) $texte=img_object($langs->trans("Notifications"),'email').' '.$langs->trans("SomeNotificationsWillBeSent",$nb);
@@ -76,22 +77,25 @@ class Notify
 	}
 
     /**
-     * Return number of notifications activated for action code and third party
+     * Return number of notifications activated for action code (and third party)
      *
-     * @param	string	$action		Code of action in llx_c_action_trigger (new usage) or Id of action in llx_c_action_trigger (old usage)
-     * @param	int		$socid		Id of third party
-     * @return	int					<0 if KO, nb of notifications sent if OK
+     * @param	string	$notifcode		Code of action in llx_c_action_trigger (new usage) or Id of action in llx_c_action_trigger (old usage)
+     * @param	int		$socid			Id of third party or 0 for all thirdparties
+     * @param	Object	$object			Object the notification is about
+     * @return	int						<0 if KO, nb of notifications sent if OK
      */
-	function countDefinedNotifications($action,$socid)
+	function countDefinedNotifications($notifcode,$socid,$object=null)
 	{
 		global $conf;
 
 		$error=0;
         $num=0;
 
+        $valueforthreshold = $object->total_ht;
+
         if (! $error)
         {
-	        $sql = "SELECT n.rowid";
+	        $sql = "SELECT COUNT(n.rowid) as nb";
 	        $sql.= " FROM ".MAIN_DB_PREFIX."notify_def as n,";
 	        $sql.= " ".MAIN_DB_PREFIX."socpeople as c,";
 	        $sql.= " ".MAIN_DB_PREFIX."c_action_trigger as a,";
@@ -99,22 +103,23 @@ class Notify
 	        $sql.= " WHERE n.fk_contact = c.rowid";
 	        $sql.= " AND a.rowid = n.fk_action";
 	        $sql.= " AND n.fk_soc = s.rowid";
-	        if (is_numeric($action)) $sql.= " AND n.fk_action = ".$action;	// Old usage
-	        else $sql.= " AND a.code = '".$action."'";	// New usage
+	        if (is_numeric($notifcode)) $sql.= " AND n.fk_action = ".$notifcode;	// Old usage
+	        else $sql.= " AND a.code = '".$notifcode."'";	// New usage
 	        $sql.= " AND s.entity IN (".getEntity('societe', 1).")";
-	        $sql.= " AND s.rowid = ".$socid;
+	        if ($socid > 0) $sql.= " AND s.rowid = ".$socid;
 
-			dol_syslog(get_class($this)."::countDefinedNotifications ".$action.", ".$socid."", LOG_DEBUG);
+			dol_syslog(get_class($this)."::countDefinedNotifications ".$notifcode.", ".$socid."", LOG_DEBUG);
 
 	        $resql = $this->db->query($sql);
 	        if ($resql)
 	        {
-	            $num = $this->db->num_rows($resql);
+	            $obj = $this->db->fetch_object($resql);
+	            if ($obj) $num = $obj->nb;
 			}
 			else
 			{
 				$error++;
-				$this->error=$this->db->error.' sql='.$sql;
+				$this->error=$this->db->lasterror();
 			}
         }
 
@@ -123,12 +128,19 @@ class Notify
 		    // List of notifications enabled for fixed email
 		    foreach($conf->global as $key => $val)
 		    {
-		    	if (! preg_match('/^NOTIFICATION_FIXEDEMAIL_'.$action.'/', $key, $reg)) continue;
-		    	$num++;
+		    	if ($val == '' || ! preg_match('/^NOTIFICATION_FIXEDEMAIL_'.$notifcode.'_THRESHOLD_HIGHER_(.*)$/', $key, $reg)) continue;
+
+    			$threshold = (float) $reg[1];
+    			if ($valueforthreshold <= $threshold)
+    			{
+    				continue;
+    			}
+
+		    	$tmpemail=explode(',',$val);
+		    	$num+=count($tmpemail);
 		    }
 		}
 
-		// TODO return array with list of email instead of number, + type of notification (contacts or fixed email)
 		if ($error) return -1;
 		return $num;
 	}
@@ -137,17 +149,17 @@ class Notify
      *  Check if notification are active for couple action/company.
      * 	If yes, send mail and save trace into llx_notify.
      *
-     * 	@param	string	$action		Code of action in llx_c_action_trigger (new usage) or Id of action in llx_c_action_trigger (old usage)
-     * 	@param	Object	$object		Object the notification deals on
-     *	@return	int					<0 if KO, or number of changes if OK
+     * 	@param	string	$notifcode		Code of action in llx_c_action_trigger (new usage) or Id of action in llx_c_action_trigger (old usage)
+     * 	@param	Object	$object			Object the notification deals on
+     *	@return	int						<0 if KO, or number of changes if OK
      */
-    function send($action, $object)
+    function send($notifcode, $object)
     {
         global $conf,$langs,$mysoc,$dolibarr_main_url_root;
 
 	    include_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
 
-		dol_syslog(get_class($this)."::send action=".$action.", object=".$object->id);
+		dol_syslog(get_class($this)."::send notifcode=".$notifcode.", object=".$object->id);
 
     	$langs->load("other");
 
@@ -166,7 +178,20 @@ class Notify
         $link = '';
 		$num = 0;
 
-		if (! in_array($action, array('BILL_VALIDATE', 'ORDER_VALIDATE', 'PROPAL_VALIDATE', 'FICHINTER_VALIDATE', 'ORDER_SUPPLIER_APPROVE', 'ORDER_SUPPLIER_REFUSE', 'SHIPPING_VALIDATE')))
+		if (! in_array(
+			$notifcode,
+			array(
+				'BILL_VALIDATE',
+				'ORDER_VALIDATE',
+				'PROPAL_VALIDATE',
+				'FICHINTER_VALIDATE',
+				'ORDER_SUPPLIER_VALIDATE',
+				'ORDER_SUPPLIER_APPROVE',
+				'ORDER_SUPPLIER_REFUSE',
+				'SHIPPING_VALIDATE'
+				)
+			)
+		)
 		{
 			return 0;
 		}
@@ -181,8 +206,8 @@ class Notify
         $sql.= " ".MAIN_DB_PREFIX."societe as s";
         $sql.= " WHERE n.fk_contact = c.rowid AND a.rowid = n.fk_action";
         $sql.= " AND n.fk_soc = s.rowid";
-        if (is_numeric($action)) $sql.= " AND n.fk_action = ".$action;	// Old usage
-        else $sql.= " AND a.code = '".$action."'";	// New usage
+        if (is_numeric($notifcode)) $sql.= " AND n.fk_action = ".$notifcode;	// Old usage
+        else $sql.= " AND a.code = '".$notifcode."'";	// New usage
         $sql .= " AND s.rowid = ".$object->socid;
 
         $result = $this->db->query($sql);
@@ -197,8 +222,8 @@ class Notify
 	            {
 	                $obj = $this->db->fetch_object($result);
 
-	                $sendto = $obj->firstname . " " . $obj->lastname . " <".$obj->email.">";
-					$actiondefid = $obj->adid;
+	                $sendto = dolGetFirstLastname($obj->firstname,$obj->lastname) . " <".$obj->email.">";
+					$notifcodedefid = $obj->adid;
 
 	                if (dol_strlen($obj->email))
 	                {
@@ -210,7 +235,7 @@ class Notify
 	                		$outputlangs->setDefaultLang($obj->default_lang);
 	                	}
 
-	                    switch ($action) {
+	                    switch ($notifcode) {
 							case 'BILL_VALIDATE':
 								$link='/compta/facture.php?facid='.$object->id;
 								$dir_output = $conf->facture->dir_output;
@@ -235,6 +260,14 @@ class Notify
 								$object_type = 'ficheinter';
 								$mesg = $langs->transnoentitiesnoconv("EMailTextInterventionValidated",$object->ref);
 								break;
+							case 'ORDER_SUPPLIER_VALIDATE':
+								$link='/fourn/commande/card.php?id='.$object->id;
+								$dir_output = $conf->fournisseur->dir_output.'/commande/';
+								$object_type = 'order_supplier';
+								$mesg = $langs->transnoentitiesnoconv("Hello").",\n\n";
+								$mesg.= $langs->transnoentitiesnoconv("EMailTextOrderValidatedBy",$object->ref,$user->getFullName($langs));
+								$mesg.= "\n\n".$langs->transnoentitiesnoconv("Sincerely").".\n\n";
+								break;
 							case 'ORDER_SUPPLIER_APPROVE':
 								$link='/fourn/commande/card.php?id='.$object->id;
 								$dir_output = $conf->fournisseur->dir_output.'/commande/';
@@ -294,7 +327,7 @@ class Notify
 	                    if ($mailfile->sendfile())
 	                    {
 	                        $sql = "INSERT INTO ".MAIN_DB_PREFIX."notify (daten, fk_action, fk_soc, fk_contact, type, objet_type, objet_id, email)";
-	                        $sql.= " VALUES ('".$this->db->idate(dol_now())."', ".$actiondefid.", ".$object->socid.", ".$obj->cid.", '".$obj->type."', '".$object_type."', ".$object->id.", '".$this->db->escape($obj->email)."')";
+	                        $sql.= " VALUES ('".$this->db->idate(dol_now())."', ".$notifcodedefid.", ".$object->socid.", ".$obj->cid.", '".$obj->type."', '".$object_type."', ".$object->id.", '".$this->db->escape($obj->email)."')";
 	                        if (! $this->db->query($sql))
 	                        {
 	                            dol_print_error($this->db);
@@ -328,113 +361,133 @@ class Notify
         // Check notification using fixed email
         if (! $error)
         {
-	        $param='NOTIFICATION_FIXEDEMAIL_'.$action;
-	        if (! empty($conf->global->$param))
-	        {
-				$sendto = $conf->global->$param;
-				$actiondefid = dol_getIdFromCode($this->db, $action, 'c_action_trigger', 'code', 'rowid');
-				if ($actiondefid <= 0) dol_print_error($this->db, 'Failed to get id from code');
-
-				$object_type = '';
-		        $link = '';
-        		$num++;
-
-				switch ($action) {
-					case 'BILL_VALIDATE':
-						$link='/compta/facture.php?facid='.$object->id;
-						$dir_output = $conf->facture->dir_output;
-						$object_type = 'facture';
-						$mesg = $langs->transnoentitiesnoconv("EMailTextInvoiceValidated",$object->ref);
-						break;
-					case 'ORDER_VALIDATE':
-						$link='/commande/card.php?id='.$object->id;
-						$dir_output = $conf->commande->dir_output;
-						$object_type = 'order';
-						$mesg = $langs->transnoentitiesnoconv("EMailTextOrderValidated",$object->ref);
-						break;
-					case 'PROPAL_VALIDATE':
-						$link='/comm/propal.php?id='.$object->id;
-						$dir_output = $conf->propal->dir_output;
-						$object_type = 'propal';
-						$mesg = $langs->transnoentitiesnoconv("EMailTextProposalValidated",$object->ref);
-						break;
-					case 'FICHINTER_VALIDATE':
-						$link='/fichinter/card.php?id='.$object->id;
-						$dir_output = $conf->facture->dir_output;
-						$object_type = 'ficheinter';
-						$mesg = $langs->transnoentitiesnoconv("EMailTextInterventionValidated",$object->ref);
-						break;
-					case 'ORDER_SUPPLIER_APPROVE':
-						$link='/fourn/commande/card.php?id='.$object->id;
-						$dir_output = $conf->fournisseur->dir_output.'/commande/';
-						$object_type = 'order_supplier';
-						$mesg = $langs->transnoentitiesnoconv("Hello").",\n\n";
-						$mesg.= $langs->transnoentitiesnoconv("EMailTextOrderApprovedBy",$object->ref,$user->getFullName($langs));
-						$mesg.= "\n\n".$langs->transnoentitiesnoconv("Sincerely").".\n\n";
-						break;
-					case 'ORDER_SUPPLIER_REFUSE':
-						$link='/fourn/commande/card.php?id='.$object->id;
-						$dir_output = $conf->fournisseur->dir_output.'/commande/';
-						$object_type = 'order_supplier';
-						$mesg = $langs->transnoentitiesnoconv("Hello").",\n\n";
-						$mesg.= $langs->transnoentitiesnoconv("EMailTextOrderRefusedBy",$object->ref,$user->getFullName($langs));
-						$mesg.= "\n\n".$langs->transnoentitiesnoconv("Sincerely").".\n\n";
-						break;
-					case 'SHIPPING_VALIDATE':
-						$dir_output = $conf->expedition->dir_output.'/sending/';
-						$object_type = 'order_supplier';
-						$mesg = $langs->transnoentitiesnoconv("EMailTextExpeditionValidated",$object->ref);
-						break;
-				}
-				$ref = dol_sanitizeFileName($object->ref);
-				$pdf_path = $dir_output."/".$ref."/".$ref.".pdf";
-				if (! dol_is_file($pdf_path))
-				{
-					// We can't add PDF as it is not generated yet.
-					$filepdf = '';
-				}
-				else
-				{
-					$filepdf = $pdf_path;
-				}
-
-				$subject = '['.$application.'] '.$langs->transnoentitiesnoconv("DolibarrNotification");
-
-				$message = $langs->transnoentities("YouReceiveMailBecauseOfNotification",$application,$mysoc->name)."\n";
-				$message.= $langs->transnoentities("YouReceiveMailBecauseOfNotification2",$application,$mysoc->name)."\n";
-				$message.= "\n";
-				$message.= $mesg;
-				if ($link) $message=dol_concatdesc($message,$urlwithroot.$link);
-
-				$mailfile = new CMailFile(
-					$subject,
-					$sendto,
-					$replyto,
-					$message,
-					array($file),
-					array($mimefile),
-					array($filename[count($filename)-1]),
-					'',
-					'',
-					0,
-					-1
-				);
-
-				if ($mailfile->sendfile())
-				{
-					$sql = "INSERT INTO ".MAIN_DB_PREFIX."notify (daten, fk_action, fk_soc, fk_contact, type, objet_type, objet_id, email)";
-					$sql.= " VALUES ('".$this->db->idate(dol_now())."', ".$actiondefid.", ".$object->socid.", null, '".$obj->type."', '".$object_type."', ".$object->id.", '".$this->db->escape($conf->global->$param)."')";
-					if (! $this->db->query($sql))
+        	foreach($conf->global as $key => $val)
+    		{
+    			if ($val == '' || ! preg_match('/^NOTIFICATION_FIXEDEMAIL_'.$notifcode.'_THRESHOLD_HIGHER_(.*)$/', $key, $reg)) continue;
+
+    			$threshold = (float) $reg[1];
+    			if ($object->total_ht <= $threshold)
+    			{
+    				dol_syslog("A notification is requested for notifcode = ".$notifcode." but amount = ".$object->total_ht." so lower than threshold = ".$threshold.". We discard this notification");
+    				continue;
+    			}
+
+		        $param='NOTIFICATION_FIXEDEMAIL_'.$notifcode.'_THRESHOLD_HIGHER_'.$reg[1];
+		        //if (! empty($conf->global->$param))
+		        //{
+					$sendto = $conf->global->$param;
+					$notifcodedefid = dol_getIdFromCode($this->db, $notifcode, 'c_action_trigger', 'code', 'rowid');
+					if ($notifcodedefid <= 0) dol_print_error($this->db, 'Failed to get id from code');
+
+					$object_type = '';
+			        $link = '';
+	        		$num++;
+
+					switch ($notifcode) {
+						case 'BILL_VALIDATE':
+							$link='/compta/facture.php?facid='.$object->id;
+							$dir_output = $conf->facture->dir_output;
+							$object_type = 'facture';
+							$mesg = $langs->transnoentitiesnoconv("EMailTextInvoiceValidated",$object->ref);
+							break;
+						case 'ORDER_VALIDATE':
+							$link='/commande/card.php?id='.$object->id;
+							$dir_output = $conf->commande->dir_output;
+							$object_type = 'order';
+							$mesg = $langs->transnoentitiesnoconv("EMailTextOrderValidated",$object->ref);
+							break;
+						case 'PROPAL_VALIDATE':
+							$link='/comm/propal.php?id='.$object->id;
+							$dir_output = $conf->propal->dir_output;
+							$object_type = 'propal';
+							$mesg = $langs->transnoentitiesnoconv("EMailTextProposalValidated",$object->ref);
+							break;
+						case 'FICHINTER_VALIDATE':
+							$link='/fichinter/card.php?id='.$object->id;
+							$dir_output = $conf->facture->dir_output;
+							$object_type = 'ficheinter';
+							$mesg = $langs->transnoentitiesnoconv("EMailTextInterventionValidated",$object->ref);
+							break;
+						case 'ORDER_SUPPLIER_VALIDATE':
+							$link='/fourn/commande/card.php?id='.$object->id;
+							$dir_output = $conf->fournisseur->dir_output.'/commande/';
+							$object_type = 'order_supplier';
+							$mesg = $langs->transnoentitiesnoconv("Hello").",\n\n";
+							$mesg.= $langs->transnoentitiesnoconv("EMailTextOrderValidatedBy",$object->ref,$user->getFullName($langs));
+							$mesg.= "\n\n".$langs->transnoentitiesnoconv("Sincerely").".\n\n";
+							break;
+						case 'ORDER_SUPPLIER_APPROVE':
+							$link='/fourn/commande/card.php?id='.$object->id;
+							$dir_output = $conf->fournisseur->dir_output.'/commande/';
+							$object_type = 'order_supplier';
+							$mesg = $langs->transnoentitiesnoconv("Hello").",\n\n";
+							$mesg.= $langs->transnoentitiesnoconv("EMailTextOrderApprovedBy",$object->ref,$user->getFullName($langs));
+							$mesg.= "\n\n".$langs->transnoentitiesnoconv("Sincerely").".\n\n";
+							break;
+						case 'ORDER_SUPPLIER_REFUSE':
+							$link='/fourn/commande/card.php?id='.$object->id;
+							$dir_output = $conf->fournisseur->dir_output.'/commande/';
+							$object_type = 'order_supplier';
+							$mesg = $langs->transnoentitiesnoconv("Hello").",\n\n";
+							$mesg.= $langs->transnoentitiesnoconv("EMailTextOrderRefusedBy",$object->ref,$user->getFullName($langs));
+							$mesg.= "\n\n".$langs->transnoentitiesnoconv("Sincerely").".\n\n";
+							break;
+						case 'SHIPPING_VALIDATE':
+							$dir_output = $conf->expedition->dir_output.'/sending/';
+							$object_type = 'order_supplier';
+							$mesg = $langs->transnoentitiesnoconv("EMailTextExpeditionValidated",$object->ref);
+							break;
+					}
+					$ref = dol_sanitizeFileName($object->ref);
+					$pdf_path = $dir_output."/".$ref."/".$ref.".pdf";
+					if (! dol_is_file($pdf_path))
+					{
+						// We can't add PDF as it is not generated yet.
+						$filepdf = '';
+					}
+					else
+					{
+						$filepdf = $pdf_path;
+					}
+
+					$subject = '['.$application.'] '.$langs->transnoentitiesnoconv("DolibarrNotification");
+
+					$message = $langs->transnoentities("YouReceiveMailBecauseOfNotification",$application,$mysoc->name)."\n";
+					$message.= $langs->transnoentities("YouReceiveMailBecauseOfNotification2",$application,$mysoc->name)."\n";
+					$message.= "\n";
+					$message.= $mesg;
+					if ($link) $message=dol_concatdesc($message,$urlwithroot.$link);
+
+					$mailfile = new CMailFile(
+						$subject,
+						$sendto,
+						$replyto,
+						$message,
+						array($file),
+						array($mimefile),
+						array($filename[count($filename)-1]),
+						'',
+						'',
+						0,
+						-1
+					);
+
+					if ($mailfile->sendfile())
+					{
+						$sql = "INSERT INTO ".MAIN_DB_PREFIX."notify (daten, fk_action, fk_soc, fk_contact, type, objet_type, objet_id, email)";
+						$sql.= " VALUES ('".$this->db->idate(dol_now())."', ".$notifcodedefid.", ".$object->socid.", null, 'email', '".$object_type."', ".$object->id.", '".$this->db->escape($conf->global->$param)."')";
+						if (! $this->db->query($sql))
+						{
+							dol_print_error($this->db);
+						}
+					}
+					else
 					{
-						dol_print_error($this->db);
+						$error++;
+						$this->errors[]=$mailfile->error;
 					}
-				}
-				else
-				{
-					$error++;
-					$this->errors[]=$mailfile->error;
-				}
-	        }
+		        //}
+    		}
         }
 
 		if (! $error) return $num;

+ 7 - 1
htdocs/core/lib/admin.lib.php

@@ -386,6 +386,12 @@ function dolibarr_del_const($db, $name, $entity=1)
 {
     global $conf;
 
+    if (empty($name))
+    {
+    	dol_print_error('','Error call dolibar_del_const with parameter name empty');
+    	return -1;
+    }
+
     $sql = "DELETE FROM ".MAIN_DB_PREFIX."const";
     $sql.= " WHERE (".$db->decrypt('name')." = '".$db->escape($name)."'";
     if (is_numeric($name)) $sql.= " OR rowid = '".$db->escape($name)."'";
@@ -438,7 +444,7 @@ function dolibarr_get_const($db, $name, $entity=1)
 
 
 /**
- *	Insert a parameter (key,value) into database.
+ *	Insert a parameter (key,value) into database (delete old key then insert it again).
  *
  *	@param	    DoliDB		$db         Database handler
  *	@param	    string		$name		Name of constant

+ 6 - 4
htdocs/core/triggers/interface_50_modNotification_Notification.class.php

@@ -40,6 +40,7 @@ class InterfaceNotification extends DolibarrTriggers
     	'ORDER_VALIDATE',
     	'PROPAL_VALIDATE',
         'FICHINTER_VALIDATE',
+    	'ORDER_SUPPLIER_VALIDATE',
     	'ORDER_SUPPLIER_APPROVE',
     	'ORDER_SUPPLIER_REFUSE',
         'SHIPPING_VALIDATE'
@@ -84,8 +85,8 @@ class InterfaceNotification extends DolibarrTriggers
 
         $sql = "SELECT rowid, code, label, description, elementtype";
         $sql.= " FROM ".MAIN_DB_PREFIX."c_action_trigger";
-        $sql.= $this->db->order("elementtype, code");
-        dol_syslog("Get list of notifications", LOG_DEBUG);
+        $sql.= $this->db->order("rang, elementtype, code");
+        dol_syslog("getListOfManagedEvents Get list of notifications", LOG_DEBUG);
         $resql=$this->db->query($sql);
         if ($resql)
         {
@@ -103,13 +104,14 @@ class InterfaceNotification extends DolibarrTriggers
                 {
                     //print 'xx'.$obj->code;
                     $element=$obj->elementtype;
+
+                    // Exclude events if related module is disabled
                     if ($element == 'order_supplier' && empty($conf->fournisseur->enabled)) $qualified=0;
                     elseif ($element == 'invoice_supplier' && empty($conf->fournisseur->enabled)) $qualified=0;
                     elseif ($element == 'withdraw' && empty($conf->prelevement->enabled)) $qualified=0;
                     elseif ($element == 'shipping' && empty($conf->expedition->enabled)) $qualified=0;
                     elseif ($element == 'member' && empty($conf->adherent->enabled)) $qualified=0;
-                    elseif (! in_array($element,array('order_supplier','invoice_supplier','withdraw','shipping','member'))
-                                 && empty($conf->$element->enabled)) $qualified=0;
+                    elseif (! in_array($element,array('order_supplier','invoice_supplier','withdraw','shipping','member')) && empty($conf->$element->enabled)) $qualified=0;
                 }
 
                 if ($qualified)

+ 4 - 4
htdocs/expedition/card.php

@@ -602,7 +602,7 @@ if ($action == 'create')
 		        print $form->select_incoterms((!empty($object->fk_incoterms) ? $object->fk_incoterms : ''), (!empty($object->location_incoterms)?$object->location_incoterms:''));
 				print '</td></tr>';
 			}
-			
+
             // Other attributes
             $parameters=array('colspan' => ' colspan="3"');
             $reshook=$hookmanager->executeHooks('formObjectOptions',$parameters,$expe,$action);    // Note that $action and $object may have been modified by hook
@@ -934,7 +934,7 @@ else if ($id || $ref)
 				require_once DOL_DOCUMENT_ROOT .'/core/class/notify.class.php';
 				$notify=new Notify($db);
 				$text.='<br>';
-				$text.=$notify->confirmMessage('SHIPPING_VALIDATE',$object->socid);
+				$text.=$notify->confirmMessage('SHIPPING_VALIDATE',$object->socid, $object);
 			}
 
 			print $form->formconfirm($_SERVER['PHP_SELF'].'?id='.$object->id,$langs->trans('ValidateSending'),$text,'confirm_valid','',0,1);
@@ -1193,7 +1193,7 @@ else if ($id || $ref)
 
 		// Incoterms
 		if (!empty($conf->incoterm->enabled))
-		{			
+		{
 			print '<tr><td>';
 	        print '<table width="100%" class="nobordernopadding"><tr><td>';
 	        print $langs->trans('IncotermLabel');
@@ -1207,7 +1207,7 @@ else if ($id || $ref)
 			{
 				print $form->textwithpicto($object->display_incoterms(), $object->libelle_incoterms, 1);
 			}
-			else 
+			else
 			{
 				print $form->select_incoterms((!empty($object->fk_incoterms) ? $object->fk_incoterms : ''), (!empty($object->location_incoterms)?$object->location_incoterms:''), $_SERVER['PHP_SELF'].'?id='.$object->id);
 			}

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

@@ -1657,7 +1657,7 @@ elseif (! empty($object->id))
 				require_once DOL_DOCUMENT_ROOT .'/core/class/notify.class.php';
 				$notify=new	Notify($db);
 				$text.='<br>';
-				$text.=$notify->confirmMessage('ORDER_SUPPLIER_APPROVE', $object->socid);
+				$text.=$notify->confirmMessage('ORDER_SUPPLIER_APPROVE', $object->socid, $object);
 			}
 
 			$formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('ValidateOrder'), $text, 'confirm_valid', '', 0, 1);

+ 1 - 1
htdocs/fourn/facture/card.php

@@ -1664,7 +1664,7 @@ else
             	require_once DOL_DOCUMENT_ROOT .'/core/class/notify.class.php';
             	$notify=new Notify($db);
             	$text.='<br>';
-            	$text.=$notify->confirmMessage('BILL_SUPPLIER_VALIDATE',$object->socid);
+            	$text.=$notify->confirmMessage('BILL_SUPPLIER_VALIDATE',$object->socid, $object);
             }*/
             $formquestion=array();
 

+ 42 - 0
htdocs/install/mysql/migration/3.7.0-3.8.0.sql

@@ -373,3 +373,45 @@ INSERT INTO llx_c_incoterms (code, libelle, active) VALUES ('DDP', 'Delivered Du
 -- Extrafields fk_object must be unique (1-1 relation)
 ALTER TABLE llx_societe_extrafields DROP INDEX idx_societe_extrafields;
 ALTER TABLE llx_societe_extrafields ADD UNIQUE INDEX uk_societe_extrafields (fk_object);
+
+
+insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('BILL_VALIDATE','Customer invoice validated','Executed when a customer invoice is approved','facture',6);
+insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('ORDER_SUPPLIER_APPROVE','Supplier order request approved','Executed when a supplier order is approved','order_supplier',12);
+insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('ORDER_SUPPLIER_REFUSE','Supplier order request refused','Executed when a supplier order is refused','order_supplier',13);
+insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('ORDER_VALIDATE','Customer order validate','Executed when a customer order is validated','commande',4);
+insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('PROPAL_VALIDATE','Customer proposal validated','Executed when a commercial proposal is validated','propal',2);
+insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('COMPANY_SENTBYMAIL','Mails sent from third party card','Executed when you send email from third party card','societe',1);
+insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('COMPANY_CREATE','Third party created','Executed when a third party is created','societe',1);
+insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('CONTRACT_VALIDATE','Contract validated','Executed when a contract is validated','contrat',18);
+insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('PROPAL_SENTBYMAIL','Commercial proposal sent by mail','Executed when a commercial proposal is sent by mail','propal',3);
+insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('ORDER_SENTBYMAIL','Customer order sent by mail','Executed when a customer order is sent by mail ','commande',5);
+insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('BILL_PAYED','Customer invoice payed','Executed when a customer invoice is payed','facture',7);
+insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('BILL_CANCEL','Customer invoice canceled','Executed when a customer invoice is conceled','facture',8);
+insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('BILL_SENTBYMAIL','Customer invoice sent by mail','Executed when a customer invoice is sent by mail','facture',9);
+insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('ORDER_SUPPLIER_VALIDATE','Supplier order validated','Executed when a supplier order is validated','order_supplier',11);
+insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('ORDER_SUPPLIER_SENTBYMAIL','Supplier order sent by mail','Executed when a supplier order is sent by mail','order_supplier',14);
+insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('BILL_SUPPLIER_VALIDATE','Supplier invoice validated','Executed when a supplier invoice is validated','invoice_supplier',15);
+insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('BILL_SUPPLIER_PAYED','Supplier invoice payed','Executed when a supplier invoice is payed','invoice_supplier',16);
+insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('BILL_SUPPLIER_SENTBYMAIL','Supplier invoice sent by mail','Executed when a supplier invoice is sent by mail','invoice_supplier',17);
+insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('BILL_SUPPLIER_CANCELED','Supplier invoice cancelled','Executed when a supplier invoice is cancelled','invoice_supplier',17);
+insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('SHIPPING_VALIDATE','Shipping validated','Executed when a shipping is validated','shipping',20);
+insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('SHIPPING_SENTBYMAIL','Shipping sent by mail','Executed when a shipping is sent by mail','shipping',21);
+insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('MEMBER_VALIDATE','Member validated','Executed when a member is validated','member',22);
+insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('MEMBER_SUBSCRIPTION','Member subscribed','Executed when a member is subscribed','member',23);
+insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('MEMBER_RESILIATE','Member resiliated','Executed when a member is resiliated','member',24);
+insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('MEMBER_MODIFY','Member modified','Executed when a member is modified','member',24);
+insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('MEMBER_DELETE','Member deleted','Executed when a member is deleted','member',25);
+insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('BILL_UNVALIDATE','Customer invoice unvalidated','Executed when a customer invoice status set back to draft','facture',10);
+insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('FICHINTER_VALIDATE','Intervention validated','Executed when a intervention is validated','ficheinter',19);
+insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('FICHINTER_CLASSIFY_BILLED','Intervention set billed','Executed when a intervention is set to billed (when option FICHINTER_CLASSIFY_BILLED is set)','ficheinter',19);
+insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('FICHINTER_CLASSIFY_UNBILLED','Intervention set unbilled','Executed when a intervention is set to unbilled (when option FICHINTER_CLASSIFY_BILLED is set)','ficheinter',19);
+insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('FICHINTER_REOPEN','Intervention opened','Executed when a intervention is re-opened','ficheinter',19);
+insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('FICHINTER_SENTBYMAIL','Intervention sent by mail','Executed when a intervention is sent by mail','ficheinter',19);
+insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('PROJECT_CREATE','Project creation','Executed when a project is created','project',30);
+insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('PROPAL_CLOSE_SIGNED','Customer proposal closed signed','Executed when a customer proposal is closed signed','propal',2);
+insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('PROPAL_CLOSE_REFUSED','Customer proposal closed refused','Executed when a customer proposal is closed refused','propal',2);
+insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('PROPAL_CLASSIFY_BILLED','Customer proposal set billed','Executed when a customer proposal is set to billed','propal',2);
+insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('TASK_CREATE','Task created','Executed when a project task is created','project',35);
+insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('TASK_MODIFY','Task modified','Executed when a project task is modified','project',36);
+insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('TASK_DELETE','Task deleted','Executed when a project task is deleted','project',37);
+

+ 1 - 1
htdocs/install/mysql/tables/llx_c_action_trigger.sql

@@ -22,9 +22,9 @@
 create table llx_c_action_trigger
 (
   rowid			integer AUTO_INCREMENT PRIMARY KEY,
+  elementtype	varchar(16) 			NOT NULL,
   code			varchar(32)				NOT NULL,
   label			varchar(128)			NOT NULL,
   description	varchar(255),
-  elementtype	varchar(16) 			NOT NULL,
   rang			integer		DEFAULT 0
 )ENGINE=innodb;

+ 6 - 1
htdocs/langs/en_US/admin.lang

@@ -1107,7 +1107,7 @@ ModuleCompanyCodeAquarium=Return an accountancy code built by:<br>%s followed by
 ModuleCompanyCodePanicum=Return an empty accountancy code.
 ModuleCompanyCodeDigitaria=Accountancy code depends on third party code. The code is composed of the character "C" in the first position followed by the first 5 characters of the third party code.  
 UseNotifications=Use notifications
-NotificationsDesc=EMails notifications feature allows you to silently send automatic mail, for some Dolibarr events. Targets of notifications can be defined:<br>* per third parties contacts (customers or suppliers), one third party at time.<br>* or by setting a global target email address on module setup page.
+NotificationsDesc=EMails notifications feature allows you to silently send automatic mail, for some Dolibarr events. Targets of notifications can be defined:<br>* per third parties contacts (customers or suppliers), one contact at time.<br>* or by setting a global target email address on module setup page.
 ModelModules=Documents templates
 DocumentModelOdt=Generate documents from OpenDocuments templates (.ODT or .ODS files for OpenOffice, KOffice, TextEdit,...)
 WatermarkOnDraft=Watermark on draft document
@@ -1601,3 +1601,8 @@ ExpenseReportsSetup=Setup of module Expense Reports
 TemplatePDFExpenseReports=Document templates to generate expense report document
 NoModueToManageStockDecrease=No module able to manage automatic stock decrease has been activated. Stock decrease will be done on manual input only.
 NoModueToManageStockIncrease=No module able to manage automatic stock increase has been activated. Stock increase will be done on manual input only.
+YouMayFindNotificationsFeaturesIntoModuleNotification=You may find options for EMail notifications by enabling and configuring the module "Notification".
+ListOfNotificationsPerContact=List of notifications per contact*
+ListOfFixedNotifications=List of fixed notifications
+GoOntoContactCardToAddMore=Go on the tab "Notifications" of a thirdparty contact to add or remove notifications for contact
+Threshold=Threshold

+ 2 - 0
htdocs/langs/en_US/other.lang

@@ -12,6 +12,7 @@ Notify_FICHINTER_VALIDATE=Intervention validated
 Notify_FICHINTER_SENTBYMAIL=Intervention sent by mail
 Notify_BILL_VALIDATE=Customer invoice validated
 Notify_BILL_UNVALIDATE=Customer invoice unvalidated
+Notify_ORDER_SUPPLIER_VALIDATE=Supplier order recorded
 Notify_ORDER_SUPPLIER_APPROVE=Supplier order approved
 Notify_ORDER_SUPPLIER_REFUSE=Supplier order refused
 Notify_ORDER_VALIDATE=Customer order validated
@@ -170,6 +171,7 @@ EMailTextInvoiceValidated=The invoice %s has been validated.
 EMailTextProposalValidated=The proposal %s has been validated.
 EMailTextOrderValidated=The order %s has been validated.
 EMailTextOrderApproved=The order %s has been approved.
+EMailTextOrderValidatedBy=The order %s has been recorded by %s.
 EMailTextOrderApprovedBy=The order %s has been approved by %s.
 EMailTextOrderRefused=The order %s has been refused.
 EMailTextOrderRefusedBy=The order %s has been refused by %s.

+ 3 - 27
htdocs/societe/notify/card.php

@@ -24,6 +24,7 @@
  */
 
 require '../../main.inc.php';
+require_once DOL_DOCUMENT_ROOT.'/core/class/notify.class.php';
 require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php';
 require_once DOL_DOCUMENT_ROOT.'/contact/class/contact.class.php';
 require_once DOL_DOCUMENT_ROOT.'/core/triggers/interface_50_modNotification_Notification.class.php';
@@ -173,33 +174,8 @@ if ($result > 0)
 
     print '<tr><td>'.$langs->trans("NbOfActiveNotifications").'</td>';
     print '<td colspan="3">';
-    $nb=0;
-    // List of per contact notifications
-    $sql = "SELECT COUNT(n.rowid) as nb";
-    $sql.= " FROM ".MAIN_DB_PREFIX."notify_def as n";
-    $sql.= " WHERE fk_soc = ".$object->id;
-    $resql=$db->query($sql);
-    if ($resql)
-    {
-        $num = $db->num_rows($resql);
-        $i = 0;
-        while ($i < $num)
-        {
-            $obj = $db->fetch_object($resql);
-            $nb=$obj->nb;
-            $i++;
-        }
-    }
-    else {
-        dol_print_error($db);
-    }
-    // List of notifications enabled for fixed email
-    foreach($conf->global as $key => $val)
-    {
-    	if (! preg_match('/^NOTIFICATION_FIXEDEMAIL_(.*)/', $key, $reg)) continue;
-    	$listtmp=explode(',',$val);
-    	$nb+=count($listtmp);
-    }
+    $notify=new Notify($db);
+    $nb = $notify->countDefinedNotifications('', $object->id);
     print $nb;
     print '</td></tr>';
     print '</table>';

+ 3 - 3
htdocs/theme/eldy/style.css.php

@@ -1394,9 +1394,9 @@ div.tabsElem { margin-top: 8px; }		/* To avoid overlap of tabs when not browser
 div.tabBar {
     color: #<?php echo $colortextbacktab; ?>;
     padding-top: 9px;
-    padding-left: <?php echo ($dol_optimize_smallscreen?'4':'8'); ?>px;
-    padding-right: <?php echo ($dol_optimize_smallscreen?'4':'8'); ?>px;
-    padding-bottom: 8px;
+    padding-left: <?php echo ($dol_optimize_smallscreen?'4':'14'); ?>px;
+    padding-right: <?php echo ($dol_optimize_smallscreen?'4':'14'); ?>px;
+    padding-bottom: 12px;
     margin: 0px 0px 14px 0px;
     -moz-border-radius:6px;
     -webkit-border-radius: 6px;