diff --git a/README-FR.md b/README-FR.md index 8e6a2c5aac0..a9745bb8dbb 100644 --- a/README-FR.md +++ b/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)]. + ## CREDITS diff --git a/README.md b/README.md index 3d9ba75f1f5..b68e8b65558 100644 --- a/README.md +++ b/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)]. + ## 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)] diff --git a/htdocs/accountancy/admin/categories.php b/htdocs/accountancy/admin/categories.php index a91c22ffe4c..69d09ae301b 100644 --- a/htdocs/accountancy/admin/categories.php +++ b/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') { diff --git a/htdocs/accountancy/bookkeeping/card.php b/htdocs/accountancy/bookkeeping/card.php index f655d245e86..885b090fe0c 100644 --- a/htdocs/accountancy/bookkeeping/card.php +++ b/htdocs/accountancy/bookkeeping/card.php @@ -1,8 +1,8 @@ - * Copyright (C) 2013-2017 Florian Henry - * Copyright (C) 2013-2017 Alexandre Spangaro - * Copyright (C) 2017 Laurent Destailleur +/* Copyright (C) 2013-2017 Olivier Geffroy + * Copyright (C) 2013-2017 Florian Henry + * Copyright (C) 2013-2018 Alexandre Spangaro + * Copyright (C) 2017 Laurent Destailleur * * 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); + $object = 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->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; + $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 = $book->createStd($user,0, $mode); + $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 ''; print ''; - print '' . $langs->trans("Docref") . ''; + print '' . $langs->trans("Piece") . ''; print ''; print ''; @@ -384,13 +382,13 @@ if ($action == 'create') print ''; } 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 = '' . $langs->trans('BackToList') . ''; @@ -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 '
'; print '
'; @@ -416,7 +414,7 @@ if ($action == 'create') // Account movement print ''; print '' . $langs->trans("NumMvts") . ''; - print '' . $book->piece_num . ''; + print '' . $object->piece_num . ''; print ''; // Date @@ -425,19 +423,19 @@ if ($action == 'create') print $langs->trans('Docdate'); print ''; if ($action != 'editdate') - print 'piece_num .'&mode='. $mode .'">'.img_edit($langs->transnoentitiesnoconv('SetDate'),1).''; + print 'piece_num .'&mode='. $mode .'">'.img_edit($langs->transnoentitiesnoconv('SetDate'),1).''; print ''; print ''; if ($action == 'editdate') { - print '
'; + print ''; print ''; print ''; print ''; - $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 ''; print '
'; } else { - print $book->doc_date ? dol_print_date($book->doc_date, 'day') : ' '; + print $object->doc_date ? dol_print_date($object->doc_date, 'day') : ' '; } print ''; print ''; @@ -448,19 +446,19 @@ if ($action == 'create') print $langs->trans('Codejournal'); print ''; if ($action != 'editjournal') - print 'piece_num.'&mode='. $mode .'">'.img_edit($langs->transnoentitiesnoconv('Edit'),1).''; + print 'piece_num.'&mode='. $mode .'">'.img_edit($langs->transnoentitiesnoconv('Edit'),1).''; print ''; print ''; if ($action == 'editjournal') { - print '
'; + print ''; print ''; print ''; print ''; - 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 ''; print '
'; } else { - print $book->code_journal ; + print $object->code_journal ; } print ''; print ''; @@ -468,22 +466,22 @@ if ($action == 'create') // Ref document print ''; print ''; if ($action != 'editdocref') - print ''; + print ''; print '
'; - print $langs->trans('Docref'); + print $langs->trans('Piece'); print 'piece_num.'&mode='. $mode .'">'.img_edit($langs->transnoentitiesnoconv('Edit'),1).'piece_num.'&mode='. $mode .'">'.img_edit($langs->transnoentitiesnoconv('Edit'),1).'
'; print ''; if ($action == 'editdocref') { - print '
'; + print ''; print ''; print ''; print ''; - print ''; + print ''; print ''; print '
'; } else { - print $book->doc_ref ; + print $object->doc_ref ; } print ''; print ''; @@ -498,11 +496,11 @@ if ($action == 'create') print ''; // Doc type - if(! empty($book->doc_type)) + if(! empty($object->doc_type)) { print ''; print ''; - print ''; + print ''; print ''; } @@ -510,7 +508,7 @@ if ($action == 'create') print ''; print ''; print ''; print ''; @@ -519,7 +517,7 @@ if ($action == 'create') print ''; print ''; print ''; print ''; - 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 '
'; - $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 ''; - print '' . "\n"; - print '' . "\n"; - print '' . "\n"; - print '' . "\n"; - print '' . "\n"; - print '' . "\n"; + print ''; + print '' . "\n"; + print '' . "\n"; + print '' . "\n"; + print '' . "\n"; + print '' . "\n"; + print '' . "\n"; print '' . "\n"; print "
' . $langs->trans("Doctype") . '' . $book->doc_type . '' . $object->doc_type . '
' . $langs->trans("DateCreation") . ''; - print $book->date_creation ? dol_print_date($book->date_creation, 'day') : ' '; + print $object->date_creation ? dol_print_date($object->date_creation, 'day') : ' '; print '
' . $langs->trans("Status") . ''; - if (empty($book->validated)) { + if (empty($object->validated)) { print ''; print img_picto($langs->trans("Disabled"), 'switch_off'); print ''; @@ -536,11 +534,11 @@ if ($action == 'create') /* print '
' . $langs->trans("Control") . '
"; - if (count($book->linesmvt) > 0) { + if (count($object->linesmvt) > 0) { $total_debit = 0; $total_credit = 0; @@ -597,7 +595,7 @@ if ($action == 'create') print "\n"; - foreach ($book->linesmvt as $line) { + foreach ($object->linesmvt as $line) { print ''; $total_debit += $line->debit; $total_credit += $line->credit; @@ -692,7 +690,7 @@ if ($action == 'create') print '
'; if ($total_debit == $total_credit) { - print ''.$langs->trans("ValidTransaction").''; + print ''.$langs->trans("ValidTransaction").''; } else { diff --git a/htdocs/admin/mails.php b/htdocs/admin/mails.php index 28d243a3b13..f85853f5b97 100644 --- a/htdocs/admin/mails.php +++ b/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 ''; print '
'; + + //Add user to select destinaries list + print ''; + // Separator print ''; @@ -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 ''; + //Add user to select destinaries list + print ''; + // Separator print ''; diff --git a/htdocs/core/actions_massactions.inc.php b/htdocs/core/actions_massactions.inc.php index 9a9298528eb..4894212fa07 100644 --- a/htdocs/core/actions_massactions.inc.php +++ b/htdocs/core/actions_massactions.inc.php @@ -357,6 +357,14 @@ if (! $error && $massaction == 'confirm_presend') $substitutionarray['__CHECK_READ__'] = ''; $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); diff --git a/htdocs/core/actions_sendmails.inc.php b/htdocs/core/actions_sendmails.inc.php index 419180d6830..f1ab9305a4d 100644 --- a/htdocs/core/actions_sendmails.inc.php +++ b/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 { diff --git a/htdocs/core/class/html.formmail.class.php b/htdocs/core/class/html.formmail.class.php index ef3ff52dcfe..c5d66bc6791 100644 --- a/htdocs/core/class/html.formmail.class.php +++ b/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.= "\n"; } + // To User + if (! empty($this->withtouser) && is_array($this->withtouser) && !empty($conf->global->MAIN_MAIL_ENABLED_USER_DEST_SELECT)) + { + $out.= '\n"; + } + // withoptiononeemailperrecipient if (! empty($this->withoptiononeemailperrecipient)) { @@ -668,6 +693,28 @@ class FormMail extends Form $out.= "\n"; } + // To User cc + if (! empty($this->withtoccuser) && is_array($this->withtoccuser) && !empty($conf->global->MAIN_MAIL_ENABLED_USER_DEST_SELECT)) + { + $out.= '\n"; + } + // CCC if (! empty($this->withtoccc) || is_array($this->withtoccc)) { diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 8c856b954b4..cfc141da749 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/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 = ''; diff --git a/htdocs/core/tpl/card_presend.tpl.php b/htdocs/core/tpl/card_presend.tpl.php index 5baa70825d8..e57452ef8d3 100644 --- a/htdocs/core/tpl/card_presend.tpl.php +++ b/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; diff --git a/htdocs/core/tpl/extrafields_list_search_sql.tpl.php b/htdocs/core/tpl/extrafields_list_search_sql.tpl.php index 7006a54351b..e40ac5f2a07 100644 --- a/htdocs/core/tpl/extrafields_list_search_sql.tpl.php +++ b/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); diff --git a/htdocs/core/triggers/interface_50_modAgenda_ActionsAuto.class.php b/htdocs/core/triggers/interface_50_modAgenda_ActionsAuto.class.php index a3b11222a0f..2301b1642b4 100644 --- a/htdocs/core/triggers/interface_50_modAgenda_ActionsAuto.class.php +++ b/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) diff --git a/htdocs/holiday/list.php b/htdocs/holiday/list.php index 3397e6fced8..7335bfcf243 100644 --- a/htdocs/holiday/list.php +++ b/htdocs/holiday/list.php @@ -461,15 +461,19 @@ else // Type print ''; // 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); diff --git a/htdocs/langs/en_US/admin.lang b/htdocs/langs/en_US/admin.lang index efd33b05ba7..699b7690249 100644 --- a/htdocs/langs/en_US/admin.lang +++ b/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 diff --git a/htdocs/langs/en_US/mails.lang b/htdocs/langs/en_US/mails.lang index e38b038cfee..b155e2e4208 100644 --- a/htdocs/langs/en_US/mails.lang +++ b/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 diff --git a/htdocs/modulebuilder/template/myobject_list.php b/htdocs/modulebuilder/template/myobject_list.php index 3f3325c28e7..e085af5e6ef 100644 --- a/htdocs/modulebuilder/template/myobject_list.php +++ b/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 '; diff --git a/htdocs/supplier_proposal/class/supplier_proposal.class.php b/htdocs/supplier_proposal/class/supplier_proposal.class.php index 8a6068f7116..991e3ad5af8 100644 --- a/htdocs/supplier_proposal/class/supplier_proposal.class.php +++ b/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'); diff --git a/htdocs/user/class/user.class.php b/htdocs/user/class/user.class.php index 9df599dd0bc..8ac4963f5b5 100644 --- a/htdocs/user/class/user.class.php +++ b/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 " + */ + 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; + } + + } + }
'.$langs->trans("MAIN_MAIL_ENABLED_USER_DEST_SELECT").''; + print $form->selectyesno('MAIN_MAIL_ENABLED_USER_DEST_SELECT',$conf->global->MAIN_MAIL_ENABLED_USER_DEST_SELECT,1); + print '
 
'.$langs->trans("MAIN_MAIL_ENABLED_USER_DEST_SELECT").''.yn($conf->global->MAIN_MAIL_ENABLED_USER_DEST_SELECT).'
 
'; + $out.= $langs->trans("MailToSalaries"); + $out.= ''; + + // 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.= "
'; + $out.= $langs->trans("MailToCCSalaries"); + $out.= ''; + + // 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.= "
'; -$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 '