Browse Source

Debug Advance target emailing

Florian HENRY 9 years ago
parent
commit
ae51321040

+ 128 - 133
htdocs/comm/mailing/advtargetemailing.php

@@ -15,23 +15,18 @@
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
-$res = @include ("../../main.inc.php"); // For root directory
-if (! $res)
-	$res = @include ("../../../main.inc.php"); // For "custom" directory
-if (! $res)
-	die("Include of main fails");
+require '../../main.inc.php';
 
 require_once DOL_DOCUMENT_ROOT . '/comm/mailing/class/mailing.class.php';
 require_once DOL_DOCUMENT_ROOT . '/core/lib/emailing.lib.php';
-dol_include_once('/advtargetemailing/class/advtargetemailing.class.php');
-dol_include_once('/advtargetemailing/class/html.formadvtargetemailing.class.php');
-dol_include_once('/advtargetemailing/core/modules/mailings/advthirdparties.modules.php');
+require_once DOL_DOCUMENT_ROOT . '/comm/mailing/class/advtargetemailing.class.php';
+require_once DOL_DOCUMENT_ROOT . '/comm/mailing/class/html.formadvtargetemailing.class.php';
+require_once DOL_DOCUMENT_ROOT . '/core/modules/mailings/advthirdparties.modules.php';
 require_once DOL_DOCUMENT_ROOT . '/core/class/html.formcompany.class.php';
 require_once DOL_DOCUMENT_ROOT . '/core/class/html.formother.class.php';
 
 // Translations
 $langs->load("mails");
-$langs->load("advtargetemailing@advtargetemailing");
 $langs->load("companies");
 if (! empty($conf->categorie->enabled)) {
 	$langs->load("categories");
@@ -107,13 +102,13 @@ if ($action == 'loadfilter') {
 }
 
 if ($action == 'add') {
-	
+
 	$user_contact_query = false;
-	
+
 	$array_query = array ();
-	
+
 	// Get extra fields
-	
+
 	foreach ( $_POST as $key => $value ) {
 		// print '$key='.$key.' $value='.$value.'<BR>';
 		if (preg_match("/^options_.*(?<!_cnct)$/", $key)) {
@@ -155,20 +150,20 @@ if ($action == 'add') {
 				$array_query[$key] = GETPOST($key);
 			}
 		}
-		
+
 		if (preg_match("/^cust_/", $key)) {
 			$array_query[$key] = GETPOST($key);
 		}
-		
+
 		if (preg_match("/^contact_/", $key)) {
-			
+
 			$array_query[$key] = GETPOST($key);
-			
+
 			$specials_date_key = array (
 					'contact_update_st_dt',
 					'contact_update_end_dt',
 					'contact_create_st_dt',
-					'contact_create_end_dt' 
+					'contact_create_end_dt'
 			);
 			foreach ( $specials_date_key as $date_key ) {
 				if ($key == $date_key) {
@@ -180,17 +175,17 @@ if ($action == 'add') {
 					}
 				}
 			}
-			
+
 			if (! empty($array_query[$key])) {
 				$user_contact_query = true;
 			}
 		}
-		
+
 		if (preg_match("/^type_of_target/", $key)) {
 			$array_query[$key] = GETPOST($key);
 		}
 	}
-	
+
 	// if ($array_query ['type_of_target'] == 1 || $array_query ['type_of_target'] == 3) {
 	$result = $advTarget->query_thirdparty($array_query);
 	if ($result < 0) {
@@ -199,7 +194,7 @@ if ($action == 'add') {
 	/*} else {
 		$advTarget->thirdparty_lines = array ();
 	}*/
-	
+
 	if ($user_contact_query && ($array_query['type_of_target'] == 1 || $array_query['type_of_target'] == 2)) {
 		$result = $advTarget->query_contact($array_query);
 		if ($result < 0) {
@@ -208,13 +203,13 @@ if ($action == 'add') {
 		// If use contact but no result use artefact to so not use socid into add_to_target
 		if (count($advTarget->contact_lines) == 0) {
 			$advTarget->contact_lines = array (
-					0 
+					0
 			);
 		}
 	} else {
 		$advTarget->contact_lines = array ();
 	}
-	
+
 	if ((count($advTarget->thirdparty_lines) > 0) || (count($advTarget->contact_lines) > 0)) {
 		// Add targets into database
 		$obj = new mailing_advthirdparties($db);
@@ -222,7 +217,7 @@ if ($action == 'add') {
 	} else {
 		$result = 0;
 	}
-	
+
 	if ($result > 0) {
 		$query_temlate_id = '';
 		if (! empty($template_id)) {
@@ -244,25 +239,25 @@ if ($action == 'clear') {
 	$classname = "MailingTargets";
 	$obj = new $classname($db);
 	$obj->clear_target($id);
-	
+
 	header("Location: " . $_SERVER['PHP_SELF'] . "?id=" . $id);
 	exit();
 }
 
 if ($action == 'savefilter' || $action == 'createfilter') {
-	
+
 	$template_name = GETPOST('template_name');
 	$error = 0;
-	
+
 	if ($action == 'createfilter' && empty($template_name)) {
 		setEventMessage($langs->trans('ErrorFieldRequired', $langs->trans('AdvTgtOrCreateNewFilter')), 'errors');
 		$error ++;
 	}
-	
+
 	if (empty($error)) {
-		
+
 		$array_query = array ();
-		
+
 		// Get extra fields
 		foreach ( $_POST as $key => $value ) {
 			if (preg_match("/^options_.*(?<!_cnct)$/", $key)) {
@@ -307,20 +302,20 @@ if ($action == 'savefilter' || $action == 'createfilter') {
 					$array_query[$key] = GETPOST($key);
 				}
 			}
-			
+
 			if (preg_match("/^cust_/", $key)) {
 				$array_query[$key] = GETPOST($key);
 			}
-			
+
 			if (preg_match("/^contact_/", $key)) {
-				
+
 				$array_query[$key] = GETPOST($key);
-				
+
 				$specials_date_key = array (
 						'contact_update_st_dt',
 						'contact_update_end_dt',
 						'contact_create_st_dt',
-						'contact_create_end_dt' 
+						'contact_create_end_dt'
 				);
 				foreach ( $specials_date_key as $date_key ) {
 					if ($key == $date_key) {
@@ -333,13 +328,13 @@ if ($action == 'savefilter' || $action == 'createfilter') {
 					}
 				}
 			}
-			
+
 			if (preg_match("/^type_of_target/", $key)) {
 				$array_query[$key] = GETPOST($key);
 			}
 		}
 		$advTarget->filtervalue = json_encode($array_query);
-		
+
 		if ($action == 'createfilter') {
 			$advTarget->name = $template_name;
 			$result = $advTarget->create($user);
@@ -374,7 +369,7 @@ if ($action == 'delete') {
 			$classname = "MailingTargets";
 			$obj = new $classname($db);
 			$obj->update_nb($id);
-			
+
 			header("Location: " . $_SERVER['PHP_SELF'] . "?id=" . $id);
 			exit();
 		} else {
@@ -396,39 +391,39 @@ if ($_POST["button_removefilter"]) {
  * View
  */
 $extrajs = array (
-		'/advtargetemailing/includes/multiselect/js/ui.multiselect.js' 
+		'/includes/multiselect/js/ui.multiselect.js'
 );
 $extracss = array (
-		'/advtargetemailing/includes/multiselect/css/ui.multiselect.css',
-		'/advtargetemailing/css/advtargetemailing.css' 
+		'/includes/multiselect/css/ui.multiselect.css',
+		'/advtargetemailing/css/advtargetemailing.css'
 );
 
-llxHeader('', $langs->trans("AdvTgtTabsTarget"), '', '', '', '', $extrajs, $extracss);
+llxHeader('', $langs->trans("MailAdvTargetRecipients"), '', '', '', '', $extrajs, $extracss);
 
 print '<script type="text/javascript" language="javascript">
 	$(document).ready(function() {
-							
+
 		// Click Function
 		$(":button[name=addcontact]").click(function() {
 				$(":hidden[name=action]").val("add");
 				$("#find_customer").submit();
 		});
-					
+
 		$(":button[name=loadfilter]").click(function() {
 				$(":hidden[name=action]").val("loadfilter");
 				$("#find_customer").submit();
 		});
-	
+
 		$(":button[name=deletefilter]").click(function() {
 				$(":hidden[name=action]").val("deletefilter");
 				$("#find_customer").submit();
 		});
-		
+
 		$(":button[name=savefilter]").click(function() {
 				$(":hidden[name=action]").val("savefilter");
 				$("#find_customer").submit();
 		});
-		
+
 		$(":button[name=createfilter]").click(function() {
 				$(":hidden[name=action]").val("createfilter");
 				$("#find_customer").submit();
@@ -442,31 +437,31 @@ $formcompany = new FormCompany($db);
 $formother = new FormOther($db);
 
 if ($object->fetch($id) >= 0) {
-	
+
 	$head = emailing_prepare_head($object);
-	
-	dol_fiche_head($head, 'tabAdvTgtTabsTarget', $langs->trans("Mailing"), 0, 'email');
-	
+
+	dol_fiche_head($head, 'advtargets', $langs->trans("Mailing"), 0, 'email');
+
 	print '<table class="border" width="100%">';
-	
+
 	$linkback = '<a href="' . DOL_URL_ROOT . '/comm/mailing/liste.php">' . $langs->trans("BackToList") . '</a>';
-	
+
 	print '<tr><td width="25%">' . $langs->trans("Ref") . '</td>';
 	print '<td colspan="3">';
 	print $form->showrefnav($object, 'id', $linkback);
 	print '</td></tr>';
-	
+
 	print '<tr><td width="25%">' . $langs->trans("MailTitle") . '</td><td colspan="3">' . $object->titre . '</td></tr>';
-	
+
 	print '<tr><td width="25%">' . $langs->trans("MailFrom") . '</td><td colspan="3">' . dol_print_email($object->email_from, 0, 0, 0, 0, 1) . '</td></tr>';
-	
+
 	// Errors to
 	print '<tr><td width="25%">' . $langs->trans("MailErrorsTo") . '</td><td colspan="3">' . dol_print_email($object->email_errorsto, 0, 0, 0, 0, 1);
 	print '</td></tr>';
-	
+
 	// Status
 	print '<tr><td width="25%">' . $langs->trans("Status") . '</td><td colspan="3">' . $object->getLibStatut(4) . '</td></tr>';
-	
+
 	// Nb of distinct emails
 	print '<tr><td width="25%">';
 	print $langs->trans("TotalNbOfDistinctRecipients");
@@ -479,29 +474,29 @@ if ($object->fetch($id) >= 0) {
 		print $nbemail;
 	}
 	print '</td></tr>';
-	
+
 	print '</table>';
-	
+
 	print "</div>";
-	
+
 	// Show email selectors
 	if ($object->statut == 0 && $user->rights->mailing->creer) {
 		print_fiche_titre($langs->trans("AdvTgtTitle"));
-		
+
 		print '<div class="tabBar">' . "\n";
 		print '<form name="find_customer" id="find_customer" action="' . $_SERVER['PHP_SELF'] . '?id=' . $id . '"  method="POST">' . "\n";
 		print '<input type="hidden" name="token" value="' . $_SESSION['newtoken'] . '">' . "\n";
 		print '<input type="hidden" name="action" value="">' . "\n";
 		print '<table class="border" width="100%">' . "\n";
-		
+
 		print '<tr>' . "\n";
 		print '<td colspan="3" align="right">' . "\n";
-		
+
 		print '<input type="button" name="addcontact" id="addcontact" value="' . $langs->trans('AdvTgtAddContact') . '" class="butAction"/>' . "\n";
-		
+
 		print '</td>' . "\n";
 		print '</tr>' . "\n";
-		
+
 		print '<tr><td>' . $langs->trans('AdvTgtNameTemplate') . '</td><td>';
 		if (! empty($template_id)) {
 			$default_template = $template_id;
@@ -517,13 +512,13 @@ if ($object->fetch($id) >= 0) {
 		print '<input type="button" name="createfilter" id="createfilter" value="' . $langs->trans('AdvTgtCreateFilter') . '" class="butAction"/>';
 		print '</td><td>' . "\n";
 		print '</td></tr>' . "\n";
-		
+
 		print '<tr><td>' . $langs->trans('AdvTgtTypeOfIncude') . '</td><td>';
 		print $form->selectarray('type_of_target', $advTarget->select_target_type, $array_query['type_of_target']);
 		print '</td><td>' . "\n";
 		print $form->textwithpicto('', $langs->trans("AdvTgtTypeOfIncudeHelp"), 1, 'help');
 		print '</td></tr>' . "\n";
-		
+
 		// Customer name
 		print '<tr><td>' . $langs->trans('ThirdPartyName');
 		if (! empty($array_query['cust_name'])) {
@@ -532,7 +527,7 @@ if ($object->fetch($id) >= 0) {
 		print '</td><td><input type="text" name="cust_name" value="' . $array_query['cust_name'] . '"/></td><td>' . "\n";
 		print $form->textwithpicto('', $langs->trans("AdvTgtSearchTextHelp"), 1, 'help');
 		print '</td></tr>' . "\n";
-		
+
 		// Code Client
 		print '<tr><td>' . $langs->trans('CustomerCode');
 		if (! empty($array_query['cust_code'])) {
@@ -541,7 +536,7 @@ if ($object->fetch($id) >= 0) {
 		print '</td><td><input type="text" name="cust_code" value="' . $array_query['cust_code'] . '"/></td><td>' . "\n";
 		print $form->textwithpicto('', $langs->trans("AdvTgtSearchTextHelp"), 1, 'help');
 		print '</td></tr>' . "\n";
-		
+
 		// Address Client
 		print '<tr><td>' . $langs->trans('Address');
 		if (! empty($array_query['cust_adress'])) {
@@ -550,7 +545,7 @@ if ($object->fetch($id) >= 0) {
 		print '</td><td><input type="text" name="cust_adress" value="' . $array_query['cust_adress'] . '"/></td><td>' . "\n";
 		print $form->textwithpicto('', $langs->trans("AdvTgtSearchTextHelp"), 1, 'help');
 		print '</td></tr>' . "\n";
-		
+
 		// Zip Client
 		print '<tr><td>' . $langs->trans('Zip');
 		if (! empty($array_query['cust_zip'])) {
@@ -559,7 +554,7 @@ if ($object->fetch($id) >= 0) {
 		print '</td><td><input type="text" name="cust_zip" value="' . $array_query['cust_zip'] . '"/></td><td>' . "\n";
 		print $form->textwithpicto('', $langs->trans("AdvTgtSearchTextHelp"), 1, 'help');
 		print '</td></tr>' . "\n";
-		
+
 		// City Client
 		print '<tr><td>' . $langs->trans('Town');
 		if (! empty($array_query['cust_city'])) {
@@ -568,7 +563,7 @@ if ($object->fetch($id) >= 0) {
 		print '</td><td><input type="text" name="cust_city" value="' . $array_query['cust_city'] . '"/></td><td>' . "\n";
 		print $form->textwithpicto('', $langs->trans("AdvTgtSearchTextHelp"), 1, 'help');
 		print '</td></tr>' . "\n";
-		
+
 		// Customer Country
 		print '<tr><td>' . $langs->trans("Country");
 		if (count($array_query['cust_country']) > 0) {
@@ -578,7 +573,7 @@ if ($object->fetch($id) >= 0) {
 		print $formadvtargetemaling->multiselect_country('cust_country', $array_query['cust_country']);
 		print '</td><td>' . "\n";
 		print '</td></tr>' . "\n";
-		
+
 		// State Customer
 		print '<tr><td>' . $langs->trans('Status') . ' ' . $langs->trans('ThirdParty');
 		if (count($array_query['cust_status']) > 0) {
@@ -587,11 +582,11 @@ if ($object->fetch($id) >= 0) {
 		print '</td><td>';
 		print $formadvtargetemaling->advMultiselectarray('cust_status', array (
 				'0' => $langs->trans('ActivityCeased'),
-				'1' => $langs->trans('InActivity') 
+				'1' => $langs->trans('InActivity')
 		), $array_query['cust_status']);
 		print '</td><td>' . "\n";
 		print '</td></tr>' . "\n";
-		
+
 		// Mother Company
 		print '<tr><td>' . $langs->trans("Maison mère");
 		if (! empty($array_query['cust_mothercompany'])) {
@@ -602,7 +597,7 @@ if ($object->fetch($id) >= 0) {
 		print '</td><td>' . "\n";
 		print $form->textwithpicto('', $langs->trans("AdvTgtSearchTextHelp"), 1, 'help');
 		print '</td></tr>' . "\n";
-		
+
 		// Prospect/Customer
 		$selected = $array_query['cust_typecust'];
 		print '<tr><td>' . $langs->trans('ProspectCustomer') . ' ' . $langs->trans('ThirdParty');
@@ -614,12 +609,12 @@ if ($object->fetch($id) >= 0) {
 				2 => $langs->trans('Prospect'),
 				3 => $langs->trans('ProspectCustomer'),
 				1 => $langs->trans('Customer'),
-				0 => $langs->trans('NorProspectNorCustomer') 
+				0 => $langs->trans('NorProspectNorCustomer')
 		);
 		print $formadvtargetemaling->advMultiselectarray('cust_typecust', $options_array, $array_query['cust_typecust']);
 		print '</td><td>' . "\n";
 		print '</td></tr>' . "\n";
-		
+
 		// Prospection status
 		print '<tr><td>' . $langs->trans('ProspectLevel');
 		if (count($array_query['cust_prospect_status']) > 0) {
@@ -629,7 +624,7 @@ if ($object->fetch($id) >= 0) {
 		print $formadvtargetemaling->multiselect_prospection_status($array_query['cust_prospect_status'], 'cust_prospect_status', 1);
 		print '</td><td>' . "\n";
 		print '</td></tr>' . "\n";
-		
+
 		// Prospection comm status
 		print '<tr><td>' . $langs->trans('StatusProsp');
 		if (count($array_query['cust_comm_status']) > 0) {
@@ -639,7 +634,7 @@ if ($object->fetch($id) >= 0) {
 		print $formadvtargetemaling->advMultiselectarray('cust_comm_status', $advTarget->type_statuscommprospect, $array_query['cust_comm_status']);
 		print '</td><td>' . "\n";
 		print '</td></tr>' . "\n";
-		
+
 		// Customer Type
 		print '<tr><td>' . $langs->trans("ThirdPartyType");
 		if (count($array_query['cust_typeent']) > 0) {
@@ -649,7 +644,7 @@ if ($object->fetch($id) >= 0) {
 		print $formadvtargetemaling->advMultiselectarray('cust_typeent', $formcompany->typent_array(0, " AND id <> 0"), $array_query['cust_typeent']);
 		print '</td><td>' . "\n";
 		print '</td></tr>' . "\n";
-		
+
 		// Staff number
 		print '<td>' . $langs->trans("Staff");
 		if (count($array_query['cust_effectif_id']) > 0) {
@@ -659,7 +654,7 @@ if ($object->fetch($id) >= 0) {
 		print $formadvtargetemaling->advMultiselectarray("cust_effectif_id", $formcompany->effectif_array(0, " AND id <> 0"), $array_query['cust_effectif_id']);
 		print '</td><td>' . "\n";
 		print '</td></tr>' . "\n";
-		
+
 		// Sales manager
 		print '<tr><td>' . $langs->trans("SalesRepresentatives");
 		if (count($array_query['cust_saleman']) > 0) {
@@ -669,10 +664,10 @@ if ($object->fetch($id) >= 0) {
 		print $formadvtargetemaling->multiselectselect_salesrepresentatives('cust_saleman', $array_query['cust_saleman'], $user);
 		print '</td><td>' . "\n";
 		print '</td></tr>' . "\n";
-		
+
 		// Customer Default Langauge
 		if (! empty($conf->global->MAIN_MULTILANGS)) {
-			
+
 			print '<tr><td>' . $langs->trans("DefaultLang");
 			if (count($array_query['cust_language']) > 0) {
 				print img_picto($langs->trans('AdvTgtUse'), 'ok.png@advtargetemailing');
@@ -682,7 +677,7 @@ if ($object->fetch($id) >= 0) {
 			print '</td><td>' . "\n";
 			print '</td></tr>' . "\n";
 		}
-		
+
 		if (! empty($conf->categorie->enabled) && $user->rights->categorie->lire) {
 			// Customer Categories
 			print '<tr><td>' . $langs->trans("CustomersCategoryShort");
@@ -694,7 +689,7 @@ if ($object->fetch($id) >= 0) {
 			print '</td><td>' . "\n";
 			print '</td></tr>' . "\n";
 		}
-		
+
 		// Standard Extrafield feature
 		if (empty($conf->global->MAIN_EXTRAFIELDS_DISABLED)) {
 			// fetch optionals attributes and labels
@@ -717,21 +712,21 @@ if ($object->fetch($id) >= 0) {
 						print '</td><td>' . "\n";
 						print $form->textwithpicto('', $langs->trans("AdvTgtSearchIntHelp"), 1, 'help');
 					} elseif (($extrafields->attribute_type[$key] == 'date') || ($extrafields->attribute_type[$key] == 'datetime')) {
-						
+
 						print '<table class="nobordernopadding"><tr>';
 						print '<td>' . $langs->trans("AdvTgtStartDt") . '</td><td>';
 						print $form->select_date('', 'options_' . $key . '_st_dt');
 						print '</td><td>' . $langs->trans("AdvTgtEndDt") . '</td><td>';
 						print $form->select_date('', 'options_' . $key . '_end_dt');
 						print '</td></tr></table>';
-						
+
 						print '</td><td>' . "\n";
 						print $form->textwithpicto('', $langs->trans("AdvTgtSearchDtHelp"), 1, 'help');
 					} elseif (($extrafields->attribute_type[$key] == 'boolean')) {
 						print $form->selectarray('options_' . $key, array (
 								'' => '',
 								'1' => $langs->trans('Yes'),
-								'0' => $langs->trans('No') 
+								'0' => $langs->trans('No')
 						), $array_query['options_' . $key]);
 						print '</td><td>' . "\n";
 					} elseif (($extrafields->attribute_type[$key] == 'select')) {
@@ -741,7 +736,7 @@ if ($object->fetch($id) >= 0) {
 						print $formadvtargetemaling->advMultiselectarray_selllist('options_' . $key, $extrafields->attribute_param[$key]['options'], $array_query['options_' . $key]);
 						print '</td><td>' . "\n";
 					} else {
-						
+
 						print '<table class="nobordernopadding"><tr>';
 						print '<td></td><td>';
 						if (is_array($array_query['options_' . $key])) {
@@ -750,7 +745,7 @@ if ($object->fetch($id) >= 0) {
 							print $extrafields->showInputField($key, $array_query['options_' . $key]);
 						}
 						print '</td></tr></table>';
-						
+
 						print '</td><td>' . "\n";
 					}
 					print '</td></tr>' . "\n";
@@ -763,17 +758,17 @@ if ($object->fetch($id) >= 0) {
 			include_once DOL_DOCUMENT_ROOT . '/core/class/hookmanager.class.php';
 			$hookmanager = new HookManager($db);
 			$hookmanager->initHooks(array (
-					'thirdpartycard' 
+					'thirdpartycard'
 			));
 			if (! empty($advTarget->id)) {
 				$parameters = array (
-						'array_query' => $advTarget->filtervalue 
+						'array_query' => $advTarget->filtervalue
 				);
 			}
 			// Module extrafield feature
 			$reshook = $hookmanager->executeHooks('formObjectOptions', $parameters, $std_soc, $action_search);
 		}
-		
+
 		// State Contact
 		print '<tr><td>' . $langs->trans('Status') . ' ' . $langs->trans('Contact');
 		if (count($array_query['contact_status']) > 0) {
@@ -782,12 +777,12 @@ if ($object->fetch($id) >= 0) {
 		print '</td><td>';
 		print $formadvtargetemaling->advMultiselectarray('contact_status', array (
 				'0' => $langs->trans('ActivityCeased'),
-				'1' => $langs->trans('InActivity') 
+				'1' => $langs->trans('InActivity')
 		), $array_query['contact_status']);
 		print '</td><td>' . "\n";
 		print $form->textwithpicto('', $langs->trans("AdvTgtContactHelp"), 1, 'help');
 		print '</td></tr>' . "\n";
-		
+
 		// Civility
 		print '<tr><td width="15%">' . $langs->trans("UserTitle");
 		if (count($array_query['contact_civility']) > 0) {
@@ -796,7 +791,7 @@ if ($object->fetch($id) >= 0) {
 		print '</td><td>';
 		print $formadvtargetemaling->multiselect_civility('contact_civility', $array_query['contact_civility']);
 		print '</td></tr>';
-		
+
 		// contact name
 		print '<tr><td>' . $langs->trans('Contact') . ' ' . $langs->trans('Lastname');
 		if (! empty($array_query['contact_lastname'])) {
@@ -812,7 +807,7 @@ if ($object->fetch($id) >= 0) {
 		print '</td><td><input type="text" name="contact_firstname" value="' . $array_query['contact_firstname'] . '"/></td><td>' . "\n";
 		print $form->textwithpicto('', $langs->trans("AdvTgtSearchTextHelp"), 1, 'help');
 		print '</td></tr>' . "\n";
-		
+
 		// Contact Country
 		print '<tr><td>' . $langs->trans('Contact') . ' ' . $langs->trans("Country");
 		if (count($array_query['contact_country']) > 0) {
@@ -822,7 +817,7 @@ if ($object->fetch($id) >= 0) {
 		print $formadvtargetemaling->multiselect_country('contact_country', $array_query['contact_country']);
 		print '</td><td>' . "\n";
 		print '</td></tr>' . "\n";
-		
+
 		// Never send mass mailing
 		print '<tr><td>' . $langs->trans('Contact') . ' ' . $langs->trans("No_Email");
 		if (! empty($array_query['contact_no_email'])) {
@@ -832,11 +827,11 @@ if ($object->fetch($id) >= 0) {
 		print $form->selectarray('contact_no_email', array (
 				'' => '',
 				'1' => $langs->trans('Yes'),
-				'0' => $langs->trans('No') 
+				'0' => $langs->trans('No')
 		), $array_query['contact_no_email']);
 		print '</td><td>' . "\n";
 		print '</td></tr>' . "\n";
-		
+
 		// Contact Date Create
 		print '<tr><td>' . $langs->trans('Contact') . ' ' . $langs->trans("DateCreation");
 		if (! empty($array_query['contact_create_st_dt'])) {
@@ -851,7 +846,7 @@ if ($object->fetch($id) >= 0) {
 		print '</td></tr></table>';
 		print '</td><td>' . "\n";
 		print '</td></tr>' . "\n";
-		
+
 		// Contact update Create
 		print '<tr><td>' . $langs->trans('Contact') . ' ' . $langs->trans("DateLastModification");
 		if (! empty($array_query['contact_update_st_dt'])) {
@@ -866,7 +861,7 @@ if ($object->fetch($id) >= 0) {
 		print '</td></tr></table>';
 		print '</td><td>' . "\n";
 		print '</td></tr>' . "\n";
-		
+
 		if (! empty($conf->categorie->enabled) && $user->rights->categorie->lire) {
 			// Customer Categories
 			print '<tr><td>' . $langs->trans("ContactCategoriesShort");
@@ -878,7 +873,7 @@ if ($object->fetch($id) >= 0) {
 			print '</td><td>' . "\n";
 			print '</td></tr>' . "\n";
 		}
-		
+
 		// Standard Extrafield feature
 		if (empty($conf->global->MAIN_EXTRAFIELDS_DISABLED)) {
 			// fetch optionals attributes and labels
@@ -886,7 +881,7 @@ if ($object->fetch($id) >= 0) {
 			$extrafields = new ExtraFields($db);
 			$extralabels = $extrafields->fetch_name_optionals_label('socpeople');
 			foreach ( $extralabels as $key => $val ) {
-				
+
 				print '<tr><td>' . $extrafields->attribute_label[$key];
 				if ($array_query['options_' . $key . '_cnct'] != '' || (is_array($array_query['options_' . $key . '_cnct']) && count($array_query['options_' . $key . '_cnct']) > 0)) {
 					print img_picto($langs->trans('AdvTgtUse'), 'ok.png@advtargetemailing');
@@ -901,21 +896,21 @@ if ($object->fetch($id) >= 0) {
 					print '</td><td>' . "\n";
 					print $form->textwithpicto('', $langs->trans("AdvTgtSearchIntHelp"), 1, 'help');
 				} elseif (($extrafields->attribute_type[$key] == 'date') || ($extrafields->attribute_type[$key] == 'datetime')) {
-					
+
 					print '<table class="nobordernopadding"><tr>';
 					print '<td>' . $langs->trans("AdvTgtStartDt") . '</td><td>';
 					print $form->select_date('', 'options_' . $key . '_st_dt' . '_cnct');
 					print '</td><td>' . $langs->trans("AdvTgtEndDt") . '</td><td>';
 					print $form->select_date('', 'options_' . $key . '_end_dt' . '_cnct');
 					print '</td></tr></table>';
-					
+
 					print '</td><td>' . "\n";
 					print $form->textwithpicto('', $langs->trans("AdvTgtSearchDtHelp"), 1, 'help');
 				} elseif (($extrafields->attribute_type[$key] == 'boolean')) {
 					print $form->selectarray('options_' . $key . '_cnct', array (
 							'' => '',
 							'1' => $langs->trans('Yes'),
-							'0' => $langs->trans('No') 
+							'0' => $langs->trans('No')
 					), $array_query['options_' . $key . '_cnct']);
 					print '</td><td>' . "\n";
 				} elseif (($extrafields->attribute_type[$key] == 'select')) {
@@ -925,7 +920,7 @@ if ($object->fetch($id) >= 0) {
 					print $formadvtargetemaling->advMultiselectarray_selllist('options_' . $key . '_cnct', $extrafields->attribute_param[$key]['options'], $array_query['options_' . $key . '_cnct']);
 					print '</td><td>' . "\n";
 				} else {
-					
+
 					print '<table class="nobordernopadding"><tr>';
 					print '<td></td><td>';
 					if (is_array($array_query['options_' . $key . '_cnct'])) {
@@ -934,24 +929,24 @@ if ($object->fetch($id) >= 0) {
 						print $extrafields->showInputField($key, $array_query['options_' . $key . '_cnct'], '', '_cnct');
 					}
 					print '</td></tr></table>';
-					
+
 					print '</td><td>' . "\n";
 				}
 				print '</td></tr>' . "\n";
 			}
 		}
-		
+
 		print '<tr>' . "\n";
 		print '<td colspan="3" align="right">' . "\n";
-		
+
 		print '<input type="button" name="addcontact" id="addcontact" value="' . $langs->trans('AdvTgtAddContact') . '" class="butAction"/>' . "\n";
-		
+
 		print '</td>' . "\n";
 		print '</tr>' . "\n";
 		print '</table>' . "\n";
 		print '</form>' . "\n";
 		print '</div>' . "\n";
-		
+
 		print '<form action="' . $_SERVER['PHP_SELF'] . '?action=clear&id=' . $object->id . '" method="POST">';
 		print '<input type="hidden" name="token" value="' . $_SESSION['newtoken'] . '">';
 		print_titre($langs->trans("ToClearAllRecipientsClickHere"));
@@ -971,7 +966,7 @@ if ($object->fetch($id) >= 0) {
 		print '<input type="hidden" name="sortfield" value="' . $sortfield . '">';
 		print '<input type="hidden" name="sortorder" value="' . $sortorder . '">';
 		print '<input type="hidden" name="id" value="' . $object->id . '">';
-		
+
 		$sql = "SELECT mc.rowid, mc.lastname, mc.firstname, mc.email, mc.other, mc.statut, mc.date_envoi, mc.source_url, mc.source_id, mc.source_type";
 		$sql .= " FROM " . MAIN_DB_PREFIX . "mailing_cibles as mc";
 		$sql .= " WHERE mc.fk_mailing=" . $object->id;
@@ -983,12 +978,12 @@ if ($object->fetch($id) >= 0) {
 			$sql .= " AND mc.email  LIKE '%" . $db->escape($search_email) . "%'";
 		$sql .= $db->order($sortfield, $sortorder);
 		$sql .= $db->plimit($conf->liste_limit + 1, $offset);
-		
+
 		dol_syslog('advtargetemailing.php:: sql=' . $sql);
 		$resql = $db->query($sql);
 		if ($resql) {
 			$num = $db->num_rows($resql);
-			
+
 			$parm = "&amp;id=" . $object->id;
 			if ($search_nom)
 				$parm .= "&amp;search_nom=" . urlencode($search_nom);
@@ -996,9 +991,9 @@ if ($object->fetch($id) >= 0) {
 				$parm .= "&amp;search_prenom=" . urlencode($search_prenom);
 			if ($search_email)
 				$parm .= "&amp;search_email=" . urlencode($search_email);
-			
+
 			print_barre_liste($langs->trans("MailSelectedRecipients"), $page, $_SERVER["PHP_SELF"], $parm, $sortfield, $sortorder, "", $num, $object->nbemail, '');
-			
+
 			if ($page)
 				$parm .= "&amp;page=" . $page;
 			print '<table class="noborder" width="100%">';
@@ -1008,19 +1003,19 @@ if ($object->fetch($id) >= 0) {
 			print_liste_field_titre($langs->trans("Firstname"), $_SERVER["PHP_SELF"], "mc.firstname", $parm, "", "", $sortfield, $sortorder);
 			print_liste_field_titre($langs->trans("OtherInformations"), $_SERVER["PHP_SELF"], "", $parm, "", "", $sortfield, $sortorder);
 			print_liste_field_titre($langs->trans("Source"), $_SERVER["PHP_SELF"], "", $parm, "", 'align="center"', $sortfield, $sortorder);
-			
+
 			// Date sendinf
 			if ($object->statut < 2) {
 				print '<td class="liste_titre">&nbsp;</td>';
 			} else {
 				print_liste_field_titre($langs->trans("DateSending"), $_SERVER["PHP_SELF"], "mc.date_envoi", $parm, '', 'align="center"', $sortfield, $sortorder);
 			}
-			
+
 			// Statut
 			print_liste_field_titre($langs->trans("Status"), $_SERVER["PHP_SELF"], "mc.statut", $parm, '', 'align="right"', $sortfield, $sortorder);
-			
+
 			print '</tr>';
-			
+
 			// Ligne des champs de filtres
 			print '<tr class="liste_titre">';
 			// EMail
@@ -1050,15 +1045,15 @@ if ($object->fetch($id) >= 0) {
 			print '<input type="image" class="liste_titre" src="' . DOL_URL_ROOT . '/theme/' . $conf->theme . '/img/searchclear.png" name="button_removefilter" value="' . dol_escape_htmltag($langs->trans("RemoveFilter")) . '" title="' . dol_escape_htmltag($langs->trans("RemoveFilter")) . '">';
 			print '</td>';
 			print '</tr>';
-			
+
 			$var = true;
 			$i = 0;
-			
+
 			if ($num) {
 				while ( $i < min($num, $conf->liste_limit) ) {
 					$obj = $db->fetch_object($resql);
 					$var = ! $var;
-					
+
 					print "<tr $bc[$var]>";
 					print '<td>' . $obj->email . '</td>';
 					print '<td>' . $obj->lastname . '</td>';
@@ -1068,7 +1063,7 @@ if ($object->fetch($id) >= 0) {
 					if (empty($obj->source_id) || empty($obj->source_type)) {
 						print $obj->source_url; // For backward compatibility
 					} else {
-						
+
 						if ($obj->source_type == 'thirdparty') {
 							include_once DOL_DOCUMENT_ROOT . '/societe/class/societe.class.php';
 							$m = new Societe($db);
@@ -1082,7 +1077,7 @@ if ($object->fetch($id) >= 0) {
 						}
 					}
 					print '</td>';
-					
+
 					// Statut pour l'email destinataire (Attentioon != statut du mailing)
 					if ($obj->statut == 0) {
 						print '<td>&nbsp;</td>';
@@ -1105,19 +1100,19 @@ if ($object->fetch($id) >= 0) {
 						print '</td>';
 					}
 					print '</tr>';
-					
+
 					$i ++;
 				}
 			} else {
 				print '<tr ' . $bc[false] . '><td colspan="7">' . $langs->trans("NoTargetYet") . '</td></tr>';
 			}
 			print "</table><br>";
-			
+
 			$db->free($resql);
 		} else {
 			setEventMessage($db->lasterror(), 'errors');
 		}
-		
+
 		print '</form>';
 	}
 }

+ 1 - 1
htdocs/core/lib/emailing.lib.php

@@ -50,7 +50,7 @@ function emailing_prepare_head(Mailing $object)
 
 	$head[$h][0] = DOL_URL_ROOT."/comm/mailing/advtargetemailing.php?id=".$object->id;
 	$head[$h][1] = $langs->trans("MailAdvTargetRecipients");
-	$head[$h][2] = 'targets';
+	$head[$h][2] = 'advtargets';
 	$h++;
 
 	$head[$h][0] = DOL_URL_ROOT."/comm/mailing/info.php?id=".$object->id;

+ 6 - 7
htdocs/core/modules/mailings/modules_mailings.php

@@ -169,6 +169,7 @@ class MailingTargets    // This can't be abstract as it is used for some method
         		$sql.= (empty($targetarray['source_id']) ? 'null' : "'".$this->db->escape($targetarray['source_id'])."'").",";
        			$sql .= "'".$this->db->escape(dol_hash($targetarray['email'].';'.$targetarray['lastname'].';'.$mailing_id.';'.$conf->global->MAILING_EMAIL_UNSUBSCRIBE_KEY))."',";
         		$sql .= "'".$this->db->escape($targetarray['source_type'])."')";
+        		dol_syslog(get_class($this)."::".__METHOD__,LOG_DEBUG);
         		$result=$this->db->query($sql);
         		if ($result)
         		{
@@ -188,28 +189,26 @@ class MailingTargets    // This can't be abstract as it is used for some method
         	}
         }
 
-        dol_syslog(get_class($this)."::add_to_target: sql ".$sql,LOG_DEBUG);
-        dol_syslog(get_class($this)."::add_to_target: mailing ".$j." targets added");
+        dol_syslog(get_class($this)."::".__METHOD__.": mailing ".$j." targets added");
 
         //Update the status to show thirdparty 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 email FROM ".MAIN_DB_PREFIX."societe where fk_stcomm=-1)";
         $sql .= " AND source_type='thirdparty'";
+        dol_syslog(get_class($this)."::".__METHOD__.": mailing update status to display thirdparty mail that do not want to be contacted");
         $result=$this->db->query($sql);
 
-        dol_syslog(get_class($this)."::add_to_target: mailing update status to display thirdparty mail that do not want to be contacted sql:".$sql);
+
 
         //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 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 .= "  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(get_class($this)."::".__METHOD__.": mailing update status to display contact mail that do not want to be contacted",LOG_DEBUG);
         $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);
-
 
         $this->update_nb($mailing_id);
 

+ 20 - 0
htdocs/includes/multiselect/MIT-LICENSE.txt

@@ -0,0 +1,20 @@
+Copyright (c) 2009 Michael Aufreiter, http://www.quasipartikel.at
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

+ 144 - 0
htdocs/includes/multiselect/css/ui.multiselect.css

@@ -0,0 +1,144 @@
+/* Multiselect
+----------------------------------*/
+.multiselect {
+	width: 600px;
+	height: 150px;
+}
+
+.ui-multiselect {
+	border: solid 1px;
+	font-size: 0.8em;
+}
+
+.ui-multiselect ul {
+	-moz-user-select: none;
+}
+
+.ui-multiselect li {
+	margin: 0;
+	padding: 0;
+	cursor: default;
+	line-height: 20px;
+	height: 20px;
+	font-size: 11px;
+	list-style: none;
+}
+
+.ui-multiselect li a {
+	color: #999;
+	text-decoration: none;
+	padding: 0;
+	display: block;
+	float: left;
+	cursor: pointer;
+}
+
+.ui-multiselect li.ui-draggable-dragging {
+	padding-left: 10px;
+}
+
+.ui-multiselect div.selected {
+	position: relative;
+	padding: 0;
+	margin: 0;
+	border: 0;
+	float: left;
+}
+
+.ui-multiselect ul.selected {
+	position: relative;
+	padding: 0;
+	overflow: auto;
+	overflow-x: hidden;
+	background: #fff;
+	margin: 0;
+	list-style: none;
+	border: 0;
+	position: relative;
+	width: 100%;
+}
+
+.ui-multiselect ul.selected li {
+	
+}
+
+.ui-multiselect div.available {
+	position: relative;
+	padding: 0;
+	margin: 0;
+	border: 0;
+	float: left;
+	border-left: 1px solid;
+}
+
+.ui-multiselect ul.available {
+	position: relative;
+	padding: 0;
+	overflow: auto;
+	overflow-x: hidden;
+	background: #fff;
+	margin: 0;
+	list-style: none;
+	border: 0;
+	width: 100%;
+}
+
+.ui-multiselect ul.available li {
+	padding-left: 10px;
+}
+
+.ui-multiselect .ui-state-default {
+	border: none;
+	margin-bottom: 1px;
+	position: relative;
+	padding-left: 20px;
+}
+
+.ui-multiselect .ui-state-hover {
+	border: none;
+}
+
+.ui-multiselect .ui-widget-header {
+	border: none;
+	font-size: 11px;
+	margin-bottom: 1px;
+}
+
+.ui-multiselect .add-all {
+	float: right;
+	padding: 7px;
+}
+
+.ui-multiselect .remove-all {
+	float: right;
+	padding: 7px;
+}
+
+.ui-multiselect .search {
+	float: left;
+	padding: 4px;
+}
+
+.ui-multiselect .count {
+	float: left;
+	padding: 7px;
+}
+
+.ui-multiselect li span.ui-icon-arrowthick-2-n-s {
+	position: absolute;
+	left: 2px;
+}
+
+.ui-multiselect li a.action {
+	position: absolute;
+	right: 2px;
+	top: 2px;
+}
+
+.ui-multiselect input.search {
+	height: 14px;
+	padding: 1px;
+	opacity: 0.5;
+	margin: 4px;
+	width: 100px;
+}

+ 336 - 0
htdocs/includes/multiselect/js/ui.multiselect.js

@@ -0,0 +1,336 @@
+/*
+ * jQuery UI Multiselect
+ *
+ * Authors:
+ *  Michael Aufreiter (quasipartikel.at)
+ *  Yanick Rochon (yanick.rochon[at]gmail[dot]com)
+ * 
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ * 
+ * http://www.quasipartikel.at/multiselect/
+ *
+ * 
+ * Depends:
+ *	ui.core.js
+ *	ui.sortable.js
+ *
+ * Optional:
+ * localization (http://plugins.jquery.com/project/localisation)
+ * scrollTo (http://plugins.jquery.com/project/ScrollTo)
+ * 
+ * Todo:
+ *  Make batch actions faster
+ *  Implement dynamic insertion through remote calls
+ */
+
+
+(function($) {
+
+$.widget("ui.multiselect", {
+  options: {
+		sortable: true,
+		searchable: true,
+		doubleClickable: true,
+		animated: 'fast',
+		show: 'slideDown',
+		hide: 'slideUp',
+		dividerLocation: 0.6,
+		nodeComparator: function(node1,node2) {
+			var text1 = node1.text(),
+			    text2 = node2.text();
+			return text1 == text2 ? 0 : (text1 < text2 ? -1 : 1);
+		}
+	},
+	_create: function() {
+		this.element.hide();
+		this.id = this.element.attr("id");
+		this.container = $('<div class="ui-multiselect ui-helper-clearfix ui-widget"></div>').insertAfter(this.element);
+		this.count = 0; // number of currently selected options
+		this.selectedContainer = $('<div class="selected"></div>').appendTo(this.container);
+		this.availableContainer = $('<div class="available"></div>').appendTo(this.container);
+		this.selectedActions = $('<div class="actions ui-widget-header ui-helper-clearfix"><span class="count">0 '+$.ui.multiselect.locale.itemsCount+'</span><a href="#" class="remove-all">'+$.ui.multiselect.locale.removeAll+'</a></div>').appendTo(this.selectedContainer);
+		this.availableActions = $('<div class="actions ui-widget-header ui-helper-clearfix"><input type="text" class="search empty ui-widget-content ui-corner-all"/><a href="#" class="add-all">'+$.ui.multiselect.locale.addAll+'</a></div>').appendTo(this.availableContainer);
+		this.selectedList = $('<ul class="selected connected-list"><li class="ui-helper-hidden-accessible"></li></ul>').bind('selectstart', function(){return false;}).appendTo(this.selectedContainer);
+		this.availableList = $('<ul class="available connected-list"><li class="ui-helper-hidden-accessible"></li></ul>').bind('selectstart', function(){return false;}).appendTo(this.availableContainer);
+		
+		var that = this;
+
+		// set dimensions
+		this.container.width(this.element.width()+1);
+		this.selectedContainer.width(Math.floor(this.element.width()*this.options.dividerLocation));
+		this.availableContainer.width(Math.floor(this.element.width()*(1-this.options.dividerLocation)));
+
+		// fix list height to match <option> depending on their individual header's heights
+		this.selectedList.height(Math.max(this.element.height()-this.selectedActions.height(),1));
+		this.availableList.height(Math.max(this.element.height()-this.availableActions.height(),1));
+		
+		if ( !this.options.animated ) {
+			this.options.show = 'show';
+			this.options.hide = 'hide';
+		}
+		
+		// init lists
+		this._populateLists(this.element.find('option'));
+		
+		// make selection sortable
+		if (this.options.sortable) {
+			this.selectedList.sortable({
+				placeholder: 'ui-state-highlight',
+				axis: 'y',
+				update: function(event, ui) {
+					// apply the new sort order to the original selectbox
+					that.selectedList.find('li').each(function() {
+						if ($(this).data('optionLink'))
+							$(this).data('optionLink').remove().appendTo(that.element);
+					});
+				},
+				receive: function(event, ui) {
+					ui.item.data('optionLink').attr('selected', true);
+					// increment count
+					that.count += 1;
+					that._updateCount();
+					// workaround, because there's no way to reference 
+					// the new element, see http://dev.jqueryui.com/ticket/4303
+					that.selectedList.children('.ui-draggable').each(function() {
+						$(this).removeClass('ui-draggable');
+						$(this).data('optionLink', ui.item.data('optionLink'));
+						$(this).data('idx', ui.item.data('idx'));
+						that._applyItemState($(this), true);
+					});
+			
+					// workaround according to http://dev.jqueryui.com/ticket/4088
+					setTimeout(function() { ui.item.remove(); }, 1);
+				}
+			});
+		}
+		
+		// set up livesearch
+		if (this.options.searchable) {
+			this._registerSearchEvents(this.availableContainer.find('input.search'));
+		} else {
+			$('.search').hide();
+		}
+		
+		// batch actions
+		this.container.find(".remove-all").click(function() {
+			that._populateLists(that.element.find('option').removeAttr('selected'));
+			return false;
+		});
+		
+		this.container.find(".add-all").click(function() {
+			var options = that.element.find('option').not(":selected");
+			if (that.availableList.children('li:hidden').length > 1) {
+				that.availableList.children('li').each(function(i) {
+					if ($(this).is(":visible")) $(options[i-1]).attr('selected', 'selected'); 
+				});
+			} else {
+				options.attr('selected', 'selected');
+			}
+			that._populateLists(that.element.find('option'));
+			return false;
+		});
+	},
+	destroy: function() {
+		this.element.show();
+		this.container.remove();
+
+		$.Widget.prototype.destroy.apply(this, arguments);
+	},
+	_populateLists: function(options) {
+		this.selectedList.children('.ui-element').remove();
+		this.availableList.children('.ui-element').remove();
+		this.count = 0;
+
+		var that = this;
+		var items = $(options.map(function(i) {
+	      var item = that._getOptionNode(this).appendTo(this.selected ? that.selectedList : that.availableList).show();
+
+			if (this.selected) that.count += 1;
+			that._applyItemState(item, this.selected);
+			item.data('idx', i);
+			return item[0];
+    }));
+		
+		// update count
+		this._updateCount();
+		that._filter.apply(this.availableContainer.find('input.search'), [that.availableList]);
+  },
+	_updateCount: function() {
+		this.selectedContainer.find('span.count').text(this.count+" "+$.ui.multiselect.locale.itemsCount);
+	},
+	_getOptionNode: function(option) {
+		option = $(option);
+		var node = $('<li class="ui-state-default ui-element" title="'+option.text()+'"><span class="ui-icon"/>'+option.text()+'<a href="#" class="action"><span class="ui-corner-all ui-icon"/></a></li>').hide();
+		node.data('optionLink', option);
+		return node;
+	},
+	// clones an item with associated data
+	// didn't find a smarter away around this
+	_cloneWithData: function(clonee) {
+		var clone = clonee.clone(false,false);
+		clone.data('optionLink', clonee.data('optionLink'));
+		clone.data('idx', clonee.data('idx'));
+		return clone;
+	},
+	_setSelected: function(item, selected) {
+		item.data('optionLink').attr('selected', selected);
+
+		if (selected) {
+			var selectedItem = this._cloneWithData(item);
+			item[this.options.hide](this.options.animated, function() { $(this).remove(); });
+			selectedItem.appendTo(this.selectedList).hide()[this.options.show](this.options.animated);
+			
+			this._applyItemState(selectedItem, true);
+			return selectedItem;
+		} else {
+			
+			// look for successor based on initial option index
+			var items = this.availableList.find('li'), comparator = this.options.nodeComparator;
+			var succ = null, i = item.data('idx'), direction = comparator(item, $(items[i]));
+
+			// TODO: test needed for dynamic list populating
+			if ( direction ) {
+				while (i>=0 && i<items.length) {
+					direction > 0 ? i++ : i--;
+					if ( direction != comparator(item, $(items[i])) ) {
+						// going up, go back one item down, otherwise leave as is
+						succ = items[direction > 0 ? i : i+1];
+						break;
+					}
+				}
+			} else {
+				succ = items[i];
+			}
+			
+			var availableItem = this._cloneWithData(item);
+			succ ? availableItem.insertBefore($(succ)) : availableItem.appendTo(this.availableList);
+			item[this.options.hide](this.options.animated, function() { $(this).remove(); });
+			availableItem.hide()[this.options.show](this.options.animated);
+			
+			this._applyItemState(availableItem, false);
+			return availableItem;
+		}
+	},
+	_applyItemState: function(item, selected) {
+		if (selected) {
+			if (this.options.sortable)
+				item.children('span').addClass('ui-icon-arrowthick-2-n-s').removeClass('ui-helper-hidden').addClass('ui-icon');
+			else
+				item.children('span').removeClass('ui-icon-arrowthick-2-n-s').addClass('ui-helper-hidden').removeClass('ui-icon');
+			item.find('a.action span').addClass('ui-icon-minus').removeClass('ui-icon-plus');
+			this._registerRemoveEvents(item.find('a.action'));
+			
+		} else {
+			item.children('span').removeClass('ui-icon-arrowthick-2-n-s').addClass('ui-helper-hidden').removeClass('ui-icon');
+			item.find('a.action span').addClass('ui-icon-plus').removeClass('ui-icon-minus');
+			this._registerAddEvents(item.find('a.action'));
+		}
+		
+		this._registerDoubleClickEvents(item);
+		this._registerHoverEvents(item);
+	},
+	// taken from John Resig's liveUpdate script
+	_filter: function(list) {
+		var input = $(this);
+		var rows = list.children('li'),
+			cache = rows.map(function(){
+				
+				return $(this).text().toLowerCase();
+			});
+		
+		var term = $.trim(input.val().toLowerCase()), scores = [];
+		
+		if (!term) {
+			rows.show();
+		} else {
+			rows.hide();
+
+			cache.each(function(i) {
+				if (this.indexOf(term)>-1) { scores.push(i); }
+			});
+
+			$.each(scores, function() {
+				$(rows[this]).show();
+			});
+		}
+	},
+	_registerDoubleClickEvents: function(elements) {
+		if (!this.options.doubleClickable) return;
+		elements.dblclick(function() {
+			elements.find('a.action').click();
+		});
+	},
+	_registerHoverEvents: function(elements) {
+		elements.removeClass('ui-state-hover');
+		elements.mouseover(function() {
+			$(this).addClass('ui-state-hover');
+		});
+		elements.mouseout(function() {
+			$(this).removeClass('ui-state-hover');
+		});
+	},
+	_registerAddEvents: function(elements) {
+		var that = this;
+		elements.click(function() {
+			var item = that._setSelected($(this).parent(), true);
+			that.count += 1;
+			that._updateCount();
+			return false;
+		});
+		
+		// make draggable
+		if (this.options.sortable) {
+  		elements.each(function() {
+  			$(this).parent().draggable({
+  	      connectToSortable: that.selectedList,
+  				helper: function() {
+  					var selectedItem = that._cloneWithData($(this)).width($(this).width() - 50);
+  					selectedItem.width($(this).width());
+  					return selectedItem;
+  				},
+  				appendTo: that.container,
+  				containment: that.container,
+  				revert: 'invalid'
+  	    });
+  		});		  
+		}
+	},
+	_registerRemoveEvents: function(elements) {
+		var that = this;
+		elements.click(function() {
+			that._setSelected($(this).parent(), false);
+			that.count -= 1;
+			that._updateCount();
+			return false;
+		});
+ 	},
+	_registerSearchEvents: function(input) {
+		var that = this;
+
+		input.focus(function() {
+			$(this).addClass('ui-state-active');
+		})
+		.blur(function() {
+			$(this).removeClass('ui-state-active');
+		})
+		.keypress(function(e) {
+			if (e.keyCode == 13)
+				return false;
+		})
+		.keyup(function() {
+			that._filter.apply(this, [that.availableList]);
+		});
+	}
+});
+		
+$.extend($.ui.multiselect, {
+	locale: {
+		addAll:'Add all',
+		removeAll:'Remove all',
+		itemsCount:'items selected'
+	}
+});
+
+
+})(jQuery);

+ 15 - 0
htdocs/install/mysql/migration/3.9.0-4.0.0.sql

@@ -342,3 +342,18 @@ CREATE TABLE llx_c_accounting_category (
 ) ENGINE=innodb;
 
 ALTER TABLE llx_c_accounting_category ADD UNIQUE INDEX uk_c_accounting_category(code);
+
+CREATE TABLE IF NOT EXISTS llx_advtargetemailing
+(
+  rowid integer NOT NULL AUTO_INCREMENT PRIMARY KEY,
+  name varchar(200) NOT NULL,
+  entity integer NOT NULL DEFAULT 1,
+  fk_mailing	integer NOT NULL,
+  filtervalue	text,
+  fk_user_author integer NOT NULL,
+  datec datetime NOT NULL,
+  fk_user_mod integer NOT NULL,
+  tms timestamp NOT NULL
+) ENGINE=innodb;
+
+ALTER TABLE llx_advtargetemailing ADD UNIQUE INDEX uk_advtargetemailing_name (name);

+ 17 - 0
htdocs/install/mysql/tables/llx_advtargetemailing.key.sql

@@ -0,0 +1,17 @@
+-- <Mailjet connector>
+-- Copyright (C) 2013 Florian Henry florian.henry@open-concept.pro
+--
+-- 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/>.
+
+ALTER TABLE llx_advtargetemailing ADD UNIQUE INDEX uk_advtargetemailing_name (name);

+ 31 - 0
htdocs/install/mysql/tables/llx_advtargetemailing.sql

@@ -0,0 +1,31 @@
+-- ============================================================================
+-- Copyright (C) 2013 Florian Henry <florian.henry@open-concept.pro>
+--
+-- 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/>.
+--
+-- Table of "Plan de comptes" for accountancy expert module
+-- ============================================================================
+
+CREATE TABLE IF NOT EXISTS llx_advtargetemailing
+(
+  rowid integer NOT NULL auto_increment PRIMARY KEY,
+  name varchar(200) NOT NULL,
+  entity integer NOT NULL DEFAULT 1,
+  fk_mailing	integer NOT NULL,
+  filtervalue	text,
+  fk_user_author integer NOT NULL,
+  datec datetime NOT NULL,
+  fk_user_mod integer NOT NULL,
+  tms timestamp NOT NULL
+)ENGINE=InnoDB;

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

@@ -148,3 +148,24 @@ MailSendSetupIs3=If you have any questions on how to setup your SMTP server, you
 YouCanAlsoUseSupervisorKeyword=You can also add the keyword <strong>__SUPERVISOREMAIL__</strong> to have email being sent to the supervisor of user (works only if an email is defined for this supervisor) 
 NbOfTargetedContacts=Current number of targeted contact emails
 MailAdvTargetRecipients=Advance recipients targeting
+AdvTgtTitle=Fill the input ro preselect the customer (or contact) destinaries
+AdvTgtSearchTextHelp=Use %% as magic caracters. For exemple to find all item like <b>jean, joe, jim</b>, you can input <b>j%%</b>, you can also use ; as separator for value, and use ! for except this value. For exemple  <b>jean;joe;jim%%;!jimo;!jima%</b> will target all jean, joe, start with jim but not jimo and not everythnig taht start by jima 
+AdvTgtSearchIntHelp=Use interval to select int or float value
+AdvTgtMinVal=Minimum value
+AdvTgtMaxVal=Maximum value
+AdvTgtSearchDtHelp=Use interval to select date value
+AdvTgtStartDt=Start dt.
+AdvTgtEndDt=End dt.
+AdvTgtTypeOfIncudeHelp=Target Email of thirdparty and email of contact of the thridparty, or just thridparty email or just contact email
+AdvTgtTypeOfIncude=Type of targeted email
+AdvTgtContactHelp=Use only if you target contact into "Type of targeted email"
+AddAll=Add all
+RemoveAll=Remove all
+ItemsCount=Item(s)
+AdvTgtNameTemplate=Filter name
+AdvTgtAddContact=Add email according filter criteria
+AdvTgtLoadFilter=Load filter
+AdvTgtDeleteFilter=Delete filter
+AdvTgtSaveFilter=Save filter
+AdvTgtCreateFilter=Create filter
+AdvTgtOrCreateNewFilter=Name of new filter