Browse Source

Merge branch '13.0' of git@github.com:Dolibarr/dolibarr.git into 14.0

Conflicts:
	htdocs/contact/card.php
	htdocs/contact/list.php
	htdocs/core/modules/mailings/modules_mailings.php
	htdocs/product/card.php
	htdocs/public/emailing/mailing-unsubscribe.php
Laurent Destailleur 3 years ago
parent
commit
da2ce063b3

+ 12 - 0
dev/dolibarr_changes.txt

@@ -168,6 +168,18 @@ In htdocs/includes/tecnickcom/tcpdf/tcpdf.php
 -       protected $default_monospaced_font = 'courier';
 -       protected $default_monospaced_font = 'courier';
 +       protected $default_monospaced_font = 'freemono';
 +       protected $default_monospaced_font = 'freemono';
 
 
+* In tecnickcom/tcpdf/include/tcpdf_static, in function intToRoman, right at the beginning
+  of the function, replace:
+
+		$roman = '';
+
+with:
+
+		$roman = '';
+		if ($number >= 4000) {
+			// do not represent numbers above 4000 in Roman numerals
+			return strval($number);
+		}
 
 
 
 
 
 

+ 10 - 0
htdocs/compta/facture/card.php

@@ -2831,6 +2831,16 @@ if (empty($reshook)) {
  * View
  * View
  */
  */
 
 
+if (empty($object->id)) {
+	llxHeader();
+	$head = facture_prepare_head($object);
+	$langs->load('errors');
+	echo dol_get_fiche_head($head, 'compta', $langs->trans("InvoiceCustomer"), -1, 'bill'),
+		'<div class="error">' . $langs->trans("ErrorRecordNotFound") . '</div>';
+	llxFooter();
+	exit;
+}
+
 $form = new Form($db);
 $form = new Form($db);
 $formother = new FormOther($db);
 $formother = new FormOther($db);
 $formfile = new FormFile($db);
 $formfile = new FormFile($db);

+ 10 - 0
htdocs/compta/facture/contact.php

@@ -100,6 +100,16 @@ if ($action == 'addcontact' && $user->rights->facture->creer) {
  * View
  * View
  */
  */
 
 
+if (empty($object->id)) {
+	llxHeader();
+	$head = facture_prepare_head($object);
+	$langs->load('errors');
+	echo dol_get_fiche_head($head, 'contact', $langs->trans("InvoiceCustomer"), -1, 'bill'),
+		'<div class="error">' . $langs->trans("ErrorRecordNotFound") . '</div>';
+	llxFooter();
+	exit;
+}
+
 $title = $langs->trans('InvoiceCustomer')." - ".$langs->trans('ContactsAddresses');
 $title = $langs->trans('InvoiceCustomer')." - ".$langs->trans('ContactsAddresses');
 $helpurl = "EN:Customers_Invoices|FR:Factures_Clients|ES:Facturas_a_clientes";
 $helpurl = "EN:Customers_Invoices|FR:Factures_Clients|ES:Facturas_a_clientes";
 llxHeader('', $title, $helpurl);
 llxHeader('', $title, $helpurl);

+ 10 - 0
htdocs/compta/facture/document.php

@@ -92,6 +92,16 @@ include DOL_DOCUMENT_ROOT.'/core/actions_linkedfiles.inc.php';
  * View
  * View
  */
  */
 
 
+if (empty($object->id)) {
+	llxHeader();
+	$head = facture_prepare_head($object);
+	$langs->load('errors');
+	echo dol_get_fiche_head($head, 'documents', $langs->trans("InvoiceCustomer"), -1, 'bill'),
+		'<div class="error">' . $langs->trans("ErrorRecordNotFound") . '</div>';
+	llxFooter();
+	exit;
+}
+
 $title = $langs->trans('InvoiceCustomer')." - ".$langs->trans('Documents');
 $title = $langs->trans('InvoiceCustomer')." - ".$langs->trans('Documents');
 
 
 $help_url = "EN:Customers_Invoices|FR:Factures_Clients|ES:Facturas_a_clientes";
 $help_url = "EN:Customers_Invoices|FR:Factures_Clients|ES:Facturas_a_clientes";

+ 10 - 0
htdocs/compta/facture/info.php

@@ -62,6 +62,16 @@ $result = restrictedArea($user, 'facture', $object->id, '', '', 'fk_soc', $field
  * View
  * View
  */
  */
 
 
+if (empty($object->id)) {
+	llxHeader();
+	$head = facture_prepare_head($object);
+	$langs->load('errors');
+	echo dol_get_fiche_head($head, 'info', $langs->trans("InvoiceCustomer"), -1, 'bill'),
+		'<div class="error">' . $langs->trans("ErrorRecordNotFound") . '</div>';
+	llxFooter();
+	exit;
+}
+
 $form = new Form($db);
 $form = new Form($db);
 
 
 $title = $langs->trans('InvoiceCustomer')." - ".$langs->trans('Info');
 $title = $langs->trans('InvoiceCustomer')." - ".$langs->trans('Info');

+ 10 - 0
htdocs/compta/facture/note.php

@@ -69,6 +69,16 @@ include DOL_DOCUMENT_ROOT.'/core/actions_setnotes.inc.php'; // Must be include,
  * View
  * View
  */
  */
 
 
+if (empty($object->id)) {
+	llxHeader();
+	$head = facture_prepare_head($object);
+	$langs->load('errors');
+	echo dol_get_fiche_head($head, 'note', $langs->trans("InvoiceCustomer"), -1, 'bill'),
+		'<div class="error">' . $langs->trans("ErrorRecordNotFound") . '</div>';
+	llxFooter();
+	exit;
+}
+
 $title = $langs->trans('InvoiceCustomer')." - ".$langs->trans('Notes');
 $title = $langs->trans('InvoiceCustomer')." - ".$langs->trans('Notes');
 $helpurl = "EN:Customers_Invoices|FR:Factures_Clients|ES:Facturas_a_clientes";
 $helpurl = "EN:Customers_Invoices|FR:Factures_Clients|ES:Facturas_a_clientes";
 llxHeader('', $title, $helpurl);
 llxHeader('', $title, $helpurl);

+ 13 - 3
htdocs/contact/card.php

@@ -801,7 +801,9 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) {
 				}
 				}
 				print '<tr>';
 				print '<tr>';
 				print '<td class="noemail"><label for="no_email">'.$langs->trans("No_Email").'</label></td>';
 				print '<td class="noemail"><label for="no_email">'.$langs->trans("No_Email").'</label></td>';
-				print '<td>'.$form->selectyesno('no_email', (GETPOSTISSET("no_email") ? GETPOST("no_email", 'int') : $conf->global->MAILING_CONTACT_DEFAULT_BULK_STATUS), 1, false, ($conf->global->MAILING_CONTACT_DEFAULT_BULK_STATUS == 2)).'</td>';
+				print '<td>';
+				print $form->selectyesno('no_email', (GETPOSTISSET("no_email") ? GETPOST("no_email", 'int') : $conf->global->MAILING_CONTACT_DEFAULT_BULK_STATUS), 1, false, ($conf->global->MAILING_CONTACT_DEFAULT_BULK_STATUS == 2));
+				print '</td>';
 				print '</tr>';
 				print '</tr>';
 			}
 			}
 
 
@@ -1087,8 +1089,10 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) {
 				}
 				}
 				print '<tr>';
 				print '<tr>';
 				print '<td class="noemail"><label for="no_email">'.$langs->trans("No_Email").'</label></td>';
 				print '<td class="noemail"><label for="no_email">'.$langs->trans("No_Email").'</label></td>';
+				print '<td>';
 				$useempty = (isset($conf->global->MAILING_CONTACT_DEFAULT_BULK_STATUS) && ($conf->global->MAILING_CONTACT_DEFAULT_BULK_STATUS == 2));
 				$useempty = (isset($conf->global->MAILING_CONTACT_DEFAULT_BULK_STATUS) && ($conf->global->MAILING_CONTACT_DEFAULT_BULK_STATUS == 2));
-				print '<td>'.$form->selectyesno('no_email', (GETPOSTISSET("no_email") ? GETPOST("no_email", 'int') : $object->no_email), 1, false, $useempty).'</td>';
+				print $form->selectyesno('no_email', (GETPOSTISSET("no_email") ? GETPOST("no_email", 'int') : $object->no_email), 1, false, $useempty);
+				print '</td>';
 				print '</tr>';
 				print '</tr>';
 			}
 			}
 
 
@@ -1319,7 +1323,13 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) {
 			if ($result < 0) {
 			if ($result < 0) {
 				setEventMessages($object->error, $object->errors, 'errors');
 				setEventMessages($object->error, $object->errors, 'errors');
 			}
 			}
-			print '<tr><td>'.$langs->trans("No_Email").'</td><td>'.yn($object->no_email).'</td></tr>';
+			print '<tr><td>'.$langs->trans("No_Email").'</td><td>';
+			if ($object->email) {
+				print yn($object->no_email);
+			} else {
+				print '<span class="opacitymedium">'.$langs->trans("EMailNotDefined").'</span>';
+			}
+			print '</td></tr>';
 		}
 		}
 
 
 		print '<tr><td>'.$langs->trans("ContactVisibility").'</td><td>';
 		print '<tr><td>'.$langs->trans("ContactVisibility").'</td><td>';

+ 28 - 8
htdocs/contact/list.php

@@ -203,6 +203,12 @@ if (empty($conf->global->SOCIETE_DISABLE_CONTACTS)) {
 	$arrayfields['s.nom'] = array('label'=>"ThirdParty", 'position'=>25, 'checked'=>1);
 	$arrayfields['s.nom'] = array('label'=>"ThirdParty", 'position'=>25, 'checked'=>1);
 }
 }
 
 
+$arrayfields['unsubscribed'] = array(
+		'label'=>'No_Email',
+		'checked'=>0,
+		'enabled'=>(!empty($conf->mailing->enabled)),
+		'position'=>41);
+
 if (!empty($conf->socialnetworks->enabled)) {
 if (!empty($conf->socialnetworks->enabled)) {
 	foreach ($socialnetworks as $key => $value) {
 	foreach ($socialnetworks as $key => $value) {
 		if ($value['active']) {
 		if ($value['active']) {
@@ -353,7 +359,7 @@ if ($resql) {
 }
 }
 
 
 $sql = "SELECT s.rowid as socid, s.nom as name,";
 $sql = "SELECT s.rowid as socid, s.nom as name,";
-$sql .= " p.rowid, p.lastname as lastname, p.statut, p.firstname, p.zip, p.town, p.poste, p.email, p.no_email,";
+$sql .= " p.rowid, p.lastname as lastname, p.statut, p.firstname, p.zip, p.town, p.poste, p.email,";
 $sql .= " p.socialnetworks, p.photo,";
 $sql .= " p.socialnetworks, p.photo,";
 $sql .= " p.phone as phone_pro, p.phone_mobile, p.phone_perso, p.fax, p.fk_pays, p.priv, p.datec as date_creation, p.tms as date_update,";
 $sql .= " p.phone as phone_pro, p.phone_mobile, p.phone_perso, p.fax, p.fk_pays, p.priv, p.datec as date_creation, p.tms as date_update,";
 $sql .= " st.libelle as stcomm, st.picto as stcomm_picto, p.fk_stcommcontact as stcomm_id, p.fk_prospectcontactlevel,";
 $sql .= " st.libelle as stcomm, st.picto as stcomm_picto, p.fk_stcommcontact as stcomm_id, p.fk_prospectcontactlevel,";
@@ -364,6 +370,9 @@ if (!empty($extrafields->attributes[$object->table_element]['label'])) {
 		$sql .= ($extrafields->attributes[$object->table_element]['type'][$key] != 'separate' ? ", ef.".$key.' as options_'.$key : '');
 		$sql .= ($extrafields->attributes[$object->table_element]['type'][$key] != 'separate' ? ", ef.".$key.' as options_'.$key : '');
 	}
 	}
 }
 }
+if(!empty($conf->mailing->enabled)) {
+	$sql .= ", (SELECT count(*) FROM ".MAIN_DB_PREFIX."mailing_unsubscribe WHERE email = p.email) as unsubscribed";
+}
 // Add fields from hooks
 // Add fields from hooks
 $parameters = array();
 $parameters = array();
 $reshook = $hookmanager->executeHooks('printFieldListSelect', $parameters); // Note that $action and $object may have been modified by hook
 $reshook = $hookmanager->executeHooks('printFieldListSelect', $parameters); // Note that $action and $object may have been modified by hook
@@ -494,8 +503,11 @@ if (strlen($search_town)) {
 if (count($search_roles) > 0) {
 if (count($search_roles) > 0) {
 	$sql .= " AND p.rowid IN (SELECT sc.fk_socpeople FROM ".MAIN_DB_PREFIX."societe_contacts as sc WHERE sc.fk_c_type_contact IN (".$db->sanitize(implode(',', $search_roles))."))";
 	$sql .= " AND p.rowid IN (SELECT sc.fk_socpeople FROM ".MAIN_DB_PREFIX."societe_contacts as sc WHERE sc.fk_c_type_contact IN (".$db->sanitize(implode(',', $search_roles))."))";
 }
 }
-if ($search_no_email != '' && $search_no_email >= 0) {
-	$sql .= " AND p.no_email = ".((int) $search_no_email);
+if ($search_no_email != -1 && $search_no_email > 0) {
+	$sql .= " AND (SELECT count(*) FROM ".MAIN_DB_PREFIX."mailing_unsubscribe WHERE email = p.email) > 0";
+}
+if ($search_no_email != -1 && $search_no_email == 0) {
+	$sql .= " AND (SELECT count(*) FROM ".MAIN_DB_PREFIX."mailing_unsubscribe WHERE email = p.email) = 0 AND p.email IS NOT NULL  AND p.email <> ''";
 }
 }
 if ($search_status != '' && $search_status >= 0) {
 if ($search_status != '' && $search_status >= 0) {
 	$sql .= " AND p.statut = ".((int) $search_status);
 	$sql .= " AND p.statut = ".((int) $search_status);
@@ -830,7 +842,8 @@ if (!empty($arrayfields['p.email']['checked'])) {
 	print '<input class="flat" type="text" name="search_email" size="6" value="'.dol_escape_htmltag($search_email).'">';
 	print '<input class="flat" type="text" name="search_email" size="6" value="'.dol_escape_htmltag($search_email).'">';
 	print '</td>';
 	print '</td>';
 }
 }
-if (!empty($arrayfields['p.no_email']['checked'])) {
+if (!empty($arrayfields['unsubscribed']['checked']))
+{
 	print '<td class="liste_titre center">';
 	print '<td class="liste_titre center">';
 	print $form->selectarray('search_no_email', array('-1'=>'', '0'=>$langs->trans('No'), '1'=>$langs->trans('Yes')), $search_no_email);
 	print $form->selectarray('search_no_email', array('-1'=>'', '0'=>$langs->trans('No'), '1'=>$langs->trans('Yes')), $search_no_email);
 	print '</td>';
 	print '</td>';
@@ -949,8 +962,8 @@ if (!empty($arrayfields['p.fax']['checked'])) {
 if (!empty($arrayfields['p.email']['checked'])) {
 if (!empty($arrayfields['p.email']['checked'])) {
 	print_liste_field_titre($arrayfields['p.email']['label'], $_SERVER["PHP_SELF"], "p.email", $begin, $param, '', $sortfield, $sortorder);
 	print_liste_field_titre($arrayfields['p.email']['label'], $_SERVER["PHP_SELF"], "p.email", $begin, $param, '', $sortfield, $sortorder);
 }
 }
-if (!empty($arrayfields['p.no_email']['checked'])) {
-	print_liste_field_titre($arrayfields['p.no_email']['label'], $_SERVER["PHP_SELF"], "p.no_email", $begin, $param, '', $sortfield, $sortorder, 'center ');
+if (!empty($arrayfields['unsubscribed']['checked'])) {
+	print_liste_field_titre($arrayfields['unsubscribed']['label'], $_SERVER["PHP_SELF"], "unsubscribed", $begin, $param, '', $sortfield, $sortorder, 'center ');
 }
 }
 if (!empty($conf->socialnetworks->enabled)) {
 if (!empty($conf->socialnetworks->enabled)) {
 	foreach ($socialnetworks as $key => $value) {
 	foreach ($socialnetworks as $key => $value) {
@@ -1131,8 +1144,15 @@ while ($i < min($num, $limit)) {
 		}
 		}
 	}
 	}
 	// No EMail
 	// No EMail
-	if (!empty($arrayfields['p.no_email']['checked'])) {
-		print '<td class="center">'.yn($obj->no_email).'</td>';
+	if (!empty($arrayfields['unsubscribed']['checked']))
+	{
+		print '<td class="center">';
+		if (empty($obj->email)) {
+			//print '<span class="opacitymedium">'.$langs->trans("NoEmail").'</span>';
+		} else {
+			print yn(($obj->unsubscribed > 0) ? 1 : 0);
+		}
+		print '</td>';
 		if (!$i) {
 		if (!$i) {
 			$totalarray['nbfield']++;
 			$totalarray['nbfield']++;
 		}
 		}

+ 15 - 21
htdocs/core/modules/mailings/contacts1.modules.php

@@ -79,8 +79,8 @@ class mailing_contacts1 extends MailingTargets
 		$statssql[0] .= " count(distinct(c.email)) as nb";
 		$statssql[0] .= " count(distinct(c.email)) as nb";
 		$statssql[0] .= " FROM ".MAIN_DB_PREFIX."socpeople as c";
 		$statssql[0] .= " FROM ".MAIN_DB_PREFIX."socpeople as c";
 		$statssql[0] .= " WHERE c.entity IN (".getEntity('socpeople').")";
 		$statssql[0] .= " WHERE c.entity IN (".getEntity('socpeople').")";
-		$statssql[0] .= " AND c.email != ''"; // Note that null != '' is false
-		$statssql[0] .= " AND c.no_email = 0";
+		$statssql[0] .= " AND c.email <> ''"; // Note that null != '' is false
+		$statssql[0] .= " AND (SELECT count(*) FROM ".MAIN_DB_PREFIX."mailing_unsubscribe WHERE email = c.email) = 0";
 		$statssql[0] .= " AND c.statut = 1";
 		$statssql[0] .= " AND c.statut = 1";
 
 
 		return $statssql;
 		return $statssql;
@@ -103,8 +103,7 @@ class mailing_contacts1 extends MailingTargets
 		$sql .= " FROM ".MAIN_DB_PREFIX."socpeople as c";
 		$sql .= " FROM ".MAIN_DB_PREFIX."socpeople as c";
 		$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s ON s.rowid = c.fk_soc";
 		$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s ON s.rowid = c.fk_soc";
 		$sql .= " WHERE c.entity IN (".getEntity('socpeople').")";
 		$sql .= " WHERE c.entity IN (".getEntity('socpeople').")";
-		$sql .= " AND c.email != ''"; // Note that null != '' is false
-		$sql .= " AND c.no_email = 0";
+		$sql .= " AND c.email <> ''"; // Note that null != '' is false
 		$sql .= " AND (SELECT count(*) FROM ".MAIN_DB_PREFIX."mailing_unsubscribe WHERE email = c.email) = 0";
 		$sql .= " AND (SELECT count(*) FROM ".MAIN_DB_PREFIX."mailing_unsubscribe WHERE email = c.email) = 0";
 		// exclude unsubscribed users
 		// exclude unsubscribed users
 		$sql .= " AND c.statut = 1";
 		$sql .= " AND c.statut = 1";
@@ -132,10 +131,9 @@ class mailing_contacts1 extends MailingTargets
 		$sql = "SELECT sp.poste, count(distinct(sp.email)) AS nb";
 		$sql = "SELECT sp.poste, count(distinct(sp.email)) AS nb";
 		$sql .= " FROM ".MAIN_DB_PREFIX."socpeople as sp";
 		$sql .= " FROM ".MAIN_DB_PREFIX."socpeople as sp";
 		$sql .= " WHERE sp.entity IN (".getEntity('socpeople').")";
 		$sql .= " WHERE sp.entity IN (".getEntity('socpeople').")";
-		/*$sql.= " AND sp.email != ''";    // Note that null != '' is false
-		 $sql.= " AND sp.no_email = 0";
-		 $sql.= " AND sp.statut = 1";*/
-		$sql .= " AND (sp.poste IS NOT NULL AND sp.poste != '')";
+		$sql .= " AND sp.email <> ''";    // Note that null != '' is false
+		$sql .= " AND sp.statut = 1";
+		$sql .= " AND (sp.poste IS NOT NULL AND sp.poste <> '')";
 		$sql .= " GROUP BY sp.poste";
 		$sql .= " GROUP BY sp.poste";
 		$sql .= " ORDER BY sp.poste";
 		$sql .= " ORDER BY sp.poste";
 		$resql = $this->db->query($sql);
 		$resql = $this->db->query($sql);
@@ -169,10 +167,9 @@ class mailing_contacts1 extends MailingTargets
 		$sql .= " ".MAIN_DB_PREFIX."socpeople as sp,";
 		$sql .= " ".MAIN_DB_PREFIX."socpeople as sp,";
 		$sql .= " ".MAIN_DB_PREFIX."categorie as c,";
 		$sql .= " ".MAIN_DB_PREFIX."categorie as c,";
 		$sql .= " ".MAIN_DB_PREFIX."categorie_contact as cs";
 		$sql .= " ".MAIN_DB_PREFIX."categorie_contact as cs";
-		$sql .= " WHERE sp.statut = 1"; // Note that null != '' is false
-		//$sql.= " AND sp.no_email = 0";
-		//$sql.= " AND sp.email != ''";
-		//$sql.= " AND sp.entity IN (".getEntity('socpeople').")";
+		$sql .= " WHERE sp.entity IN (".getEntity('socpeople').")";
+		$sql .= " AND sp.email <> ''";    // Note that null != '' is false
+		$sql .= " AND sp.statut = 1";
 		$sql .= " AND cs.fk_categorie = c.rowid";
 		$sql .= " AND cs.fk_categorie = c.rowid";
 		$sql .= " AND cs.fk_socpeople = sp.rowid";
 		$sql .= " AND cs.fk_socpeople = sp.rowid";
 		$sql .= " GROUP BY c.label";
 		$sql .= " GROUP BY c.label";
@@ -244,10 +241,9 @@ class mailing_contacts1 extends MailingTargets
 		$sql .= " ".MAIN_DB_PREFIX."socpeople as sp,";
 		$sql .= " ".MAIN_DB_PREFIX."socpeople as sp,";
 		$sql .= " ".MAIN_DB_PREFIX."categorie as c,";
 		$sql .= " ".MAIN_DB_PREFIX."categorie as c,";
 		$sql .= " ".MAIN_DB_PREFIX."categorie_societe as cs";
 		$sql .= " ".MAIN_DB_PREFIX."categorie_societe as cs";
-		$sql .= " WHERE sp.statut = 1"; // Note that null != '' is false
-		//$sql.= " AND sp.no_email = 0";
-		//$sql.= " AND sp.email != ''";
-		//$sql.= " AND sp.entity IN (".getEntity('socpeople').")";
+		$sql .= " WHERE sp.entity IN (".getEntity('socpeople').")";
+		$sql .= " AND sp.email <> ''";    // Note that null != '' is false
+		$sql .= " AND sp.statut = 1";
 		$sql .= " AND cs.fk_categorie = c.rowid";
 		$sql .= " AND cs.fk_categorie = c.rowid";
 		$sql .= " AND cs.fk_soc = sp.fk_soc";
 		$sql .= " AND cs.fk_soc = sp.fk_soc";
 		$sql .= " GROUP BY c.label";
 		$sql .= " GROUP BY c.label";
@@ -282,10 +278,9 @@ class mailing_contacts1 extends MailingTargets
 		$sql .= " ".MAIN_DB_PREFIX."socpeople as sp,";
 		$sql .= " ".MAIN_DB_PREFIX."socpeople as sp,";
 		$sql .= " ".MAIN_DB_PREFIX."categorie as c,";
 		$sql .= " ".MAIN_DB_PREFIX."categorie as c,";
 		$sql .= " ".MAIN_DB_PREFIX."categorie_fournisseur as cs";
 		$sql .= " ".MAIN_DB_PREFIX."categorie_fournisseur as cs";
-		$sql .= " WHERE sp.statut = 1"; // Note that null != '' is false
-		//$sql.= " AND sp.no_email = 0";
-		//$sql.= " AND sp.email != ''";
-		//$sql.= " AND sp.entity IN (".getEntity('socpeople').")";
+		$sql .= " WHERE sp.entity IN (".getEntity('socpeople').")";
+		$sql .= " AND sp.email <> ''";    // Note that null != '' is false
+		$sql .= " AND sp.statut = 1";
 		$sql .= " AND cs.fk_categorie = c.rowid";
 		$sql .= " AND cs.fk_categorie = c.rowid";
 		$sql .= " AND cs.fk_soc = sp.fk_soc";
 		$sql .= " AND cs.fk_soc = sp.fk_soc";
 		$sql .= " GROUP BY c.label";
 		$sql .= " GROUP BY c.label";
@@ -391,7 +386,6 @@ class mailing_contacts1 extends MailingTargets
 		}
 		}
 		$sql .= " WHERE sp.entity IN (".getEntity('socpeople').")";
 		$sql .= " WHERE sp.entity IN (".getEntity('socpeople').")";
 		$sql .= " AND sp.email <> ''";
 		$sql .= " AND sp.email <> ''";
-		$sql .= " AND sp.no_email = 0";
 		$sql .= " AND (SELECT count(*) FROM ".MAIN_DB_PREFIX."mailing_unsubscribe WHERE email = sp.email) = 0";
 		$sql .= " AND (SELECT count(*) FROM ".MAIN_DB_PREFIX."mailing_unsubscribe WHERE email = sp.email) = 0";
 		// Exclude unsubscribed email adresses
 		// Exclude unsubscribed email adresses
 		$sql .= " AND sp.statut = 1";
 		$sql .= " AND sp.statut = 1";

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

@@ -208,7 +208,7 @@ class MailingTargets // This can't be abstract as it is used for some method
 		//Update the status to show thirdparty mail that don't want to be contacted anymore'
 		//Update the status to show thirdparty mail that don't want to be contacted anymore'
 		$sql = "UPDATE ".MAIN_DB_PREFIX."mailing_cibles";
 		$sql = "UPDATE ".MAIN_DB_PREFIX."mailing_cibles";
 		$sql .= " SET statut=3";
 		$sql .= " SET statut=3";
-		$sql .= " WHERE fk_mailing=".$mailing_id." AND email in (SELECT email FROM ".MAIN_DB_PREFIX."societe where fk_stcomm=-1)";
+		$sql .= " WHERE fk_mailing=".((int) $mailing_id)." AND email in (SELECT email FROM ".MAIN_DB_PREFIX."societe where fk_stcomm=-1)";
 		$sql .= " AND source_type='thirdparty'";
 		$sql .= " AND source_type='thirdparty'";
 		dol_syslog(__METHOD__.": mailing update status to display thirdparty mail that do not want to be contacted");
 		dol_syslog(__METHOD__.": mailing update status to display thirdparty mail that do not want to be contacted");
 		$result=$this->db->query($sql);
 		$result=$this->db->query($sql);
@@ -216,7 +216,7 @@ 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'
 		//Update the status to show contact mail that don't want to be contacted anymore'
 		$sql = "UPDATE ".MAIN_DB_PREFIX."mailing_cibles";
 		$sql = "UPDATE ".MAIN_DB_PREFIX."mailing_cibles";
 		$sql .= " SET statut=3";
 		$sql .= " SET statut=3";
-		$sql .= " WHERE fk_mailing=".$mailing_id." AND source_type='contact' AND (email in (SELECT sc.email FROM ".MAIN_DB_PREFIX."socpeople AS sc ";
+		$sql .= " WHERE fk_mailing=".((int) $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.rowid=sc.fk_soc WHERE s.fk_stcomm=-1 OR no_email=1))";
 		$sql .= " INNER JOIN ".MAIN_DB_PREFIX."societe s ON s.rowid=sc.fk_soc WHERE s.fk_stcomm=-1 OR no_email=1))";
 		dol_syslog(__METHOD__.": mailing update status to display contact mail that do not want to be contacted",LOG_DEBUG);
 		dol_syslog(__METHOD__.": mailing update status to display contact mail that do not want to be contacted",LOG_DEBUG);
 		$result=$this->db->query($sql);
 		$result=$this->db->query($sql);
@@ -224,7 +224,7 @@ class MailingTargets // This can't be abstract as it is used for some method
 
 
 		$sql = "UPDATE ".MAIN_DB_PREFIX."mailing_cibles";
 		$sql = "UPDATE ".MAIN_DB_PREFIX."mailing_cibles";
 		$sql .= " SET statut=3";
 		$sql .= " SET statut=3";
-		$sql .= " WHERE fk_mailing=".$mailing_id." AND email IN (SELECT mu.email FROM ".MAIN_DB_PREFIX."mailing_unsubscribe AS mu WHERE mu.entity IN ('".getEntity('mailing')."'))";
+		$sql .= " WHERE fk_mailing=".((int) $mailing_id)." AND email IN (SELECT mu.email FROM ".MAIN_DB_PREFIX."mailing_unsubscribe AS mu WHERE mu.entity IN ('".getEntity('mailing')."'))";
 
 
 		dol_syslog(__METHOD__.":mailing update status to display emails that do not want to be contacted anymore", LOG_DEBUG);
 		dol_syslog(__METHOD__.":mailing update status to display emails that do not want to be contacted anymore", LOG_DEBUG);
 		$result = $this->db->query($sql);
 		$result = $this->db->query($sql);

+ 4 - 0
htdocs/includes/tecnickcom/tcpdf/include/tcpdf_static.php

@@ -1440,6 +1440,10 @@ class TCPDF_STATIC {
 	 */
 	 */
 	public static function intToRoman($number) {
 	public static function intToRoman($number) {
 		$roman = '';
 		$roman = '';
+		if ($number >= 4000) {
+			// do not represent numbers above 4000 in Roman numerals
+			return strval($number);
+		}
 		while ($number >= 1000) {
 		while ($number >= 1000) {
 			$roman .= 'M';
 			$roman .= 'M';
 			$number -= 1000;
 			$number -= 1000;

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

@@ -60,6 +60,7 @@ EMailTestSubstitutionReplacedByGenericValues=When using test mode, substitutions
 MailingAddFile=Attach this file
 MailingAddFile=Attach this file
 NoAttachedFiles=No attached files
 NoAttachedFiles=No attached files
 BadEMail=Bad value for Email
 BadEMail=Bad value for Email
+EMailNotDefined=Email not defined
 ConfirmCloneEMailing=Are you sure you want to clone this emailing?
 ConfirmCloneEMailing=Are you sure you want to clone this emailing?
 CloneContent=Clone message
 CloneContent=Clone message
 CloneReceivers=Cloner recipients
 CloneReceivers=Cloner recipients

+ 3 - 2
htdocs/product/card.php

@@ -1836,11 +1836,12 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) {
 				print '<tr><td>'.$langs->trans("CountryOrigin").'</td>';
 				print '<tr><td>'.$langs->trans("CountryOrigin").'</td>';
 				print '<td>';
 				print '<td>';
 				print img_picto('', 'globe-americas', 'class="paddingrightonly"');
 				print img_picto('', 'globe-americas', 'class="paddingrightonly"');
-				print $form->select_country($object->country_id, 'country_id', '', 0, 'minwidth100 maxwidthonsmartphone');
+				print $form->select_country(GETPOSTISSET('country_id') ? GETPOST('country_id', 'int') : $object->country_id, 'country_id', '', 0, 'minwidth100 maxwidthonsmartphone');
 				if ($user->admin) {
 				if ($user->admin) {
 					print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
 					print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
 				}
 				}
 				print '</td></tr>';
 				print '</td></tr>';
+
 				// State
 				// State
 				if (empty($conf->global->PRODUCT_DISABLE_STATE)) {
 				if (empty($conf->global->PRODUCT_DISABLE_STATE)) {
 					print '<tr>';
 					print '<tr>';
@@ -1851,7 +1852,7 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) {
 					}
 					}
 
 
 					print img_picto('', 'state', 'class="pictofixedwidth"');
 					print img_picto('', 'state', 'class="pictofixedwidth"');
-					print $formcompany->select_state($object->state_id, $object->country_code);
+					print $formcompany->select_state(GETPOSTISSET('state_id') ? GETPOST('state_id', 'int') : $object->state_id, $object->country_code);
 					print '</td>';
 					print '</td>';
 					print '</tr>';
 					print '</tr>';
 				}
 				}