diff --git a/dev/namespacemig/aaa.class.php b/dev/namespacemig/aaa.class.php index 7b165349472..d7578b78e40 100644 --- a/dev/namespacemig/aaa.class.php +++ b/dev/namespacemig/aaa.class.php @@ -2,10 +2,14 @@ namespace Dolibarr; - global $globalaaa; $globalaaa = 'globalaaa'; +/** + * faaa + * + * @return string + */ function faaa() { return 'faaa'; @@ -15,6 +19,10 @@ class Aaa { const AAA='aaa'; + /** + * do + * @return void + */ public function do() { echo 'doaaa'."\n"; diff --git a/dev/namespacemig/bbb.class.php b/dev/namespacemig/bbb.class.php index 0fb6fd3d7ae..f68b3b2f36c 100644 --- a/dev/namespacemig/bbb.class.php +++ b/dev/namespacemig/bbb.class.php @@ -1,11 +1,12 @@ entity); @@ -212,7 +211,7 @@ if (! empty($user->admin)) { // TO DO Mutualize code for yes/no constants print ''; - print '' . $langs->trans("ACCOUNTING_LIST_SORT_VENTILATION_TODO") . ''; + print '' . $langs->trans("ACCOUNTING_LIST_SORT_VENTILATION_TODO") . ''; if (! empty($conf->global->ACCOUNTING_LIST_SORT_VENTILATION_TODO)) { print ''; print img_picto($langs->trans("Activated"), 'switch_on'); @@ -224,7 +223,7 @@ if (! empty($user->admin)) } print ''; - print ''; + print ''; print '' . $langs->trans("ACCOUNTING_LIST_SORT_VENTILATION_DONE") . ''; if (! empty($conf->global->ACCOUNTING_LIST_SORT_VENTILATION_DONE)) { print ''; @@ -237,7 +236,7 @@ if (! empty($user->admin)) } print ''; - print ''; + print ''; print '' . $langs->trans("ACCOUNTING_ENABLE_EXPORT_DRAFT_JOURNAL") . ''; if (! empty($conf->global->ACCOUNTING_ENABLE_EXPORT_DRAFT_JOURNAL)) { print ''; @@ -250,7 +249,7 @@ if (! empty($user->admin)) } print ''; - print ''; + print ''; print '' . $langs->trans("BANK_DISABLE_DIRECT_INPUT") . ''; if (! empty($conf->global->BANK_DISABLE_DIRECT_INPUT)) { print ''; @@ -263,7 +262,7 @@ if (! empty($user->admin)) } print ''; - print ''; + print ''; print '' . $langs->trans("ACCOUNTANCY_COMBO_FOR_AUX") . ''; if (! empty($conf->global->ACCOUNTANCY_COMBO_FOR_AUX)) { print ''; @@ -276,7 +275,7 @@ if (! empty($user->admin)) } print ''; - print ''; + print ''; print '' . $langs->trans("ACCOUNTING_MANAGE_ZERO") . ''; if (! empty($conf->global->ACCOUNTING_MANAGE_ZERO)) { print ''; diff --git a/htdocs/accountancy/class/accountingjournal.class.php b/htdocs/accountancy/class/accountingjournal.class.php index 8d6f037dc96..f922ac06655 100644 --- a/htdocs/accountancy/class/accountingjournal.class.php +++ b/htdocs/accountancy/class/accountingjournal.class.php @@ -235,7 +235,7 @@ class AccountingJournal extends CommonObject { if (! empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) { - $label=$langs->trans("ShowAccoutingJournal"); + $label=$langs->trans("ShowAccountingJournal"); $linkclose.=' alt="'.dol_escape_htmltag($label, 1).'"'; } $linkclose.= ' title="'.dol_escape_htmltag($label, 1).'"'; diff --git a/htdocs/accountancy/class/bookkeeping.class.php b/htdocs/accountancy/class/bookkeeping.class.php index cf6681bf3c6..16dc458d833 100644 --- a/htdocs/accountancy/class/bookkeeping.class.php +++ b/htdocs/accountancy/class/bookkeeping.class.php @@ -406,7 +406,7 @@ class BookKeeping extends CommonObject } /** - * Return a link to the object card (with optionaly the picto) + * Return a link to the object card (with optionally the picto) * * @param int $withpicto Include picto in link (0=No picto, 1=Include picto into link, 2=Only picto) * @param string $option On what the link point to ('nolink', ...) @@ -1309,7 +1309,7 @@ class BookKeeping extends CommonObject } /** - * Delete bookkepping by importkey + * Delete bookkeeping by importkey * * @param string $importkey Import key * @return int Result @@ -1337,7 +1337,7 @@ class BookKeeping extends CommonObject } /** - * Delete bookkepping by year + * Delete bookkeeping by year * * @param string $delyear Year to delete * @param string $journal Journal to delete @@ -1379,7 +1379,7 @@ class BookKeeping extends CommonObject } /** - * Delete bookkepping by piece number + * Delete bookkeeping by piece number * * @param int $piecenum Piecenum to delete * @return int Result @@ -1624,12 +1624,12 @@ class BookKeeping extends CommonObject // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps /** - * Export bookkeping + * Export bookkeeping * * @param string $model Model * @return int Result */ - public function export_bookkeping($model = 'ebp') + public function export_bookkeeping($model = 'ebp') { // phpcs:enable global $conf; @@ -1641,7 +1641,7 @@ class BookKeeping extends CommonObject $sql .= " FROM " . MAIN_DB_PREFIX . $this->table_element; $sql .= " WHERE entity IN (" . getEntity('accountancy') . ")"; - dol_syslog(get_class($this) . "::export_bookkeping", LOG_DEBUG); + dol_syslog(get_class($this) . "::export_bookkeeping", LOG_DEBUG); $resql = $this->db->query($sql); @@ -1679,7 +1679,7 @@ class BookKeeping extends CommonObject return $num; } else { $this->error = "Error " . $this->db->lasterror(); - dol_syslog(get_class($this) . "::export_bookkeping " . $this->error, LOG_ERR); + dol_syslog(get_class($this) . "::export_bookkeeping " . $this->error, LOG_ERR); return - 1; } } diff --git a/htdocs/accountancy/index.php b/htdocs/accountancy/index.php index 54cf83d03cb..4eab81ea49f 100644 --- a/htdocs/accountancy/index.php +++ b/htdocs/accountancy/index.php @@ -1,7 +1,7 @@ - * Copyright (C) 2016-2019 Alexandre Spangaro - * Copyright (C) 2019 Frédéric France +/* Copyright (C) 2016 Laurent Destailleur + * Copyright (C) 2016-2019 Alexandre Spangaro + * Copyright (C) 2019 Frédéric France * * 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 @@ -26,6 +26,7 @@ require '../main.inc.php'; require_once DOL_DOCUMENT_ROOT . '/core/lib/date.lib.php'; require_once DOL_DOCUMENT_ROOT . '/core/lib/accounting.lib.php'; +require_once DOL_DOCUMENT_ROOT . '/core/class/html.formother.class.php'; // Load translation files required by the page $langs->loadLangs(array("compta","bills","other","accountancy","loans","banks","admin","dict")); @@ -41,8 +42,17 @@ $hookmanager->initHooks(array('accountancyindex')); * Actions */ -// None +if (GETPOST('addbox')) // Add box (when submit is done from a form when ajax disabled) +{ + require_once DOL_DOCUMENT_ROOT.'/core/class/infobox.class.php'; + $zone=GETPOST('areacode', 'aZ09'); + $userid=GETPOST('userid', 'int'); + $boxorder=GETPOST('boxorder', 'aZ09'); + $boxorder.=GETPOST('boxcombo', 'aZ09'); + $result=InfoBox::saveboxorder($db, $zone, $boxorder, $userid); + if ($result > 0) setEventMessages($langs->trans("BoxAdded"), null); +} /* * View @@ -50,14 +60,39 @@ $hookmanager->initHooks(array('accountancyindex')); llxHeader('', $langs->trans("AccountancyArea")); -print load_fiche_titre($langs->trans("AccountancyArea"), '', 'accountancy'); -//dol_fiche_head(); - -$step = 0; - if ($conf->accounting->enabled) { - print ''.$langs->trans("AccountancyAreaDescIntro")."
\n"; + $step = 0; + + $resultboxes=FormOther::getBoxesArea($user, "27"); // Load $resultboxes (selectboxlist + boxactivated + boxlista + boxlistb) + + $helpisexpanded = empty($resultboxes['boxactivated']); // If there is no widget, the tooltip help is expanded by default. + $showtutorial = ''; + + if (! $helpisexpanded) + { + $showtutorial = '
'; + $showtutorial .= img_picto('', 'chevron-down'); + $showtutorial .= ' ' . $langs->trans("ShowTutorial"); + $showtutorial .= '
'; + + $showtutorial .= ''; + } + + + print load_fiche_titre($langs->trans("AccountancyArea"), $showtutorial . $resultboxes['selectboxlist'], 'accountancy'); + + print '
'; // hideobject is to start hidden + print "
\n"; + print ''.$langs->trans("AccountancyAreaDescIntro")."
\n"; print "
\n";print "
\n"; print load_fiche_titre(' '.$langs->trans("AccountancyAreaDescActionOnce"), '', '')."\n"; @@ -172,12 +207,51 @@ if ($conf->accounting->enabled) $step++; print img_picto('', 'puce').' '.$langs->trans("AccountancyAreaDescAnalyze", chr(64+$step))."
\n"; print "
\n"; + + print '
'; + + print '
'; + + print '
'; + + print '
'; + + /* + * Show boxes + */ + $boxlist.='
'; + + $boxlist.='
'; + if(!empty($nbworkboardcount)) + { + $boxlist.=$boxwork; + } + + $boxlist.=$resultboxes['boxlista']; + + $boxlist.= '
'; + + $boxlist.= '
'; + + $boxlist.=$boxstat; + $boxlist.=$resultboxes['boxlistb']; + + $boxlist.= '
'; + $boxlist.= "\n"; + + $boxlist.='
'; + + + print $boxlist; + + print '
'; } else { + print load_fiche_titre($langs->trans("AccountancyArea"), '', 'accountancy'); + print $langs->trans("Module10Desc")."
\n"; } -//dol_fiche_end(); // End of page llxFooter(); diff --git a/htdocs/adherents/admin/website.php b/htdocs/adherents/admin/website.php index 47bd51bdc98..ead5e767243 100644 --- a/htdocs/adherents/admin/website.php +++ b/htdocs/adherents/admin/website.php @@ -225,7 +225,7 @@ if (! empty($conf->global->MEMBER_ENABLE_PUBLIC)) { print '
'; //print $langs->trans('FollowingLinksArePublic').'
'; - print img_picto('', 'object_globe.png').' '.$langs->trans('BlankSubscriptionForm').':
'; + print img_picto('', 'globe').' '.$langs->trans('BlankSubscriptionForm').':
'; if ($conf->multicompany->enabled) { $entity_qr='?entity='.$conf->entity; } else { diff --git a/htdocs/admin/agenda_xcal.php b/htdocs/admin/agenda_xcal.php index 65074cbe8f1..f3c16941ebc 100644 --- a/htdocs/admin/agenda_xcal.php +++ b/htdocs/admin/agenda_xcal.php @@ -161,13 +161,13 @@ $urlwithroot=$urlwithouturlroot.DOL_URL_ROOT; // This is to use external domain // Show message $message=''; $urlvcal=''.$urlwithroot.'/public/agenda/agendaexport.php?format=vcal&exportkey='.($conf->global->MAIN_AGENDA_XCAL_EXPORTKEY?urlencode($conf->global->MAIN_AGENDA_XCAL_EXPORTKEY):'KEYNOTDEFINED').''; -$message.=img_picto('', 'object_globe.png').' '.$langs->trans("WebCalUrlForVCalExport", 'vcal', $urlvcal); +$message.=img_picto('', 'globe').' '.$langs->trans("WebCalUrlForVCalExport", 'vcal', $urlvcal); $message.='
'; $urlical=''.$urlwithroot.'/public/agenda/agendaexport.php?format=ical&type=event&exportkey='.($conf->global->MAIN_AGENDA_XCAL_EXPORTKEY?urlencode($conf->global->MAIN_AGENDA_XCAL_EXPORTKEY):'KEYNOTDEFINED').''; -$message.=img_picto('', 'object_globe.png').' '.$langs->trans("WebCalUrlForVCalExport", 'ical/ics', $urlical); +$message.=img_picto('', 'globe').' '.$langs->trans("WebCalUrlForVCalExport", 'ical/ics', $urlical); $message.='
'; $urlrss=''.$urlwithroot.'/public/agenda/agendaexport.php?format=rss&exportkey='.($conf->global->MAIN_AGENDA_XCAL_EXPORTKEY?urlencode($conf->global->MAIN_AGENDA_XCAL_EXPORTKEY):'KEYNOTDEFINED').''; -$message.=img_picto('', 'object_globe.png').' '.$langs->trans("WebCalUrlForVCalExport", 'rss', $urlrss); +$message.=img_picto('', 'globe').' '.$langs->trans("WebCalUrlForVCalExport", 'rss', $urlrss); $message.='
'; $message.='
'; print $message; diff --git a/htdocs/admin/boxes.php b/htdocs/admin/boxes.php index 1edb1fe8759..58c07b5ca3e 100644 --- a/htdocs/admin/boxes.php +++ b/htdocs/admin/boxes.php @@ -29,7 +29,7 @@ require_once DOL_DOCUMENT_ROOT.'/core/class/infobox.class.php'; include_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php'; // Load translation files required by the page -$langs->loadLangs(array('admin', 'boxes')); +$langs->loadLangs(array('admin', 'boxes', 'accountancy')); if (! $user->admin) accessforbidden(); diff --git a/htdocs/admin/dav.php b/htdocs/admin/dav.php index cb3f7ab2072..1d187c57e17 100644 --- a/htdocs/admin/dav.php +++ b/htdocs/admin/dav.php @@ -123,7 +123,9 @@ else { print ''; $tooltiphelp = (($langs->trans($key.'Tooltip') != $key.'Tooltip') ? $langs->trans($key.'Tooltip') : ''); - print $form->textwithpicto($langs->trans($key), $tooltiphelp); + $label = $langs->trans($key); + if ($key == 'DAV_RESTICT_ON_IP') $label = $langs->trans("RESTRICT_ON_IP"); + print $form->textwithpicto($label, $tooltiphelp); print ''; if ($key == 'DAV_ALLOW_PRIVATE_DIR') { @@ -172,13 +174,13 @@ $urlwithroot=$urlwithouturlroot.DOL_URL_ROOT; // This is to use external domain // Show message $message=''; $url=''.$urlwithroot.'/dav/fileserver.php'; -$message.=img_picto('', 'object_globe.png').' '.$langs->trans("WebDavServer", 'WebDAV', $url); +$message.=img_picto('', 'globe').' '.$langs->trans("WebDavServer", 'WebDAV', $url); $message.='
'; if (! empty($conf->global->DAV_ALLOW_PUBLIC_DIR)) { $urlEntity = (! empty($conf->multicompany->enabled)?'?entity='.$conf->entity:''); $url=''.$urlwithroot.'/dav/fileserver.php/public/'.$urlEntity.''; - $message.=img_picto('', 'object_globe.png').' '.$langs->trans("WebDavServer", 'WebDAV public', $url); + $message.=img_picto('', 'globe').' '.$langs->trans("WebDavServer", 'WebDAV public', $url); $message.='
'; } print $message; diff --git a/htdocs/admin/security.php b/htdocs/admin/security.php index 50db74dafdf..d2d5ecde622 100644 --- a/htdocs/admin/security.php +++ b/htdocs/admin/security.php @@ -170,9 +170,23 @@ elseif ($action == 'disable_MAIN_SECURITY_DISABLEFORGETPASSLINK') if ($action == 'maj_pattern') { - dolibarr_set_const($db, "USER_PASSWORD_PATTERN", GETPOST("pattern"), 'chaine', 0, '', $conf->entity); - header("Location: security.php"); - exit; + $pattern = GETPOST("pattern"); + $explodePattern = explode(';', $pattern); + + $patternInError = false; + if($explodePattern[0] < 1 || $explodePattern[4] < 0){ + $patternInError = true; + } + + if($explodePattern[0] < $explodePattern[1] + $explodePattern[2] + $explodePattern[3]){ + $patternInError = true; + } + + if(!$patternInError){ + dolibarr_set_const($db, "USER_PASSWORD_PATTERN", $pattern, 'chaine', 0, '', $conf->entity); + header("Location: security.php"); + exit; + } } @@ -278,13 +292,6 @@ if ($conf->global->USER_PASSWORD_GENERATED == "Perso"){ $tabConf = explode(";", $conf->global->USER_PASSWORD_PATTERN); - /*$this->length2 = $tabConf[0]; - $this->NbMaj = $tabConf[1]; - $this->NbNum = $tabConf[2]; - $this->NbSpe = $tabConf[3]; - $this->NbRepeat = $tabConf[4]; - $this->WithoutAmbi = $tabConf[5]; - */ print '
'; print ''; print ''; @@ -350,6 +357,13 @@ if ($conf->global->USER_PASSWORD_GENERATED == "Perso"){ print ' }'; print ' function valuePossible(){'; + print ' var fields = ["#minlenght", "#NbMajMin", "#NbNumMin", "#NbSpeMin", "#NbIteConsecutive"];'; + print ' for(var i = 0 ; i < fields.length ; i++){'; + print ' if($(fields[i]).val() < $(fields[i]).attr("min")){'; + print ' return false;'; + print ' }'; + print ' }'; + print ' '; print ' var length = parseInt($("#minlenght").val());'; print ' var length_mini = parseInt($("#NbMajMin").val()) + parseInt($("#NbNumMin").val()) + parseInt($("#NbSpeMin").val());'; print ' return length >= length_mini;'; diff --git a/htdocs/admin/translation.php b/htdocs/admin/translation.php index 693ad3d1f47..ad7a2278991 100644 --- a/htdocs/admin/translation.php +++ b/htdocs/admin/translation.php @@ -553,7 +553,7 @@ if ($mode == 'searchkey') //$transifexurl = 'https://www.transifex.com/dolibarr-association/dolibarr/translate/#'.$langcode.'/'.$transifexlangfile.'?key='.$key; $transifexurl = 'https://www.transifex.com/dolibarr-association/dolibarr/translate/#'.$langcode.'/'.$transifexlangfile.'?q=key%3A'.$key; - print '   '.img_picto('FixOnTransifex', 'object_globe').''; + print '   '.img_picto('FixOnTransifex', 'globe').''; } } else diff --git a/htdocs/api/admin/explorer.php b/htdocs/api/admin/explorer.php index 278c2750cd4..0f541b93708 100644 --- a/htdocs/api/admin/explorer.php +++ b/htdocs/api/admin/explorer.php @@ -179,7 +179,7 @@ print '
'; $message=''; $url=''.$urlwithroot.'/api/index.php/login?login='.urlencode($user->login).'&password=yourpassword[&reset=1]'; $message.=$langs->trans("UrlToGetKeyToUseAPIs").':
'; -$message.=img_picto('', 'object_globe.png').' '.$url; +$message.=img_picto('', 'globe').' '.$url; print $message; print '
'; print '
'; @@ -208,7 +208,7 @@ foreach($listofapis['v1'] as $key => $val) //print $key.' - '.$val['classname'].' - '.$val['fullpath']." - ".DOL_MAIN_URL_ROOT.'/api/index.php/'.strtolower(preg_replace('/Api$/','',$val['classname']))."/xxx
\n"; $url=$urlwithroot.'/api/index.php/'.$key; $url.='?api_key=token'; - print img_picto('', 'object_globe.png').' '.$method.' '.$url."
\n"; + print img_picto('', 'globe').' '.$method.' '.$url."
\n"; } } } diff --git a/htdocs/api/admin/index.php b/htdocs/api/admin/index.php index b005f257160..f8a354683e0 100644 --- a/htdocs/api/admin/index.php +++ b/htdocs/api/admin/index.php @@ -152,7 +152,7 @@ $urlwithroot=$urlwithouturlroot.DOL_URL_ROOT; // This is to use external domain $message=''; $url=$urlwithroot.'/api/index.php/login?login=auserlogin&password=thepassword[&reset=1]'; $message.=$langs->trans("UrlToGetKeyToUseAPIs").':
'; -$message.=img_picto('', 'object_globe.png').' '.$url; +$message.=img_picto('', 'globe').' '.$url; print $message; print '
'; print '
'; @@ -162,7 +162,7 @@ print ''.$langs->trans("ApiExporerIs").':
'; if (dol_is_dir(DOL_DOCUMENT_ROOT.'/includes/restler/framework/Luracast/Restler/explorer')) { $url=DOL_MAIN_URL_ROOT.'/api/index.php/explorer'; - print img_picto('', 'object_globe.png').' '.$url."
\n"; + print img_picto('', 'globe').' '.$url."
\n"; } else { diff --git a/htdocs/comm/action/card.php b/htdocs/comm/action/card.php index 78248719908..baf454fdf67 100644 --- a/htdocs/comm/action/card.php +++ b/htdocs/comm/action/card.php @@ -1622,7 +1622,7 @@ if ($id > 0) // Type if (! empty($conf->global->AGENDA_USE_EVENT_TYPE)) { - print ''; + print ''; } // Full day event diff --git a/htdocs/comm/action/index.php b/htdocs/comm/action/index.php index bd6b88d51ff..d503c1bc71d 100644 --- a/htdocs/comm/action/index.php +++ b/htdocs/comm/action/index.php @@ -1562,7 +1562,7 @@ function show_day_events($db, $day, $month, $year, $monthshown, $style, &$eventa $savlabel=$event->label?$event->label:$event->libelle; $event->label=$titletoshow; $event->libelle=$titletoshow; - print $event->getNomUrl(0, $maxnbofchar, 'cal_event', '', 0, 1); + print $event->getNomUrl(0, $maxnbofchar, 'cal_event', '', 0, 0); $event->label=$savlabel; $event->libelle=$savlabel; } diff --git a/htdocs/comm/propal/card.php b/htdocs/comm/propal/card.php index 96aa12062d4..92267d97033 100644 --- a/htdocs/comm/propal/card.php +++ b/htdocs/comm/propal/card.php @@ -1595,7 +1595,7 @@ if ($action == 'create') if ($socid > 0) { - // Contacts (ask contact only if thirdparty already defined). TODO do this also into order and invoice. + // Contacts (ask contact only if thirdparty already defined). print "'; @@ -2493,7 +2493,7 @@ if ($action == 'create') } // Send - if ($object->statut == Propal::STATUS_VALIDATED || $object->statut == Propal::STATUS_SIGNED) { + if ($object->statut == Propal::STATUS_VALIDATED || $object->statut == Propal::STATUS_SIGNED || !empty($conf->global->PROPOSAL_SENDBYEMAIL_FOR_ALL_STATUS)) { if ($usercansend) { print '
' . $langs->trans('SendMail') . '
'; } else diff --git a/htdocs/comm/propal/list.php b/htdocs/comm/propal/list.php index f81949fb11d..919ad77168d 100644 --- a/htdocs/comm/propal/list.php +++ b/htdocs/comm/propal/list.php @@ -1013,9 +1013,8 @@ if ($resql) // Author if (! empty($arrayfields['u.login']['checked'])) { - print '\n"; if (! $i) $totalarray['nbfield']++; } @@ -1088,7 +1087,7 @@ if ($resql) print ''; if (! $i) $totalarray['nbfield']++; } - // Date cloture + // Date cloture if (! empty($arrayfields['p.date_cloture']['checked'])) { print ''; // Ligne info remises tiers @@ -2539,7 +2541,7 @@ if ($action == 'create' && $usercancreate) $reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action); if (empty($reshook)) { // Send - if ($object->statut > Commande::STATUS_DRAFT) { + if ($object->statut > Commande::STATUS_DRAFT || !empty($conf->global->COMMANDE_SENDBYEMAIL_FOR_ALL_STATUS)) { if ($usercansend) { print '
' . $langs->trans('SendMail') . '
'; } else diff --git a/htdocs/compta/bank/list.php b/htdocs/compta/bank/list.php index 77971439f75..6f8ea3a286d 100644 --- a/htdocs/compta/bank/list.php +++ b/htdocs/compta/bank/list.php @@ -242,7 +242,7 @@ print ''; print ''; print ''; -print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, '', $num, $nbtotalofrecords, 'title_bank.png', 0, $newcardbutton, '', $limit, 1); +print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, '', $num, $nbtotalofrecords, 'bank', 0, $newcardbutton, '', $limit, 1); $topicmail="Information"; //$modelmail="subscription"; diff --git a/htdocs/contact/card.php b/htdocs/contact/card.php index 6923134c0ab..f5e39907bcc 100644 --- a/htdocs/contact/card.php +++ b/htdocs/contact/card.php @@ -388,6 +388,7 @@ if (empty($reshook)) $object->priv = GETPOST("priv", 'int'); $object->note_public = GETPOST("note_public", 'none'); $object->note_private = GETPOST("note_private", 'none'); + $object->roles = GETPOST("roles", 'array'); // Fill array 'array_options' with data from add form $ret = $extrafields->setOptionalsFromPost(null, $object); @@ -491,9 +492,9 @@ else // Si edition contact deja existant $object = new Contact($db); $res=$object->fetch($id, $user); - if ($res < 0) { dol_print_error($db, $object->error); exit; } - $res=$object->fetch_optionals(); - if ($res < 0) { dol_print_error($db, $object->error); exit; } + if ($res<0) { + setEventMessages($object->error, $object->errors, 'errors'); + } // Show tabs $head = contact_prepare_head($object); @@ -755,6 +756,15 @@ else print ""; } + // Contact by default + if (!empty($socid)) { + print ''; + print ''; + } + // Other attributes $parameters=array('socid' => $socid, 'objsoc' => $objsoc, 'colspan' => ' colspan="3"', 'cols' => 3); $reshook=$hookmanager->executeHooks('formObjectOptions', $parameters, $object, $action); // Note that $action and $object may have been modified by hook @@ -1085,6 +1095,14 @@ else print ""; } + // Contact by default + if (!empty($object->socid)) { + print ''; + print ''; + } + // Other attributes $parameters=array('colspan' => ' colspan="3"', 'cols'=>3); $reshook=$hookmanager->executeHooks('formObjectOptions', $parameters, $object, $action); // Note that $action and $object may have been modified by hook @@ -1233,7 +1251,7 @@ else print $object->getCivilityLabel(); print ''; - // Role + // Job / position print ''; // Email @@ -1283,6 +1301,13 @@ else print ''; } + if (!empty($object->socid)) { + print ''; + print ''; + } + // Other attributes $cols = 3; $parameters=array('socid'=>$socid); diff --git a/htdocs/contact/class/contact.class.php b/htdocs/contact/class/contact.class.php index cbe9318f178..2e5bcc74200 100644 --- a/htdocs/contact/class/contact.class.php +++ b/htdocs/contact/class/contact.class.php @@ -167,6 +167,8 @@ class Contact extends CommonObject */ public $oldcopy; // To contains a clone of this when we need to save old properties of object + public $roles=array(); + /** * Constructor @@ -421,6 +423,14 @@ class Contact extends CommonObject } } + if (! $error) { + $result=$this->updateRoles(); + if ($result < 0) + { + $error++; + } + } + if (! $error && $this->user_id > 0) { $tmpobj = new User($this->db); @@ -885,6 +895,11 @@ class Contact extends CommonObject // fetch optionals attributes and labels $this->fetch_optionals(); + $resultRole=$this->fetchRoles(); + if ($resultRole<0) { + return $resultRole; + } + return 1; } else @@ -1019,6 +1034,20 @@ class Contact extends CommonObject } } + if (! $error) + { + // Remove Roles + $sql = "DELETE FROM ".MAIN_DB_PREFIX."societe_contacts WHERE fk_socpeople = ".$this->id; + dol_syslog(get_class($this)."::delete", LOG_DEBUG); + $resql=$this->db->query($sql); + if (! $resql) + { + $error++; + $this->error .= $this->db->lasterror(); + $errorflag=-1; + } + } + if (! $error) { // Remove category @@ -1478,4 +1507,150 @@ class Contact extends CommonObject return CommonObject::commonReplaceThirdparty($db, $origin_id, $dest_id, $tables); } + + /** + * Fetch Role for a contact + * + * @return float|int + * @throws Exception + */ + public function fetchRoles() + { + global $langs; + $error= 0; + $num=0; + + $sql ="SELECT tc.rowid, tc.element, tc.source, tc.code, tc.libelle, sc.rowid as contactroleid"; + $sql.=" FROM ".MAIN_DB_PREFIX."societe_contacts as sc "; + $sql.=" INNER JOIN ".MAIN_DB_PREFIX."c_type_contact as tc"; + $sql.=" ON tc.rowid = sc.fk_c_type_contact"; + $sql.=" AND sc.fk_socpeople = ". $this->id; + $sql.=" AND tc.source = 'external' AND tc.active=1"; + $sql.=" AND sc.entity IN (".getEntity('societe').')'; + + dol_syslog(get_class($this)."::".__METHOD__, LOG_DEBUG); + + $this->roles=array(); + $resql=$this->db->query($sql); + if ($resql) { + $num = $this->db->num_rows($resql); + if ($num > 0) { + while ($obj = $this->db->fetch_object($resql)) { + $transkey="TypeContact_".$obj->element."_".$obj->source."_".$obj->code; + $libelle_element = $langs->trans('ContactDefault_'.$obj->element); + $this->roles[$obj->contactroleid]=array('id'=>$obj->rowid,'element'=>$obj->element,'source'=>$obj->source,'code'=>$obj->code,'label'=>$libelle_element. ' - '.($langs->trans($transkey)!=$transkey ? $langs->trans($transkey) : $obj->libelle)); + } + } + } else { + $error++; + $this->error=$this->db->lasterror(); + $this->errors[]=$this->db->lasterror(); + } + + if (empty($error)) { + return $num; + } else { + return $error * -1; + } + } + + /** + * Get Contact roles for a thirdparty + * + * @param string $element element type + * @return array|int + * @throws Exception + */ + public function getContactRoles($element = '') + { + $tab=array(); + + $sql = "SELECT sc.fk_socpeople as id, sc.fk_c_type_contact"; + $sql.= " FROM ".MAIN_DB_PREFIX."c_type_contact tc"; + $sql.= ", ".MAIN_DB_PREFIX."societe_contacts sc"; + $sql.= " WHERE sc.fk_soc =".$this->socid; + $sql.= " AND sc.fk_c_type_contact=tc.rowid"; + $sql.= " AND tc.element='".$element."'"; + $sql.= " AND tc.active=1"; + + dol_syslog(get_class($this)."::".__METHOD__, LOG_DEBUG); + $resql=$this->db->query($sql); + if ($resql) + { + $num=$this->db->num_rows($resql); + $i=0; + while ($i < $num) + { + $obj = $this->db->fetch_object($resql); + $tab[]=array('fk_socpeople'=>$obj->id, 'type_contact'=>$obj->fk_c_type_contact); + + $i++; + } + + return $tab; + } + else + { + $this->error=$this->db->error(); + dol_print_error($this->db); + return -1; + } + } + + /** + * Updates Roles + * + * @return float|int + * @throws Exception + */ + public function updateRoles() + { + global $conf; + + $error=0; + + $this->db->begin(); + + $sql = "DELETE FROM ".MAIN_DB_PREFIX."societe_contacts WHERE fk_soc=".$this->socid; + + dol_syslog(get_class($this)."::".__METHOD__, LOG_DEBUG); + $result = $this->db->query($sql); + if (!$result) { + $this->errors[]=$this->db->lasterror().' sql='.$sql; + $error++; + } else { + if (count($this->roles)>0) { + foreach ($this->roles as $keyRoles => $valRoles) { + $sql = "INSERT INTO " . MAIN_DB_PREFIX . "societe_contacts"; + $sql .= " (entity,"; + $sql .= "date_creation,"; + $sql .= "fk_soc,"; + $sql .= "fk_c_type_contact,"; + $sql .= "fk_socpeople) "; + $sql .= " VALUES (" . $conf->entity . ","; + $sql .= "'" . $this->db->idate(dol_now()) . "',"; + $sql .= $this->socid . ", "; + $sql .= $valRoles . " , " ; + $sql .= $this->id; + $sql .= ")"; + dol_syslog(get_class($this) . "::".__METHOD__, LOG_DEBUG); + + $result = $this->db->query($sql); + if (!$result) + { + $this->errors[]=$this->db->lasterror().' sql='.$sql; + $error++; + } + } + } + } + if (empty($error)) { + $this->db->commit(); + return 1; + } else { + $this->error=implode(' ', $this->errors); + $this->db->rollback(); + return $error*-1; + } + } } diff --git a/htdocs/contact/list.php b/htdocs/contact/list.php index e90ff50892f..f7d9b91cc39 100644 --- a/htdocs/contact/list.php +++ b/htdocs/contact/list.php @@ -36,6 +36,7 @@ require '../main.inc.php'; require_once DOL_DOCUMENT_ROOT.'/contact/class/contact.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php'; // Load translation files required by the page $langs->loadLangs(array("companies", "suppliers", "categories")); @@ -89,6 +90,7 @@ $search_zip=GETPOST('search_zip', 'alpha'); $search_town=GETPOST('search_town', 'alpha'); $search_import_key=GETPOST("search_import_key", "alpha"); $search_country=GETPOST("search_country", 'intcomma'); +$search_roles=GETPOST("search_roles", 'array'); if ($search_status=='') $search_status=1; // always display active customer first @@ -256,6 +258,7 @@ if (empty($reshook)) $search_import_key=''; $toselect=''; $search_array_options=array(); + $search_roles=array(); } // Mass actions @@ -276,6 +279,7 @@ if ($search_priv < 0) $search_priv=''; $form=new Form($db); $formother=new FormOther($db); +$formcompany=new FormCompany($db); $contactstatic=new Contact($db); $title = (! empty($conf->global->SOCIETE_ADDRESSES_MANAGEMENT) ? $langs->trans("Contacts") : $langs->trans("ContactsAddresses")); @@ -353,6 +357,9 @@ if (! empty($conf->socialnetworks->enabled)) { if (strlen($search_email)) $sql.= natural_search('p.email', $search_email); if (strlen($search_zip)) $sql.= natural_search("p.zip", $search_zip); if (strlen($search_town)) $sql.= natural_search("p.town", $search_town); +if (count($search_roles)>0) { + $sql .= " AND p.rowid IN (SELECT sc.fk_socpeople FROM ".MAIN_DB_PREFIX."societe_contacts as sc WHERE sc.fk_c_type_contact IN (".implode(',', $search_roles)."))"; +} if ($search_no_email != '' && $search_no_email >= 0) $sql.= " AND p.no_email = ".$db->escape($search_no_email); if ($search_status != '' && $search_status >= 0) $sql.= " AND p.statut = ".$db->escape($search_status); @@ -457,6 +464,7 @@ if ($search_status != '') $param.='&search_status='.urlencode($search_status if ($search_priv == '0' || $search_priv == '1') $param.="&search_priv=".urlencode($search_priv); if ($search_import_key != '') $param.='&search_import_key='.urlencode($search_import_key); if ($optioncss != '') $param.='&optioncss='.$optioncss; +if (count($search_roles)>0) $param.=implode('&search_roles[]=', $search_roles); // Add $param from extra fields include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_param.tpl.php'; @@ -529,6 +537,10 @@ if (! empty($conf->categorie->enabled)) $moreforfilter.=$formother->select_categories(Categorie::TYPE_SUPPLIER, $search_categ_supplier, 'search_categ_supplier', 1); $moreforfilter.=''; } + $moreforfilter.='
'; + $moreforfilter.=$langs->trans('Roles'). ': '; + $moreforfilter.=$formcompany->showRoles("search_roles", $objecttmp, 'edit', $search_roles); + $moreforfilter.='
'; } if ($moreforfilter) { diff --git a/htdocs/contrat/class/contrat.class.php b/htdocs/contrat/class/contrat.class.php index c6462cba9b9..99a5f78691f 100644 --- a/htdocs/contrat/class/contrat.class.php +++ b/htdocs/contrat/class/contrat.class.php @@ -2077,7 +2077,7 @@ class Contrat extends CommonObject * Return list of line rowid * * @param int $statut Status of lines to get - * @return array Array of line's rowid + * @return array|int Array of line's rowid or <0 if error */ public function array_detail($statut = -1) { @@ -2114,7 +2114,7 @@ class Contrat extends CommonObject * Return list of other contracts for same company than current contract * * @param string $option 'all' or 'others' - * @return array Array of contracts id + * @return array|int Array of contracts id or <0 if error */ public function getListOfContracts($option = 'all') { diff --git a/htdocs/core/boxes/box_accountancy_last_manual_entries.php b/htdocs/core/boxes/box_accountancy_last_manual_entries.php new file mode 100644 index 00000000000..2c788b66b71 --- /dev/null +++ b/htdocs/core/boxes/box_accountancy_last_manual_entries.php @@ -0,0 +1,173 @@ + + * Copyright (C) 2004-2009 Laurent Destailleur + * Copyright (C) 2005-2009 Regis Houssin + * Copyright (C) 2019 Alexandre Spangaro + * + * 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 . + */ + +/** + * \file htdocs/core/boxes/box_accountancy_last_manual_entries.php + * \ingroup Accountancy + * \brief Module to generated widget of last manual entries + */ + +include_once DOL_DOCUMENT_ROOT.'/core/boxes/modules_boxes.php'; + + +/** + * Class to manage the box to show last manual entries + */ +class box_accountancy_last_manual_entries extends ModeleBoxes +{ + public $boxcode="accountancy_last_manual_entries"; + public $boximg="object_invoice"; + public $boxlabel="BoxLastManualEntries"; + public $depends = array("accounting"); + + /** + * @var DoliDB Database handler. + */ + public $db; + + public $param; + + public $info_box_head = array(); + public $info_box_contents = array(); + + + /** + * Constructor + * + * @param DoliDB $db Database handler + * @param string $param More parameters + */ + public function __construct($db, $param) + { + global $user; + + $this->db = $db; + + $this->hidden = ! ($user->rights->accounting->mouvements->lire); + } + + /** + * Load data for box to show them later + * + * @param int $max Maximum number of records to load + * @return void + */ + public function loadBox($max = 5) + { + global $user, $langs, $conf; + + include_once DOL_DOCUMENT_ROOT.'/accountancy/class/bookkeeping.class.php'; + + $bookkeepingstatic = new BookKeeping($this->db); + + $this->info_box_head = array('text' => $langs->trans("BoxTitleLastManualEntries", $max)); + + if ($user->rights->accounting->mouvements->lire) + { + $sql = "SELECT DISTINCT b.piece_num"; + $sql.= ", b.doc_date as date_movement"; + $sql.= ", b.label_operation"; + $sql.= ", b.montant"; + $sql.= ", b.code_journal"; + $sql.= " FROM ".MAIN_DB_PREFIX."accounting_bookkeeping as b"; + $sql.= " WHERE b.fk_doc = 0"; + $sql.= " AND b.entity = ".$conf->entity; + $sql.= " ORDER BY b.piece_num DESC "; + $sql.= $this->db->plimit($max, 0); + + $result = $this->db->query($sql); + if ($result) { + $num = $this->db->num_rows($result); + + $line = 0; + + while ($line < $num) { + $objp = $this->db->fetch_object($result); + $date = $this->db->jdate($objp->date_movement); + $journal = $objp->code_journal; + $label = $objp->label_operation; + $amount = $objp->montant; + + $bookkeepingstatic->id = $objp->id; + $bookkeepingstatic->piece_num = $objp->piece_num; + + $this->info_box_contents[$line][] = array( + 'td' => '', + 'text' => $bookkeepingstatic->getNomUrl(1), + 'asis' => 1, + ); + + $this->info_box_contents[$line][] = array( + 'td' => 'class="right"', + 'text' => dol_print_date($date, 'day'), + 'asis' => 1, + ); + + $this->info_box_contents[$line][] = array( + 'td' => 'class="center"', + 'text' => $journal, + 'asis' => 1, + ); + + $this->info_box_contents[$line][] = array( + 'td' => 'class="tdoverflowmax150 maxwidth150onsmartphone"', + 'text' => $label, + 'asis' => 1, + ); + + $this->info_box_contents[$line][] = array( + 'td' => 'class="nowrap right"', + 'text' => price($amount, 0, $langs, 0, -1, -1, $conf->currency), + ); + + $line++; + } + + if ($num==0) $this->info_box_contents[$line][0] = array('td' => 'class="center"','text'=>$langs->trans("NoRecordedManualEntries")); + + $this->db->free($result); + } else { + $this->info_box_contents[0][0] = array( + 'td' => '', + 'maxlength'=>500, + 'text' => ($this->db->error().' sql='.$sql), + ); + } + } else { + $this->info_box_contents[0][0] = array( + 'td' => 'class="nohover opacitymedium left"', + 'text' => $langs->trans("ReadPermissionNotAllowed") + ); + } + } + + /** + * Method to show box + * + * @param array $head Array with properties of box title + * @param array $contents Array with properties of box lines + * @param int $nooutput No print, only return string + * @return string + */ + public function showBox($head = null, $contents = null, $nooutput = 0) + { + return parent::showBox($this->info_box_head, $this->info_box_contents, $nooutput); + } +} diff --git a/htdocs/core/boxes/box_accountancy_suspense_account.php b/htdocs/core/boxes/box_accountancy_suspense_account.php new file mode 100644 index 00000000000..9740de82fbc --- /dev/null +++ b/htdocs/core/boxes/box_accountancy_suspense_account.php @@ -0,0 +1,135 @@ + + * Copyright (C) 2004-2009 Laurent Destailleur + * Copyright (C) 2005-2009 Regis Houssin + * Copyright (C) 2019 Alexandre Spangaro + * + * 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 . + */ + +/** + * \file htdocs/core/boxes/box_accountancy_suspense_account.php + * \ingroup Accountancy + * \brief Module to generated widget of suspense account + */ + +include_once DOL_DOCUMENT_ROOT.'/core/boxes/modules_boxes.php'; + + +/** + * Class to manage the box to show suspense account + */ +class box_accountancy_suspense_account extends ModeleBoxes +{ + public $boxcode="accountancy_suspense_account"; + public $boximg="object_invoice"; + public $boxlabel="BoxSuspenseAccount"; + public $depends = array("accounting"); + + /** + * @var DoliDB Database handler. + */ + public $db; + + public $param; + + public $info_box_head = array(); + public $info_box_contents = array(); + + + /** + * Constructor + * + * @param DoliDB $db Database handler + * @param string $param More parameters + */ + public function __construct($db, $param) + { + global $user; + + $this->db = $db; + + $this->hidden = ! ($user->rights->accounting->mouvements->lire); + } + + /** + * Load data for box to show them later + * + * @return void + */ + public function loadBox() + { + global $user, $langs, $conf; + + include_once DOL_DOCUMENT_ROOT.'/accountancy/class/bookkeeping.class.php'; + + $bookkeepingstatic = new BookKeeping($this->db); + + $this->info_box_head = array('text' => $langs->trans("BoxTitleSuspenseAccount")); + + if ($user->rights->accounting->mouvements->lire) + { + $suspenseAccount = $conf->global->ACCOUNTING_ACCOUNT_SUSPENSE; + if (! empty($suspenseAccount) && $suspenseAccount > 0) + { + $sql = "SELECT COUNT(*) as nb_suspense_account"; + $sql .= " FROM " . MAIN_DB_PREFIX . "accounting_bookkeeping as b"; + $sql .= " WHERE b.numero_compte = ". $suspenseAccount; + $sql .= " AND b.entity = " . $conf->entity; + + $result = $this->db->query($sql); + $nbSuspenseAccount = 0; + if ($result) + { + $obj=$this->db->fetch_object($result); + $nbSuspenseAccount = $obj->nb_suspense_account; + } + + $this->info_box_contents[0][0] = array( + 'td' => '', + 'text' => $langs->trans("NumberOfLinesInSuspenseAccount") . ':' + ); + + $this->info_box_contents[0][1] = array( + 'td' => 'class="right"', + 'text' => '' . $nbSuspenseAccount . '', + 'asis' => 1 + ); + } else { + $this->info_box_contents[0][0] = array( + 'td' => 'class="nohover opacitymedium left"', + 'text' => $langs->trans("SuspenseAccountNotDefined") + ); + } + } else { + $this->info_box_contents[0][0] = array( + 'td' => 'class="nohover opacitymedium left"', + 'text' => $langs->trans("ReadPermissionNotAllowed") + ); + } + } + + /** + * Method to show box + * + * @param array $head Array with properties of box title + * @param array $contents Array with properties of box lines + * @param int $nooutput No print, only return string + * @return string + */ + public function showBox($head = null, $contents = null, $nooutput = 0) + { + return parent::showBox($this->info_box_head, $this->info_box_contents, $nooutput); + } +} diff --git a/htdocs/core/boxes/box_bookmarks.php b/htdocs/core/boxes/box_bookmarks.php index 5d4f51840fa..eec82f0e091 100644 --- a/htdocs/core/boxes/box_bookmarks.php +++ b/htdocs/core/boxes/box_bookmarks.php @@ -29,7 +29,7 @@ include_once DOL_DOCUMENT_ROOT.'/core/boxes/modules_boxes.php'; class box_bookmarks extends ModeleBoxes { public $boxcode="bookmarks"; - public $boximg="object_bookmark"; + public $boximg="bookmark"; public $boxlabel="BoxMyLastBookmarks"; public $depends = array("bookmark"); @@ -77,12 +77,12 @@ class box_bookmarks extends ModeleBoxes 'sublink' => DOL_URL_ROOT.'/bookmarks/list.php', ); if ($user->rights->bookmark->creer) { - $this->info_box_head['subpicto']='object_bookmark'; + $this->info_box_head['subpicto']='bookmark'; $this->info_box_head['subtext']=$langs->trans("BookmarksManagement"); } else { - $this->info_box_head['subpicto']='object_bookmark'; + $this->info_box_head['subpicto']='bookmark'; $this->info_box_head['subtext']=$langs->trans("ListOfBookmark"); } diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index 1144ad8b9dd..54fbb374b09 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -1224,6 +1224,82 @@ abstract class CommonObject } } + // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps + /** + * Return array with list of possible values for type of contacts + * + * @param string $source 'internal', 'external' or 'all' + * @param int $option 0=Return array id->label, 1=Return array code->label + * @param int $activeonly 0=all status of contact, 1=only the active + * @param string $code Type of contact (Example: 'CUSTOMER', 'SERVICE') + * @param string $element Filter Element Type + * @return array Array list of type of contacts (id->label if option=0, code->label if option=1) + */ + public function listeTypeContacts($source = 'internal', $option = 0, $activeonly = 0, $code = '', $element = '') + { + // phpcs:enable + global $langs, $conf; + + $tab = array(); + + $sql = "SELECT DISTINCT tc.rowid, tc.code, tc.libelle, tc.position, tc.element"; + $sql.= " FROM ".MAIN_DB_PREFIX."c_type_contact as tc"; + + $sqlWhere=array(); + if (!empty($element)) + $sqlWhere[]=" tc.element='".$this->db->escape($element)."'"; + + if ($activeonly == 1) + $sqlWhere[]=" tc.active=1"; // only the active types + + if (! empty($source) && $source != 'all') + $sqlWhere[]=" tc.source='".$this->db->escape($source)."'"; + + if (! empty($code)) + $sqlWhere[]=" tc.code='".$this->db->escape($code)."'"; + + if (count($sqlWhere)>0) { + $sql .= " WHERE ". implode(' AND ', $sqlWhere); + } + + $sql.= $this->db->order('tc.element, tc.position', 'ASC'); + + dol_syslog(get_class($this)."::".__METHOD__, LOG_DEBUG); + $resql=$this->db->query($sql); + if ($resql) { + $num = $this->db->num_rows($resql); + if ($num > 0) { + while ($obj = $this->db->fetch_object($resql)) { + if (strpos($obj->element, 'project')!==false) { + $element='projet'; + } elseif($obj->element=='contrat') { + $element='contract'; + } elseif(strpos($obj->element, 'supplier')!==false && $obj->element!='supplier_proposal') { + $element='fournisseur'; + } elseif(strpos($obj->element, 'supplier')!==false && $obj->element!='supplier_proposal') { + $element='fournisseur'; + } else { + $element=$obj->element; + } + if ($conf->{$element}->enabled) { + $libelle_element = $langs->trans('ContactDefault_' . $obj->element); + $transkey = "TypeContact_" . $this->element . "_" . $source . "_" . $obj->code; + $libelle_type = ($langs->trans($transkey) != $transkey ? $langs->trans($transkey) : $obj->libelle); + if (empty($option)) + $tab[$obj->rowid] = $libelle_element . ' - ' . $libelle_type; + else $tab[$obj->rowid] = $libelle_element . ' - ' . $libelle_type; + } + } + } + return $tab; + } + else + { + $this->error=$this->db->lasterror(); + return null; + } + } + /** * Return id of contacts for a source and a contact code. * Example: contact client de facturation ('external', 'BILLING') diff --git a/htdocs/core/class/cunits.class.php b/htdocs/core/class/cunits.class.php index 919d2ad3aae..1837f82a2a4 100644 --- a/htdocs/core/class/cunits.class.php +++ b/htdocs/core/class/cunits.class.php @@ -160,11 +160,11 @@ class CUnits // extends CommonObject /** * Load object in memory from database * - * @param int $id Id object - * @param string $code Code - * @param string $short_label Short Label - * @param string $unit_type unit type - * @return int <0 if KO, >0 if OK + * @param int $id Id object + * @param string $code Code + * @param string $short_label Short Label ('g', 'kg', ...) + * @param string $unit_type Unit type ('size', 'surface', 'volume', 'weight', ...) + * @return int <0 if KO, >0 if OK */ public function fetch($id, $code = '', $short_label = '', $unit_type = '') { @@ -175,6 +175,7 @@ class CUnits // extends CommonObject $sql.= " t.code,"; $sql.= " t.label,"; $sql.= " t.short_label,"; + $sql.= " t.scale,"; $sql.= " t.unit_type,"; $sql.= " t.scale,"; $sql.= " t.active"; @@ -199,6 +200,7 @@ class CUnits // extends CommonObject $this->code = $obj->code; $this->label = $obj->label; $this->short_label = $obj->short_label; + $this->scale = $obj->scale; $this->unit_type = $obj->unit_type; $this->scale = $obj->scale; $this->active = $obj->active; diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index 23dcc5b8e5d..d9442e43457 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -6574,7 +6574,6 @@ class Form return 'ErrorBadValueForParameterRenderMode'; // Should not happened } - /** * Show linked object block. * diff --git a/htdocs/core/class/html.formcompany.class.php b/htdocs/core/class/html.formcompany.class.php index 9ca50bc97fc..76b9d07a2c4 100644 --- a/htdocs/core/class/html.formcompany.class.php +++ b/htdocs/core/class/html.formcompany.class.php @@ -29,28 +29,11 @@ * Class to build HTML component for third parties management * Only common components are here. */ -class FormCompany + +require_once DOL_DOCUMENT_ROOT.'/core/class/html.form.class.php'; + +class FormCompany extends Form { - /** - * @var DoliDB Database handler. - */ - public $db; - - /** - * @var string Error code (or message) - */ - public $error=''; - - /** - * Constructor - * - * @param DoliDB $db Database handler - */ - public function __construct($db) - { - $this->db = $db; - } - // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps /** @@ -763,6 +746,45 @@ class FormCompany } } + /** + * showContactRoles on view and edit mode + * + * @param string $htmlname Html component name and id + * @param Contact $contact Contact Obejct + * @param string $rendermode view, edit + * @param array $selected $key=>$val $val is selected Roles for input mode + * @return string String with contacts roles + */ + public function showRoles($htmlname, Contact $contact, $rendermode = 'view', $selected = array()) + { + if ($rendermode === 'view') { + $toprint = array(); + foreach ($contact->roles as $key => $val) { + $toprint[] = '
  • ' . $val['label'] . '
  • '; + } + return '
      ' . implode(' ', $toprint) . '
    '; + } + + if ($rendermode === 'edit') + { + $contactType=$contact->listeTypeContacts('external', '', 1); + if (count($selected)>0) { + $newselected=array(); + foreach($selected as $key=>$val) { + if (is_array($val) && array_key_exists('id', $val) && in_array($val['id'], array_keys($contactType))) { + $newselected[]=$val['id']; + } else { + break; + } + } + if (count($newselected)>0) $selected=$newselected; + } + return $this->multiselectarray($htmlname, $contactType, $selected); + } + + return 'ErrorBadValueForParameterRenderMode'; // Should not happened + } + // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps /** * Return a select list with zip codes and their town diff --git a/htdocs/core/class/html.formfile.class.php b/htdocs/core/class/html.formfile.class.php index 908fe200a97..76eec464399 100644 --- a/htdocs/core/class/html.formfile.class.php +++ b/htdocs/core/class/html.formfile.class.php @@ -1334,7 +1334,7 @@ class FormFile $fulllink=$urlwithroot.'/document.php'.($paramlink?'?'.$paramlink:''); - print img_picto($langs->trans("FileSharedViaALink"), 'object_globe.png').' '; + print img_picto($langs->trans("FileSharedViaALink"), 'globe').' '; print ''; } else @@ -1851,7 +1851,7 @@ class FormFile else { print '
    '; @@ -1077,6 +1089,10 @@ function show_contacts($conf, $langs, $db, $object, $backtopage = '') if (in_array($val['type'], array('timestamp'))) $align.=($align?' ':'').'nowrap'; if ($key == 'status' || $key == 'statut') $align.=($align?' ':'').'center'; if (! empty($arrayfields['t.'.$key]['checked'])) print getTitleFieldOfList($val['label'], 0, $_SERVER['PHP_SELF'], 't.'.$key, '', $param, ($align?'class="'.$align.'"':''), $sortfield, $sortorder, $align.' ')."\n"; + if ($key == 'role') $align.=($align?' ':'').'center'; + if (! empty($arrayfields['sc.'.$key]['checked'])) { + print getTitleFieldOfList($arrayfields['sc.'.$key]['label'], 0, $_SERVER['PHP_SELF'], 'sc.'.$key, '', $param, ($align?'class="'.$align.'"':''), $sortfield, $sortorder, $align.' ')."\n"; + } } // Extra fields $extrafieldsobjectkey=$contactstatic->table_element; @@ -1123,6 +1139,11 @@ function show_contacts($conf, $langs, $db, $object, $backtopage = '') $contactstatic->setGenderFromCivility(); $contactstatic->fetch_optionals(); + $resultRole=$contactstatic->fetchRoles(); + if ($resultRole<0) { + setEventMessages(null, $contactstatic->errors, 'errors'); + } + if (is_array($contactstatic->array_options)) { foreach($contactstatic->array_options as $key => $val) @@ -1166,6 +1187,14 @@ function show_contacts($conf, $langs, $db, $object, $backtopage = '') print ''; } + // Role + if (! empty($arrayfields['sc.role']['checked'])) + { + print ''; + } + // Status if (! empty($arrayfields['t.statut']['checked'])) { @@ -1599,7 +1628,7 @@ function show_actions_done($conf, $langs, $db, $filterobj, $objcon = '', $noprin } // Ref - $out.=''; // Link -print ''; // Link -print ''; print ''; // Img of credit card print '\n"; // Stripe customer print "\n"; // Link diff --git a/htdocs/stripe/lib/stripe.lib.php b/htdocs/stripe/lib/stripe.lib.php index 95fb80ce9dc..8a4284f491e 100644 --- a/htdocs/stripe/lib/stripe.lib.php +++ b/htdocs/stripe/lib/stripe.lib.php @@ -70,7 +70,7 @@ function showStripePaymentUrl($type, $ref) $servicename='Stripe'; $out='

    '; - $out.=img_picto('', 'object_globe.png').' '.$langs->trans("ToOfferALinkForOnlinePayment", $servicename).'
    '; + $out.=img_picto('', 'globe').' '.$langs->trans("ToOfferALinkForOnlinePayment", $servicename).'
    '; $url=getStripePaymentUrl(0, $type, $ref); $out.='
    '; $out.=ajax_autoselect("stripeurl", 0); diff --git a/htdocs/stripe/payout.php b/htdocs/stripe/payout.php index e66318506ed..5870427757a 100644 --- a/htdocs/stripe/payout.php +++ b/htdocs/stripe/payout.php @@ -169,7 +169,7 @@ if (! $rowid) { $url='https://dashboard.stripe.com/'.$connect.'payouts/'.$payout->id; } - print "\n"; + print "\n"; // Stripe customer diff --git a/htdocs/stripe/transaction.php b/htdocs/stripe/transaction.php index 4ad04011f99..873adfc1cf7 100644 --- a/htdocs/stripe/transaction.php +++ b/htdocs/stripe/transaction.php @@ -178,7 +178,7 @@ if (! $rowid) { if ($txn->type == 'stripe_fee' || $txn->type == 'reserve_transaction') { print ""; } else { - print "\n"; + print "\n"; } // Stripe customer diff --git a/htdocs/theme/eldy/global.inc.php b/htdocs/theme/eldy/global.inc.php index 98bfddc196d..7dcac4d68ba 100644 --- a/htdocs/theme/eldy/global.inc.php +++ b/htdocs/theme/eldy/global.inc.php @@ -834,7 +834,7 @@ table[summary="list_of_modules"] .fa-cog { .minheight20 { min-height: 20px; } .minheight40 { min-height: 40px; } .titlefieldcreate { width: 20%; } -.titlefield { width: 25%; } +.titlefield { /* width: 25%; */ width: 250px; } .titlefieldmiddle { width: 50%; } .imgmaxwidth180 { max-width: 180px; } .imgmaxheight50 { max-height: 50px; } @@ -852,7 +852,7 @@ table[summary="list_of_modules"] .fa-cog { /* Force values for small screen 1400 */ @media only screen and (max-width: 1400px) { - .titlefield { width: 30% !important; } + .titlefield { /* width: 30% !important; */ } .titlefieldcreate { width: 30% !important; } .minwidth50imp { min-width: 50px !important; } .minwidth75imp { min-width: 75px !important; } @@ -1442,7 +1442,7 @@ img.photorefnoborder { } .trextrafieldseparator td { /* border-bottom: 2px solid rgb() !important; */ - border-bottom: 2px dashed rgb() !important; + border-bottom: 2px solid rgb() !important; } .tdhrthin { @@ -1660,7 +1660,7 @@ a.tmenuimage:hover{ /* Do not load menu img for other if hidden to save bandwidth */ - global->MAIN_DISABLE_FONT_AWESOME_5)) { ?> + div.mainmenu.home{ @@ -1794,7 +1794,7 @@ a.tmenuimage:hover{ // Img file not found if (! $found) { - if (! defined('DISABLE_FONT_AWSOME') && empty($conf->global->MAIN_DISABLE_FONT_AWESOME_5)) { + if (! defined('DISABLE_FONT_AWSOME')) { print "/* A mainmenu entry was found but img file ".$val.".png not found (check /".$val."/img/".$val.".png), so we use a generic one */\n"; print 'div.mainmenu.'.$val.'::before { content: "\f249"; @@ -2068,8 +2068,8 @@ img.userphoto { /* size for user photo in lists */ } img.userphotosmall { /* size for user photo in lists */ border-radius: 6px; - width: 12px; - height: 12px; + width: 1em; + height: 1em; background-size: contain; vertical-align: middle; background-color: #FFF; diff --git a/htdocs/theme/md/style.css.php b/htdocs/theme/md/style.css.php index ec1f04ab9db..a17a33bd898 100644 --- a/htdocs/theme/md/style.css.php +++ b/htdocs/theme/md/style.css.php @@ -1003,7 +1003,7 @@ table[summary="list_of_modules"] .fa-cog { .minheight20 { min-height: 20px; } .minheight40 { min-height: 40px; } .titlefieldcreate { width: 20%; } -.titlefield { width: 25%; } +.titlefield { /* width: 25%; */ width: 250px; } .titlefieldmiddle { width: 50%; } .imgmaxwidth180 { max-width: 180px; } @@ -1011,7 +1011,7 @@ table[summary="list_of_modules"] .fa-cog { /* Force values for small screen 1400 */ @media only screen and (max-width: 1400px) { - .titlefield { width: 30% !important; } + .titlefield { /* width: 30% !important; */ } .titlefieldcreate { width: 30% !important; } .minwidth50imp { min-width: 50px !important; } .minwidth75imp { min-width: 75px !important; } @@ -1786,7 +1786,7 @@ div.mainmenu { /* Do not load menu img if hidden to save bandwidth */ - global->MAIN_DISABLE_FONT_AWESOME_5)) { ?> + @@ -1926,7 +1926,7 @@ foreach($mainmenuusedarray as $val) // Img file not found if (! $found) { - if (! defined('DISABLE_FONT_AWSOME') && empty($conf->global->MAIN_DISABLE_FONT_AWESOME_5)) { + if (! defined('DISABLE_FONT_AWSOME')) { print "/* A mainmenu entry was found but img file ".$val.".png not found (check /".$val."/img/".$val.".png), so we use a generic one */\n"; print 'div.mainmenu.'.$val.'::before { content: "\f249"; @@ -5805,7 +5805,7 @@ border-top-right-radius: 6px; -global->MAIN_DISABLE_FONT_AWESOME_5)) { ?> +note = GETPOST("note", 'none'); $object->ldap_sid = GETPOST("ldap_sid", 'alphanohtml'); $object->fk_user = GETPOST("fk_user", 'int') > 0 ? GETPOST("fk_user", 'int') : 0; + $object->fk_user_expense_validator = GETPOST("fk_user_expense_validator", 'int') > 0 ? GETPOST("fk_user_expense_validator", 'int') : 0; + $object->fk_user_holiday_validator = GETPOST("fk_user_holiday_validator", 'int') > 0 ? GETPOST("fk_user_holiday_validator", 'int') : 0; $object->employee = GETPOST('employee', 'alphanohtml'); $object->thm = GETPOST("thm", 'alphanohtml') != '' ? GETPOST("thm", 'alphanohtml') : ''; @@ -387,6 +389,8 @@ if (empty($reshook)) { $object->accountancy_code = GETPOST("accountancy_code", 'alphanohtml'); $object->openid = GETPOST("openid", 'alphanohtml'); $object->fk_user = GETPOST("fk_user", 'int') > 0 ? GETPOST("fk_user", 'int') : 0; + $object->fk_user_expense_validator = GETPOST("fk_user_expense_validator", 'int') > 0 ? GETPOST("fk_user_expense_validator", 'int') : 0; + $object->fk_user_holiday_validator = GETPOST("fk_user_holiday_validator", 'int') > 0 ? GETPOST("fk_user_holiday_validator", 'int') : 0; $object->employee = GETPOST('employee', 'int'); $object->thm = GETPOST("thm", 'alphanohtml') != '' ? GETPOST("thm", 'alphanohtml') : ''; @@ -976,6 +980,32 @@ if ($action == 'create' || $action == 'adduserldap') print ''; print "\n"; + // Expense report validator + if(!empty($conf->expensereport->enabled)) + { + print ''; + print ''; + print "\n"; + } + + // Holiday request validator + if(!empty($conf->holiday->enabled)) + { + print ''; + print ''; + print "\n"; + } + print '
    '.$langs->trans("Type").''.$object->type.'
    '.$langs->trans("Type").''.$langs->trans($object->type).'
    " . $langs->trans("DefaultContact") . ''; $form->select_contacts($soc->id, $contactid, 'contactid', 1, $srccontactslist); print '
    '; + print ''; if ($userstatic->id) print $userstatic->getLoginUrl(1); - else print ' '; print "'; diff --git a/htdocs/commande/card.php b/htdocs/commande/card.php index ed08c39d869..968607ed660 100644 --- a/htdocs/commande/card.php +++ b/htdocs/commande/card.php @@ -70,6 +70,7 @@ $action = GETPOST('action', 'alpha'); $cancel = GETPOST('cancel', 'alpha'); $confirm = GETPOST('confirm', 'alpha'); $lineid = GETPOST('lineid', 'int'); +$contactid = GETPOST('contactid', 'int'); $projectid = GETPOST('projectid', 'int'); $origin = GETPOST('origin', 'alpha'); $originid = (GETPOST('originid', 'int') ? GETPOST('originid', 'int') : GETPOST('origin_id', 'int')); // For backward compatibility @@ -1646,8 +1647,9 @@ if ($action == 'create' && $usercancreate) // Contact of order if ($socid > 0) { + // Contacts (ask contact only if thirdparty already defined). print "
    " . $langs->trans("DefaultContact") . ''; - $form->select_contacts($soc->id, $setcontact, 'contactid', 1, $srccontactslist, '', 1); + $form->select_contacts($soc->id, $contactid, 'contactid', 1, $srccontactslist, '', 1); print '
    ' . $langs->trans("ContactByDefaultFor") . ''; + $contactType = $object->listeTypeContacts('external', '', 1); + print $form->multiselectarray('roles', $contactType); + print '
    ' . $langs->trans("ContactByDefaultFor") . ''; + print $formcompany->showRoles("roles", $object, 'edit', $object->roles); + print '
    '.$langs->trans("PostOrFunction").''.$object->poste.'
    ' . $langs->trans("ContactByDefaultFor") . ''; + print $formcompany->showRoles("roles", $object, 'view'); + print '
    '; - print img_picto('', 'object_globe').' '; + print img_picto('', 'globe').' '; print ''; print dol_escape_htmltag($link->label); print ''; diff --git a/htdocs/core/class/html.formother.class.php b/htdocs/core/class/html.formother.class.php index 2111b479d25..48db977255f 100644 --- a/htdocs/core/class/html.formother.class.php +++ b/htdocs/core/class/html.formother.class.php @@ -989,8 +989,8 @@ class FormOther * Class 'Form' must be known. * * @param User $user Object User - * @param String $areacode Code of area for pages ('0'=value for Home page) - * @return array array('selectboxlist'=>, 'boxactivated'=>, 'boxlista'=>, 'boxlistb'=>) + * @param String $areacode Code of area for pages - 0 = Home page ... See getListOfPagesForBoxes() + * @return array array('selectboxlist'=>, 'boxactivated'=>, 'boxlista'=>, 'boxlistb'=>) */ public static function getBoxesArea($user, $areacode) { diff --git a/htdocs/core/class/infobox.class.php b/htdocs/core/class/infobox.class.php index 6c251dd1378..a187e58cac1 100644 --- a/htdocs/core/class/infobox.class.php +++ b/htdocs/core/class/infobox.class.php @@ -29,7 +29,7 @@ class InfoBox { /** - * Name of positions 0=Home, 1=... + * Name of positions (See below) * * @return string[] Array with list of zones */ @@ -39,7 +39,10 @@ class InfoBox if (empty($conf->global->MAIN_FEATURES_LEVEL) || $conf->global->MAIN_FEATURES_LEVEL < 2) { - return array(0 => 'Home'); + return array( + 0 => 'Home', + 27 => 'Accountancy Home' + ); } else { @@ -71,7 +74,7 @@ class InfoBox 24 => 'expensereportindex', 25 => 'mailingindex', 26 => 'opensurveyindex', - 27 => 'accountancyindex' + 27 => 'Accountancy Home' ); } } @@ -81,7 +84,7 @@ class InfoBox * * @param DoliDB $db Database handler * @param string $mode 'available' or 'activated' - * @param string $zone Name or area (-1 for all, 0 for Homepage, 1 for xxx, ...) + * @param string $zone Name or area (-1 for all, 0 for Homepage, 1 for Accountancy, 2 for xxx, ...) * @param User|null $user Object user to filter * @param array $excludelist Array of box id (box.box_id = boxes_def.rowid) to exclude * @param int $includehidden Include also hidden boxes @@ -110,7 +113,7 @@ class InfoBox { $sql = "SELECT d.rowid as box_id, d.file, d.note, d.tms"; $sql.= " FROM ".MAIN_DB_PREFIX."boxes_def as d"; - $sql.= " WHERE d.entity IN (0,".$conf->entity.")"; + $sql.= " WHERE d.entity IN (0,".$conf->entity.")"; } dol_syslog(get_class()."::listBoxes get default box list for mode=".$mode." userid=".(is_object($user)?$user->id:'')."", LOG_DEBUG); @@ -152,7 +155,7 @@ class InfoBox // box properties $box->rowid = (empty($obj->rowid) ? '' : $obj->rowid); $box->id = (empty($obj->box_id) ? '' : $obj->box_id); - $box->position = ($obj->position == '' ? '' : $obj->position); // '0' must staty '0' + $box->position = ($obj->position == '' ? '' : $obj->position); // '0' must stay '0' $box->box_order = (empty($obj->box_order) ? '' : $obj->box_order); $box->fk_user = (empty($obj->fk_user) ? 0 : $obj->fk_user); $box->sourcefile= $relsourcefile; diff --git a/htdocs/core/lib/company.lib.php b/htdocs/core/lib/company.lib.php index e42d72b414b..2528018908c 100644 --- a/htdocs/core/lib/company.lib.php +++ b/htdocs/core/lib/company.lib.php @@ -859,6 +859,8 @@ function show_contacts($conf, $langs, $db, $object, $backtopage = '') global $user,$conf,$extrafields,$hookmanager; global $contextpage; + require_once DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php'; + $formcompany = new FormCompany($db); $form = new Form($db); $optioncss = GETPOST('optioncss', 'alpha'); @@ -872,6 +874,7 @@ function show_contacts($conf, $langs, $db, $object, $backtopage = '') $search_name = GETPOST("search_name", 'alpha'); $search_address = GETPOST("search_address", 'alpha'); $search_poste = GETPOST("search_poste", 'alpha'); + $search_roles = GETPOST("search_roles", 'array'); $socialnetworks = getArrayOfSocialNetworks(); @@ -916,16 +919,18 @@ function show_contacts($conf, $langs, $db, $object, $backtopage = '') 'name' =>array('type'=>'varchar(128)', 'label'=>'Name', 'enabled'=>1, 'visible'=>1, 'notnull'=>1, 'showoncombobox'=>1, 'index'=>1, 'position'=>10, 'searchall'=>1), 'poste' =>array('type'=>'varchar(128)', 'label'=>'PostOrFunction', 'enabled'=>1, 'visible'=>1, 'notnull'=>1, 'showoncombobox'=>1, 'index'=>1, 'position'=>20), 'address' =>array('type'=>'varchar(128)', 'label'=>'Address', 'enabled'=>1, 'visible'=>1, 'notnull'=>1, 'showoncombobox'=>1, 'index'=>1, 'position'=>30), - 'statut' =>array('type'=>'integer', 'label'=>'Status', 'enabled'=>1, 'visible'=>1, 'notnull'=>1, 'default'=>0, 'index'=>1, 'position'=>40, 'arrayofkeyval'=>array(0=>$contactstatic->LibStatut(0, 1), 1=>$contactstatic->LibStatut(1, 1))), + 'role' =>array('type'=>'checkbox', 'label'=>'Role', 'enabled'=>1, 'visible'=>1, 'notnull'=>1, 'showoncombobox'=>1, 'index'=>1, 'position'=>40), + 'statut' =>array('type'=>'integer', 'label'=>'Status', 'enabled'=>1, 'visible'=>1, 'notnull'=>1, 'default'=>0, 'index'=>1, 'position'=>50, 'arrayofkeyval'=>array(0=>$contactstatic->LibStatut(0, 1), 1=>$contactstatic->LibStatut(1, 1))), ); // Definition of fields for list $arrayfields=array( - 't.rowid'=>array('label'=>"TechnicalID", 'checked'=>($conf->global->MAIN_SHOW_TECHNICAL_ID?1:0), 'enabled'=>($conf->global->MAIN_SHOW_TECHNICAL_ID?1:0), 'position'=>1), - 't.name'=>array('label'=>"Name", 'checked'=>1, 'position'=>10), - 't.poste'=>array('label'=>"PostOrFunction", 'checked'=>1, 'position'=>20), - 't.address'=>array('label'=>(empty($conf->dol_optimize_smallscreen) ? $langs->trans("Address").' / '.$langs->trans("Phone").' / '.$langs->trans("Email") : $langs->trans("Address")), 'checked'=>1, 'position'=>30), - 't.statut'=>array('label'=>"Status", 'checked'=>1, 'position'=>40, 'class'=>'center'), + 't.rowid'=>array('label'=>"TechnicalID", 'checked'=>($conf->global->MAIN_SHOW_TECHNICAL_ID?1:0), 'enabled'=>($conf->global->MAIN_SHOW_TECHNICAL_ID?1:0), 'position'=>1), + 't.name'=>array('label'=>"Name", 'checked'=>1, 'position'=>10), + 't.poste'=>array('label'=>"PostOrFunction", 'checked'=>1, 'position'=>20), + 't.address'=>array('label'=>(empty($conf->dol_optimize_smallscreen) ? $langs->trans("Address").' / '.$langs->trans("Phone").' / '.$langs->trans("Email") : $langs->trans("Address")), 'checked'=>1, 'position'=>30), + 'sc.role'=>array('label'=>"Roles", 'checked'=>1, 'position'=>40), + 't.statut'=>array('label'=>"Status", 'checked'=>1, 'position'=>50, 'class'=>'center'), ); // Extra fields if (is_array($extrafields->attributes[$contactstatic->table_element]['label']) && count($extrafields->attributes[$contactstatic->table_element]['label'])) @@ -958,9 +963,10 @@ function show_contacts($conf, $langs, $db, $object, $backtopage = '') { $search_status = ''; $search_name = ''; + $search_roles = array(); $search_address = ''; $search_poste = ''; - $search= []; + $search = array(); $search_array_options=array(); foreach($contactstatic->fields as $key => $val) @@ -1000,6 +1006,7 @@ function show_contacts($conf, $langs, $db, $object, $backtopage = '') $param="socid=".urlencode($object->id); if ($search_status != '') $param.='&search_status='.urlencode($search_status); + if (count($search_roles)>0) $param.=implode('&search_roles[]=', $search_roles); if ($search_name != '') $param.='&search_name='.urlencode($search_name); if ($search_poste != '') $param.='&search_poste='.urlencode($search_poste); if ($search_address != '') $param.='&search_address='.urlencode($search_address); @@ -1018,8 +1025,11 @@ function show_contacts($conf, $langs, $db, $object, $backtopage = '') if ($search_name) $sql .= natural_search(array('t.lastname', 't.firstname'), $search_name); if ($search_poste) $sql .= natural_search('t.poste', $search_poste); if ($search_address) { - $sql .= natural_search($searchAddressPhoneDBFields, $search_address); - } + $sql .= natural_search($searchAddressPhoneDBFields, $search_address); + } + if (count($search_roles)>0) { + $sql .= " AND t.rowid IN (SELECT sc.fk_socpeople FROM ".MAIN_DB_PREFIX."societe_contacts as sc WHERE sc.fk_c_type_contact IN (".implode(',', $search_roles)."))"; + } // Add where from extra fields $extrafieldsobjectkey=$contactstatic->table_element; include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_sql.tpl.php'; @@ -1046,7 +1056,9 @@ function show_contacts($conf, $langs, $db, $object, $backtopage = '') print ''; if (in_array($key, array('statut'))){ print $form->selectarray('search_status', array('-1'=>'','0'=>$contactstatic->LibStatut(0, 1),'1'=>$contactstatic->LibStatut(1, 1)), $search_status); - } else { + }elseif (in_array($key, array('role'))) { + print $formcompany->showRoles("search_roles", $contactstatic, 'edit', $search_roles); + } else { print ''; } print ''; + print $formcompany->showRoles("roles", $contactstatic, 'view'); + print ''; + $out.=''; if (isset($histo[$key]['type']) && $histo[$key]['type']=='mailing') { $out.=''.img_object($langs->trans("ShowEMailing"), "email").' '; $out.=$histo[$key]['id']; diff --git a/htdocs/core/lib/cron.lib.php b/htdocs/core/lib/cron.lib.php index 57af5cc5a59..4088b00c151 100644 --- a/htdocs/core/lib/cron.lib.php +++ b/htdocs/core/lib/cron.lib.php @@ -95,10 +95,10 @@ function dol_print_cron_urls() print '
    '; print $langs->trans("URLToLaunchCronJobs").':
    '; $url=$urlwithroot.'/public/cron/cron_run_jobs.php?'.(empty($conf->global->CRON_KEY)?'':'securitykey='.$conf->global->CRON_KEY.'&').'userlogin='.$user->login; - print img_picto('', 'object_globe.png').'
    '.$url."
    \n"; + print img_picto('', 'globe').' '.$url."
    \n"; print ' '.$langs->trans("OrToLaunchASpecificJob").'
    '; $url=$urlwithroot.'/public/cron/cron_run_jobs.php?'.(empty($conf->global->CRON_KEY)?'':'securitykey='.$conf->global->CRON_KEY.'&').'userlogin='.$user->login.'&id=cronjobid'; - print img_picto('', 'object_globe.png').' '.$url."
    \n"; + print img_picto('', 'globe').' '.$url."
    \n"; print '
    '; print '
    '; diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index eaffc886d4c..ff7d66f52b8 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -2137,7 +2137,7 @@ function dol_print_url($url, $target = '_blank', $max = 32, $withpicto = 0) if (! preg_match('/^http/i', $url)) $link.='http://'; $link.=dol_trunc($url, $max); $link.=''; - return '
    '.($withpicto?img_picto($langs->trans("Url"), 'object_globe.png').' ':'').$link.'
    '; + return '
    '.($withpicto?img_picto($langs->trans("Url"), 'globe').' ':'').$link.'
    '; } /** @@ -3055,7 +3055,7 @@ function img_picto($titlealt, $picto, $moreatt = '', $pictoisfullpath = false, $ //if (in_array($picto, array('switch_off', 'switch_on', 'off', 'on'))) if (empty($srconly) && in_array($pictowithouttext, array( '1downarrow', '1uparrow', '1leftarrow', '1rightarrow', '1uparrow_selected', '1downarrow_selected', '1leftarrow_selected', '1rightarrow_selected', - 'address', 'bank', 'building', 'cash-register', 'close_title', 'cubes', 'delete', 'edit', 'ellipsis-h', 'filter', 'grip', 'grip_title', 'list', 'listlight', 'note', + 'address', 'bank', 'building', 'cash-register', 'close_title', 'cubes', 'delete', 'edit', 'ellipsis-h', 'bookmark', 'filter', 'grip', 'grip_title', 'list', 'listlight', 'note', 'object_list','object_calendar', 'object_calendarweek', 'object_calendarmonth', 'object_calendarday', 'object_calendarperuser', 'off', 'on', 'play', 'playdisabled', 'printer', 'resize', 'note', 'setup', 'sign-out', 'split', 'switch_off', 'switch_on', 'tools', 'unlink', 'uparrow', 'user', 'wrench', @@ -3065,18 +3065,17 @@ function img_picto($titlealt, $picto, $moreatt = '', $pictoisfullpath = false, $ 'title_setup', 'title_accountancy', 'title_bank', 'title_hrm', 'title_agenda' ) )) { - $fa='fa'; - if (empty($conf->global->MAIN_DISABLE_FONT_AWESOME_5)) $fa='fas'; + $fa='fas'; $fakey = $pictowithouttext; $facolor = ''; $fasize = ''; $arrayconvpictotofa = array( 'address'=> 'address-book', 'setup'=>'cog', 'companies'=>'building', 'products'=>'cube', 'commercial'=>'suitcase', 'invoicing'=>'coins', 'accountancy'=>'money-check-alt', 'project'=>'sitemap', 'hrm'=>'umbrella-beach', 'members'=>'users', 'ticket'=>'ticket-alt', 'generic'=>'folder-open', - 'switch_off'=>'toggle-off', 'switch_on'=>'toggle-on', - 'bank'=>'bank', 'close_title'=>'window-close', 'delete'=>'trash', 'edit'=>'pencil', 'filter'=>'filter', 'split'=>'code-fork', + 'switch_off'=>'toggle-off', 'switch_on'=>'toggle-on', 'bookmark'=>'star', + 'bank'=>'university', 'close_title'=>'window-close', 'delete'=>'trash', 'edit'=>'pencil', 'filter'=>'filter', 'split'=>'code-fork', 'object_list'=>'list-alt','object_calendar'=>'calendar-alt', 'object_calendarweek'=>'calendar-week', 'object_calendarmonth'=>'calendar-alt', 'object_calendarday'=>'calendar-day', 'object_calendarperuser'=>'table', - 'title_setup'=>'tools', 'title_accountancy'=>'money-check-alt', 'title_bank'=>'bank', 'title_hrm'=>'umbrella-beach', 'title_agenda'=>'calendar-alt' + 'title_setup'=>'tools', 'title_accountancy'=>'money-check-alt', 'title_bank'=>'university', 'title_hrm'=>'umbrella-beach', 'title_agenda'=>'calendar-alt' ); if ($pictowithouttext == 'switch_off') { @@ -3090,21 +3089,13 @@ function img_picto($titlealt, $picto, $moreatt = '', $pictoisfullpath = false, $ $fakey = 'fa-'.$arrayconvpictotofa[$pictowithouttext]; } elseif ($pictowithouttext == 'off') { - $fakey = 'fa-square-o'; - if (empty($conf->global->MAIN_DISABLE_FONT_AWESOME_5)) - { - $fakey = 'fa-square'; - $fa='far'; - } + $fakey = 'fa-square'; + $fa='far'; $fasize = '1.3em'; } elseif ($pictowithouttext == 'on') { - $fakey = 'fa-check-square-o'; - if (empty($conf->global->MAIN_DISABLE_FONT_AWESOME_5)) - { - $fakey = 'fa-check-square'; - $fa='far'; - } + $fakey = 'fa-check-square'; + $fa='far'; $fasize = '1.3em'; } elseif ($pictowithouttext == 'bank') { @@ -3117,12 +3108,14 @@ function img_picto($titlealt, $picto, $moreatt = '', $pictoisfullpath = false, $ } elseif ($pictowithouttext == 'edit') { $facolor = '#444'; - $fakey = 'fa-'.$arrayconvpictotofa[$pictowithouttext]; - if (empty($conf->global->MAIN_DISABLE_FONT_AWESOME_5)) $fakey = 'fa-pencil-alt'; + $fakey = 'fa-pencil-alt'; } elseif ($pictowithouttext == 'grip_title' || $pictowithouttext == 'grip') { - $fakey = 'fa-arrows'; - if (empty($conf->global->MAIN_DISABLE_FONT_AWESOME_5)) $fakey = 'fa-arrows-alt'; + $fakey = 'fa-arrows-alt'; + } + elseif ($pictowithouttext == 'bookmark') { + $fakey = 'fa-'.$arrayconvpictotofa[$pictowithouttext]; + $fa='far'; } elseif ($pictowithouttext == 'listlight') { $fakey = 'fa-download'; @@ -3139,11 +3132,8 @@ function img_picto($titlealt, $picto, $moreatt = '', $pictoisfullpath = false, $ $facolor = '#444'; } elseif ($pictowithouttext == 'note') { - $fakey = 'fa-sticky-note-o'; - if (empty($conf->global->MAIN_DISABLE_FONT_AWESOME_5)) - { - $fakey = 'fa-sticky-note'; $fa = 'far'; - } + $fakey = 'fa-sticky-note'; + $fa = 'far'; $facolor = '#999'; $marginleftonlyshort=1; } @@ -3158,9 +3148,8 @@ function img_picto($titlealt, $picto, $moreatt = '', $pictoisfullpath = false, $ $marginleftonlyshort = 1; } elseif ($pictowithouttext == 'sign-out') { - $fakey = 'fa-sign-out'; + $fakey = 'fa-sign-out-alt'; $marginleftonlyshort=0; - if (empty($conf->global->MAIN_DISABLE_FONT_AWESOME_5)) $fakey = 'fa-sign-out-alt'; } elseif ($pictowithouttext == 'unlink') { $fakey = 'fa-chain-broken'; @@ -3179,7 +3168,7 @@ function img_picto($titlealt, $picto, $moreatt = '', $pictoisfullpath = false, $ } elseif (in_array($pictowithouttext, array('skype', 'twitter', 'facebook', 'linkedin', 'instagram','snapchat','youtube','google-plus-g','whatsapp'))) { $fakey = 'fa-'.$pictowithouttext; - if (empty($conf->global->MAIN_DISABLE_FONT_AWESOME_5)) $fa = 'fab'; + $fa = 'fab'; } // Img for type of views elseif (in_array($pictowithouttext, array('object_list', 'object_calendar', 'object_calendarweek', 'object_calendarmonth', 'object_calendarday', 'object_calendarperuser'))) { @@ -7735,7 +7724,7 @@ function showDirectDownloadLink($object) if ($url) { - $out.= img_picto('', 'object_globe.png').' '.$langs->trans("DirectDownloadLink").'
    '; + $out.= img_picto('', 'globe').' '.$langs->trans("DirectDownloadLink").'
    '; $out.= ''; $out.= ajax_autoselect("directdownloadlink", 0); } @@ -8138,6 +8127,11 @@ function dolGetStatus($statusLabel = '', $statusLabelShort = '', $html = '', $st $return = ''; + $dolGetBadgeParams = array(); + if(!empty($params['badgeParams'])){ + $dolGetBadgeParams = $params['badgeParams']; + } + // image's filename are still in French $statusImg=array( 'status0' => 'statut0' @@ -8193,13 +8187,13 @@ function dolGetStatus($statusLabel = '', $statusLabelShort = '', $html = '', $st $statusLabelShort = !empty($statusLabelShort)?$statusLabelShort:$statusLabel; if ($displayMode == 3) { - $return = dolGetBadge($statusLabel, '', $statusType, 'dot'); + $return = dolGetBadge($statusLabel, '', $statusType, 'dot', $url, $dolGetBadgeParams); } elseif ($displayMode === 5) { - $return = dolGetBadge($statusLabelShort, $html, $statusType); + $return = dolGetBadge($statusLabelShort, $html, $statusType, '', $url, $dolGetBadgeParams); } else { - $return = dolGetBadge($statusLabel, $html, $statusType); + $return = dolGetBadge($statusLabel, $html, $statusType, '', $url, $dolGetBadgeParams); } } diff --git a/htdocs/core/lib/payments.lib.php b/htdocs/core/lib/payments.lib.php index 1c90503ea63..75e2ee08b8f 100644 --- a/htdocs/core/lib/payments.lib.php +++ b/htdocs/core/lib/payments.lib.php @@ -132,7 +132,7 @@ function showOnlinePaymentUrl($type, $ref) $servicename=$langs->transnoentitiesnoconv('Online'); - $out = img_picto('', 'object_globe.png').' '.$langs->trans("ToOfferALinkForOnlinePayment", $servicename).'
    '; + $out = img_picto('', 'globe').' '.$langs->trans("ToOfferALinkForOnlinePayment", $servicename).'
    '; $url = getOnlinePaymentUrl(0, $type, $ref); $out.= ''; $out.= ajax_autoselect("onlinepaymenturl", 0); diff --git a/htdocs/core/lib/signature.lib.php b/htdocs/core/lib/signature.lib.php index 3ed4fb764d0..c9527c54840 100644 --- a/htdocs/core/lib/signature.lib.php +++ b/htdocs/core/lib/signature.lib.php @@ -33,7 +33,7 @@ function showOnlineSignatureUrl($type, $ref) $servicename='Online'; - $out = img_picto('', 'object_globe.png').' '.$langs->trans("ToOfferALinkForOnlineSignature", $servicename).'
    '; + $out = img_picto('', 'globe').' '.$langs->trans("ToOfferALinkForOnlineSignature", $servicename).'
    '; $url = getOnlineSignatureUrl(0, $type, $ref); $out.= ''; $out.= ajax_autoselect("onlinesignatureurl", 0); diff --git a/htdocs/core/modules/holiday/modules_holiday.php b/htdocs/core/modules/holiday/modules_holiday.php index 74cbb0dbfd5..c5f5dc16b25 100644 --- a/htdocs/core/modules/holiday/modules_holiday.php +++ b/htdocs/core/modules/holiday/modules_holiday.php @@ -96,7 +96,7 @@ class ModelNumRefHolidays public function info() { global $langs; - $langs->load("holidays"); + $langs->load("holiday"); return $langs->trans("NoDescription"); } @@ -108,7 +108,7 @@ class ModelNumRefHolidays public function getExample() { global $langs; - $langs->load("holidays"); + $langs->load("holiday"); return $langs->trans("NoExample"); } diff --git a/htdocs/core/modules/import/import_csv.modules.php b/htdocs/core/modules/import/import_csv.modules.php index bde888157dd..de428900ba9 100644 --- a/htdocs/core/modules/import/import_csv.modules.php +++ b/htdocs/core/modules/import/import_csv.modules.php @@ -489,7 +489,7 @@ class ImportCsv extends ModeleImports { if (empty($newval)) $newval='0'; } - elseif ($objimport->array_import_convertvalue[0][$val]['rule']=='fetchidfromcodeunits') + elseif ($objimport->array_import_convertvalue[0][$val]['rule']=='fetchidfromcodeunits' || $objimport->array_import_convertvalue[0][$val]['rule']=='fetchscalefromcodeunits') { $file=(empty($objimport->array_import_convertvalue[0][$val]['classfile'])?$objimport->array_import_convertvalue[0][$val]['file']:$objimport->array_import_convertvalue[0][$val]['classfile']); $class=$objimport->array_import_convertvalue[0][$val]['class']; @@ -509,16 +509,17 @@ class ImportCsv extends ModeleImports } $classinstance=new $class($this->db); // Try the fetch from code or ref - call_user_func_array(array($classinstance, $method), array('', $units, $newval)); - $this->cacheconvert[$file.'_'.$class.'_'.$method.'_'.$units][$newval]=$classinstance->code; - //print 'We have made a '.$class.'->'.$method.' to get id from code '.$newval.'. '; - if ($classinstance->code != '') // id may be 0, it is a found value + call_user_func_array(array($classinstance, $method), array('', '', $newval, $units)); + $scaleorid = (($objimport->array_import_convertvalue[0][$val]['rule']=='fetchidfromcodeunits') ? $classinstance->id : $classinstance->scale); + $this->cacheconvert[$file.'_'.$class.'_'.$method.'_'.$units][$newval]=$scaleorid; + //print 'We have made a '.$class.'->'.$method." to get a value from key '".$newval."' and we got '".$scaleorid."'.";exit; + if ($classinstance->id > 0) // we found record { - $newval=$classinstance->code; + $newval = $scaleorid ? $scaleorid : 0; } else { - if (!empty($objimport->array_import_convertvalue[0][$val]['dict'])) $this->errors[$error]['lib']=$langs->trans('ErrorFieldValueNotIn', $key, $newval, 'code', $langs->transnoentitiesnoconv($objimport->array_import_convertvalue[0][$val]['dict'])); + if (!empty($objimport->array_import_convertvalue[0][$val]['dict'])) $this->errors[$error]['lib']=$langs->trans('ErrorFieldValueNotIn', $key, $newval, 'scale', $langs->transnoentitiesnoconv($objimport->array_import_convertvalue[0][$val]['dict'])); else $this->errors[$error]['lib']='ErrorFieldValueNotIn'; $this->errors[$error]['type']='FOREIGNKEY'; $errorforthistable++; @@ -696,7 +697,7 @@ class ImportCsv extends ModeleImports // Loop on each hidden fields to add them into listfields/listvalues foreach($objimport->array_import_fieldshidden[0] as $key => $val) { - if (! preg_match('/^'.preg_quote($alias).'\./', $key)) continue; // Not a field of current table + if (! preg_match('/^'.preg_quote($alias, '/').'\./', $key)) continue; // Not a field of current table if ($val == 'user->id') { $listfields[] = preg_replace('/^'.preg_quote($alias, '/').'\./', '', $key); diff --git a/htdocs/core/modules/import/import_xlsx.modules.php b/htdocs/core/modules/import/import_xlsx.modules.php index a67a0c90c4b..c4799ba557e 100644 --- a/htdocs/core/modules/import/import_xlsx.modules.php +++ b/htdocs/core/modules/import/import_xlsx.modules.php @@ -516,7 +516,7 @@ class ImportXlsx extends ModeleImports { if (empty($newval)) $newval='0'; } - elseif ($objimport->array_import_convertvalue[0][$val]['rule']=='fetchidfromcodeunits') + elseif ($objimport->array_import_convertvalue[0][$val]['rule']=='fetchidfromcodeunits' || $objimport->array_import_convertvalue[0][$val]['rule']=='fetchscalefromcodeunits') { $file=(empty($objimport->array_import_convertvalue[0][$val]['classfile'])?$objimport->array_import_convertvalue[0][$val]['file']:$objimport->array_import_convertvalue[0][$val]['classfile']); $class=$objimport->array_import_convertvalue[0][$val]['class']; @@ -536,17 +536,18 @@ class ImportXlsx extends ModeleImports } $classinstance=new $class($this->db); // Try the fetch from code or ref - call_user_func_array(array($classinstance, $method), array('', $units, '', $newval)); - $this->cacheconvert[$file.'_'.$class.'_'.$method.'_'.$units][$newval]=$classinstance->code; - //print 'We have made a '.$class.'->'.$method.' to get id from code '.$newval.'. '; - if ($classinstance->code != '') // id may be 0, it is a found value - { - $newval=$classinstance->code; - } - else - { - if (!empty($objimport->array_import_convertvalue[0][$val]['dict'])) $this->errors[$error]['lib']=$langs->trans('ErrorFieldValueNotIn', $key, $newval, 'code', $langs->transnoentitiesnoconv($objimport->array_import_convertvalue[0][$val]['dict'])); - else $this->errors[$error]['lib']='ErrorFieldValueNotIn'; + call_user_func_array(array($classinstance, $method), array('', '', $newval, $units)); + $scaleorid = (($objimport->array_import_convertvalue[0][$val]['rule']=='fetchidfromcodeunits') ? $classinstance->id : $classinstance->scale); + $this->cacheconvert[$file.'_'.$class.'_'.$method.'_'.$units][$newval]=$scaleorid; + //print 'We have made a '.$class.'->'.$method." to get a value from key '".$newval."' and we got '".$scaleorid."'.";exit; + if ($classinstance->id > 0) // we found record + { + $newval = $scaleorid ? $scaleorid : 0; + } + else + { + if (!empty($objimport->array_import_convertvalue[0][$val]['dict'])) $this->errors[$error]['lib']=$langs->trans('ErrorFieldValueNotIn', $key, $newval, 'scale', $langs->transnoentitiesnoconv($objimport->array_import_convertvalue[0][$val]['dict'])); + else $this->errors[$error]['lib']='ErrorFieldValueNotIn'; $this->errors[$error]['type']='FOREIGNKEY'; $errorforthistable++; $error++; @@ -687,8 +688,9 @@ class ImportXlsx extends ModeleImports $errorforthistable++; $error++; } - } elseif (! preg_match('/'.$objimport->array_import_regex[0][$val].'/i', $newval)) { - // If test is just a static regex + } + // If test is just a static regex + elseif (! preg_match('/'.$objimport->array_import_regex[0][$val].'/i', $newval)) { //if ($key == 19) print "xxx".$newval."zzz".$objimport->array_import_regex[0][$val]."
    "; $this->errors[$error]['lib']=$langs->transnoentitiesnoconv('ErrorWrongValueForField', $key, $newval, $objimport->array_import_regex[0][$val]); $this->errors[$error]['type']='REGEX'; @@ -797,7 +799,7 @@ class ImportXlsx extends ModeleImports $error++; } } else { - // We have a last INSERT ID. Check if we have a row referencing this foreign key. + // We have a last INSERT ID (got by previous pass), so we check if we have a row referencing this foreign key. // This is required when updating table with some extrafields. When inserting a record in parent table, we can make // a direct insert into subtable extrafields, but when me wake an update, the insertid is defined and the child record // may already exists. So we rescan the extrafield table to know if record exists or not for the rowid. diff --git a/htdocs/core/modules/modAccounting.class.php b/htdocs/core/modules/modAccounting.class.php index efd58b0ea1b..a806cab111f 100644 --- a/htdocs/core/modules/modAccounting.class.php +++ b/htdocs/core/modules/modAccounting.class.php @@ -162,7 +162,10 @@ class modAccounting extends DolibarrModules $this->module_parts = array(); // Boxes - $this->boxes = array(); + $this->boxes = array( + 0=>array('file'=>'box_accountancy_last_manual_entries.php', 'enabledbydefaulton'=>'accountancyindex'), + 1=>array('file'=>'box_accountancy_suspense_account.php', 'enabledbydefaulton'=>'accountancyindex') + ); // Permissions $this->rights_class = 'accounting'; diff --git a/htdocs/core/modules/modProduct.class.php b/htdocs/core/modules/modProduct.class.php index c71694c48ec..c3e010cbb4f 100644 --- a/htdocs/core/modules/modProduct.class.php +++ b/htdocs/core/modules/modProduct.class.php @@ -168,16 +168,22 @@ class modProduct extends DolibarrModules $this->export_label[$r]="Products"; // Translation key (used only if key ExportDataset_xxx_z not found) $this->export_permission[$r]=array(array("produit","export")); $this->export_fields_array[$r]=array( - 'p.rowid'=>"Id",'p.ref'=>"Ref",'p.label'=>"Label",'p.description'=>"Description",'p.url'=>"PublicUrl",'p.accountancy_code_sell'=>"ProductAccountancySellCode", - 'p.accountancy_code_sell_intra'=>"ProductAccountancySellIntraCode", 'p.accountancy_code_sell_export'=>"ProductAccountancySellExportCode", - 'p.accountancy_code_buy'=>"ProductAccountancyBuyCode",'p.note'=>"Note",'p.length'=>"Length",'p.width'=>"Width",'p.height'=>"Height",'p.surface'=>"Surface", - 'p.volume'=>"Volume",'p.weight'=>"Weight",'p.customcode'=>'CustomCode','p.price_base_type'=>"PriceBase",'p.price'=>"UnitPriceHT",'p.price_ttc'=>"UnitPriceTTC", - 'p.tva_tx'=>'VATRate','p.tosell'=>"OnSell",'p.tobuy'=>"OnBuy",'p.datec'=>'DateCreation','p.tms'=>'DateModification' + 'p.rowid'=>"Id",'p.ref'=>"Ref",'p.label'=>"Label", + 'p.fk_product_type'=>'Type','p.tosell'=>"OnSell",'p.tobuy'=>"OnBuy", + 'p.description'=>"Description",'p.url'=>"PublicUrl", + 'p.customcode'=>'CustomCode','p.fk_country'=>'IDCountry', + 'p.accountancy_code_sell'=>"ProductAccountancySellCode", 'p.accountancy_code_sell_intra'=>"ProductAccountancySellIntraCode", + 'p.accountancy_code_sell_export'=>"ProductAccountancySellExportCode", 'p.accountancy_code_buy'=>"ProductAccountancyBuyCode", + 'p.note'=>"NotePrivate",'p.note_public'=>'NotePublic', + 'p.weight'=>"Weight",'p.length'=>"Length",'p.width'=>"Width",'p.height'=>"Height",'p.surface'=>"Surface",'p.volume'=>"Volume", + //'p.duration'=>"Duration", + 'p.price_base_type'=>"PriceBase",'p.price'=>"UnitPriceHT",'p.price_ttc'=>"UnitPriceTTC", + 'p.tva_tx'=>'VATRate','p.datec'=>'DateCreation','p.tms'=>'DateModification' ); if (is_object($mysoc) && $mysoc->useNPR()) $this->export_fields_array[$r]['p.recuperableonly']='NPR'; + if (! empty($conf->fournisseur->enabled) || !empty($conf->margin->enabled)) $this->export_fields_array[$r]=array_merge($this->export_fields_array[$r], array('p.cost_price'=>'CostPrice')); if (! empty($conf->stock->enabled)) $this->export_fields_array[$r]=array_merge($this->export_fields_array[$r], array('p.stock'=>'Stock','p.seuil_stock_alerte'=>'StockLimit','p.desiredstock'=>'DesiredStock','p.pmp'=>'PMPValue')); if (! empty($conf->barcode->enabled)) $this->export_fields_array[$r]=array_merge($this->export_fields_array[$r], array('p.barcode'=>'BarCode')); - if (! empty($conf->fournisseur->enabled) || !empty($conf->margin->enabled)) $this->export_fields_array[$r]=array_merge($this->export_fields_array[$r], array('p.cost_price'=>'CostPrice')); $keyforselect='product'; $keyforelement='product'; $keyforaliasextra='extra'; include DOL_DOCUMENT_ROOT.'/core/extrafieldsinexport.inc.php'; if (! empty($conf->fournisseur->enabled)) $this->export_fields_array[$r]=array_merge($this->export_fields_array[$r], array('s.nom'=>'Supplier','pf.ref_fourn'=>'SupplierRef','pf.quantity'=>'QtyMin','pf.remise_percent'=>'DiscountQtyMin','pf.unitprice'=>'BuyingPrice','pf.delivery_time_days'=>'NbDaysToDelivery')); @@ -187,9 +193,11 @@ class modProduct extends DolibarrModules $this->export_TypeFields_array[$r]=array( 'p.ref'=>"Text",'p.label'=>"Text",'p.description'=>"Text",'p.url'=>"Text",'p.accountancy_code_sell'=>"Text", 'p.accountancy_code_sell_intra'=>"Text",'p.accountancy_code_sell_export'=>"Text",'p.accountancy_code_buy'=>"Text", - 'p.note'=>"Text",'p.length'=>"Numeric",'p.width'=>"Numeric",'p.height'=>"Numeric",'p.surface'=>"Numeric",'p.volume'=>"Numeric",'p.weight'=>"Numeric", + 'p.note'=>"Text",'p.note_public'=>"Text", + 'p.weight'=>"Numeric",'p.length'=>"Numeric",'p.width'=>"Numeric",'p.height'=>"Numeric",'p.surface'=>"Numeric",'p.volume'=>"Numeric", 'p.customcode'=>'Text','p.price_base_type'=>"Text",'p.price'=>"Numeric",'p.price_ttc'=>"Numeric",'p.tva_tx'=>'Numeric','p.tosell'=>"Boolean", 'p.tobuy'=>"Boolean",'p.datec'=>'Date','p.tms'=>'Date' + //'p.duration'=>"Duree", ); if (! empty($conf->stock->enabled)) $this->export_TypeFields_array[$r]=array_merge($this->export_TypeFields_array[$r], array('p.stock'=>'Numeric','p.seuil_stock_alerte'=>'Numeric','p.desiredstock'=>'Numeric','p.pmp'=>'Numeric','p.cost_price'=>'Numeric')); if (! empty($conf->barcode->enabled)) $this->export_TypeFields_array[$r]=array_merge($this->export_TypeFields_array[$r], array('p.barcode'=>'Text')); @@ -292,8 +300,9 @@ class modProduct extends DolibarrModules $this->export_fields_array[$r]=array( 'p.rowid'=>"Id",'p.ref'=>"Ref",'p.label'=>"Label",'p.description'=>"Description",'p.url'=>"PublicUrl", 'p.accountancy_code_sell'=>"ProductAccountancySellCode",'p.accountancy_code_sell_intra'=>"ProductAccountancySellIntraCode", - 'p.accountancy_code_sell_export'=>"ProductAccountancySellExportCode",'p.accountancy_code_buy'=>"ProductAccountancyBuyCode",'p.note'=>"Note", - 'p.length'=>"Length",'p.surface'=>"Surface",'p.volume'=>"Volume",'p.weight'=>"Weight",'p.customcode'=>'CustomCode', + 'p.accountancy_code_sell_export'=>"ProductAccountancySellExportCode",'p.accountancy_code_buy'=>"ProductAccountancyBuyCode", + 'p.note'=>"NotePrivate",'p.note_public'=>'NotePublic', + 'p.weight'=>"Weight",'p.length'=>"Length",'p.surface'=>"Surface",'p.volume'=>"Volume",'p.customcode'=>'CustomCode', 'p.price_base_type'=>"PriceBase",'p.price'=>"UnitPriceHT",'p.price_ttc'=>"UnitPriceTTC",'p.tva_tx'=>'VATRate','p.tosell'=>"OnSell", 'p.tobuy'=>"OnBuy",'p.datec'=>'DateCreation','p.tms'=>'DateModification' ); @@ -301,9 +310,10 @@ class modProduct extends DolibarrModules if (! empty($conf->barcode->enabled)) $this->export_fields_array[$r]=array_merge($this->export_fields_array[$r], array('p.barcode'=>'BarCode')); $this->export_fields_array[$r]=array_merge($this->export_fields_array[$r], array('pa.qty'=>'Qty','pa.incdec'=>'ComposedProductIncDecStock')); $this->export_TypeFields_array[$r]=array( - 'p.ref'=>"Text",'p.label'=>"Text",'p.description'=>"Text",'p.url'=>"Text",'p.accountancy_code_sell'=>"Text", - 'p.accountancy_code_sell_intra'=>"Text",'p.accountancy_code_sell_export'=>"Text",'p.accountancy_code_buy'=>"Text", - 'p.note'=>"Text",'p.length'=>"Numeric",'p.surface'=>"Numeric",'p.volume'=>"Numeric",'p.weight'=>"Numeric",'p.customcode'=>'Text', + 'p.ref'=>"Text",'p.label'=>"Text",'p.description'=>"Text",'p.url'=>"Text", + 'p.accountancy_code_sell'=>"Text",'p.accountancy_code_sell_intra'=>"Text",'p.accountancy_code_sell_export'=>"Text",'p.accountancy_code_buy'=>"Text", + 'p.note'=>"Text",'p.note_public'=>"Text", + 'p.weight'=>"Numeric",'p.length'=>"Numeric",'p.surface'=>"Numeric",'p.volume'=>"Numeric",'p.customcode'=>'Text', 'p.price_base_type'=>"Text",'p.price'=>"Numeric",'p.price_ttc'=>"Numeric",'p.tva_tx'=>'Numeric','p.tosell'=>"Boolean",'p.tobuy'=>"Boolean", 'p.datec'=>'Date','p.tms'=>'Date' ); @@ -346,31 +356,23 @@ class modProduct extends DolibarrModules $this->import_entities_array[$r]=array(); // We define here only fields that use a different icon from the one defined in import_icon $this->import_tables_array[$r]=array('p'=>MAIN_DB_PREFIX.'product','extra'=>MAIN_DB_PREFIX.'product_extrafields'); $this->import_tables_creator_array[$r]=array('p'=>'fk_user_author'); // Fields to store import user id - $this->import_fields_array[$r]=array(//field order as per structure of table llx_product + $this->import_fields_array[$r]=array( 'p.ref' => "Ref*", - 'p.datec' => 'DateCreation', 'p.label' => "Label*", - 'p.description' => "Description", - 'p.note_public' => "PublicNote",//public note - 'p.note' => "PrivateNote",//private note - 'p.customcode' => 'CustomCode', - 'p.price' => "SellingPriceHT",//without - 'p.price_min' => "MinPrice", - 'p.price_ttc' => "SellingPriceTTC",//with tax - 'p.price_min_ttc' => "SellingMinPriceTTC", - 'p.price_base_type' => "PriceBaseType",//price base: with-tax (TTC) or without (HT) tax. Displays accordingly in Product card - 'p.cost_price' => "CostPrice", - 'p.tva_tx' => 'VATRate', - 'p.tosell' => "OnSell*", - 'p.tobuy' => "OnBuy*", - 'p.fk_product_type' => "Type*", - 'p.duration' => "Duration",///duration of service - 'p.url' => "PublicUrl", + 'p.fk_product_type' => "Type*", + 'p.tosell' => "OnSell*", + 'p.tobuy' => "OnBuy*", + 'p.description' => "Description", + 'p.url' => "PublicUrl", + 'p.customcode' => 'CustomCode', + 'p.fk_country' => 'CountryCode', 'p.accountancy_code_sell' => "ProductAccountancySellCode", 'p.accountancy_code_sell_intra' => "ProductAccountancySellIntraCode", 'p.accountancy_code_sell_export' => "ProductAccountancySellExportCode", 'p.accountancy_code_buy' => "ProductAccountancyBuyCode", - 'p.weight' => "Weight", + 'p.note_public' => "NotePublic", + 'p.note' => "NotePrivate", + 'p.weight' => "Weight", 'p.weight_units' => "WeightUnits", 'p.length' => "Length", 'p.length_units' => "LengthUnit", @@ -382,7 +384,16 @@ class modProduct extends DolibarrModules 'p.surface_units' => "SurfaceUnit", 'p.volume' => "Volume", 'p.volume_units' => "VolumeUnits", - 'p.finished' => 'Nature', + 'p.duration' => "Duration",//duration of service + 'p.finished' => 'Nature', + 'p.price' => "SellingPriceHT",//without + 'p.price_min' => "MinPrice", + 'p.price_ttc' => "SellingPriceTTC",//with tax + 'p.price_min_ttc' => "SellingMinPriceTTC", + 'p.price_base_type' => "PriceBaseType",//price base: with-tax (TTC) or without (HT) tax. Displays accordingly in Product card + 'p.tva_tx' => 'VATRate', + 'p.datec' => 'DateCreation', + 'p.cost_price' => "CostPrice", ); if (!empty($conf->stock->enabled)) {//if Stock module enabled $this->import_fields_array[$r] = array_merge($this->import_fields_array[$r], array( @@ -392,10 +403,9 @@ class modProduct extends DolibarrModules )); } - /* Disabled: The value of fields xxx_units is the scale for reference unit, not the rowid in table llx_c_unit !!! $this->import_convertvalue_array[$r] = array( - 'p.weight_units' => array( - 'rule' => 'fetchidfromcodeunits', + 'p.weight_units' => array( + 'rule' => 'fetchscalefromcodeunits', // Switch this to fetchidfromcodeunits when we will store id instead of scale in product table 'classfile' => '/core/class/cunits.class.php', 'class' => 'CUnits', 'method' => 'fetch', @@ -403,7 +413,7 @@ class modProduct extends DolibarrModules 'dict' => 'DictionaryMeasuringUnits' ), 'p.length_units' => array( - 'rule' => 'fetchidfromcodeunits', + 'rule' => 'fetchscalefromcodeunits', // Switch this to fetchidfromcodeunits when we will store id instead of scale in product table 'classfile' => '/core/class/cunits.class.php', 'class' => 'CUnits', 'method' => 'fetch', @@ -411,7 +421,7 @@ class modProduct extends DolibarrModules 'dict' => 'DictionaryMeasuringUnits' ), 'p.width_units' => array( - 'rule' => 'fetchidfromcodeunits', + 'rule' => 'fetchscalefromcodeunits', // Switch this to fetchidfromcodeunits when we will store id instead of scale in product table 'classfile' => '/core/class/cunits.class.php', 'class' => 'CUnits', 'method' => 'fetch', @@ -419,7 +429,7 @@ class modProduct extends DolibarrModules 'dict' => 'DictionaryMeasuringUnits' ), 'p.height_units' => array( - 'rule' => 'fetchidfromcodeunits', + 'rule' => 'fetchscalefromcodeunits', // Switch this to fetchidfromcodeunits when we will store id instead of scale in product table 'classfile' => '/core/class/cunits.class.php', 'class' => 'CUnits', 'method' => 'fetch', @@ -427,7 +437,7 @@ class modProduct extends DolibarrModules 'dict' => 'DictionaryMeasuringUnits' ), 'p.surface_units' => array( - 'rule' => 'fetchidfromcodeunits', + 'rule' => 'fetchscalefromcodeunits', // Switch this to fetchidfromcodeunits when we will store id instead of scale in product table 'classfile' => '/core/class/cunits.class.php', 'class' => 'CUnits', 'method' => 'fetch', @@ -435,14 +445,21 @@ class modProduct extends DolibarrModules 'dict' => 'DictionaryMeasuringUnits' ), 'p.volume_units' => array( - 'rule' => 'fetchidfromcodeunits', + 'rule' => 'fetchscalefromcodeunits', // Switch this to fetchidfromcodeunits when we will store id instead of scale in product table 'classfile' => '/core/class/cunits.class.php', 'class' => 'CUnits', 'method' => 'fetch', 'units' => 'volume', 'dict' => 'DictionaryMeasuringUnits' - ) - );*/ + ), + 'p.fk_country' => array( + 'rule' => 'fetchidfromcodeid', + 'classfile' => '/core/class/ccountry.class.php', + 'class' => 'Ccountry', + 'method' => 'fetch', + 'dict' => 'DictionaryCountry' + ) + ); if (! empty($conf->fournisseur->enabled) || !empty($conf->margin->enabled)) $this->import_fields_array[$r]=array_merge($this->import_fields_array[$r], array('p.cost_price'=>'CostPrice')); if (is_object($mysoc) && $mysoc->useNPR()) $this->import_fields_array[$r]=array_merge($this->import_fields_array[$r], array('p.recuperableonly'=>'NPR')); @@ -480,18 +497,19 @@ class modProduct extends DolibarrModules // field order as per structure of table llx_product $import_sample = array( 'p.ref' => "PREF123456", - 'p.datec' => 'formatted as '.dol_print_date(dol_now(), '%Y-%m-%d'), + 'p.datec' => dol_print_date(dol_now(), '%Y-%m-%d'), 'p.label' => "Product name in default language", 'p.description' => "Product description in default language", 'p.note_public' => "a public note (free text)", 'p.note' => "a private note (free text)", 'p.customcode' => 'customs code', - 'p.price' => "price ex-vat eg. 100", - 'p.price_min' => "price ex-vat eg. 100", - 'p.price_ttc' => "price inc-vat eg. 110", - 'p.price_min_ttc' => "price inc-vat eg. 110", + 'p.fk_country' => 'FR', + 'p.price' => "100", + 'p.price_min' => "100", + 'p.price_ttc' => "110", + 'p.price_min_ttc' => "110", 'p.price_base_type' => "HT (show/use price excl. tax) / TTC (show/use price incl. tax)", - 'p.tva_tx' => 'tax rate eg: 10. Must match numerically one of the tax rates defined for your country', + 'p.tva_tx' => '10', // tax rate eg: 10. Must match numerically one of the tax rates defined for your country' 'p.tosell' => "0 (not for sale to customer, eg. raw material) / 1 (for sale)", 'p.tobuy' => "0 (not for purchase from supplier, eg. virtual product) / 1 (for purchase)", 'p.fk_product_type' => "0 (product) / 1 (service)", @@ -502,27 +520,27 @@ class modProduct extends DolibarrModules 'p.accountancy_code_sell_export' => "", 'p.accountancy_code_buy' => "", 'p.weight' => "", - 'p.weight_units' => 'use a unit of measure from the dictionary. g/Kg/T etc....matches field "Scale" for unit type "weight" in table "' . MAIN_DB_PREFIX . 'c_units', + 'p.weight_units' => 'kg', // Use a unit of measure from the dictionary. g/Kg/T etc....matches field "Short label" for unit type "weight" in table "' . MAIN_DB_PREFIX . 'c_units', 'p.length' => "", - 'p.length_units' => 'use a unit of measure from the dictionary. m/cm/mm etc....matches field "Scale" for unit type "size" in table "' . MAIN_DB_PREFIX . 'c_units', + 'p.length_units' => 'm', // Use a unit of measure from the dictionary. m/cm/mm etc....matches field "Short label" for unit type "size" in table "' . MAIN_DB_PREFIX . 'c_units', 'p.width' => "", - 'p.width_units' => 'use a unit of measure from the dictionary. m/cm/mm etc....matches field "Scale" for unit type "size" in table "' . MAIN_DB_PREFIX . 'c_units', + 'p.width_units' => 'm', // Use a unit of measure from the dictionary. m/cm/mm etc....matches field "Short label" for unit type "size" in table "' . MAIN_DB_PREFIX . 'c_units', 'p.height' => "", - 'p.height_units' => 'use a unit of measure from the dictionary. m/cm/mm etc....matches field "Scale" for unit type "size" in table "' . MAIN_DB_PREFIX . 'c_units', + 'p.height_units' => 'm', // Use a unit of measure from the dictionary. m/cm/mm etc....matches field "Short label" for unit type "size" in table "' . MAIN_DB_PREFIX . 'c_units', 'p.surface' => "", - 'p.surface_units' => 'use a unit of measure from the dictionary. m2/cm2/mm2 etc....matches field "Scale" for unit type "surface" in table "' . MAIN_DB_PREFIX . 'c_units', + 'p.surface_units' => 'm2', // Use a unit of measure from the dictionary. m2/cm2/mm2 etc....matches field "Short label" for unit type "surface" in table "' . MAIN_DB_PREFIX . 'c_units', 'p.volume' => "", - 'p.volume_units' => 'use a unit of measure from the dictionary. m3/cm3/mm3 etc....matches field "Scale" for unit type "volume" in table "' . MAIN_DB_PREFIX . 'c_units', + 'p.volume_units' => 'm3', //Use a unit of measure from the dictionary. m3/cm3/mm3 etc....matches field "Short label" for unit type "volume" in table "' . MAIN_DB_PREFIX . 'c_units', 'p.finished' => '0 (raw material) / 1 (finished goods)' ); //clauses copied from import_fields_array if (!empty($conf->stock->enabled)) $import_sample = array_merge($import_sample, array( - 'p.seuil_stock_alerte' => 'quantity for low-stock warning (empty for no warning)', - 'p.pmp' => '0 (default)', - 'p.desiredstock' => 'target quantity to maintain in stock (for replenishment feature)' + 'p.seuil_stock_alerte' => '', + 'p.pmp' => '0', + 'p.desiredstock' => '' )); - if (! empty($conf->fournisseur->enabled) || !empty($conf->margin->enabled)) $import_sample=array_merge($import_sample, array('p.cost_price'=>'user-editable, used for margin calculations only')); - if (is_object($mysoc) && $mysoc->useNPR()) $import_sample=array_merge($import_sample, array('p.recuperableonly'=>'0 / 1 (French VAT NPR yes/no')); + if (! empty($conf->fournisseur->enabled) || !empty($conf->margin->enabled)) $import_sample=array_merge($import_sample, array('p.cost_price'=>'90')); + if (is_object($mysoc) && $mysoc->useNPR()) $import_sample=array_merge($import_sample, array('p.recuperableonly'=>'0')); if (is_object($mysoc) && $mysoc->useLocalTax(1)) $import_sample=array_merge($import_sample, array('p.localtax1_tx'=>'', 'p.localtax1_type'=>'')); if (is_object($mysoc) && $mysoc->useLocalTax(2)) $import_sample=array_merge($import_sample, array('p.localtax2_tx'=>'', 'p.localtax2_type'=>'')); if (! empty($conf->barcode->enabled)) $import_sample=array_merge($import_sample, array('p.barcode'=>'')); @@ -596,34 +614,34 @@ class modProduct extends DolibarrModules $this->import_examplevalues_array[$r]=array( 'sp.fk_product' => "PRODUCT_REF or id:123456", 'sp.fk_soc' => "My Supplier", - 'sp.ref_fourn' => "eg: XYZ-F123456", + 'sp.ref_fourn' => "XYZ-F123456", 'sp.quantity' => "5", - 'sp.tva_tx' => 'one of the defined rates eg. 21', + 'sp.tva_tx' => '10', 'sp.price'=>"50", 'sp.unitprice'=>'50', 'sp.remise_percent'=>'0', 'sp.default_vat_code' => '', - 'sp.delivery_time_days' => 'eg. 5', + 'sp.delivery_time_days' => '5', 'sp.supplier_reputation' => 'FAVORITE / NOTTHGOOD / DONOTORDER' ); if (is_object($mysoc) && $mysoc->useNPR()) $this->import_examplevalues_array[$r]=array_merge($this->import_examplevalues_array[$r], array('sp.recuperableonly'=>'')); if (is_object($mysoc) && $mysoc->useLocalTax(1)) $this->import_examplevalues_array[$r]=array_merge($this->import_examplevalues_array[$r], array('sp.localtax1_tx'=>'LT1', 'sp.localtax1_type'=>'LT1Type')); if (is_object($mysoc) && $mysoc->useLocalTax(2)) $this->import_examplevalues_array[$r]=array_merge($this->import_examplevalues_array[$r], array('sp.localtax2_tx'=>'LT2', 'sp.localtax2_type'=>'LT2Type')); $this->import_examplevalues_array[$r] = array_merge($this->import_examplevalues_array[$r], array( - 'sp.price' => "eg. 50.00", - 'sp.unitprice' => 'eg. 10', + 'sp.price' => "50.00", + 'sp.unitprice' => '10', // TODO Make this field not required and calculate it from price and qty - 'sp.remise_percent' => 'eg: 20' + 'sp.remise_percent' => '20' )); if ($conf->multicurrency->enabled) { $this->import_examplevalues_array[$r]=array_merge($this->import_examplevalues_array[$r], array( 'sp.fk_multicurrency'=>'eg: 2, rowid for code of multicurrency currency', - 'sp.multicurrency_code'=>'eg: GBP', - 'sp.multicurrency_tx'=>'currency rate eg: 1.12345', - 'sp.multicurrency_unitprice'=>'cost per unit in supplier currency', + 'sp.multicurrency_code'=>'GBP', + 'sp.multicurrency_tx'=>'1.12345', + 'sp.multicurrency_unitprice'=>'', // TODO Make this field not required and calculate it from price and qty - 'sp.multicurrency_price'=>'cost for min quantity in supplier currency' + 'sp.multicurrency_price'=>'' )); } @@ -653,8 +671,8 @@ class modProduct extends DolibarrModules ); $this->import_examplevalues_array[$r]=array('pr.fk_product'=>"PRODUCT_REF or id:123456", 'pr.price_base_type'=>"HT (for excl tax) or TTC (for inc tax)",'pr.price_level'=>"1", - 'pr.price'=>"100",'pr.price_ttc'=>"110", - 'pr.price_min'=>"100",'pr.price_min_ttc'=>"110", + 'pr.price'=>"100", 'pr.price_ttc'=>"110", + 'pr.price_min'=>"100", 'pr.price_min_ttc'=>"110", 'pr.tva_tx'=>'20', 'pr.recuperableonly'=>'0', 'pr.date_price'=>'2013-04-10'); diff --git a/htdocs/core/modules/modService.class.php b/htdocs/core/modules/modService.class.php index ba82ecfeb19..43fabdb5acd 100644 --- a/htdocs/core/modules/modService.class.php +++ b/htdocs/core/modules/modService.class.php @@ -141,19 +141,39 @@ class modService extends DolibarrModules $this->export_code[$r]=$this->rights_class.'_'.$r; $this->export_label[$r]="Services"; // Translation key (used only if key ExportDataset_xxx_z not found) $this->export_permission[$r]=array(array("service","export")); - $this->export_fields_array[$r]=array('p.rowid'=>"Id",'p.ref'=>"Ref",'p.label'=>"Label",'p.description'=>"Description",'p.url'=>"PublicUrl",'p.accountancy_code_sell'=>"ProductAccountancySellCode",'p.accountancy_code_buy'=>"ProductAccountancyBuyCode",'p.note'=>"Note",'p.price_base_type'=>"PriceBase",'p.price'=>"UnitPriceHT",'p.price_ttc'=>"UnitPriceTTC",'p.tva_tx'=>'VATRate','p.tosell'=>"OnSell",'p.tobuy'=>"OnBuy",'p.duration'=>"Duration",'p.datec'=>'DateCreation','p.tms'=>'DateModification'); + $this->export_fields_array[$r]=array( + 'p.rowid'=>"Id",'p.ref'=>"Ref",'p.label'=>"Label", + 'p.fk_product_type'=>'Type','p.tosell'=>"OnSell",'p.tobuy'=>"OnBuy", + 'p.description'=>"Description",'p.url'=>"PublicUrl", + 'p.customcode'=>'CustomCode','p.fk_country'=>'IDCountry', + 'p.accountancy_code_sell'=>"ProductAccountancySellCode", 'p.accountancy_code_sell_intra'=>"ProductAccountancySellIntraCode", + 'p.accountancy_code_sell_export'=>"ProductAccountancySellExportCode", 'p.accountancy_code_buy'=>"ProductAccountancyBuyCode", + 'p.note'=>"NotePrivate",'p.note_public'=>'NotePublic', + //'p.weight'=>"Weight",'p.length'=>"Length",'p.width'=>"Width",'p.height'=>"Height",'p.surface'=>"Surface",'p.volume'=>"Volume", + 'p.duration'=>"Duration", + 'p.price_base_type'=>"PriceBase",'p.price'=>"UnitPriceHT",'p.price_ttc'=>"UnitPriceTTC", + 'p.tva_tx'=>'VATRate','p.datec'=>'DateCreation','p.tms'=>'DateModification' + ); if (is_object($mysoc) && $mysoc->useNPR()) $this->export_fields_array[$r]['p.recuperableonly']='NPR'; + if (! empty($conf->fournisseur->enabled) || !empty($conf->margin->enabled)) $this->export_fields_array[$r]=array_merge($this->export_fields_array[$r], array('p.cost_price'=>'CostPrice')); if (! empty($conf->stock->enabled)) $this->export_fields_array[$r]=array_merge($this->export_fields_array[$r], array('p.stock'=>'Stock','p.seuil_stock_alerte'=>'StockLimit','p.desiredstock'=>'DesiredStock','p.pmp'=>'PMPValue')); if (! empty($conf->barcode->enabled)) $this->export_fields_array[$r]=array_merge($this->export_fields_array[$r], array('p.barcode'=>'BarCode')); - if (! empty($conf->fournisseur->enabled) || !empty($conf->margin->enabled)) $this->export_fields_array[$r]=array_merge($this->export_fields_array[$r], array('p.cost_price'=>'CostPrice')); $keyforselect='product'; $keyforelement='product'; $keyforaliasextra='extra'; include DOL_DOCUMENT_ROOT.'/core/extrafieldsinexport.inc.php'; if (! empty($conf->fournisseur->enabled)) $this->export_fields_array[$r]=array_merge($this->export_fields_array[$r], array('s.nom'=>'Supplier','pf.ref_fourn'=>'SupplierRef','pf.quantity'=>'QtyMin','pf.remise_percent'=>'DiscountQtyMin','pf.unitprice'=>'BuyingPrice','pf.delivery_time_days'=>'NbDaysToDelivery')); if (! empty($conf->global->EXPORTTOOL_CATEGORIES)) $this->export_fields_array[$r]=array_merge($this->export_fields_array[$r], array('group_concat(cat.label)'=>'Categories')); if (! empty($conf->global->MAIN_MULTILANGS)) $this->export_fields_array[$r]=array_merge($this->export_fields_array[$r], array('l.lang'=>'Language', 'l.label'=>'TranslatedLabel','l.description'=>'TranslatedDescription','l.note'=>'TranslatedNote')); if (! empty($conf->global->PRODUCT_USE_UNITS)) $this->export_fields_array[$r]['p.fk_unit'] = 'Unit'; - $this->export_TypeFields_array[$r]=array('p.ref'=>"Text",'p.label'=>"Text",'p.description'=>"Text",'p.url'=>"Text",'p.accountancy_code_sell'=>"Text",'p.accountancy_code_buy'=>"Text",'p.note'=>"Text",'p.price_base_type'=>"Text",'p.price'=>"Numeric",'p.price_ttc'=>"Numeric",'p.tva_tx'=>'Numeric','p.tosell'=>"Boolean",'p.tobuy'=>"Boolean",'p.duration'=>"Duree",'p.datec'=>'Date','p.tms'=>'Date'); - if (! empty($conf->stock->enabled)) $this->export_TypeFields_array[$r]=array_merge($this->export_TypeFields_array[$r], array('p.stock'=>'Numeric')); + $this->export_TypeFields_array[$r]=array( + 'p.ref'=>"Text",'p.label'=>"Text",'p.description'=>"Text",'p.url'=>"Text",'p.accountancy_code_sell'=>"Text", + 'p.accountancy_code_sell_intra'=>"Text",'p.accountancy_code_sell_export'=>"Text",'p.accountancy_code_buy'=>"Text", + 'p.note'=>"Text",'p.note_public'=>"Text", + 'p.weight'=>"Numeric",'p.length'=>"Numeric",'p.width'=>"Numeric",'p.height'=>"Numeric",'p.surface'=>"Numeric",'p.volume'=>"Numeric", + 'p.customcode'=>'Text','p.price_base_type'=>"Text",'p.price'=>"Numeric",'p.price_ttc'=>"Numeric",'p.tva_tx'=>'Numeric','p.tosell'=>"Boolean", + 'p.tobuy'=>"Boolean",'p.datec'=>'Date','p.tms'=>'Date', + 'p.duration'=>"Duree", + ); + if (! empty($conf->stock->enabled)) $this->export_TypeFields_array[$r]=array_merge($this->export_TypeFields_array[$r], array('p.stock'=>'Numeric','p.seuil_stock_alerte'=>'Numeric','p.desiredstock'=>'Numeric','p.pmp'=>'Numeric','p.cost_price'=>'Numeric')); if (! empty($conf->barcode->enabled)) $this->export_TypeFields_array[$r]=array_merge($this->export_TypeFields_array[$r], array('p.barcode'=>'Text')); if (! empty($conf->fournisseur->enabled)) $this->export_TypeFields_array[$r]=array_merge($this->export_TypeFields_array[$r], array('s.nom'=>'Text','pf.ref_fourn'=>'Text','pf.unitprice'=>'Numeric','pf.quantity'=>'Numeric','pf.remise_percent'=>'Numeric','pf.delivery_time_days'=>'Numeric')); if (! empty($conf->global->MAIN_MULTILANGS)) $this->export_TypeFields_array[$r]=array_merge($this->export_TypeFields_array[$r], array('l.lang'=>'Text', 'l.label'=>'Text','l.description'=>'Text','l.note'=>'Text')); @@ -211,7 +231,7 @@ class modService extends DolibarrModules $this->export_sql_start[$r]='SELECT DISTINCT '; $this->export_sql_end[$r] =' FROM '.MAIN_DB_PREFIX.'product as p'; $this->export_sql_end[$r] .=' LEFT JOIN '.MAIN_DB_PREFIX.'product_price as pr ON p.rowid = pr.fk_product AND pr.entity = '.$conf->entity; // export prices only for the current entity - $this->export_sql_end[$r] .=' WHERE p.entity IN ('.getEntity('product').')'; + $this->export_sql_end[$r] .=' WHERE p.entity IN ('.getEntity('product').')'; // For product and service profile } if (! empty($conf->global->PRODUIT_CUSTOMER_PRICES)) @@ -243,7 +263,7 @@ class modService extends DolibarrModules $this->export_sql_end[$r] =' FROM '.MAIN_DB_PREFIX.'product as p'; $this->export_sql_end[$r] .=' LEFT JOIN '.MAIN_DB_PREFIX.'product_customer_price as pr ON p.rowid = pr.fk_product AND pr.entity = '.$conf->entity; // export prices only for the current entity $this->export_sql_end[$r] .=' LEFT JOIN '.MAIN_DB_PREFIX.'societe as s ON pr.fk_soc = s.rowid'; - $this->export_sql_end[$r] .=' WHERE p.entity IN ('.getEntity('product').')'; + $this->export_sql_end[$r] .=' WHERE p.entity IN ('.getEntity('product').')'; // For product and service profile } if (! empty($conf->global->PRODUIT_SOUSPRODUITS)) @@ -255,8 +275,10 @@ class modService extends DolibarrModules $this->export_permission[$r]=array(array("produit","export")); $this->export_fields_array[$r]=array( 'p.rowid'=>"Id",'p.ref'=>"Ref",'p.label'=>"Label",'p.description'=>"Description",'p.url'=>"PublicUrl", - 'p.accountancy_code_sell'=>"ProductAccountancySellCode",'p.accountancy_code_buy'=>"ProductAccountancyBuyCode",'p.note'=>"Note", - 'p.length'=>"Length",'p.surface'=>"Surface",'p.volume'=>"Volume",'p.weight'=>"Weight",'p.customcode'=>'CustomCode', + 'p.accountancy_code_sell'=>"ProductAccountancySellCode",'p.accountancy_code_sell_intra'=>"ProductAccountancySellIntraCode", + 'p.accountancy_code_sell_export'=>"ProductAccountancySellExportCode",'p.accountancy_code_buy'=>"ProductAccountancyBuyCode", + 'p.note'=>"NotePrivate",'p.note_public'=>'NotePublic', + 'p.weight'=>"Weight",'p.length'=>"Length",'p.surface'=>"Surface",'p.volume'=>"Volume",'p.customcode'=>'CustomCode', 'p.price_base_type'=>"PriceBase",'p.price'=>"UnitPriceHT",'p.price_ttc'=>"UnitPriceTTC",'p.tva_tx'=>'VATRate','p.tosell'=>"OnSell", 'p.tobuy'=>"OnBuy",'p.datec'=>'DateCreation','p.tms'=>'DateModification' ); @@ -264,8 +286,10 @@ class modService extends DolibarrModules if (! empty($conf->barcode->enabled)) $this->export_fields_array[$r]=array_merge($this->export_fields_array[$r], array('p.barcode'=>'BarCode')); $this->export_fields_array[$r]=array_merge($this->export_fields_array[$r], array('pa.qty'=>'Qty','pa.incdec'=>'ComposedProductIncDecStock')); $this->export_TypeFields_array[$r]=array( - 'p.ref'=>"Text",'p.label'=>"Text",'p.description'=>"Text",'p.url'=>"Text",'p.accountancy_code_sell'=>"Text",'p.accountancy_code_buy'=>"Text", - 'p.note'=>"Text",'p.length'=>"Numeric",'p.surface'=>"Numeric",'p.volume'=>"Numeric",'p.weight'=>"Numeric",'p.customcode'=>'Text', + 'p.ref'=>"Text",'p.label'=>"Text",'p.description'=>"Text",'p.url'=>"Text", + 'p.accountancy_code_sell'=>"Text",'p.accountancy_code_sell_intra'=>"Text",'p.accountancy_code_sell_export'=>"Text",'p.accountancy_code_buy'=>"Text", + 'p.note'=>"Text",'p.note_public'=>"Text", + 'p.weight'=>"Numeric",'p.length'=>"Numeric",'p.surface'=>"Numeric",'p.volume'=>"Numeric",'p.customcode'=>'Text', 'p.price_base_type'=>"Text",'p.price'=>"Numeric",'p.price_ttc'=>"Numeric",'p.tva_tx'=>'Numeric','p.tosell'=>"Boolean",'p.tobuy'=>"Boolean", 'p.datec'=>'Date','p.tms'=>'Date' ); @@ -274,7 +298,8 @@ class modService extends DolibarrModules $this->export_TypeFields_array[$r]=array_merge($this->export_TypeFields_array[$r], array('pa.qty'=>'Numeric')); $this->export_entities_array[$r]=array( 'p.rowid'=>"virtualproduct",'p.ref'=>"virtualproduct",'p.label'=>"virtualproduct",'p.description'=>"virtualproduct",'p.url'=>"virtualproduct", - 'p.accountancy_code_sell'=>'virtualproduct','p.accountancy_code_buy'=>'virtualproduct','p.note'=>"virtualproduct",'p.length'=>"virtualproduct", + 'p.accountancy_code_sell'=>'virtualproduct','p.accountancy_code_sell_intra'=>'virtualproduct','p.accountancy_code_sell_export'=>'virtualproduct', + 'p.accountancy_code_buy'=>'virtualproduct','p.note'=>"virtualproduct",'p.length'=>"virtualproduct", 'p.surface'=>"virtualproduct",'p.volume'=>"virtualproduct",'p.weight'=>"virtualproduct",'p.customcode'=>'virtualproduct', 'p.price_base_type'=>"virtualproduct",'p.price'=>"virtualproduct",'p.price_ttc'=>"virtualproduct",'p.tva_tx'=>"virtualproduct", 'p.tosell'=>"virtualproduct",'p.tobuy'=>"virtualproduct",'p.datec'=>"virtualproduct",'p.tms'=>"virtualproduct" @@ -290,55 +315,7 @@ class modService extends DolibarrModules $this->export_sql_end[$r] =' FROM '.MAIN_DB_PREFIX.'product as p'; $this->export_sql_end[$r] .=' LEFT JOIN '.MAIN_DB_PREFIX.'product_extrafields as extra ON p.rowid = extra.fk_object,'; $this->export_sql_end[$r] .=' '.MAIN_DB_PREFIX.'product_association as pa, '.MAIN_DB_PREFIX.'product as p2'; - $this->export_sql_end[$r] .=' WHERE p.entity IN ('.getEntity('product').')'; - $this->export_sql_end[$r] .=' AND p.rowid = pa.fk_product_pere AND p2.rowid = pa.fk_product_fils'; - } - - if (! empty($conf->global->PRODUIT_SOUSPRODUITS)) - { - // Exports virtual products - $r++; - $this->export_code[$r]=$this->rights_class.'_'.$r; - $this->export_label[$r]="AssociatedProducts"; // Translation key (used only if key ExportDataset_xxx_z not found) - $this->export_permission[$r]=array(array("service","export")); - $this->export_fields_array[$r]=array( - 'p.rowid'=>"Id",'p.ref'=>"Ref",'p.label'=>"Label",'p.description'=>"Description",'p.url'=>"PublicUrl", - 'p.accountancy_code_sell'=>"ProductAccountancySellCode",'p.accountancy_code_buy'=>"ProductAccountancyBuyCode",'p.note'=>"Note", - 'p.length'=>"Length",'p.surface'=>"Surface",'p.volume'=>"Volume",'p.weight'=>"Weight",'p.customcode'=>'CustomCode', - 'p.price_base_type'=>"PriceBase",'p.price'=>"UnitPriceHT",'p.price_ttc'=>"UnitPriceTTC",'p.tva_tx'=>'VATRate','p.tosell'=>"OnSell", - 'p.tobuy'=>"OnBuy",'p.datec'=>'DateCreation','p.tms'=>'DateModification' - ); - if (! empty($conf->stock->enabled)) $this->export_fields_array[$r]=array_merge($this->export_fields_array[$r], array('p.stock'=>'Stock','p.seuil_stock_alerte'=>'StockLimit','p.desiredstock'=>'DesiredStock','p.pmp'=>'PMPValue')); - if (! empty($conf->barcode->enabled)) $this->export_fields_array[$r]=array_merge($this->export_fields_array[$r], array('p.barcode'=>'BarCode')); - $this->export_fields_array[$r]=array_merge($this->export_fields_array[$r], array('pa.qty'=>'Qty','pa.incdec'=>'ComposedProductIncDecStock')); - $this->export_TypeFields_array[$r]=array( - 'p.ref'=>"Text",'p.label'=>"Text",'p.description'=>"Text",'p.url'=>"Text",'p.accountancy_code_sell'=>"Text",'p.accountancy_code_buy'=>"Text", - 'p.note'=>"Text",'p.length'=>"Numeric",'p.surface'=>"Numeric",'p.volume'=>"Numeric",'p.weight'=>"Numeric",'p.customcode'=>'Text', - 'p.price_base_type'=>"Text",'p.price'=>"Numeric",'p.price_ttc'=>"Numeric",'p.tva_tx'=>'Numeric','p.tosell'=>"Boolean",'p.tobuy'=>"Boolean", - 'p.datec'=>'Date','p.tms'=>'Date' - ); - if (! empty($conf->stock->enabled)) $this->export_TypeFields_array[$r]=array_merge($this->export_TypeFields_array[$r], array('p.stock'=>'Numeric','p.seuil_stock_alerte'=>'Numeric','p.desiredstock'=>'Numeric','p.pmp'=>'Numeric','p.cost_price'=>'Numeric')); - if (! empty($conf->barcode->enabled)) $this->export_TypeFields_array[$r]=array_merge($this->export_TypeFields_array[$r], array('p.barcode'=>'Text')); - $this->export_TypeFields_array[$r]=array_merge($this->export_TypeFields_array[$r], array('pa.qty'=>'Numeric')); - $this->export_entities_array[$r]=array( - 'p.rowid'=>"virtualproduct",'p.ref'=>"virtualproduct",'p.label'=>"virtualproduct",'p.description'=>"virtualproduct",'p.url'=>"virtualproduct", - 'p.accountancy_code_sell'=>'virtualproduct','p.accountancy_code_buy'=>'virtualproduct','p.note'=>"virtualproduct",'p.length'=>"virtualproduct", - 'p.surface'=>"virtualproduct",'p.volume'=>"virtualproduct",'p.weight'=>"virtualproduct",'p.customcode'=>'virtualproduct', - 'p.price_base_type'=>"virtualproduct",'p.price'=>"virtualproduct",'p.price_ttc'=>"virtualproduct",'p.tva_tx'=>"virtualproduct", - 'p.tosell'=>"virtualproduct",'p.tobuy'=>"virtualproduct",'p.datec'=>"virtualproduct",'p.tms'=>"virtualproduct" - ); - if (! empty($conf->stock->enabled)) $this->export_entities_array[$r]=array_merge($this->export_entities_array[$r], array('p.stock'=>'virtualproduct','p.seuil_stock_alerte'=>'virtualproduct','p.desiredstock'=>'virtualproduct','p.pmp'=>'virtualproduct')); - if (! empty($conf->barcode->enabled)) $this->export_entities_array[$r]=array_merge($this->export_entities_array[$r], array('p.barcode'=>'virtualproduct')); - $this->export_entities_array[$r]=array_merge($this->export_entities_array[$r], array('pa.qty'=>"subproduct",'pa.incdec'=>'subproduct')); - $keyforselect='product'; $keyforelement='product'; $keyforaliasextra='extra'; - include DOL_DOCUMENT_ROOT.'/core/extrafieldsinexport.inc.php'; - $this->export_fields_array[$r]=array_merge($this->export_fields_array[$r], array('p2.rowid'=>"Id",'p2.ref'=>"Ref",'p2.label'=>"Label",'p2.description'=>"Description")); - $this->export_entities_array[$r]=array_merge($this->export_entities_array[$r], array('p2.rowid'=>"subproduct",'p2.ref'=>"subproduct",'p2.label'=>"subproduct",'p2.description'=>"subproduct")); - $this->export_sql_start[$r]='SELECT DISTINCT '; - $this->export_sql_end[$r] =' FROM '.MAIN_DB_PREFIX.'product as p'; - $this->export_sql_end[$r] .=' LEFT JOIN '.MAIN_DB_PREFIX.'product_extrafields as extra ON p.rowid = extra.fk_object,'; - $this->export_sql_end[$r] .=' '.MAIN_DB_PREFIX.'product_association as pa, '.MAIN_DB_PREFIX.'product as p2'; - $this->export_sql_end[$r] .=' WHERE p.fk_product_type = 0 AND p.entity IN ('.getEntity('product').')'; + $this->export_sql_end[$r] .=' WHERE p.entity IN ('.getEntity('product').')'; // For product and service profile $this->export_sql_end[$r] .=' AND p.rowid = pa.fk_product_pere AND p2.rowid = pa.fk_product_fils'; } } @@ -357,12 +334,109 @@ class modService extends DolibarrModules $this->import_tables_array[$r]=array('p'=>MAIN_DB_PREFIX.'product','extra'=>MAIN_DB_PREFIX.'product_extrafields'); $this->import_tables_creator_array[$r]=array('p'=>'fk_user_author'); // Fields to store import user id $this->import_fields_array[$r]=array( - 'p.ref'=>"Ref*",'p.label'=>"Label*",'p.description'=>"Description",'p.url'=>"PublicUrl",'p.accountancy_code_sell'=>"ProductAccountancySellCode", - 'p.accountancy_code_buy'=>"ProductAccountancyBuyCode",'p.note'=>"Note",'p.length'=>"Length",'p.surface'=>"Surface",'p.volume'=>"Volume", - 'p.weight'=>"Weight",'p.duration'=>"Duration",'p.customcode'=>'CustomCode','p.price'=>"SellingPriceHT",'p.price_ttc'=>"SellingPriceTTC", - 'p.tva_tx'=>'VATRate','p.tosell'=>"OnSell*",'p.tobuy'=>"OnBuy*",'p.fk_product_type'=>"Type*",'p.finished'=>'Nature','p.datec'=>'DateCreation' + 'p.ref' => "Ref*", + 'p.label' => "Label*", + 'p.fk_product_type' => "Type*", + 'p.tosell' => "OnSell*", + 'p.tobuy' => "OnBuy*", + 'p.description' => "Description", + 'p.url' => "PublicUrl", + 'p.customcode' => 'CustomCode', + 'p.fk_country' => 'CountryCode', + 'p.accountancy_code_sell' => "ProductAccountancySellCode", + 'p.accountancy_code_sell_intra' => "ProductAccountancySellIntraCode", + 'p.accountancy_code_sell_export' => "ProductAccountancySellExportCode", + 'p.accountancy_code_buy' => "ProductAccountancyBuyCode", + 'p.note_public' => "NotePublic", + 'p.note' => "NotePrivate", + 'p.weight' => "Weight", + 'p.weight_units' => "WeightUnits", + 'p.length' => "Length", + 'p.length_units' => "LengthUnit", + 'p.width' => "Width", + 'p.width_units' => "VolumeUnits", + 'p.height' => "Height", + 'p.height_units' => "HeightUnit", + 'p.surface' => "Surface", + 'p.surface_units' => "SurfaceUnit", + 'p.volume' => "Volume", + 'p.volume_units' => "VolumeUnits", + 'p.duration' => "Duration",//duration of service + 'p.finished' => 'Nature', + 'p.price' => "SellingPriceHT",//without + 'p.price_min' => "MinPrice", + 'p.price_ttc' => "SellingPriceTTC",//with tax + 'p.price_min_ttc' => "SellingMinPriceTTC", + 'p.price_base_type' => "PriceBaseType",//price base: with-tax (TTC) or without (HT) tax. Displays accordingly in Product card + 'p.tva_tx' => 'VATRate', + 'p.datec' => 'DateCreation', + 'p.cost_price' => "CostPrice", ); - //if (! empty($conf->stock->enabled)) $this->import_fields_array[$r]=array_merge($this->import_fields_array[$r],array('p.seuil_stock_alerte'=>'StockLimit','p.desiredstock'=>'DesiredStock','p.pmp'=>'PMPValue')); + if (!empty($conf->stock->enabled)) {//if Stock module enabled + $this->import_fields_array[$r] = array_merge($this->import_fields_array[$r], array( + 'p.seuil_stock_alerte' => 'StockLimit',//lower limit for warning + 'p.pmp' => 'PMPValue',//weighted average price + 'p.desiredstock' => 'DesiredStock'//desired stock for replenishment feature + )); + } + + $this->import_convertvalue_array[$r] = array( + 'p.weight_units' => array( + 'rule' => 'fetchscalefromcodeunits', // Switch this to fetchidfromcodeunits when we will store id instead of scale in product table + 'classfile' => '/core/class/cunits.class.php', + 'class' => 'CUnits', + 'method' => 'fetch', + 'units' => 'weight', + 'dict' => 'DictionaryMeasuringUnits' + ), + 'p.length_units' => array( + 'rule' => 'fetchscalefromcodeunits', // Switch this to fetchidfromcodeunits when we will store id instead of scale in product table + 'classfile' => '/core/class/cunits.class.php', + 'class' => 'CUnits', + 'method' => 'fetch', + 'units' => 'size', + 'dict' => 'DictionaryMeasuringUnits' + ), + 'p.width_units' => array( + 'rule' => 'fetchscalefromcodeunits', // Switch this to fetchidfromcodeunits when we will store id instead of scale in product table + 'classfile' => '/core/class/cunits.class.php', + 'class' => 'CUnits', + 'method' => 'fetch', + 'units' => 'size', + 'dict' => 'DictionaryMeasuringUnits' + ), + 'p.height_units' => array( + 'rule' => 'fetchscalefromcodeunits', // Switch this to fetchidfromcodeunits when we will store id instead of scale in product table + 'classfile' => '/core/class/cunits.class.php', + 'class' => 'CUnits', + 'method' => 'fetch', + 'units' => 'size', + 'dict' => 'DictionaryMeasuringUnits' + ), + 'p.surface_units' => array( + 'rule' => 'fetchscalefromcodeunits', // Switch this to fetchidfromcodeunits when we will store id instead of scale in product table + 'classfile' => '/core/class/cunits.class.php', + 'class' => 'CUnits', + 'method' => 'fetch', + 'units' => 'surface', + 'dict' => 'DictionaryMeasuringUnits' + ), + 'p.volume_units' => array( + 'rule' => 'fetchscalefromcodeunits', // Switch this to fetchidfromcodeunits when we will store id instead of scale in product table + 'classfile' => '/core/class/cunits.class.php', + 'class' => 'CUnits', + 'method' => 'fetch', + 'units' => 'volume', + 'dict' => 'DictionaryMeasuringUnits' + ), + 'p.fk_country' => array( + 'rule' => 'fetchidfromcodeid', + 'classfile' => '/core/class/ccountry.class.php', + 'class' => 'Ccountry', + 'method' => 'fetch', + 'dict' => 'DictionaryCountry' + ) + ); if (! empty($conf->fournisseur->enabled) || !empty($conf->margin->enabled)) $this->import_fields_array[$r]=array_merge($this->import_fields_array[$r], array('p.cost_price'=>'CostPrice')); if (is_object($mysoc) && $mysoc->useNPR()) $this->import_fields_array[$r]=array_merge($this->import_fields_array[$r], array('p.recuperableonly'=>'NPR')); if (is_object($mysoc) && $mysoc->useLocalTax(1)) $this->import_fields_array[$r]=array_merge($this->import_fields_array[$r], array('p.localtax1_tx'=>'LT1', 'p.localtax1_type'=>'LT1Type')); @@ -387,13 +461,82 @@ class modService extends DolibarrModules $this->import_fieldshidden_array[$r]=array('extra.fk_object'=>'lastrowid-'.MAIN_DB_PREFIX.'product'); // aliastable.field => ('user->id' or 'lastrowid-'.tableparent) $this->import_regex_array[$r]=array( 'p.ref'=>'[^ ]', - 'p.tosell'=>'^[0|1]$', + 'p.price_base_type' => '\AHT\z|\ATTC\z', + 'p.tosell'=>'^[0|1]$', 'p.tobuy'=>'^[0|1]$', 'p.fk_product_type'=>'^[0|1]$', 'p.datec'=>'^[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]$', - 'p.recuperableonly'=>'^[0|1]$' - ); - $import_sample=array('p.ref'=>"SERVICE_REF or id:123456",'p.label'=>"My product",'p.description'=>"This is a description example for record",'p.note'=>"Some note",'p.price'=>"100",'p.price_ttc'=>"110",'p.tva_tx'=>'10','p.tosell'=>"0 or 1",'p.tobuy'=>"0 or 1",'p.fk_product_type'=>"0 for product/1 for service",'p.finished'=>'','p.duration'=>"1y",'p.datec'=>'2008-12-31','p.recuperableonly'=>'0 or 1'); + 'p.recuperableonly' => '^[0|1]$', + 'p.finished' => '^[0|1]$' + ); + // field order as per structure of table llx_product + $import_sample = array( + 'p.ref' => "PREF123456", + 'p.datec' => dol_print_date(dol_now(), '%Y-%m-%d'), + 'p.label' => "Product name in default language", + 'p.description' => "Product description in default language", + 'p.note_public' => "a public note (free text)", + 'p.note' => "a private note (free text)", + 'p.customcode' => 'customs code', + 'p.fk_country' => 'FR', + 'p.price' => "100", + 'p.price_min' => "100", + 'p.price_ttc' => "110", + 'p.price_min_ttc' => "110", + 'p.price_base_type' => "HT (show/use price excl. tax) / TTC (show/use price incl. tax)", + 'p.tva_tx' => '10', // tax rate eg: 10. Must match numerically one of the tax rates defined for your country' + 'p.tosell' => "0 (not for sale to customer, eg. raw material) / 1 (for sale)", + 'p.tobuy' => "0 (not for purchase from supplier, eg. virtual product) / 1 (for purchase)", + 'p.fk_product_type' => "0 (product) / 1 (service)", + 'p.duration' => "eg. 365d/12m/1y", + 'p.url' => 'link to product (no https)', + 'p.accountancy_code_sell' => "", + 'p.accountancy_code_sell_intra' => "", + 'p.accountancy_code_sell_export' => "", + 'p.accountancy_code_buy' => "", + 'p.weight' => "", + 'p.weight_units' => 'kg', // Use a unit of measure from the dictionary. g/Kg/T etc....matches field "Short label" for unit type "weight" in table "' . MAIN_DB_PREFIX . 'c_units', + 'p.length' => "", + 'p.length_units' => 'm', // Use a unit of measure from the dictionary. m/cm/mm etc....matches field "Short label" for unit type "size" in table "' . MAIN_DB_PREFIX . 'c_units', + 'p.width' => "", + 'p.width_units' => 'm', // Use a unit of measure from the dictionary. m/cm/mm etc....matches field "Short label" for unit type "size" in table "' . MAIN_DB_PREFIX . 'c_units', + 'p.height' => "", + 'p.height_units' => 'm', // Use a unit of measure from the dictionary. m/cm/mm etc....matches field "Short label" for unit type "size" in table "' . MAIN_DB_PREFIX . 'c_units', + 'p.surface' => "", + 'p.surface_units' => 'm2', // Use a unit of measure from the dictionary. m2/cm2/mm2 etc....matches field "Short label" for unit type "surface" in table "' . MAIN_DB_PREFIX . 'c_units', + 'p.volume' => "", + 'p.volume_units' => 'm3', //Use a unit of measure from the dictionary. m3/cm3/mm3 etc....matches field "Short label" for unit type "volume" in table "' . MAIN_DB_PREFIX . 'c_units', + 'p.finished' => '0 (raw material) / 1 (finished goods)' + ); + //clauses copied from import_fields_array + if (!empty($conf->stock->enabled)) $import_sample = array_merge($import_sample, array( + 'p.seuil_stock_alerte' => '', + 'p.pmp' => '0', + 'p.desiredstock' => '' + )); + if (! empty($conf->fournisseur->enabled) || !empty($conf->margin->enabled)) $import_sample=array_merge($import_sample, array('p.cost_price'=>'90')); + if (is_object($mysoc) && $mysoc->useNPR()) $import_sample=array_merge($import_sample, array('p.recuperableonly'=>'0')); + if (is_object($mysoc) && $mysoc->useLocalTax(1)) $import_sample=array_merge($import_sample, array('p.localtax1_tx'=>'', 'p.localtax1_type'=>'')); + if (is_object($mysoc) && $mysoc->useLocalTax(2)) $import_sample=array_merge($import_sample, array('p.localtax2_tx'=>'', 'p.localtax2_type'=>'')); + if (! empty($conf->barcode->enabled)) $import_sample=array_merge($import_sample, array('p.barcode'=>'')); + if (! empty($conf->global->PRODUCT_USE_UNITS)) { + $import_sample = array_merge( + $import_sample, + array( + 'p.fk_unit' => 'use a unit of measure from the dictionary. G/KG/M2/M3 etc....matches field "code" in table "' . MAIN_DB_PREFIX . 'c_units"' + ) + ); + + $this->import_convertvalue_array[$r] = array_merge($this->import_convertvalue_array[$r], array( + 'p.fk_unit' => array( + 'rule' => 'fetchidfromcodeorlabel', + 'classfile' => '/core/class/cunits.class.php', + 'class' => 'CUnits', + 'method' => 'fetch', + 'dict' => 'DictionaryUnits' + ) + )); + } $this->import_examplevalues_array[$r]=array_merge($import_sample, $import_extrafield_sample); $this->import_updatekeys_array[$r] = array('p.ref'=>'Ref'); if (! empty($conf->barcode->enabled)) $this->import_updatekeys_array[$r]=array_merge($this->import_updatekeys_array[$r], array('p.barcode'=>'BarCode'));//only show/allow barcode as update key if Barcode module enabled @@ -445,12 +588,39 @@ class modService extends DolibarrModules 'sp.fk_product'=>array('rule'=>'fetchidfromref','classfile'=>'/product/class/product.class.php','class'=>'Product','method'=>'fetch','element'=>'Product') ); $this->import_examplevalues_array[$r]=array( - 'sp.fk_product'=>"SERVICE_REF or id:123456", - 'sp.fk_soc'=>"My Supplier",'sp.ref_fourn'=>"SupplierRef", 'sp.quantity'=>"1", 'sp.tva_tx'=>'21', - 'sp.price'=>"50", - 'sp.unitprice'=>'50', - 'sp.remise_percent'=>'0' + 'sp.fk_product' => "PRODUCT_REF or id:123456", + 'sp.fk_soc' => "My Supplier", + 'sp.ref_fourn' => "XYZ-F123456", + 'sp.quantity' => "5", + 'sp.tva_tx' => '10', + 'sp.price'=>"50", + 'sp.unitprice'=>'50', + 'sp.remise_percent'=>'0', + 'sp.default_vat_code' => '', + 'sp.delivery_time_days' => '5', + 'sp.supplier_reputation' => 'FAVORITE / NOTTHGOOD / DONOTORDER' ); + if (is_object($mysoc) && $mysoc->useNPR()) $this->import_examplevalues_array[$r]=array_merge($this->import_examplevalues_array[$r], array('sp.recuperableonly'=>'')); + if (is_object($mysoc) && $mysoc->useLocalTax(1)) $this->import_examplevalues_array[$r]=array_merge($this->import_examplevalues_array[$r], array('sp.localtax1_tx'=>'LT1', 'sp.localtax1_type'=>'LT1Type')); + if (is_object($mysoc) && $mysoc->useLocalTax(2)) $this->import_examplevalues_array[$r]=array_merge($this->import_examplevalues_array[$r], array('sp.localtax2_tx'=>'LT2', 'sp.localtax2_type'=>'LT2Type')); + $this->import_examplevalues_array[$r] = array_merge($this->import_examplevalues_array[$r], array( + 'sp.price' => "50.00", + 'sp.unitprice' => '10', + // TODO Make this field not required and calculate it from price and qty + 'sp.remise_percent' => '20' + )); + if ($conf->multicurrency->enabled) + { + $this->import_examplevalues_array[$r]=array_merge($this->import_examplevalues_array[$r], array( + 'sp.fk_multicurrency'=>'eg: 2, rowid for code of multicurrency currency', + 'sp.multicurrency_code'=>'GBP', + 'sp.multicurrency_tx'=>'1.12345', + 'sp.multicurrency_unitprice'=>'', + // TODO Make this field not required and calculate it from price and qty + 'sp.multicurrency_price'=>'' + )); + } + $this->import_updatekeys_array[$r]=array('sp.fk_product'=>'ProductOrService','sp.ref_fourn'=>'SupplierRef','sp.fk_soc'=>'Supplier'); } diff --git a/htdocs/core/modules/modSyslog.class.php b/htdocs/core/modules/modSyslog.class.php index bd45e21fc9e..88582c487e4 100644 --- a/htdocs/core/modules/modSyslog.class.php +++ b/htdocs/core/modules/modSyslog.class.php @@ -84,6 +84,10 @@ class modSyslog extends DolibarrModules $this->rights_class = 'syslog'; // Cronjobs + $comment = 'Compress and archive log files. The number of versions to keep is defined into the setup of module. '; + $comment.= 'Warning: Main application cron script must be run with same account than your web server to avoid to get log files with different owner than required by web server. '; + $comment.= 'Another solution is to set web server Operating System group as the group of directory documents and set GROUP permission "rws" on this directory so log files will always have the group and permissions of the web server Operating System group.'; + $this->cronjobs = array( 0 => array( 'label' => 'CompressSyslogs', @@ -92,7 +96,7 @@ class modSyslog extends DolibarrModules 'objectname' => 'Utils', 'method' => 'compressSyslogs', 'parameters' => '', - 'comment' => 'Compress and archive log files. The number of versions to keep is defined into the setup of module. Warning: Main application cron script must be run with same account than your web server to avoid to get log files with different owner than required by web server. Another solution is to set web server Operating System group as the group of directory documents and set GROUP permission "rws" on this directory so log files will always have the group and permissions of the web server Operating System group', + 'comment' => $comment, 'frequency' => 1, 'unitfrequency' => 3600 * 24, 'priority' => 50, diff --git a/htdocs/core/modules/security/generate/modGeneratePassPerso.class.php b/htdocs/core/modules/security/generate/modGeneratePassPerso.class.php index d9d625f0433..4c02d40cc6b 100644 --- a/htdocs/core/modules/security/generate/modGeneratePassPerso.class.php +++ b/htdocs/core/modules/security/generate/modGeneratePassPerso.class.php @@ -206,7 +206,7 @@ class modGeneratePassPerso extends ModeleGenPassword } /** - * consecutive iterations of the same character + * Consecutive iterations of the same character * * @param string $password Password to check * @return int 0 if KO, >0 if OK @@ -214,8 +214,12 @@ class modGeneratePassPerso extends ModeleGenPassword public function consecutiveInterationSameCharacter($password) { $last = ""; + + if (empty($this->NbRepeat)) return 1; + $count = 0; $char = str_split($password); + foreach($char as $c) { if($c != $last) { $last = $c; diff --git a/htdocs/core/tpl/objectline_create.tpl.php b/htdocs/core/tpl/objectline_create.tpl.php index 462af9173c1..7f860586909 100644 --- a/htdocs/core/tpl/objectline_create.tpl.php +++ b/htdocs/core/tpl/objectline_create.tpl.php @@ -677,7 +677,7 @@ jQuery(document).ready(function() { jQuery('#trlinefordates').show(); global->MAIN_EDIT_PREDEF_PRICEHT)) + if (empty($conf->global->MAIN_DISABLE_EDIT_PREDEF_PRICEHT)) { ?> // get the HT price for the product and display it @@ -851,11 +851,15 @@ function setforpredef() { jQuery("#select_type").val(-1); jQuery("#prod_entry_mode_free").prop('checked',false).change(); jQuery("#prod_entry_mode_predef").prop('checked',true).change(); - global->MAIN_EDIT_PREDEF_PRICEHT)) { ?> + global->MAIN_DISABLE_EDIT_PREDEF_PRICEHT)) { ?> + jQuery("#price_ht").val('').show(); + jQuery("#multicurrency_price_ht").val('').show(); + jQuery("#price_ht").val('').hide(); + jQuery("#multicurrency_price_ht").val('').hide(); jQuery("#price_ht").val(''); - jQuery("#price_ht, #multicurrency_price_ht, #price_ttc, #fourn_ref, #tva_tx, #title_vat, #title_up_ht, #title_up_ht_currency, #title_up_ttc, #title_up_ttc_currency").hide(); + jQuery("#price_ttc, #fourn_ref, #tva_tx, #title_vat, #title_up_ht, #title_up_ht_currency, #title_up_ttc, #title_up_ttc_currency").hide(); jQuery("#np_marginRate, #np_markRate, .np_marginRate, .np_markRate, #units, #title_units").hide(); jQuery("#buying_price").show(); jQuery('#trlinefordates, .divlinefordates').show(); diff --git a/htdocs/core/tpl/onlinepaymentlinks.tpl.php b/htdocs/core/tpl/onlinepaymentlinks.tpl.php index ef43fd585e2..c06772d8bca 100644 --- a/htdocs/core/tpl/onlinepaymentlinks.tpl.php +++ b/htdocs/core/tpl/onlinepaymentlinks.tpl.php @@ -28,12 +28,12 @@ print ''; // Url list print ''.$langs->trans("FollowingUrlAreAvailableToMakePayments").':

    '; -print img_picto('', 'object_globe.png').' '.$langs->trans("ToOfferALinkForOnlinePaymentOnFreeAmount", $servicename).':
    '; +print img_picto('', 'globe').' '.$langs->trans("ToOfferALinkForOnlinePaymentOnFreeAmount", $servicename).':
    '; print ''.getOnlinePaymentUrl(1, 'free')."

    \n"; if (! empty($conf->commande->enabled)) { print '
    '; - print img_picto('', 'object_globe.png').' '.$langs->trans("ToOfferALinkForOnlinePaymentOnOrder", $servicename).':
    '; + print img_picto('', 'globe').' '.$langs->trans("ToOfferALinkForOnlinePaymentOnOrder", $servicename).':
    '; print ''.getOnlinePaymentUrl(1, 'order')."
    \n"; if (! empty($conf->global->PAYMENT_SECURITY_TOKEN) && ! empty($conf->global->PAYMENT_SECURITY_TOKEN_UNIQUE)) { @@ -56,7 +56,7 @@ if (! empty($conf->commande->enabled)) if (! empty($conf->facture->enabled)) { print '
    '; - print img_picto('', 'object_globe.png').' '.$langs->trans("ToOfferALinkForOnlinePaymentOnInvoice", $servicename).':
    '; + print img_picto('', 'globe').' '.$langs->trans("ToOfferALinkForOnlinePaymentOnInvoice", $servicename).':
    '; print ''.getOnlinePaymentUrl(1, 'invoice')."
    \n"; if (! empty($conf->global->PAYMENT_SECURITY_TOKEN) && ! empty($conf->global->PAYMENT_SECURITY_TOKEN_UNIQUE)) { @@ -79,7 +79,7 @@ if (! empty($conf->facture->enabled)) if (! empty($conf->contrat->enabled)) { print '
    '; - print img_picto('', 'object_globe.png').' '.$langs->trans("ToOfferALinkForOnlinePaymentOnContractLine", $servicename).':
    '; + print img_picto('', 'globe').' '.$langs->trans("ToOfferALinkForOnlinePaymentOnContractLine", $servicename).':
    '; print ''.getOnlinePaymentUrl(1, 'contractline')."
    \n"; if (! empty($conf->global->PAYMENT_SECURITY_TOKEN) && ! empty($conf->global->PAYMENT_SECURITY_TOKEN_UNIQUE)) { @@ -102,7 +102,7 @@ if (! empty($conf->contrat->enabled)) if (! empty($conf->adherent->enabled)) { print '
    '; - print img_picto('', 'object_globe.png').' '.$langs->trans("ToOfferALinkForOnlinePaymentOnMemberSubscription", $servicename).':
    '; + print img_picto('', 'globe').' '.$langs->trans("ToOfferALinkForOnlinePaymentOnMemberSubscription", $servicename).':
    '; print ''.getOnlinePaymentUrl(1, 'membersubscription')."
    \n"; if (! empty($conf->global->PAYMENT_SECURITY_TOKEN) && ! empty($conf->global->PAYMENT_SECURITY_TOKEN_UNIQUE)) { @@ -125,7 +125,7 @@ if (! empty($conf->adherent->enabled)) if (! empty($conf->don->enabled)) { print '
    '; - print img_picto('', 'object_globe.png').' '.$langs->trans("ToOfferALinkForOnlinePaymentOnDonation", $servicename).':
    '; + print img_picto('', 'globe').' '.$langs->trans("ToOfferALinkForOnlinePaymentOnDonation", $servicename).':
    '; print ''.getOnlinePaymentUrl(1, 'donation')."
    \n"; if (! empty($conf->global->PAYMENT_SECURITY_TOKEN) && ! empty($conf->global->PAYMENT_SECURITY_TOKEN_UNIQUE)) { diff --git a/htdocs/core/triggers/interface_90_modSociete_ContactRoles.class.php b/htdocs/core/triggers/interface_90_modSociete_ContactRoles.class.php new file mode 100644 index 00000000000..13eb44d4eee --- /dev/null +++ b/htdocs/core/triggers/interface_90_modSociete_ContactRoles.class.php @@ -0,0 +1,112 @@ + + * Copyright (C) 2009-2017 Regis Houssin + * Copyright (C) 2011-2014 Juanjo Menent + * Copyright (C) 2013 Cedric GROSS + * Copyright (C) 2014 Marcos García + * Copyright (C) 2015 Bahfir Abbes + * + * 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 . + */ + +/** + * \file htdocs/core/triggers/interface_50_modAgenda_ActionsAuto.class.php + * \ingroup agenda + * \brief Trigger file for agenda module + */ + +require_once DOL_DOCUMENT_ROOT.'/core/triggers/dolibarrtriggers.class.php'; + + +/** + * Class of triggered functions for agenda module + */ +class InterfaceContactRoles extends DolibarrTriggers +{ + public $family = 'agenda'; + public $description = "Triggers of this module add actions in agenda according to setup made in agenda setup."; + + /** + * Version of the trigger + * @var string + */ + public $version = self::VERSION_DOLIBARR; + + /** + * @var string Image of the trigger + */ + public $picto = 'action'; + + /** + * Function called when a Dolibarrr business event is done. + * All functions "runTrigger" are triggered if file is inside directory htdocs/core/triggers or htdocs/module/code/triggers (and declared) + * + * Following properties may be set before calling trigger. The may be completed by this trigger to be used for writing the event into database: + * $object->socid or $object->fk_soc(id of thirdparty) + * $object->element (element type of object) + * + * @param string $action Event action code + * @param Object $object Object + * @param User $user Object user + * @param Translate $langs Object langs + * @param conf $conf Object conf + * @return int <0 if KO, 0 if no triggered ran, >0 if OK + */ + public function runTrigger($action, $object, User $user, Translate $langs, Conf $conf) + { + + if ($action === 'PROPAL_CREATE' || $action === 'ORDER_CREATE' || $action === 'BILL_CREATE' || $action === 'ORDER_SUPPLIER_CREATE' || $action === 'BILL_SUPPLIER_CREATE' + || $action === 'CONTRACT_CREATE' || $action === 'FICHINTER_CREATE' || $action === 'PROJECT_CREATE' || $action === 'TICKET_CREATE' || $action === 'ACTION_CREATE') { + + dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id); + + $socid=(property_exists($object, 'socid')?$object->socid:$object->fk_soc); + + if (! empty($socid) && $socid > 0) { + global $db, $langs; + require_once DOL_DOCUMENT_ROOT.'/contact/class/contact.class.php'; + $contactdefault = new Contact($this->db); + $contactdefault->socid=$socid; + $TContact = $contactdefault->getContactRoles($object->element); + + $TContactAlreadyLinked = array(); + if ($object->id > 0) + { + $class = get_class($object); + $cloneFrom = new $class($db); + $r = $cloneFrom->fetch($object->id); + + if (!empty($cloneFrom->id)) $TContactAlreadyLinked = array_merge($cloneFrom->liste_contact(-1, 'external'), $cloneFrom->liste_contact(-1, 'internal')); + } + + foreach($TContact as $i => $infos) { + foreach ($TContactAlreadyLinked as $contactData) { + if($contactData['id'] == $infos['fk_socpeople'] && $contactData['fk_c_type_contact'] == $infos['type_contact']) unset($TContact[$i]); + } + } + + $nb = 0; + foreach($TContact as $infos) { + $res = $object->add_contact($infos['fk_socpeople'], $infos['type_contact']); + if($res > 0) $nb++; + } + + if($nb > 0) { + setEventMessages($langs->trans('ContactAddedAutomatically', $nb), null, 'mesgs'); + } + } + } + return 0; + } +} diff --git a/htdocs/ecm/file_card.php b/htdocs/ecm/file_card.php index b796dcfd26f..38504088068 100644 --- a/htdocs/ecm/file_card.php +++ b/htdocs/ecm/file_card.php @@ -318,7 +318,7 @@ if ($forcedownload) $rellink.='&attachment=1'; if (! empty($object->entity)) $rellink.='&entity='.$object->entity; $rellink.='&file='.urlencode($filepath); $fulllink=$urlwithroot.$rellink; -print img_picto('', 'object_globe.png').' '; +print img_picto('', 'globe').' '; if ($action != 'edit') print ''; else print $fulllink; if ($action != 'edit') print ' '.$langs->trans("Download").''; // No target here. @@ -343,7 +343,7 @@ if (! empty($object->share)) //if (! empty($object->ref)) $fulllink.='&hashn='.$object->ref; // Hash of file path //elseif (! empty($object->label)) $fulllink.='&hashc='.$object->label; // Hash of file content - print img_picto('', 'object_globe.png').' '; + print img_picto('', 'globe').' '; if ($action != 'edit') print ''; else print $fulllink; if ($action != 'edit') print ' '.$langs->trans("Download").''; // No target here diff --git a/htdocs/expensereport/card.php b/htdocs/expensereport/card.php index 6361bf22cbc..95b9e0cd1f5 100644 --- a/htdocs/expensereport/card.php +++ b/htdocs/expensereport/card.php @@ -1491,7 +1491,7 @@ if ($action == 'create') if (empty($include_users)) print img_warning().' '.$langs->trans("NobodyHasPermissionToValidateExpenseReport"); else { - $defaultselectuser=$user->fk_user; // Will work only if supervisor has permission to approve so is inside include_users + $defaultselectuser=(empty($user->fk_user_expense_validator) ? $user->fk_user : $user->fk_user_expense_validator); // Will work only if supervisor has permission to approve so is inside include_users if (! empty($conf->global->EXPENSEREPORT_DEFAULT_VALIDATOR)) $defaultselectuser=$conf->global->EXPENSEREPORT_DEFAULT_VALIDATOR; // Can force default approver if (GETPOST('fk_user_validator', 'int') > 0) $defaultselectuser=GETPOST('fk_user_validator', 'int'); $s=$form->select_dolusers($defaultselectuser, "fk_user_validator", 1, "", ((empty($defaultselectuser) || empty($conf->global->EXPENSEREPORT_DEFAULT_VALIDATOR_UNCHANGEABLE))?0:1), $include_users); diff --git a/htdocs/fichinter/class/fichinterrec.class.php b/htdocs/fichinter/class/fichinterrec.class.php index 4fabf64be49..f88653e70eb 100644 --- a/htdocs/fichinter/class/fichinterrec.class.php +++ b/htdocs/fichinter/class/fichinterrec.class.php @@ -155,7 +155,7 @@ class FichinterRec extends Fichinter $sql.= ", ".($this->socid >0 ? $this->socid : 'null'); $sql.= ", ".$conf->entity; $sql.= ", '".$this->db->idate($now)."'"; - $sql.= ", ".(!empty($fichintsrc->duree)?$fichintsrc->duree:'0'); + $sql.= ", ".(!empty($fichintsrc->duration)?$fichintsrc->duration:'0'); $sql.= ", ".(!empty($this->description)?("'".$this->db->escape($this->description)."'"):"null"); $sql.= ", ".(!empty($fichintsrc->note_private)?("'".$this->db->escape($fichintsrc->note_private)."'"):"null"); $sql.= ", ".(!empty($fichintsrc->note_public)?("'".$this->db->escape($fichintsrc->note_public)."'"):"null"); @@ -271,6 +271,7 @@ class FichinterRec extends Fichinter $this->ref = $obj->titre; $this->description = $obj->description; $this->datec = $obj->datec; + $this->duration = $obj->duree; $this->socid = $obj->fk_soc; $this->statut = 0; $this->fk_project = $obj->fk_projet; diff --git a/htdocs/fourn/class/fournisseur.commande.class.php b/htdocs/fourn/class/fournisseur.commande.class.php index 3428a49aba5..4536cdc5bbd 100644 --- a/htdocs/fourn/class/fournisseur.commande.class.php +++ b/htdocs/fourn/class/fournisseur.commande.class.php @@ -625,18 +625,17 @@ class CommandeFournisseur extends CommonOrder /** * Return label of a status * - * @param int $statut Id statut + * @param int $status Id statut * @param int $mode 0=Long label, 1=Short label, 2=Picto + Short label, 3=Picto, 4=Picto + Long label, 5=Short label + Picto * @param int $billed 1=Billed * @return string Label of status */ - public function LibStatut($statut, $mode = 0, $billed = 0) + public function LibStatut($status, $mode = 0, $billed = 0) { // phpcs:enable global $conf, $langs; - if (empty($this->statuts) || empty($this->statutshort)) - { + if (empty($this->statuts) || empty($this->statutshort)){ $langs->load('orders'); $this->statuts[0] = 'StatusSupplierOrderDraft'; @@ -662,55 +661,33 @@ class CommandeFournisseur extends CommonOrder $this->statutshort[9] = 'StatusSupplierOrderRefusedShort'; } - $billedtext=''; - //if ($statut==5 && $this->billed == 1) $statut = 8; - if ($billed == 1) $billedtext=$langs->trans("Billed"); + $statustrans = array( + 0 => 'status0', + 1 => 'status1', + 2 => 'status3', + 3 => 'status3', + 4 => 'status3', + 5 => 'status6', + 6 => 'status5', + 7 => 'status5', - if ($mode == 0) - { - return $langs->trans($this->statuts[$statut]); + 9 => 'status5', + ); + + $statusClass = 'status0'; + if(!empty($statustrans[$status])){ + $statusClass = $statustrans[$status]; } - elseif ($mode == 1) - { - return $langs->trans($this->statutshort[$statut]); - } - elseif ($mode == 2) - { - return $langs->trans($this->statuts[$statut]); - } - elseif ($mode == 3) - { - if ($statut==0) return img_picto($langs->trans($this->statuts[$statut]), 'statut0'); - elseif ($statut==1) return img_picto($langs->trans($this->statuts[$statut]), 'statut1'); - elseif ($statut==2) return img_picto($langs->trans($this->statuts[$statut]), 'statut3'); - elseif ($statut==3) return img_picto($langs->trans($this->statuts[$statut]), 'statut3'); - elseif ($statut==4) return img_picto($langs->trans($this->statuts[$statut]), 'statut3'); - elseif ($statut==5) return img_picto($langs->trans($this->statuts[$statut]), 'statut6'); - elseif ($statut==6 || $statut==7) return img_picto($langs->trans($this->statuts[$statut]), 'statut5'); - elseif ($statut==9) return img_picto($langs->trans($this->statuts[$statut]), 'statut5'); - } - elseif ($mode == 4) - { - if ($statut==0) return img_picto($langs->trans($this->statuts[$statut]), 'statut0').' '.$langs->trans($this->statuts[$statut]).($billedtext?' - '.$billedtext:''); - elseif ($statut==1) return img_picto($langs->trans($this->statuts[$statut]), 'statut1').' '.$langs->trans($this->statuts[$statut]).($billedtext?' - '.$billedtext:''); - elseif ($statut==2) return img_picto($langs->trans($this->statuts[$statut]), 'statut3').' '.$langs->trans($this->statuts[$statut]).($billedtext?' - '.$billedtext:''); - elseif ($statut==3) return img_picto($langs->trans($this->statuts[$statut]), 'statut3').' '.$langs->trans($this->statuts[$statut]).($billedtext?' - '.$billedtext:''); - elseif ($statut==4) return img_picto($langs->trans($this->statuts[$statut]), 'statut3').' '.$langs->trans($this->statuts[$statut]).($billedtext?' - '.$billedtext:''); - elseif ($statut==5) return img_picto($langs->trans($this->statuts[$statut]), 'statut6').' '.$langs->trans($this->statuts[$statut]).($billedtext?' - '.$billedtext:''); - elseif ($statut==6 || $statut==7) return img_picto($langs->trans($this->statuts[$statut]), 'statut5').' '.$langs->trans($this->statuts[$statut]).($billedtext?' - '.$billedtext:''); - elseif ($statut==9) return img_picto($langs->trans($this->statuts[$statut]), 'statut5').' '.$langs->trans($this->statuts[$statut]).($billedtext?' - '.$billedtext:''); - } - elseif ($mode == 5) - { - if ($statut==0) return ''.$langs->trans($this->statutshort[$statut]).' '.img_picto($langs->trans($this->statuts[$statut]), 'statut0'); - elseif ($statut==1) return ''.$langs->trans($this->statutshort[$statut]).' '.img_picto($langs->trans($this->statuts[$statut]), 'statut1'); - elseif ($statut==2) return ''.$langs->trans($this->statutshort[$statut]).' '.img_picto($langs->trans($this->statuts[$statut]), 'statut3'); - elseif ($statut==3) return ''.$langs->trans($this->statutshort[$statut]).' '.img_picto($langs->trans($this->statuts[$statut]), 'statut3'); - elseif ($statut==4) return ''.$langs->trans($this->statutshort[$statut]).' '.img_picto($langs->trans($this->statuts[$statut]), 'statut3'); - elseif ($statut==5) return ''.$langs->trans($this->statutshort[$statut]).' '.img_picto($langs->trans($this->statuts[$statut]), 'statut6'); - elseif ($statut==6 || $statut==7) return ''.$langs->trans($this->statutshort[$statut]).' '.img_picto($langs->trans($this->statuts[$statut]), 'statut5'); - elseif ($statut==9) return ''.$langs->trans($this->statutshort[$statut]).' '.img_picto($langs->trans($this->statuts[$statut]), 'statut5'); + + $billedtext = ''; + if($mode == 4 && $billed){ + $billedtext = ' - '.$langs->trans("Billed"); } + + $statusLong = $langs->trans($this->statuts_long[$status]).$billedtext; + $statusShort = $langs->trans($this->statutshort[$status]); + + return dolGetStatus($statusLong, $statusShort, '', $statusClass, $mode); } diff --git a/htdocs/fourn/commande/card.php b/htdocs/fourn/commande/card.php index adcd683dba0..7fe73ab425e 100644 --- a/htdocs/fourn/commande/card.php +++ b/htdocs/fourn/commande/card.php @@ -2408,7 +2408,7 @@ elseif (! empty($object->id)) } // Send - if (in_array($object->statut, array(CommandeFournisseur::STATUS_ACCEPTED, 3, 4, 5))) + if (in_array($object->statut, array(CommandeFournisseur::STATUS_ACCEPTED, 3, 4, 5)) || !empty($conf->global->SUPPLIER_ORDER_SENDBYEMAIL_FOR_ALL_STATUS)) { if ($user->rights->fournisseur->commande->commander) { diff --git a/htdocs/holiday/card.php b/htdocs/holiday/card.php index 56acfd5f432..b464d336fd2 100644 --- a/htdocs/holiday/card.php +++ b/htdocs/holiday/card.php @@ -1091,7 +1091,7 @@ if ((empty($id) && empty($ref)) || $action == 'add' || $action == 'request' || $ if (empty($include_users)) print img_warning().' '.$langs->trans("NobodyHasPermissionToValidateHolidays"); else { - $defaultselectuser=$user->fk_user; // Will work only if supervisor has permission to approve so is inside include_users + $defaultselectuser=(empty($user->fk_user_holiday_validator) ? $user->fk_user : $user->fk_user_holiday_validator); // Will work only if supervisor has permission to approve so is inside include_users if (! empty($conf->global->HOLIDAY_DEFAULT_VALIDATOR)) $defaultselectuser=$conf->global->HOLIDAY_DEFAULT_VALIDATOR; // Can force default approver if (GETPOST('valideur', 'int') > 0) $defaultselectuser=GETPOST('valideur', 'int'); $s=$form->select_dolusers($defaultselectuser, "valideur", 1, "", 0, $include_users); diff --git a/htdocs/holiday/document.php b/htdocs/holiday/document.php index 00bc7ac1b24..05ddf164105 100644 --- a/htdocs/holiday/document.php +++ b/htdocs/holiday/document.php @@ -37,7 +37,7 @@ require_once DOL_DOCUMENT_ROOT.'/core/lib/holiday.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php'; // Load translation files required by the page -$langs->loadLangs(array('other', 'holidays', 'companies')); +$langs->loadLangs(array('other', 'holiday', 'companies')); $id = GETPOST('id', 'int'); $ref = GETPOST('ref', 'alpha'); @@ -48,8 +48,6 @@ $confirm = GETPOST('confirm', 'alpha'); if ($user->societe_id) $socid=$user->societe_id; $result = restrictedArea($user, 'holiday', $id, 'holiday'); -$langs->load("holiday"); - // Get parameters $sortfield = GETPOST('sortfield', 'alpha'); $sortorder = GETPOST('sortorder', 'alpha'); diff --git a/htdocs/holiday/list.php b/htdocs/holiday/list.php index 42515d0de48..bd948a58453 100644 --- a/htdocs/holiday/list.php +++ b/htdocs/holiday/list.php @@ -36,7 +36,7 @@ require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/usergroups.lib.php'; // Load translation files required by the page -$langs->loadLangs(array('users', 'holidays', 'hrm')); +$langs->loadLangs(array('users', 'holiday', 'hrm')); // Protection if external user if ($user->societe_id > 0) accessforbidden(); diff --git a/htdocs/index.php b/htdocs/index.php index 050058cd819..7279eebe80f 100644 --- a/htdocs/index.php +++ b/htdocs/index.php @@ -301,7 +301,7 @@ if (empty($user->societe_id) && empty($conf->global->MAIN_DISABLE_GLOBAL_BOXSTAT "supplier_proposal", "projects", "trips", - "holidays", + "holiday", "donations" ); diff --git a/htdocs/install/mysql/migration/10.0.0-11.0.0.sql b/htdocs/install/mysql/migration/10.0.0-11.0.0.sql index f72db462c23..f9faae4a8ee 100644 --- a/htdocs/install/mysql/migration/10.0.0-11.0.0.sql +++ b/htdocs/install/mysql/migration/10.0.0-11.0.0.sql @@ -135,6 +135,23 @@ ALTER TABLE llx_projet ADD COLUMN usage_organize_event integer DEFAULT 0; UPDATE llx_projet set usage_opportunity = 1 WHERE fk_opp_status > 0; +create table llx_societe_contacts +( + rowid integer AUTO_INCREMENT PRIMARY KEY, + entity integer DEFAULT 1 NOT NULL, + date_creation datetime NOT NULL, + fk_soc integer NOT NULL, + fk_c_type_contact int NOT NULL, + fk_socpeople integer NOT NULL, + tms TIMESTAMP, + import_key VARCHAR(14) +)ENGINE=innodb; + +ALTER TABLE llx_societe_contacts ADD UNIQUE INDEX idx_societe_contacts_idx1 (entity, fk_soc, fk_c_type_contact, fk_socpeople); +ALTER TABLE llx_societe_contacts ADD CONSTRAINT fk_societe_contacts_fk_c_type_contact FOREIGN KEY (fk_c_type_contact) REFERENCES llx_c_type_contact(rowid); +ALTER TABLE llx_societe_contacts ADD CONSTRAINT fk_societe_contacts_fk_soc FOREIGN KEY (fk_soc) REFERENCES llx_societe(rowid); +ALTER TABLE llx_societe_contacts ADD CONSTRAINT fk_societe_contacts_fk_socpeople FOREIGN KEY (fk_socpeople) REFERENCES llx_socpeople(rowid); + ALTER TABLE llx_accounting_account MODIFY COLUMN rowid bigint AUTO_INCREMENT; @@ -332,3 +349,5 @@ create table llx_fichinterdet_rec import_key varchar(14) NULL DEFAULT NULL )ENGINE=innodb; +ALTER TABLE llx_supplier_proposaldet ADD COLUMN date_start datetime DEFAULT NULL AFTER product_type; +ALTER TABLE llx_supplier_proposaldet ADD COLUMN date_end datetime DEFAULT NULL AFTER date_start; diff --git a/htdocs/install/mysql/tables/llx_societe_contacts.key.sql b/htdocs/install/mysql/tables/llx_societe_contacts.key.sql new file mode 100644 index 00000000000..2b2eae8b2ca --- /dev/null +++ b/htdocs/install/mysql/tables/llx_societe_contacts.key.sql @@ -0,0 +1,22 @@ +-- ======================================================================== +-- Copyright (C) 2019 Florian HENRY +-- +-- 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 . +-- +-- ======================================================================== + +ALTER TABLE llx_societe_contacts ADD UNIQUE INDEX idx_societe_contacts_idx1 (entity, fk_soc, fk_c_type_contact, fk_socpeople); +ALTER TABLE llx_societe_contacts ADD CONSTRAINT fk_societe_contacts_fk_c_type_contact FOREIGN KEY (fk_c_type_contact) REFERENCES llx_c_type_contact(rowid); +ALTER TABLE llx_societe_contacts ADD CONSTRAINT fk_societe_contacts_fk_soc FOREIGN KEY (fk_soc) REFERENCES llx_societe(rowid); +ALTER TABLE llx_societe_contacts ADD CONSTRAINT fk_societe_contacts_fk_socpeople FOREIGN KEY (fk_socpeople) REFERENCES llx_socpeople(rowid); diff --git a/htdocs/install/mysql/tables/llx_societe_contacts.sql b/htdocs/install/mysql/tables/llx_societe_contacts.sql new file mode 100644 index 00000000000..31d82f3003d --- /dev/null +++ b/htdocs/install/mysql/tables/llx_societe_contacts.sql @@ -0,0 +1,30 @@ +-- ======================================================================== +-- Copyright (C) 2019 Florian HENRY +-- +-- 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 . +-- +-- ======================================================================== + + +create table llx_societe_contacts +( + rowid integer AUTO_INCREMENT PRIMARY KEY, + entity integer DEFAULT 1 NOT NULL, + date_creation datetime NOT NULL, + fk_soc integer NOT NULL, + fk_c_type_contact int NOT NULL, + fk_socpeople integer NOT NULL, + tms TIMESTAMP, + import_key VARCHAR(14) +)ENGINE=innodb; diff --git a/htdocs/langs/en_US/accountancy.lang b/htdocs/langs/en_US/accountancy.lang index 8e44c378ba6..a76e79aa701 100644 --- a/htdocs/langs/en_US/accountancy.lang +++ b/htdocs/langs/en_US/accountancy.lang @@ -1,4 +1,5 @@ -# Dolibarr language file - en_US - Accounting Expert +# Dolibarr language file - en_US - Accountancy (Double entries) +Accountancy=Accountancy Accounting=Accounting ACCOUNTING_EXPORT_SEPARATORCSV=Column separator for export file ACCOUNTING_EXPORT_DATE=Date format for export file @@ -256,6 +257,7 @@ ListOfProductsWithoutAccountingAccount=List of products not bound to any account ChangeBinding=Change the binding Accounted=Accounted in ledger NotYetAccounted=Not yet accounted in ledger +ShowTutorial=Show Tutorial ## Admin ApplyMassCategories=Apply mass categories @@ -264,7 +266,7 @@ CategoryDeleted=Category for the accounting account has been removed AccountingJournals=Accounting journals AccountingJournal=Accounting journal NewAccountingJournal=New accounting journal -ShowAccoutingJournal=Show accounting journal +ShowAccountingJournal=Show accounting journal NatureOfJournal=Nature of Journal AccountingJournalType1=Miscellaneous operations AccountingJournalType2=Sales diff --git a/htdocs/langs/en_US/admin.lang b/htdocs/langs/en_US/admin.lang index 225cada814f..99155377c13 100644 --- a/htdocs/langs/en_US/admin.lang +++ b/htdocs/langs/en_US/admin.lang @@ -526,7 +526,7 @@ Module50Desc=Management of Products Module51Name=Mass mailings Module51Desc=Mass paper mailing management Module52Name=Stocks -Module52Desc=Stock management (for products only) +Module52Desc=Stock management Module53Name=Services Module53Desc=Management of Services Module54Name=Contracts/Subscriptions diff --git a/htdocs/langs/en_US/agenda.lang b/htdocs/langs/en_US/agenda.lang index 30c2a3d4038..8ad19e06695 100644 --- a/htdocs/langs/en_US/agenda.lang +++ b/htdocs/langs/en_US/agenda.lang @@ -86,6 +86,10 @@ InvoiceDeleted=Invoice deleted PRODUCT_CREATEInDolibarr=Product %s created PRODUCT_MODIFYInDolibarr=Product %s modified PRODUCT_DELETEInDolibarr=Product %s deleted +HOLIDAY_CREATEInDolibarr=Request for leave %s created +HOLIDAY_MODIFYInDolibarr=Request for leave %s modified +HOLIDAY_VALIDATEDInDolibarr=Request for leave %s validated +HOLIDAY_DELETEInDolibarr=Request for leave %s deleted EXPENSE_REPORT_CREATEInDolibarr=Expense report %s created EXPENSE_REPORT_VALIDATEInDolibarr=Expense report %s validated EXPENSE_REPORT_APPROVEInDolibarr=Expense report %s approved diff --git a/htdocs/langs/en_US/boxes.lang b/htdocs/langs/en_US/boxes.lang index c0d301710c4..84815016b7d 100644 --- a/htdocs/langs/en_US/boxes.lang +++ b/htdocs/langs/en_US/boxes.lang @@ -86,4 +86,11 @@ ForProposals=Proposals LastXMonthRolling=The latest %s month rolling ChooseBoxToAdd=Add widget to your dashboard BoxAdded=Widget was added in your dashboard -BoxTitleUserBirthdaysOfMonth=Birthdays of this month (users) \ No newline at end of file +BoxTitleUserBirthdaysOfMonth=Birthdays of this month (users) +BoxLastManualEntries=Last manual entries in accountancy +BoxTitleLastManualEntries=%s last manual entries +NoRecordedManualEntries=No manual entries record in accountancy +BoxSuspenseAccount=Count accountancy operation with suspense account +BoxTitleSuspenseAccount=Number of unallocated lines +NumberOfLinesInSuspenseAccount=Number of line in suspense account +SuspenseAccountNotDefined=Suspense account isn't defined diff --git a/htdocs/langs/en_US/companies.lang b/htdocs/langs/en_US/companies.lang index 532fbf14cb7..a4ab22d47c5 100644 --- a/htdocs/langs/en_US/companies.lang +++ b/htdocs/langs/en_US/companies.lang @@ -298,6 +298,7 @@ FromContactName=Name: NoContactDefinedForThirdParty=No contact defined for this third party NoContactDefined=No contact defined DefaultContact=Default contact/address +ContactByDefaultFor=Default contact/address for AddThirdParty=Create third party DeleteACompany=Delete a company PersonalInformations=Personal data diff --git a/htdocs/langs/en_US/exports.lang b/htdocs/langs/en_US/exports.lang index 2ee374ee670..691a1770ac8 100644 --- a/htdocs/langs/en_US/exports.lang +++ b/htdocs/langs/en_US/exports.lang @@ -113,7 +113,7 @@ ExportDateFilter=YYYY, YYYYMM, YYYYMMDD: filters by one year/month/day
    YYYY+Y ExportNumericFilter=NNNNN filters by one value
    NNNNN+NNNNN filters over a range of values
    < NNNNN filters by lower values
    > NNNNN filters by higher values ImportFromLine=Import starting from line number EndAtLineNb=End at line number -ImportFromToLine=Limit range (From - To) eg. to omit header line(s) +ImportFromToLine=Limit range (From - To). Eg. to omit header line(s). SetThisValueTo2ToExcludeFirstLine=For example, set this value to 3 to exclude the 2 first lines.
    If the header lines are NOT omitted, this will result in multiple errors in the Import Simulation. KeepEmptyToGoToEndOfFile=Keep this field empty to process all lines to the end of the file. SelectPrimaryColumnsForUpdateAttempt=Select column(s) to use as primary key for an UPDATE import diff --git a/htdocs/langs/en_US/main.lang b/htdocs/langs/en_US/main.lang index a69947dfd8c..04f45f8de4b 100644 --- a/htdocs/langs/en_US/main.lang +++ b/htdocs/langs/en_US/main.lang @@ -991,4 +991,17 @@ ToApprove=To approve GlobalOpenedElemView=Global view NoArticlesFoundForTheKeyword=No article found for the keyword '%s' NoArticlesFoundForTheCategory=No article found for the category -ToAcceptRefuse=To accept | refuse \ No newline at end of file +ToAcceptRefuse=To accept | refuse +ContactDefault_agenda=Event +ContactDefault_commande=Order +ContactDefault_contrat=Contract +ContactDefault_facture=Invoice +ContactDefault_fichinter=Intervention +ContactDefault_invoice_supplier=Supplier Invoice +ContactDefault_order_supplier=Supplier Order +ContactDefault_project=Project +ContactDefault_project_task=Task +ContactDefault_propal=Proposal +ContactDefault_supplier_proposal=Supplier Proposal +ContactDefault_ticketsup=Ticket +ContactAddedAutomatically=Contact added from contact thirdparty roles diff --git a/htdocs/langs/en_US/users.lang b/htdocs/langs/en_US/users.lang index fb35cb5e112..8780e7d2c0d 100644 --- a/htdocs/langs/en_US/users.lang +++ b/htdocs/langs/en_US/users.lang @@ -109,4 +109,7 @@ UserLogoff=User logout UserLogged=User logged DateEmployment=Employment Start Date DateEmploymentEnd=Employment End Date -CantDisableYourself=You can't disable your own user record \ No newline at end of file +CantDisableYourself=You can't disable your own user record +ForceUserExpenseValidator=Force expense report validator +ForceUserHolidayValidator=Force leave request validator +ValidatorIsSupervisorByDefault=By default, the validator is the supervisor of the user. Keep empty to keep this behaviour. diff --git a/htdocs/opensurvey/card.php b/htdocs/opensurvey/card.php index ae40a13701d..1cdab974833 100644 --- a/htdocs/opensurvey/card.php +++ b/htdocs/opensurvey/card.php @@ -327,7 +327,7 @@ if ($object->fk_user_creat) { print '
    '.img_picto('', 'object_globe.png').' '.$langs->trans("UrlForSurvey", '').''; +print '
    '.img_picto('', 'globe').' '.$langs->trans("UrlForSurvey", '').''; // Define $urlwithroot $urlwithouturlroot=preg_replace('/'.preg_quote(DOL_URL_ROOT, '/').'$/i', '', trim($dolibarr_main_url_root)); diff --git a/htdocs/opensurvey/results.php b/htdocs/opensurvey/results.php index d30f24694e9..ad31d99e645 100644 --- a/htdocs/opensurvey/results.php +++ b/htdocs/opensurvey/results.php @@ -474,7 +474,7 @@ if ($object->fk_user_creat) { print '
    '.img_picto('', 'object_globe.png').' '.$langs->trans("UrlForSurvey", '').''; +print '
    '.img_picto('', 'globe').' '.$langs->trans("UrlForSurvey", '').''; // Define $urlwithroot $urlwithouturlroot=preg_replace('/'.preg_quote(DOL_URL_ROOT, '/').'$/i', '', trim($dolibarr_main_url_root)); diff --git a/htdocs/paypal/lib/paypal.lib.php b/htdocs/paypal/lib/paypal.lib.php index 4a528c449a2..22356994008 100644 --- a/htdocs/paypal/lib/paypal.lib.php +++ b/htdocs/paypal/lib/paypal.lib.php @@ -70,7 +70,7 @@ function showPaypalPaymentUrl($type, $ref) $langs->load("paybox"); $servicename='PayPal'; $out='

    '; - $out.=img_picto('', 'object_globe.png').' '.$langs->trans("ToOfferALinkForOnlinePayment", $servicename).'
    '; + $out.=img_picto('', 'globe').' '.$langs->trans("ToOfferALinkForOnlinePayment", $servicename).'
    '; $url=getPaypalPaymentUrl(0, $type, $ref); $out.=''; $out.=ajax_autoselect("paypalurl", 0); diff --git a/htdocs/product/class/api_products.class.php b/htdocs/product/class/api_products.class.php index 866eeb116cf..346aef06a91 100644 --- a/htdocs/product/class/api_products.class.php +++ b/htdocs/product/class/api_products.class.php @@ -15,10 +15,11 @@ * along with this program. If not, see . */ - use Luracast\Restler\RestException; +use Luracast\Restler\RestException; - require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php'; - require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php'; +require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php'; +require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.product.class.php'; +require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php'; /** * API class for products @@ -41,6 +42,11 @@ class Products extends DolibarrApi */ public $product; + /** + * @var ProductFournisseur $productsupplier {@type ProductFournisseur} + */ + public $productsupplier; + /** * Constructor */ @@ -49,6 +55,7 @@ class Products extends DolibarrApi global $db, $conf; $this->db = $db; $this->product = new Product($this->db); + $this->productsupplier = new ProductFournisseur($this->db); } /** @@ -475,7 +482,7 @@ class Products extends DolibarrApi * * @url DELETE {id}/purchase_prices/{priceid} * - * @return array + * @return int * * @throws 401 * @throws 404 @@ -494,13 +501,13 @@ class Products extends DolibarrApi if(! DolibarrApi::_checkAccessToResource('product', $this->product->id)) { throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } - - if($result) { - $this->product = new ProductFournisseur($this->db); - $this->product->fetch($id); + $resultsupplier = 0; + if ($result) { + $this->productsupplier->fetch($id); + $resultsupplier = $this->product->remove_product_fournisseur_price($priceid); } - return $this->product->remove_product_fournisseur_price($priceid); + return $resultsupplier; } /** @@ -632,16 +639,15 @@ class Products extends DolibarrApi } if ($includestockdata) { - $this->product->load_stock(); + $this->product->load_stock(); } - if($result) { - $this->product = new ProductFournisseur($this->db); - $this->product->fetch($id, $ref); - $this->product->list_product_fournisseur_price($id, '', '', 0, 0); + if ($result) { + $this->productsupplier->fetch($id, $ref); + $this->productsupplier->list_product_fournisseur_price($id, '', '', 0, 0); } - return $this->_cleanObjectDatas($this->product); + return $this->_cleanObjectDatas($this->productsupplier); } // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore diff --git a/htdocs/projet/class/project.class.php b/htdocs/projet/class/project.class.php index 027fe6503b2..e14cd53c3c3 100644 --- a/htdocs/projet/class/project.class.php +++ b/htdocs/projet/class/project.class.php @@ -942,48 +942,27 @@ class Project extends CommonObject /** * Renvoi status label for a status * - * @param int $statut id statut - * @param int $mode 0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=Short label + Picto + * @param int $status id status + * @param int $mode 0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=Short label + Picto, 6=Long label + Picto * @return string Label */ - public function LibStatut($statut, $mode = 0) + public function LibStatut($status, $mode = 0) { // phpcs:enable global $langs; - if ($mode == 0) { - return $langs->trans($this->statuts_long[$statut]); - } elseif ($mode == 1) { - return $langs->trans($this->statuts_short[$statut]); - } elseif ($mode == 2) { - if ($statut == 0) - return img_picto($langs->trans($this->statuts_long[$statut]), 'statut0') . ' ' . $langs->trans($this->statuts_short[$statut]); - elseif ($statut == 1) - return img_picto($langs->trans($this->statuts_long[$statut]), 'statut4') . ' ' . $langs->trans($this->statuts_short[$statut]); - elseif ($statut == 2) - return img_picto($langs->trans($this->statuts_long[$statut]), 'statut6') . ' ' . $langs->trans($this->statuts_short[$statut]); - } elseif ($mode == 3) { - if ($statut == 0) - return img_picto($langs->trans($this->statuts_long[$statut]), 'statut0'); - elseif ($statut == 1) - return img_picto($langs->trans($this->statuts_long[$statut]), 'statut4'); - elseif ($statut == 2) - return img_picto($langs->trans($this->statuts_long[$statut]), 'statut6'); - } elseif ($mode == 4) { - if ($statut == 0) - return img_picto($langs->trans($this->statuts_long[$statut]), 'statut0') . ' ' . $langs->trans($this->statuts_long[$statut]); - elseif ($statut == 1) - return img_picto($langs->trans($this->statuts_long[$statut]), 'statut4') . ' ' . $langs->trans($this->statuts_long[$statut]); - if ($statut == 2) - return img_picto($langs->trans($this->statuts_long[$statut]), 'statut6') . ' ' . $langs->trans($this->statuts_long[$statut]); - } elseif ($mode == 5) { - if ($statut == 0) - return $langs->trans($this->statuts_short[$statut]) . ' ' . img_picto($langs->trans($this->statuts_long[$statut]), 'statut0'); - elseif ($statut == 1) - return $langs->trans($this->statuts_short[$statut]) . ' ' . img_picto($langs->trans($this->statuts_long[$statut]), 'statut4'); - elseif ($statut == 2) - return $langs->trans($this->statuts_short[$statut]) . ' ' . img_picto($langs->trans($this->statuts_long[$statut]), 'statut6'); + $statustrans = array( + 0 => 'status0', + 1 => 'status4', + 2 => 'status6', + ); + + $statusClass = 'status0'; + if(!empty($statustrans[$status])){ + $statusClass = $statustrans[$status]; } + + return dolGetStatus($langs->trans($this->statuts_long[$status]), $langs->trans($this->statuts_short[$status]), '', $statusClass, $mode); } /** diff --git a/htdocs/societe/agenda.php b/htdocs/societe/agenda.php index af0d7670141..231174a0afa 100644 --- a/htdocs/societe/agenda.php +++ b/htdocs/societe/agenda.php @@ -2,7 +2,7 @@ /* Copyright (C) 2001-2007 Rodolphe Quiedeville * Copyright (C) 2005 Brice Davoleau * Copyright (C) 2005-2012 Regis Houssin - * Copyright (C) 2006-2015 Laurent Destailleur + * Copyright (C) 2006-2019 Laurent Destailleur * Copyright (C) 2007 Patrick Raguin * Copyright (C) 2010 Juanjo Menent * Copyright (C) 2015 Marcos García diff --git a/htdocs/societe/paymentmodes.php b/htdocs/societe/paymentmodes.php index 915040bf36a..19b11994114 100644 --- a/htdocs/societe/paymentmodes.php +++ b/htdocs/societe/paymentmodes.php @@ -857,7 +857,7 @@ if ($socid && $action != 'edit' && $action != 'create' && $action != 'editcard' { $url='https://dashboard.stripe.com/'.$connect.'customers/'.$stripecu; } - print ' '.img_picto($langs->trans('ShowInStripe'), 'object_globe').''; + print ' '.img_picto($langs->trans('ShowInStripe'), 'globe').''; } print '
    '; if (empty($stripecu)) @@ -911,7 +911,7 @@ if ($socid && $action != 'edit' && $action != 'create' && $action != 'editcard' { $url='https://dashboard.stripe.com/connect/accounts/'.$stripesupplieracc; } - print ' '.img_picto($langs->trans('ShowInStripe'), 'object_globe').''; + print ' '.img_picto($langs->trans('ShowInStripe'), 'globe').''; } print ''; if (empty($stripesupplieracc)) @@ -1064,7 +1064,7 @@ if ($socid && $action != 'edit' && $action != 'create' && $action != 'editcard' { $url='https://dashboard.stripe.com/'.$connect.'search?query='.$companypaymentmodetemp->stripe_card_ref; } - print ' '.img_picto($langs->trans('ShowInStripe'), 'object_globe').''; + print ' '.img_picto($langs->trans('ShowInStripe'), 'globe').''; } print ''; @@ -1159,7 +1159,7 @@ if ($socid && $action != 'edit' && $action != 'create' && $action != 'editcard' //$url='https://dashboard.stripe.com/'.$connect.'sources/'.$src->id; $url='https://dashboard.stripe.com/'.$connect.'search?query='.$src->id; } - print " ".img_picto($langs->trans('ShowInStripe'), 'object_globe').""; + print " ".img_picto($langs->trans('ShowInStripe'), 'globe').""; print ''; diff --git a/htdocs/stripe/admin/stripe.php b/htdocs/stripe/admin/stripe.php index 7621f48eeae..05d8937f293 100644 --- a/htdocs/stripe/admin/stripe.php +++ b/htdocs/stripe/admin/stripe.php @@ -207,7 +207,7 @@ if (empty($conf->stripeconnect->enabled)) } print ''; print '   '.$langs->trans("Example").': whsec_xxxxxxxxxxxxxxxxxxxxxxxx'; - $out = img_picto('', 'object_globe.png').' '.$langs->trans("ToOfferALinkForTestWebhook").' '; + $out = img_picto('', 'globe').' '.$langs->trans("ToOfferALinkForTestWebhook").' '; $url = dol_buildpath('/public/stripe/ipn.php?test', 3); $out.= ''; $out.= ajax_autoselect("onlinetestwebhookurl", 0); @@ -280,7 +280,7 @@ if (empty($conf->stripeconnect->enabled)) } print ''; print '   '.$langs->trans("Example").': whsec_xxxxxxxxxxxxxxxxxxxxxxxx'; - $out = img_picto('', 'object_globe.png').' '.$langs->trans("ToOfferALinkForLiveWebhook").' '; + $out = img_picto('', 'globe').' '.$langs->trans("ToOfferALinkForLiveWebhook").' '; $url = dol_buildpath('/public/stripe/ipn.php', 3); $out.= ''; $out.= ajax_autoselect("onlinelivewebhookurl", 0); diff --git a/htdocs/stripe/charge.php b/htdocs/stripe/charge.php index 200f4c31703..1189b94923b 100644 --- a/htdocs/stripe/charge.php +++ b/htdocs/stripe/charge.php @@ -183,7 +183,7 @@ if (!$rowid) $url='https://dashboard.stripe.com/'.$connect.'payments/'.$charge->id; } print ""; - print "".img_picto($langs->trans('ShowInStripe'), 'object_globe')." ".$charge->id.""; + print "".img_picto($langs->trans('ShowInStripe'), 'globe')." ".$charge->id.""; print ""; @@ -195,7 +195,7 @@ if (!$rowid) } if (! empty($charge->customer)) { - print ''.img_picto($langs->trans('ShowInStripe'), 'object_globe').' '.$charge->customer.''; + print ''.img_picto($langs->trans('ShowInStripe'), 'globe').' '.$charge->customer.''; } print "".img_picto($langs->trans('ShowInStripe'), 'object_globe')." " . $payout->id . "".img_picto($langs->trans('ShowInStripe'), 'globe')." " . $payout->id . "".$txn->type."".img_picto($langs->trans('ShowInStripe'), 'object_globe')." " . $txn->source . "".img_picto($langs->trans('ShowInStripe'), 'globe')." " . $txn->source . "
    '; + $text = $langs->trans("ForceUserExpenseValidator"); + print $form->textwithpicto($text, $langs->trans("ValidatorIsSupervisorByDefault"), 1, 'help'); + print ''; + print $form->select_dolusers($object->fk_user_expense_validator, 'fk_user_expense_validator', 1, array($object->id), 0, '', 0, $conf->entity, 0, 0, '', 0, '', 'maxwidth300'); + print '
    '; + $text = $langs->trans("ForceUserHolidayValidator"); + print $form->textwithpicto($text, $langs->trans("ValidatorIsSupervisorByDefault"), 1, 'help'); + print ''; + print $form->select_dolusers($object->fk_user_holiday_validator, 'fk_user_holiday_validator', 1, array($object->id), 0, '', 0, $conf->entity, 0, 0, '', 0, '', 'maxwidth300'); + print '

    '; @@ -1234,20 +1264,20 @@ if ($action == 'create' || $action == 'adduserldap') // TODO Move this into tab RH (HierarchicalResponsible must be on both tab) - // Position/Job - print ''; - print ''; - // Default warehouse - if (! empty($conf->stock->enabled)) + if (! empty($conf->stock->enabled) && ! empty($conf->global->USER_DEFAULT_WAREHOUSE)) // TODO What is goal of this. How it is used ? { print ''; } + // Position/Job + print ''; + print ''; + if ((! empty($conf->salaries->enabled) && ! empty($user->rights->salaries->read)) || (! empty($conf->hrm->enabled) && ! empty($user->rights->hrm->employee->read))) { @@ -1595,13 +1625,36 @@ else print ''; print "\n"; - // Position/Job - print ''; - print ''; - print ''."\n"; + // Expense report validator + print ''; + print ''; + print "\n"; + + // Holiday request validator + print ''; + print ''; + print "\n"; // Default warehouse - if (! empty($conf->stock->enabled)) + if (! empty($conf->stock->enabled) && ! empty($conf->global->USER_DEFAULT_WAREHOUSE)) // TODO What is goal of this. How it is used ? { require_once DOL_DOCUMENT_ROOT .'/product/stock/class/entrepot.class.php'; $warehousestatic=new Entrepot($db); @@ -1611,7 +1664,12 @@ else print ''; } - //$childids = $user->getAllChildIds(1); + // Position/Job + print ''; + print ''; + print ''."\n"; + + //$childids = $user->getAllChildIds(1); if ((! empty($conf->salaries->enabled) && ! empty($user->rights->salaries->read)) || (! empty($conf->hrm->enabled) && ! empty($user->rights->hrm->employee->read))) @@ -2276,6 +2334,46 @@ else print ''; print "\n"; + // Expense report validator + print ''; + print ''; + print "\n"; + + // Holiday request validator + print ''; + print ''; + print "\n"; + print '
    '.$langs->trans("PostOrFunction").''; - print ''; - print '
    '.$langs->trans("DefaultWarehouse").''; print $formproduct->selectWarehouses($object->fk_warehouse, 'fk_warehouse', 'warehouseopen', 1); print '
    '.$langs->trans("PostOrFunction").''; + print ''; + print '
    '.$langs->trans("PostOrFunction").''.$object->job.'
    '; + $text = $langs->trans("ForceUserExpenseValidator"); + print $form->textwithpicto($text, $langs->trans("ValidatorIsSupervisorByDefault"), 1, 'help'); + print ''; + if (! empty($object->fk_user_expense_validator)) { + $evuser=new User($db); + $evuser->fetch($object->fk_user_expense_validator); + print $evuser->getNomUrl(1); + } + print '
    '; + $text = $langs->trans("ForceUserHolidayValidator"); + print $form->textwithpicto($text, $langs->trans("ValidatorIsSupervisorByDefault"), 1, 'help'); + print ''; + if (! empty($object->fk_user_holiday_validator)) { + $hvuser=new User($db); + $hvuser->fetch($object->fk_user_holiday_validator); + print $hvuser->getNomUrl(1); + } + print '
    '.$langs->trans("PostOrFunction").''.$object->job.'
    '; + $text = $langs->trans("ForceUserExpenseValidator"); + print $form->textwithpicto($text, $langs->trans("ValidatorIsSupervisorByDefault"), 1, 'help'); + print ''; + if ($caneditfield) + { + print $form->select_dolusers($object->fk_user_expense_validator, 'fk_user_expense_validator', 1, array($object->id), 0, '', 0, $object->entity, 0, 0, '', 0, '', 'maxwidth300'); + } + else + { + print ''; + $evuser=new User($db); + $evuser->fetch($object->fk_user_expense_validator); + print $evuser->getNomUrl(1); + } + print '
    '; + $text = $langs->trans("ForceUserHolidayValidator"); + print $form->textwithpicto($text, $langs->trans("ValidatorIsSupervisorByDefault"), 1, 'help'); + print ''; + if ($caneditfield) + { + print $form->select_dolusers($object->fk_user_holiday_validator, 'fk_user_holiday_validator', 1, array($object->id), 0, '', 0, $object->entity, 0, 0, '', 0, '', 'maxwidth300'); + } + else + { + print ''; + $hvuser=new User($db); + $hvuser->fetch($object->fk_user_holiday_validator); + print $hvuser->getNomUrl(1); + } + print '

    '; @@ -2641,22 +2739,8 @@ else // TODO Move this into tab RH (HierarchicalResponsible must be on both tab) - // Position/Job - print ''; - print ''; - // Default warehouse - if (! empty($conf->stock->enabled)) + if (! empty($conf->stock->enabled) && ! empty($conf->global->USER_DEFAULT_WAREHOUSE)) // TODO What is goal of this. How it is used ? { print ''; } - if ((! empty($conf->salaries->enabled) && ! empty($user->rights->salaries->read)) + // Position/Job + print ''; + print ''; + + if ((! empty($conf->salaries->enabled) && ! empty($user->rights->salaries->read)) || (! empty($conf->hrm->enabled) && ! empty($user->rights->hrm->employee->read))) { $langs->load("salaries"); diff --git a/htdocs/user/class/user.class.php b/htdocs/user/class/user.class.php index 420f874cf71..0e945027c0e 100644 --- a/htdocs/user/class/user.class.php +++ b/htdocs/user/class/user.class.php @@ -1319,7 +1319,7 @@ class User extends CommonObject $this->db->begin(); // Cree et positionne $this->id - $result=$this->create($user); + $result=$this->create($user, 1); if ($result > 0) { $sql = "UPDATE ".MAIN_DB_PREFIX."user"; diff --git a/htdocs/webservices/admin/index.php b/htdocs/webservices/admin/index.php index 93467c2c964..dbe3082b5de 100644 --- a/htdocs/webservices/admin/index.php +++ b/htdocs/webservices/admin/index.php @@ -120,7 +120,7 @@ foreach($webservices as $name => $right) { if (!empty($right) && !verifCond($right)) continue; $url=DOL_MAIN_URL_ROOT.'/webservices/server_'.$name.'.php?wsdl'; - print img_picto('', 'object_globe.png').' '.$url."
    \n"; + print img_picto('', 'globe').' '.$url."
    \n"; } print '
    '; @@ -131,7 +131,7 @@ foreach($webservices as $name => $right) { if (!empty($right) && !verifCond($right)) continue; $url=DOL_MAIN_URL_ROOT.'/webservices/server_'.$name.'.php'; - print img_picto('', 'object_globe.png').' '.$url."
    \n"; + print img_picto('', 'globe').' '.$url."
    \n"; } print '
    '; diff --git a/htdocs/website/index.php b/htdocs/website/index.php index 777201707ad..2769fb33cd0 100644 --- a/htdocs/website/index.php +++ b/htdocs/website/index.php @@ -2064,7 +2064,7 @@ if (! GETPOST('hide_websitemenu')) print ''; $linktotestonwebserver = ''; - $linktotestonwebserver.= $langs->trans("TestDeployOnWeb", $virtualurl).' '.img_picto('', 'object_globe'); + $linktotestonwebserver.= $langs->trans("TestDeployOnWeb", $virtualurl).' '.img_picto('', 'globe'); $linktotestonwebserver.= ''; $htmltext = ''; if (empty($object->fk_default_home))
    '.$langs->trans("PostOrFunction").''; - if ($caneditfield) - { - print ''; - } - else - { - print ''; - print $object->job; - } - print '
    '.$langs->trans("DefaultWarehouse").''; print $formproduct->selectWarehouses($object->fk_warehouse, 'fk_warehouse', 'warehouseopen', 1); @@ -2664,7 +2748,21 @@ else print '
    '.$langs->trans("PostOrFunction").''; + if ($caneditfield) + { + print ''; + } + else + { + print ''; + print $object->job; + } + print '