Pārlūkot izejas kodu

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

Laurent Destailleur 7 gadi atpakaļ
vecāks
revīzija
dd022ee423

+ 3 - 2
README-FR.md

@@ -138,9 +138,10 @@ Voici un liste de fonctionnalites pas encore gérées par Dolibarr:
 Les documentations utilisateur, développeur et traducteur sont disponible sous forme de ressources de la communautés via la site [Wiki](https://wiki.dolibarr.org).
 
 
-## CONTRIBUTING
+## CONTRIBUER
 
-Voir le fichier [CONTRIBUTING](https://github.com/Dolibarr/dolibarr/blob/develop/.github/CONTRIBUTING.md)
+Ce projet existe grâce à ses nombreux contributeurs [[Contribuer](https://github.com/Dolibarr/dolibarr/blob/develop/.github/CONTRIBUTING.md)].
+<a href="https://github.com/Dolibarr/dolibarr/graphs/contributors"><img src="https://opencollective.com/dolibarr/contributors.svg?width=890&button=false" /></a>
 
 
 ## CREDITS

+ 8 - 2
README.md

@@ -162,7 +162,7 @@ See the [ChangeLog](https://github.com/Dolibarr/dolibarr/blob/develop/ChangeLog)
 Dolibarr can be extended with a lot of other external application or modules from third party developers available at the [DoliStore](https://www.dolistore.com).
 
 
-## FUTURE
+## WHAT DOLIBARR CAN'T DO YET
 
 These are features that Dolibarr does **not** yet fully support:
 
@@ -179,7 +179,8 @@ Administrator, user, developer and translator's documentations are available alo
 
 ## CONTRIBUTING
 
-See [CONTRIBUTING](https://github.com/Dolibarr/dolibarr/blob/develop/.github/CONTRIBUTING.md) file
+This project exists thanks to all the people who contribute. [[Contribute](https://github.com/Dolibarr/dolibarr/blob/develop/.github/CONTRIBUTING.md)].
+<a href="https://github.com/Dolibarr/dolibarr/graphs/contributors"><img src="https://opencollective.com/dolibarr/contributors.svg?width=890&button=false" /></a>
 
 
 ## CREDITS
@@ -199,3 +200,8 @@ Follow Dolibarr project on:
 - [LinkedIn](https://www.linkedin.com/company/association-dolibarr)
 - [YouTube](https://www.youtube.com/user/DolibarrERPCRM)
 - [GitHub](https://github.com/Dolibarr/dolibarr)
+
+
+### Sponsors
+
+Support this project by becoming a sponsor. Your logo will show up here. 🙏 [[Become a sponsor/backer](https://opencollective.com/dolibarr#backer)]

+ 1 - 1
htdocs/accountancy/admin/categories.php

@@ -71,7 +71,7 @@ if (! empty($selectcpt)) {
 	if ($return<0) {
 		setEventMessages($langs->trans('errors'), $accountingcategory->errors, 'errors');
 	} else {
-		setEventMessages($langs->trans('Saved'), null, 'mesgs');
+		setEventMessages($langs->trans('SetupSaved'), null, 'mesgs');
 	}
 }
 if ($action == 'delete') {

+ 111 - 113
htdocs/accountancy/bookkeeping/card.php

@@ -1,8 +1,8 @@
 <?php
-/* Copyright (C) 2013-2017 Olivier Geffroy	  <jeff@jeffinfo.com>
- * Copyright (C) 2013-2017 Florian Henry		<florian.henry@open-concept.pro>
- * Copyright (C) 2013-2017 Alexandre Spangaro   <aspangaro@zendsi.com>
- * Copyright (C) 2017	  Laurent Destailleur  <eldy@users.sourceforge.net>
+/* Copyright (C) 2013-2017 Olivier Geffroy      <jeff@jeffinfo.com>
+ * Copyright (C) 2013-2017 Florian Henry        <florian.henry@open-concept.pro>
+ * Copyright (C) 2013-2018 Alexandre Spangaro   <aspangaro@zendsi.com>
+ * Copyright (C) 2017      Laurent Destailleur  <eldy@users.sourceforge.net>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -32,9 +32,7 @@ require_once DOL_DOCUMENT_ROOT . '/compta/facture/class/facture.class.php';
 require_once DOL_DOCUMENT_ROOT . '/fourn/class/fournisseur.facture.class.php';
 require_once DOL_DOCUMENT_ROOT . '/accountancy/class/accountingjournal.class.php';
 
-$langs->load("accountancy");
-$langs->load("bills");
-$langs->load("compta");
+$langs->loadLangs(array("accountancy", "bills", "compta"));
 
 $action = GETPOST('action','aZ09');
 
@@ -89,36 +87,36 @@ if ($action == "confirm_update") {
 
 	if (! $error)
 	{
-		$book = new BookKeeping($db);
+		$object = new BookKeeping($db);
 
-		$result = $book->fetch($id, null, $mode);
+		$result = $object->fetch($id, null, $mode);
 		if ($result < 0) {
 			$error++;
-			setEventMessages($book->error, $book->errors, 'errors');
+			setEventMessages($object->error, $object->errors, 'errors');
 		} else {
-			$book->numero_compte = $account_number;
-			$book->subledger_account = $subledger_account;
-			$book->label_compte = $label_compte;
-			$book->label_operation= $label_operation;
-			$book->debit = $debit;
-			$book->credit = $credit;
+			$object->numero_compte = $account_number;
+			$object->subledger_account = $subledger_account;
+			$object->label_compte = $label_compte;
+			$object->label_operation= $label_operation;
+			$object->debit = $debit;
+			$object->credit = $credit;
 
 			if (floatval($debit) != 0.0) {
-				$book->montant = $debit;
-				$book->sens = 'D';
+				$object->montant = $debit;
+				$object->sens = 'D';
 			}
 			if (floatval($credit) != 0.0) {
-				$book->montant = $credit;
-				$book->sens = 'C';
+				$object->montant = $credit;
+				$object->sens = 'C';
 			}
 
-			$result = $book->update($user, false, $mode);
+			$result = $object->update($user, false, $mode);
 			if ($result < 0) {
-				setEventMessages($book->error, $book->errors, 'errors');
+				setEventMessages($object->error, $object->errors, 'errors');
 			} else {
 				if ($mode != '_tmp')
 				{
-					setEventMessages($langs->trans('Saved'), null, 'mesgs');
+					setEventMessages($langs->trans('RecordSaved'), null, 'mesgs');
 				}
 
 				$debit = 0;
@@ -147,39 +145,39 @@ else if ($action == "add") {
 	}
 
 	if (! $error) {
-		$book = new BookKeeping($db);
-
-		$book->numero_compte = $account_number;
-		$book->subledger_account = $subledger_account;
-		$book->label_compte = $label_compte;
-		$book->label_operation= $label_operation;
-		$book->debit = $debit;
-		$book->credit = $credit;
-		$book->doc_date = GETPOST('doc_date','alpha');
-		$book->doc_type = GETPOST('doc_type','alpha');
-		$book->piece_num = $piece_num;
-		$book->doc_ref = GETPOST('doc_ref','alpha');
-		$book->code_journal = GETPOST('code_journal','alpha');
-		$book->fk_doc = GETPOST('fk_doc','alpha');
-		$book->fk_docdet = GETPOST('fk_docdet','alpha');
+		$object = new BookKeeping($db);
+
+		$object->numero_compte = $account_number;
+		$object->subledger_account = $subledger_account;
+		$object->label_compte = $label_compte;
+		$object->label_operation= $label_operation;
+		$object->debit = $debit;
+		$object->credit = $credit;
+		$object->doc_date = GETPOST('doc_date','alpha');
+		$object->doc_type = GETPOST('doc_type','alpha');
+		$object->piece_num = $piece_num;
+		$object->doc_ref = GETPOST('doc_ref','alpha');
+		$object->code_journal = GETPOST('code_journal','alpha');
+		$object->fk_doc = GETPOST('fk_doc','alpha');
+		$object->fk_docdet = GETPOST('fk_docdet','alpha');
 
 		if (floatval($debit) != 0.0) {
-			$book->montant = $debit;
-			$book->sens = 'D';
+			$object->montant = $debit;
+			$object->sens = 'D';
 		}
 
 		if (floatval($credit) != 0.0) {
-			$book->montant = $credit;
-			$book->sens = 'C';
+			$object->montant = $credit;
+			$object->sens = 'C';
 		}
 
-		$result = $book->createStd($user, false, $mode);
+		$result = $object->createStd($user, false, $mode);
 		if ($result < 0) {
-			setEventMessages($book->error, $book->errors, 'errors');
+			setEventMessages($object->error, $object->errors, 'errors');
 		} else {
 			if ($mode != '_tmp')
 			{
-				setEventMessages($langs->trans('Saved'), null, 'mesgs');
+				setEventMessages($langs->trans('RecordSaved'), null, 'mesgs');
 			}
 
 			$debit = 0;
@@ -191,17 +189,17 @@ else if ($action == "add") {
 }
 
 else if ($action == "confirm_delete") {
-	$book = new BookKeeping($db);
+	$object = new BookKeeping($db);
 
-	$result = $book->fetch($id, null, $mode);
-	$piece_num = $book->piece_num;
+	$result = $object->fetch($id, null, $mode);
+	$piece_num = $object->piece_num;
 
 	if ($result < 0) {
-		setEventMessages($book->error, $book->errors, 'errors');
+		setEventMessages($object->error, $object->errors, 'errors');
 	} else {
-		$result = $book->delete($user, false, $mode);
+		$result = $object->delete($user, false, $mode);
 		if ($result < 0) {
-			setEventMessages($book->error, $book->errors, 'errors');
+			setEventMessages($object->error, $object->errors, 'errors');
 		}
 	}
 	$action = '';
@@ -210,7 +208,7 @@ else if ($action == "confirm_delete") {
 else if ($action == "confirm_create") {
 	$error = 0;
 
-	$book = new BookKeeping($db);
+	$object = new BookKeeping($db);
 
 	if (! GETPOST('code_journal','alpha') || GETPOST('code_journal','alpha') == '-1') {
 		setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv("Journal")), null, 'errors');
@@ -225,29 +223,29 @@ else if ($action == "confirm_create") {
 
 	if (! $error)
 	{
-		$book->label_compte = '';
-		$book->debit = 0;
-		$book->credit = 0;
-		$book->doc_date = $date_start = dol_mktime(0, 0, 0, GETPOST('doc_datemonth','int'), GETPOST('doc_dateday','int'), GETPOST('doc_dateyear','int'));
-		$book->doc_type = GETPOST('doc_type','alpha');
-		$book->piece_num = GETPOST('next_num_mvt','alpha');
-		$book->doc_ref = GETPOST('doc_ref','alpha');
-		$book->code_journal = GETPOST('code_journal','alpha');
-		$book->fk_doc = 0;
-		$book->fk_docdet = 0;
-		$book->montant = 0;
-
-		$result = $book->createStd($user,0, $mode);
+		$object->label_compte = '';
+		$object->debit = 0;
+		$object->credit = 0;
+		$object->doc_date = $date_start = dol_mktime(0, 0, 0, GETPOST('doc_datemonth','int'), GETPOST('doc_dateday','int'), GETPOST('doc_dateyear','int'));
+		$object->doc_type = GETPOST('doc_type','alpha');
+		$object->piece_num = GETPOST('next_num_mvt','alpha');
+		$object->doc_ref = GETPOST('doc_ref','alpha');
+		$object->code_journal = GETPOST('code_journal','alpha');
+		$object->fk_doc = 0;
+		$object->fk_docdet = 0;
+		$object->montant = 0;
+
+		$result = $object->createStd($user,0, $mode);
 		if ($result < 0) {
-			setEventMessages($book->error, $book->errors, 'errors');
+			setEventMessages($object->error, $object->errors, 'errors');
 		} else {
 			if ($mode != '_tmp')
 			{
-				setEventMessages($langs->trans('Saved'), null, 'mesgs');
+				setEventMessages($langs->trans('RecordSaved'), null, 'mesgs');
 			}
 			$action = 'update';
-			$id=$book->id;
-			$piece_num = $book->piece_num;
+			$id=$object->id;
+			$piece_num = $object->piece_num;
 		}
 	}
 }
@@ -260,7 +258,7 @@ if ($action == 'setdate') {
 	} else {
 		if ($mode != '_tmp')
 		{
-			setEventMessages($langs->trans('Saved'), null, 'mesgs');
+			setEventMessages($langs->trans('RecordSaved'), null, 'mesgs');
 		}
 		$action = '';
 	}
@@ -274,7 +272,7 @@ if ($action == 'setjournal') {
 	} else {
 		if ($mode != '_tmp')
 		{
-			setEventMessages($langs->trans('Saved'), null, 'mesgs');
+			setEventMessages($langs->trans('RecordSaved'), null, 'mesgs');
 		}
 		$action = '';
 	}
@@ -288,7 +286,7 @@ if ($action == 'setdocref') {
 	} else {
 		if ($mode != '_tmp')
 		{
-			setEventMessages($langs->trans('Saved'), null, 'mesgs');
+			setEventMessages($langs->trans('RecordSaved'), null, 'mesgs');
 		}
 		$action = '';
 	}
@@ -326,8 +324,8 @@ if ($action == 'create')
 {
 	print load_fiche_titre($langs->trans("CreateMvts"));
 
-	$book = new BookKeeping($db);
-	$next_num_mvt = $book->getNextNumMvt('_tmp');
+	$object = new BookKeeping($db);
+	$next_num_mvt = $object->getNextNumMvt('_tmp');
 
 	if (empty($next_num_mvt))
 	{
@@ -361,7 +359,7 @@ if ($action == 'create')
 	print '</tr>';
 
 	print '<tr>';
-	print '<td>' . $langs->trans("Docref") . '</td>';
+	print '<td>' . $langs->trans("Piece") . '</td>';
 	print '<td><input type="text" class="minwidth200" name="doc_ref" value=""/></td>';
 	print '</tr>';
 
@@ -384,13 +382,13 @@ if ($action == 'create')
 
 	print '</form>';
 } else {
-	$book = new BookKeeping($db);
-	$result = $book->fetchPerMvt($piece_num, $mode);
+	$object = new BookKeeping($db);
+	$result = $object->fetchPerMvt($piece_num, $mode);
 	if ($result < 0) {
-		setEventMessages($book->error, $book->errors, 'errors');
+		setEventMessages($object->error, $object->errors, 'errors');
 	}
 
-	if (! empty($book->piece_num))
+	if (! empty($object->piece_num))
 	{
 		$backlink = '<a href="'.DOL_URL_ROOT.'/accountancy/bookkeeping/list.php?restore_lastsearch_values=1">' . $langs->trans('BackToList') . '</a>';
 
@@ -398,14 +396,14 @@ if ($action == 'create')
 
 		$head=array();
 		$h=0;
-		$head[$h][0] = $_SERVER['PHP_SELF'].'?piece_num='.$book->piece_num.($mode?'&mode='.$mode:'');
+		$head[$h][0] = $_SERVER['PHP_SELF'].'?piece_num='.$object->piece_num.($mode?'&mode='.$mode:'');
 		$head[$h][1] = $langs->trans("Transaction");
 		$head[$h][2] = 'transaction';
 		$h++;
 
 		dol_fiche_head($head, 'transaction', '', -1);
 
-		//dol_banner_tab($book, '', $backlink);
+		//dol_banner_tab($object, '', $backlink);
 
 		print '<div class="fichecenter">';
 		print '<div class="fichehalfleft">';
@@ -416,7 +414,7 @@ if ($action == 'create')
 		// Account movement
 		print '<tr>';
 		print '<td class="titlefield">' . $langs->trans("NumMvts") . '</td>';
-		print '<td>' . $book->piece_num . '</td>';
+		print '<td>' . $object->piece_num . '</td>';
 		print '</tr>';
 
 		// Date
@@ -425,19 +423,19 @@ if ($action == 'create')
 		print $langs->trans('Docdate');
 		print '</td>';
 		if ($action != 'editdate')
-		print '<td align="right"><a href="'.$_SERVER["PHP_SELF"].'?action=editdate&amp;piece_num='. $book->piece_num .'&amp;mode='. $mode .'">'.img_edit($langs->transnoentitiesnoconv('SetDate'),1).'</a></td>';
+		print '<td align="right"><a href="'.$_SERVER["PHP_SELF"].'?action=editdate&amp;piece_num='. $object->piece_num .'&amp;mode='. $mode .'">'.img_edit($langs->transnoentitiesnoconv('SetDate'),1).'</a></td>';
 		print '</tr></table>';
 		print '</td><td colspan="3">';
 		if ($action == 'editdate') {
-			print '<form name="setdate" action="' . $_SERVER["PHP_SELF"] . '?piece_num=' . $book->piece_num . '" method="post">';
+			print '<form name="setdate" action="' . $_SERVER["PHP_SELF"] . '?piece_num=' . $object->piece_num . '" method="post">';
 			print '<input type="hidden" name="token" value="' . $_SESSION ['newtoken'] . '">';
 			print '<input type="hidden" name="action" value="setdate">';
 			print '<input type="hidden" name="mode" value="'.$mode.'">';
-			$form->select_date($book->doc_date ? $book->doc_date : - 1, 'doc_date', '', '', '', "setdate");
+			$form->select_date($object->doc_date ? $object->doc_date : - 1, 'doc_date', '', '', '', "setdate");
 			print '<input type="submit" class="button" value="' . $langs->trans('Modify') . '">';
 			print '</form>';
 		} else {
-			print $book->doc_date ? dol_print_date($book->doc_date, 'day') : '&nbsp;';
+			print $object->doc_date ? dol_print_date($object->doc_date, 'day') : '&nbsp;';
 		}
 		print '</td>';
 		print '</tr>';
@@ -448,19 +446,19 @@ if ($action == 'create')
 		print $langs->trans('Codejournal');
 		print '</td>';
 		if ($action != 'editjournal')
-		print '<td align="right"><a href="'.$_SERVER["PHP_SELF"].'?action=editjournal&amp;piece_num='.$book->piece_num.'&amp;mode='. $mode .'">'.img_edit($langs->transnoentitiesnoconv('Edit'),1).'</a></td>';
+		print '<td align="right"><a href="'.$_SERVER["PHP_SELF"].'?action=editjournal&amp;piece_num='.$object->piece_num.'&amp;mode='. $mode .'">'.img_edit($langs->transnoentitiesnoconv('Edit'),1).'</a></td>';
 		print '</tr></table>';
 		print '</td><td>';
 		if ($action == 'editjournal') {
-			print '<form name="setjournal" action="' . $_SERVER["PHP_SELF"] . '?piece_num=' . $book->piece_num . '" method="post">';
+			print '<form name="setjournal" action="' . $_SERVER["PHP_SELF"] . '?piece_num=' . $object->piece_num . '" method="post">';
 			print '<input type="hidden" name="token" value="' . $_SESSION ['newtoken'] . '">';
 			print '<input type="hidden" name="action" value="setjournal">';
 			print '<input type="hidden" name="mode" value="'.$mode.'">';
-			print $formaccounting->select_journal($book->code_journal,'code_journal',0,0,array(),1,1);
+			print $formaccounting->select_journal($object->code_journal,'code_journal',0,0,array(),1,1);
 			print '<input type="submit" class="button" value="' . $langs->trans('Modify') . '">';
 			print '</form>';
 		} else {
-		print $book->code_journal ;
+		print $object->code_journal ;
 		}
 		print '</td>';
 		print '</tr>';
@@ -468,22 +466,22 @@ if ($action == 'create')
 		// Ref document
 		print '<tr><td>';
 		print '<table class="nobordernopadding" width="100%"><tr><td>';
-		print $langs->trans('Docref');
+		print $langs->trans('Piece');
 		print '</td>';
 		if ($action != 'editdocref')
-		print '<td align="right"><a href="'.$_SERVER["PHP_SELF"].'?action=editdocref&amp;piece_num='.$book->piece_num.'&amp;mode='. $mode .'">'.img_edit($langs->transnoentitiesnoconv('Edit'),1).'</a></td>';
+		print '<td align="right"><a href="'.$_SERVER["PHP_SELF"].'?action=editdocref&amp;piece_num='.$object->piece_num.'&amp;mode='. $mode .'">'.img_edit($langs->transnoentitiesnoconv('Edit'),1).'</a></td>';
 		print '</tr></table>';
 		print '</td><td>';
 		if ($action == 'editdocref') {
-			print '<form name="setdocref" action="' . $_SERVER["PHP_SELF"] . '?piece_num=' . $book->piece_num . '" method="post">';
+			print '<form name="setdocref" action="' . $_SERVER["PHP_SELF"] . '?piece_num=' . $object->piece_num . '" method="post">';
 			print '<input type="hidden" name="token" value="' . $_SESSION ['newtoken'] . '">';
 			print '<input type="hidden" name="action" value="setdocref">';
 			print '<input type="hidden" name="mode" value="'.$mode.'">';
-			print '<input type="text" size="20" name="doc_ref" value="'.dol_escape_htmltag($book->doc_ref).'">';
+			print '<input type="text" size="20" name="doc_ref" value="'.dol_escape_htmltag($object->doc_ref).'">';
 			print '<input type="submit" class="button" value="' . $langs->trans('Modify') . '">';
 			print '</form>';
 		} else {
-			print $book->doc_ref ;
+			print $object->doc_ref ;
 		}
 		print '</td>';
 		print '</tr>';
@@ -498,11 +496,11 @@ if ($action == 'create')
 		print '<table class="border tableforfield" width="100%">';
 
 		// Doc type
-		if(! empty($book->doc_type))
+		if(! empty($object->doc_type))
 		{
 			print '<tr>';
 			print '<td class="titlefield">' . $langs->trans("Doctype") . '</td>';
-			print '<td>' . $book->doc_type . '</td>';
+			print '<td>' . $object->doc_type . '</td>';
 			print '</tr>';
 		}
 
@@ -510,7 +508,7 @@ if ($action == 'create')
 		print '<tr>';
 		print '<td class="titlefield">' . $langs->trans("DateCreation") . '</td>';
 		print '<td>';
-		print $book->date_creation ? dol_print_date($book->date_creation, 'day') : '&nbsp;';
+		print $object->date_creation ? dol_print_date($object->date_creation, 'day') : '&nbsp;';
 		print '</td>';
 		print '</tr>';
 
@@ -519,7 +517,7 @@ if ($action == 'create')
 		print '<tr>';
 		print '<td class="titlefield">' . $langs->trans("Status") . '</td>';
 		print '<td>';
-			if (empty($book->validated)) {
+			if (empty($object->validated)) {
 				print '<a href="' . $_SERVER["PHP_SELF"] . '?piece_num=' . $line->rowid . '&action=enable">';
 				print img_picto($langs->trans("Disabled"), 'switch_off');
 				print '</a>';
@@ -536,11 +534,11 @@ if ($action == 'create')
 		/*
 		print '<tr>';
 		print '<td class="titlefield">' . $langs->trans("Control") . '</td>';
-		if ($book->doc_type == 'customer_invoice')
+		if ($object->doc_type == 'customer_invoice')
 		{
 		 $sqlmid = 'SELECT rowid as ref';
 			$sqlmid .= " FROM ".MAIN_DB_PREFIX."facture as fac";
-			$sqlmid .= " WHERE fac.rowid=" . $book->fk_doc;
+			$sqlmid .= " WHERE fac.rowid=" . $object->fk_doc;
 			dol_syslog("accountancy/bookkeeping/card.php::sqlmid=" . $sqlmid, LOG_DEBUG);
 			$resultmid = $db->query($sqlmid);
 			if ($resultmid) {
@@ -563,24 +561,24 @@ if ($action == 'create')
 
 		print '<br>';
 
-		$result = $book->fetchAllPerMvt($piece_num, $mode);
+		$result = $object->fetchAllPerMvt($piece_num, $mode);
 		if ($result < 0) {
-			setEventMessages($book->error, $book->errors, 'errors');
+			setEventMessages($object->error, $object->errors, 'errors');
 		} else {
 
 			print load_fiche_titre($langs->trans("ListeMvts"), '', '');
 
-			print '<form action="' . $_SERVER["PHP_SELF"] . '?piece_num=' . $book->piece_num . '" method="post">';
-			print '<input type="hidden" name="doc_date" value="' . $book->doc_date . '">' . "\n";
-			print '<input type="hidden" name="doc_type" value="' . $book->doc_type . '">' . "\n";
-			print '<input type="hidden" name="doc_ref" value="' . $book->doc_ref . '">' . "\n";
-			print '<input type="hidden" name="code_journal" value="' . $book->code_journal . '">' . "\n";
-			print '<input type="hidden" name="fk_doc" value="' . $book->fk_doc . '">' . "\n";
-			print '<input type="hidden" name="fk_docdet" value="' . $book->fk_docdet . '">' . "\n";
+			print '<form action="' . $_SERVER["PHP_SELF"] . '?piece_num=' . $object->piece_num . '" method="post">';
+			print '<input type="hidden" name="doc_date" value="' . $object->doc_date . '">' . "\n";
+			print '<input type="hidden" name="doc_type" value="' . $object->doc_type . '">' . "\n";
+			print '<input type="hidden" name="doc_ref" value="' . $object->doc_ref . '">' . "\n";
+			print '<input type="hidden" name="code_journal" value="' . $object->code_journal . '">' . "\n";
+			print '<input type="hidden" name="fk_doc" value="' . $object->fk_doc . '">' . "\n";
+			print '<input type="hidden" name="fk_docdet" value="' . $object->fk_docdet . '">' . "\n";
 			print '<input type="hidden" name="mode" value="' . $mode . '">' . "\n";
 
 			print "<table class=\"noborder\" width=\"100%\">";
-			if (count($book->linesmvt) > 0) {
+			if (count($object->linesmvt) > 0) {
 
 				$total_debit = 0;
 				$total_credit = 0;
@@ -597,7 +595,7 @@ if ($action == 'create')
 
 				print "</tr>\n";
 
-				foreach ($book->linesmvt as $line) {
+				foreach ($object->linesmvt as $line) {
 					print '<tr class="oddeven">';
 					$total_debit += $line->debit;
 					$total_credit += $line->credit;
@@ -692,7 +690,7 @@ if ($action == 'create')
 					print '<div class="center">';
 					if ($total_debit == $total_credit)
 					{
-						print '<a class="button" href="' . $_SERVER["PHP_SELF"] . '?piece_num=' . $book->piece_num . '&action=valid">'.$langs->trans("ValidTransaction").'</a>';
+						print '<a class="button" href="' . $_SERVER["PHP_SELF"] . '?piece_num=' . $object->piece_num . '&action=valid">'.$langs->trans("ValidTransaction").'</a>';
 					}
 					else
 					{

+ 10 - 0
htdocs/admin/mails.php

@@ -71,6 +71,7 @@ if ($action == 'update' && empty($_POST["cancel"]))
 {
 	dolibarr_set_const($db, "MAIN_DISABLE_ALL_MAILS",     GETPOST("MAIN_DISABLE_ALL_MAILS"),'chaine',0,'',$conf->entity);
 	dolibarr_set_const($db, "MAIN_MAIL_FORCE_SENDTO",     GETPOST("MAIN_MAIL_FORCE_SENDTO"),'chaine',0,'',$conf->entity);
+	dolibarr_set_const($db, "MAIN_MAIL_ENABLED_USER_DEST_SELECT",     GETPOST("MAIN_MAIL_ENABLED_USER_DEST_SELECT"),'chaine',0,'',$conf->entity);
 	// Send mode parameters
 	dolibarr_set_const($db, "MAIN_MAIL_SENDMODE",         GETPOST("MAIN_MAIL_SENDMODE"),'chaine',0,'',$conf->entity);
 	dolibarr_set_const($db, "MAIN_MAIL_SMTP_PORT",        GETPOST("MAIN_MAIL_SMTP_PORT"),'chaine',0,'',$conf->entity);
@@ -275,6 +276,12 @@ if ($action == 'edit')
 	print '<input class="flat" name="MAIN_MAIL_FORCE_SENDTO" size="32" value="' . (! empty($conf->global->MAIN_MAIL_FORCE_SENDTO)?$conf->global->MAIN_MAIL_FORCE_SENDTO:'') . '" />';
 	print '</td></tr>';
 
+
+	//Add user to select destinaries list
+	print '<tr class="oddeven"><td>'.$langs->trans("MAIN_MAIL_ENABLED_USER_DEST_SELECT").'</td><td>';
+	print $form->selectyesno('MAIN_MAIL_ENABLED_USER_DEST_SELECT',$conf->global->MAIN_MAIL_ENABLED_USER_DEST_SELECT,1);
+	print '</td></tr>';
+
 	// Separator
 
 	print '<tr class="oddeven"><td colspan="2">&nbsp;</td></tr>';
@@ -544,6 +551,9 @@ else
 	if (! empty($conf->global->MAIN_MAIL_FORCE_SENDTO) && ! isValidEmail($conf->global->MAIN_MAIL_FORCE_SENDTO)) print img_warning($langs->trans("ErrorBadEMail"));
 	print '</td></tr>';
 
+	//Add user to select destinaries list
+	print '<tr class="oddeven"><td>'.$langs->trans("MAIN_MAIL_ENABLED_USER_DEST_SELECT").'</td><td>'.yn($conf->global->MAIN_MAIL_ENABLED_USER_DEST_SELECT).'</td></tr>';
+
 	// Separator
 
 	print '<tr class="oddeven"><td colspan="2">&nbsp;</td></tr>';

+ 8 - 0
htdocs/core/actions_massactions.inc.php

@@ -357,6 +357,14 @@ if (! $error && $massaction == 'confirm_presend')
 					$substitutionarray['__CHECK_READ__'] = '<img src="'.DOL_MAIN_URL_ROOT.'/public/emailing/mailing-read.php?tag='.$thirdparty->tag.'&securitykey='.urlencode($conf->global->MAILING_EMAIL_UNSUBSCRIBE_KEY).'" width="1" height="1" style="width:1px;height:1px" border="0"/>';
 
 					$parameters=array('mode'=>'formemail');
+
+					if ( ! empty( $listofobjectthirdparties ) ) {
+						$parameters['listofobjectthirdparties'] = $listofobjectthirdparties;
+					}
+					if ( ! empty( $listofobjectref ) ) {
+						$parameters['listofobjectref'] = $listofobjectref;
+					}
+
 					complete_substitutions_array($substitutionarray, $langs, $objecttmp, $parameters);
 
 					$subject=make_substitutions($subject, $substitutionarray);

+ 41 - 34
htdocs/core/actions_sendmails.inc.php

@@ -129,38 +129,14 @@ if (($action == 'send' || $action == 'relance') && ! $_POST['addfile'] && ! $_PO
 		{
 			$thirdparty=$object;
 			if ($thirdparty->id > 0) $sendtosocid=$thirdparty->id;
-			elseif (! empty($conf->dolimail->enabled))
-			{
-				$dolimail = new Dolimail($db);
-				$possibleaccounts=$dolimail->get_societe_by_email($_POST['sendto'],"1");
-				$possibleuser=$dolimail->get_from_user_by_mail($_POST['sendto'],"1"); // suche in llx_societe and socpeople
-				if (!$possibleaccounts && !$possibleuser)
-				{
-					setEventMessages($langs->trans('ErrorFailedToFindSocieteRecord',$_POST['sendto']), null, 'errors');
-				}
-				elseif (count($possibleaccounts)>1)
-				{
-					$sendtosocid=$possibleaccounts[1]['id'];
-					$result=$object->fetch($sendtosocid);
-
-					setEventMessages($langs->trans('ErrorFoundMoreThanOneRecordWithEmail',$_POST['sendto'],$object->name), null, 'mesgs');
-				}
-				else
-				{
-					if($possibleaccounts){
-						$sendtosocid=$possibleaccounts[1]['id'];
-						$result=$object->fetch($sendtosocid);
-					}elseif($possibleuser){
-						$sendtosocid=$possibleuser[0]['id'];
-
-						$result=$uobject->fetch($sendtosocid);
-						$object=$uobject;
-					}
-
-				}
-			}
 		}
 		else dol_print_error('','Use actions_sendmails.in.php for an element/object that is not supported');
+
+		if (is_object($hookmanager))
+		{
+			$parameters=array();
+			$reshook=$hookmanager->executeHooks('initSendToSocid',$parameters,$object,$action);    // Note that $action and $object may have been modified by some hooks
+		}
 	}
 	else $thirdparty = $mysoc;
 
@@ -170,6 +146,9 @@ if (($action == 'send' || $action == 'relance') && ! $_POST['addfile'] && ! $_PO
 		$sendtocc='';
 		$sendtobcc='';
 		$sendtoid = array();
+		if (!empty($conf->global->MAIN_MAIL_ENABLED_USER_DEST_SELECT)) {
+			$sendtouserid=array();
+		}
 
 		// Define $sendto
 		$receiver=$_POST['receiver'];
@@ -200,6 +179,18 @@ if (($action == 'send' || $action == 'relance') && ! $_POST['addfile'] && ! $_PO
 				}
 			}
 		}
+		if (!empty($conf->global->MAIN_MAIL_ENABLED_USER_DEST_SELECT)) {
+			$receiveruser=$_POST['receiveruser'];
+			if (is_array($receiveruser) && count($receiveruser)>0)
+			{
+				$fuserdest = new User($db);
+				foreach($receiveruser as $key=>$val)
+				{
+					$tmparray[] = $fuserdest->user_get_property($key,'email');
+					$sendtouserid[] = $key;
+				}
+			}
+		}
 		$sendto=implode(',',$tmparray);
 
 		// Define $sendtocc
@@ -230,6 +221,19 @@ if (($action == 'send' || $action == 'relance') && ! $_POST['addfile'] && ! $_PO
 				}
 			}
 		}
+		if (!empty($conf->global->MAIN_MAIL_ENABLED_USER_DEST_SELECT)) {
+			$receiveruser=$_POST['receiveccruser'];
+
+			if (is_array($receiveruser) && count($receiveruser)>0)
+			{
+				$fuserdest = new User($db);
+				foreach($receiveruser as $key=>$val)
+				{
+					$tmparray[] = $fuserdest->user_get_property($key,'email');
+					$sendtouserid[] = $key;
+				}
+			}
+		}
 		$sendtocc=implode(',',$tmparray);
 
 		if (dol_strlen($sendto))
@@ -430,6 +434,9 @@ if (($action == 'send' || $action == 'relance') && ! $_POST['addfile'] && ! $_PO
 						if (is_array($attachedfiles) && count($attachedfiles)>0) {
 							$object->attachedfiles	= $attachedfiles;
 						}
+						if (is_array($sendtouserid) && count($sendtouserid)>0 && !empty($conf->global->MAIN_MAIL_ENABLED_USER_DEST_SELECT)) {
+							$object->sendtouserid	= $sendtouserid;
+						}
 
 						// Call of triggers
 						if (! empty($trigger_name))
@@ -448,10 +455,10 @@ if (($action == 'send' || $action == 'relance') && ! $_POST['addfile'] && ! $_PO
 					$mesg=$langs->trans('MailSuccessfulySent',$mailfile->getValidAddress($from,2),$mailfile->getValidAddress($sendto,2));
 					setEventMessages($mesg, null, 'mesgs');
 
-					$moreparam='';
-					if (isset($paramname2) || isset($paramval2)) $moreparam.= '&'.($paramname2?$paramname2:'mid').'='.$paramval2;
-					header('Location: '.$_SERVER["PHP_SELF"].'?'.($paramname?$paramname:'id').'='.(is_object($object)?$object->id:'').$moreparam);
-					exit;
+  					$moreparam='';
+	  				if (isset($paramname2) || isset($paramval2)) $moreparam.= '&'.($paramname2?$paramname2:'mid').'='.$paramval2;
+		  			header('Location: '.$_SERVER["PHP_SELF"].'?'.($paramname?$paramname:'id').'='.(is_object($object)?$object->id:'').$moreparam);
+			  		exit;
 				}
 				else
 				{

+ 47 - 0
htdocs/core/class/html.formmail.class.php

@@ -81,6 +81,9 @@ class FormMail extends Form
 	var $substit_lines=array();
 	var $param=array();
 
+	public $withtouser=array();
+	public $withtoccuser=array();
+
 	var $error;
 
 	public $lines_model;
@@ -624,6 +627,28 @@ class FormMail extends Form
 				$out.= "</td></tr>\n";
 			}
 
+			// To User
+			if (! empty($this->withtouser) && is_array($this->withtouser) && !empty($conf->global->MAIN_MAIL_ENABLED_USER_DEST_SELECT))
+			{
+				$out.= '<tr><td>';
+				$out.= $langs->trans("MailToSalaries");
+				$out.= '</td><td>';
+
+				// multiselect array convert html entities into options tags, even if we dont want this, so we encode them a second time
+				$tmparray = $this->withtouser;
+				foreach($tmparray as $key => $val)
+				{
+					$tmparray[$key]=dol_htmlentities($tmparray[$key], null, 'UTF-8', true);
+				}
+				$withtoselected=GETPOST("receiveruser",'none');     // Array of selected value
+				if (empty($withtoselected) && count($tmparray) == 1 && GETPOST('action','aZ09') == 'presend')
+				{
+					$withtoselected = array_keys($tmparray);
+				}
+				$out.= $form->multiselectarray("receiveruser", $tmparray, $withtoselected, null, null, 'inline-block minwidth500', null, "");
+				$out.= "</td></tr>\n";
+			}
+
 			// withoptiononeemailperrecipient
 			if (! empty($this->withoptiononeemailperrecipient))
 			{
@@ -668,6 +693,28 @@ class FormMail extends Form
 				$out.= "</td></tr>\n";
 			}
 
+			// To User cc
+			if (! empty($this->withtoccuser) && is_array($this->withtoccuser) && !empty($conf->global->MAIN_MAIL_ENABLED_USER_DEST_SELECT))
+			{
+				$out.= '<tr><td>';
+				$out.= $langs->trans("MailToCCSalaries");
+				$out.= '</td><td>';
+
+				// multiselect array convert html entities into options tags, even if we dont want this, so we encode them a second time
+				$tmparray = $this->withtoccuser;
+				foreach($tmparray as $key => $val)
+				{
+					$tmparray[$key]=dol_htmlentities($tmparray[$key], null, 'UTF-8', true);
+				}
+				$withtoselected=GETPOST("receiverccuser",'none');     // Array of selected value
+				if (empty($withtoselected) && count($tmparray) == 1 && GETPOST('action','aZ09') == 'presend')
+				{
+					$withtoselected = array_keys($tmparray);
+				}
+				$out.= $form->multiselectarray("receiverccuser", $tmparray, $withtoselected, null, null, 'inline-block minwidth500', null, "");
+				$out.= "</td></tr>\n";
+			}
+
 			// CCC
 			if (! empty($this->withtoccc) || is_array($this->withtoccc))
 			{

+ 22 - 0
htdocs/core/lib/functions.lib.php

@@ -7145,6 +7145,28 @@ function natural_search($fields, $value, $mode=0, $nofirstand=0)
 					$i2++;	// a criteria was added to string
 				}
 			}
+			else if ($mode == 4)
+			{
+			    $tmparray=explode(',',trim($crit));
+			    
+			    if (count($tmparray))
+			    {
+			        $listofcodes='';
+			        
+			        foreach($tmparray as $val)
+			        {
+			            if ($val)
+			            {
+			                $newres .= ($i2 > 0 ? ' OR (' : '(') . $field . ' LIKE \'' . $db->escape(trim($val)) . ',%\'';
+			                $newres .= ' OR '. $field . ' = \'' . $db->escape(trim($val)) . '\''; 
+			                $newres .= ' OR '. $field . ' LIKE \'%,' . $db->escape(trim($val)) . '\'';
+			                $newres .= ' OR '. $field . ' LIKE \'%,' . $db->escape(trim($val)) . ',%\'';
+					$newres .= ')';
+			                $i2++;
+			            }
+			        }
+			    }
+			}
 			else    // $mode=0
 			{
 				$textcrit = '';

+ 18 - 0
htdocs/core/tpl/card_presend.tpl.php

@@ -152,6 +152,24 @@ if ($action == 'presend')
 			}
 		}
 	}
+	if (!empty($conf->global->MAIN_MAIL_ENABLED_USER_DEST_SELECT)) {
+		$listeuser=array();
+		$fuserdest = new User($db);
+
+		$result= $fuserdest->fetchAll('ASC', 't.lastname', 0, 0, array('customsql'=>'t.statut=1 AND t.employee=1 AND t.email IS NOT NULL AND t.email<>\'\''));
+		if ($result>0 && is_array($fuserdest->users) && count($fuserdest->users)>0) {
+			foreach($fuserdest->users as $uuserdest) {
+				$listeuser[$uuserdest->id] = $uuserdest->user_get_property($uuserdest->id,'email');
+			}
+		} elseif ($result<0) {
+			setEventMessages(null, $fuserdest->errors,'errors');
+		}
+		if (count($listeuser)>0) {
+			$formmail->withtouser = $listeuser;
+			$formmail->withtoccuser = $listeuser;
+		}
+
+	}
 
 	$formmail->withto = GETPOST('sendto') ? GETPOST('sendto') : $liste;
 	$formmail->withtocc = $liste;

+ 2 - 1
htdocs/core/tpl/extrafields_list_search_sql.tpl.php

@@ -15,7 +15,8 @@ foreach ($search_array_options as $key => $val)
 	$typ=$extrafields->attribute_type[$tmpkey];
 	$mode_search=0;
 	if (in_array($typ, array('int','double','real'))) $mode_search=1;								// Search on a numeric
-	if (in_array($typ, array('sellist','link','chkbxlst','checkbox')) && $crit != '0' && $crit != '-1') $mode_search=2;	// Search on a foreign key int
+	if (in_array($typ, array('sellist','link')) && $crit != '0' && $crit != '-1') $mode_search=2;	// Search on a foreign key int
+	if (in_array($typ, array('chkbxlst','checkbox'))) $mode_search=4;	                            // Search on a multiselect field with sql type = text
 	if ($crit != '' && (! in_array($typ, array('select','sellist')) || $crit != '0') && (! in_array($typ, array('link')) || $crit != '-1'))
 	{
 		$sql .= natural_search('ef.'.$tmpkey, $crit, $mode_search);

+ 4 - 0
htdocs/core/triggers/interface_50_modAgenda_ActionsAuto.class.php

@@ -889,6 +889,10 @@ class InterfaceActionsAuto extends DolibarrTriggers
 		$actioncomm->fk_element  = $elementid;
 		$actioncomm->elementtype = $elementtype;
 
+		if (property_exists($object,'sendtouserid') && is_array($object->sendtouserid) && count($object->sendtouserid)>0) {
+			$actioncomm->userassigned=$object->sendtouserid;
+		}
+
 		$ret=$actioncomm->create($user);       // User creating action
 
 		if ($ret > 0 && $conf->global->MAIN_COPY_FILE_IN_EVENT_AUTO)

+ 13 - 9
htdocs/holiday/list.php

@@ -461,15 +461,19 @@ else
 
 // Type
 print '<td class="liste_titre">';
-$typeleaves=$holidaystatic->getTypes(1,-1);
-$arraytypeleaves=array();
-foreach($typeleaves as $key => $val)
-{
-	$labeltoshow = ($langs->trans($val['code'])!=$val['code'] ? $langs->trans($val['code']) : $val['label']);
-    //$labeltoshow .= ($val['delay'] > 0 ? ' ('.$langs->trans("NoticePeriod").': '.$val['delay'].' '.$langs->trans("days").')':'');
-    $arraytypeleaves[$val['rowid']]=$labeltoshow;
+if (empty($mysoc->country_id)) {
+	setEventMessages(null, array($langs->trans("ErrorSetACountryFirst"),$langs->trans("CompanyFoundation")),'errors');
+} else {
+	$typeleaves=$holidaystatic->getTypes(1,-1);
+	$arraytypeleaves=array();
+	foreach($typeleaves as $key => $val)
+	{
+		$labeltoshow = ($langs->trans($val['code'])!=$val['code'] ? $langs->trans($val['code']) : $val['label']);
+		//$labeltoshow .= ($val['delay'] > 0 ? ' ('.$langs->trans("NoticePeriod").': '.$val['delay'].' '.$langs->trans("days").')':'');
+		$arraytypeleaves[$val['rowid']]=$labeltoshow;
+	}
+	print $form->selectarray('search_type', $arraytypeleaves, $search_type, 1);
 }
-print $form->selectarray('search_type', $arraytypeleaves, $search_type, 1);
 print '</td>';
 
 // Duration
@@ -524,7 +528,7 @@ if ($id && empty($user->rights->holiday->read_all) && ! in_array($id, $childids)
 	$result = 0;
 }
 // Lines
-elseif (! empty($holiday->holiday))
+elseif (! empty($holiday->holiday) && !empty($mysoc->country_id))
 {
 	$userstatic = new User($db);
 	$approbatorstatic = new User($db);

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

@@ -273,6 +273,7 @@ MAIN_MAIL_ERRORS_TO=Email used as 'Errors-To' field in emails sent
 MAIN_MAIL_AUTOCOPY_TO= Send systematically a hidden carbon-copy of all sent emails to
 MAIN_DISABLE_ALL_MAILS=Disable all emails sendings (for test purposes or demos)
 MAIN_MAIL_FORCE_SENDTO=Send all emails to (instead of real recipients, for test purposes)
+MAIN_MAIL_ENABLED_USER_DEST_SELECT=Add salaries users with email into allowed destinaries list
 MAIN_MAIL_SENDMODE=Method to use to send EMails
 MAIN_MAIL_SMTPS_ID=SMTP ID if authentication required
 MAIN_MAIL_SMTPS_PW=SMTP Password if authentication required

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

@@ -11,7 +11,9 @@ MailFrom=Sender
 MailErrorsTo=Errors to
 MailReply=Reply to
 MailTo=Receiver(s)
+MailToSalaries=To salarie(s)
 MailCC=Copy to
+MailToCCSalaries=Copy to salarie(s)
 MailCCC=Cached copy to
 MailTopic=EMail topic
 MailText=Message

+ 1 - 0
htdocs/modulebuilder/template/myobject_list.php

@@ -205,6 +205,7 @@ $help_url='';
 $title = $langs->trans('ListOf', $langs->transnoentitiesnoconv("MyObjects"));
 
 
+// TODO : move this SQL request into fetchAll class method
 // Build and execute select
 // --------------------------------------------------------------------
 $sql = 'SELECT ';

+ 2 - 2
htdocs/supplier_proposal/class/supplier_proposal.class.php

@@ -838,8 +838,8 @@ class SupplierProposal extends CommonObject
         $sql.= ", '".$this->db->escape($this->note_private)."'";
         $sql.= ", '".$this->db->escape($this->note_public)."'";
         $sql.= ", '".$this->db->escape($this->modelpdf)."'";
-        $sql.= ", ".$this->cond_reglement_id;
-        $sql.= ", ".$this->mode_reglement_id;
+        $sql.= ", ".($this->cond_reglement_id > 0 ? $this->cond_reglement_id : 'NULL');
+        $sql.= ", ".($this->mode_reglement_id > 0 ? $this->mode_reglement_id : 'NULL');
         $sql.= ", ".($this->fk_account>0?$this->fk_account:'NULL');
         $sql.= ", ".($this->date_livraison!=''?"'".$this->db->idate($this->date_livraison)."'":"null");
         $sql.= ", ".($this->shipping_method_id>0?$this->shipping_method_id:'NULL');

+ 101 - 1
htdocs/user/class/user.class.php

@@ -115,7 +115,7 @@ class User extends CommonObject
 	public $lastsearch_values_tmp;  // To store current search criterias for user
 	public $lastsearch_values;      // To store last saved search criterias for user
 
-	public $users;					// To store all tree of users hierarchy
+	public $users = array();		// To store all tree of users hierarchy
 	public $parentof;				// To store an array of all parents for all ids.
 	private $cache_childids;
 
@@ -3003,5 +3003,105 @@ class User extends CommonObject
 		return $this->commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref);
 	}
 
+	/**
+	 *  Return property of user from its id
+	 *
+	 *  @param	int		$rowid      id of contact
+	 *  @param  string	$mode       'email' or 'mobile'
+	 *  @return string  			Email of user with format: "Full name <email>"
+	 */
+	function user_get_property($rowid,$mode)
+	{
+		$user_property='';
+
+		if (empty($rowid)) return '';
+
+		$sql = "SELECT rowid, email, user_mobile, civility, lastname, firstname";
+		$sql.= " FROM ".MAIN_DB_PREFIX."user";
+		$sql.= " WHERE rowid = '".$rowid."'";
+
+		$resql=$this->db->query($sql);
+		if ($resql)
+		{
+			$nump = $this->db->num_rows($resql);
+
+			if ($nump)
+			{
+				$obj = $this->db->fetch_object($resql);
+
+				if ($mode == 'email') $user_property = dolGetFirstLastname($obj->firstname, $obj->lastname)." <".$obj->email.">";
+				else if ($mode == 'mobile') $user_property = $obj->user_mobile;
+			}
+			return $user_property;
+		}
+		else
+		{
+			dol_print_error($this->db);
+		}
+	}
+
+	/**
+	 *	Load all objects into $this->users
+	 *
+	 *  @param	string		$sortorder    sort order
+	 *  @param	string		$sortfield    sort field
+	 *  @param	int			$limit		  limit page
+	 *  @param	int			$offset    	  page
+	 *  @param	array		$filter    	  filter output
+	 *  @return int          	<0 if KO, >0 if OK
+	 */
+	function fetchAll($sortorder='', $sortfield='', $limit=0, $offset=0, $filter=array())
+	{
+		global $conf;
+
+		$sql="SELECT t.rowid";
+		$sql.= ' FROM '.MAIN_DB_PREFIX .$this->table_element.' as t ';
+		$sql.= " WHERE 1";
+
+		//Manage filter
+		if (!empty($filter)){
+			foreach($filter as $key => $value) {
+				if (strpos($key,'date')) {
+					$sql.= ' AND '.$key.' = \''.$this->db->idate($value).'\'';
+				}
+				elseif ($key=='customsql') {
+					$sql.= ' AND '.$value;
+				} else {
+					$sql.= ' AND '.$key.' LIKE \'%'.$value.'%\'';
+				}
+			}
+		}
+		$sql.= $this->db->order($sortfield,$sortorder);
+		if ($limit) $sql.= $this->db->plimit($limit+1,$offset);
+
+		dol_syslog(get_class($this)."::".__METHOD__, LOG_DEBUG);
+
+		$resql=$this->db->query($sql);
+		if ($resql)
+		{
+			$this->users=array();
+			$num = $this->db->num_rows($resql);
+			if ($num)
+			{
+				while ($obj = $this->db->fetch_object($resql))
+				{
+					$line = new self($this->db);
+					$result = $line->fetch($obj->rowid);
+					if ($result>0 && !empty($line->id)) {
+						$this->users[$obj->rowid] = clone $line;
+					}
+				}
+				$this->db->free($resql);
+			}
+			return $num;
+		}
+		else
+		{
+			$this->errors[] = $this->db->lasterror();
+			return -1;
+		}
+
+	}
+
 }