diff --git a/.github/workflows/stale-issues-safe.yml b/.github/workflows/stale-issues-safe.yml index 55599654707..ed37c9aadc2 100644 --- a/.github/workflows/stale-issues-safe.yml +++ b/.github/workflows/stale-issues-safe.yml @@ -16,7 +16,7 @@ jobs: repo-token: ${{ secrets.GITHUB_TOKEN }} stale-message: 'This issue is stale because it has been open 1 year with no activity. If this is a bug, please comment to confirm it is still present on latest stable version. if this is a feature request, please comment to notify the request is still relevant and not yet covered by latest stable version. This issue may be closed automatically by stale bot in 15 days (you should still be able to re-open it if required).' stale-label: 'Issue Stale (automatic label)' - exempt-labels: 'Priority High / Blocking,Priority Top Strategic,Priority Medium,Hacktoberfest,good first issue,Bug Security (CVE)' + exempt-labels: 'Priority High / Blocking,Priority Top Strategic,Priority Medium,Hacktoberfest,good first issue,Bug Security (CVE),Analysis of PR in progres' days-before-stale: 365 days-before-close: 15 operations-per-run: 100 diff --git a/htdocs/admin/index.php b/htdocs/admin/index.php index cf4b5f9e9bc..c3ce7724752 100644 --- a/htdocs/admin/index.php +++ b/htdocs/admin/index.php @@ -91,14 +91,6 @@ print '
'; // Show info setup module print img_picto('', 'puce').' '.$langs->trans("SetupDescription4", DOL_URL_ROOT.'/admin/modules.php?mainmenu=home', $langs->transnoentities("Setup"), $langs->transnoentities("Modules")); - -/* -$nbofactivatedmodules=count($conf->modules); -$moreinfo=$langs->trans("TotalNumberOfActivatedModules",($nbofactivatedmodules-1), count($modules)); -if ($nbofactivatedmodules <= 1) $moreinfo .= ' '.img_warning($langs->trans("YouMustEnableOneModule")); -print '
'.$moreinfo; -*/ - if (count($conf->modules) <= (empty($conf->global->MAIN_MIN_NB_ENABLED_MODULE_FOR_WARNING) ? 1 : $conf->global->MAIN_MIN_NB_ENABLED_MODULE_FOR_WARNING)) // If only user module enabled { $langs->load("errors"); diff --git a/htdocs/admin/user.php b/htdocs/admin/user.php index 56602502715..fb15a57a87e 100644 --- a/htdocs/admin/user.php +++ b/htdocs/admin/user.php @@ -147,13 +147,13 @@ dol_fiche_head($head, 'card', $langs->trans("MenuUsersAndGroups"), -1, 'user'); print ''; print ''; -print ''; +print ''; print ''; print ''."\n"; print ''; -// Mail required for members +// Mail required for users print ''; print ''; @@ -206,6 +206,8 @@ else dol_print_error($db); } +print load_fiche_titre($langs->trans("UsersDocModules"), '', ''); + print '
'.$langs->trans("Description").''.$langs->trans("Parameter").' '.$langs->trans("Value").'
'.$langs->trans("UserMailRequired").'
'; print ''; print ''; diff --git a/htdocs/admin/usergroup.php b/htdocs/admin/usergroup.php index 43910bedb56..4f556ff19b3 100644 --- a/htdocs/admin/usergroup.php +++ b/htdocs/admin/usergroup.php @@ -152,6 +152,8 @@ else dol_print_error($db); } +print load_fiche_titre($langs->trans("GroupsDocModules"), '', ''); + print '
'.$langs->trans("Name").'
'; print ''; print ''; diff --git a/htdocs/categories/class/categorie.class.php b/htdocs/categories/class/categorie.class.php index e8296b96beb..2e8afdb0089 100644 --- a/htdocs/categories/class/categorie.class.php +++ b/htdocs/categories/class/categorie.class.php @@ -243,7 +243,49 @@ class Categorie extends CommonObject */ public function __construct($db) { + global $hookmanager; + $this->db = $db; + + if (is_object($hookmanager)) { + $hookmanager->initHooks(array('category')); + $parameters = array(); + $reshook = $hookmanager->executeHooks('constructCategory', $parameters, $this); // Note that $action and $object may have been modified by some hooks + if ($reshook >= 0 && !empty($hookmanager->resArray)) { + $mapList = $hookmanager->resArray; + $mapId = $mapList['id']; + $mapCode = $mapList['code']; + self::$MAP_ID_TO_CODE[$mapId] = $mapCode; + $this->MAP_ID[$mapCode] = $mapId; + $this->MAP_CAT_FK[$mapCode] = $mapList['cat_fk']; + $this->MAP_CAT_TABLE[$mapCode] = $mapList['cat_table']; + $this->MAP_OBJ_CLASS[$mapCode] = $mapList['obj_class']; + $this->MAP_OBJ_TABLE[$mapCode] = $mapList['obj_table']; + } + } + } + + /** + * Get map list + * + * @return array + */ + public function getMapList() + { + $mapList = array(); + + foreach ($this->MAP_ID as $mapCode => $mapId) { + $mapList[] = array( + 'id' => $mapId, + 'code' => $mapCode, + 'cat_fk' => $this->MAP_CAT_FK[$mapCode], + 'cat_table' => $this->MAP_CAT_TABLE[$mapCode], + 'obj_class' => $this->MAP_OBJ_CLASS[$mapCode], + 'obj_table' => $this->MAP_OBJ_TABLE[$mapCode] + ); + } + + return $mapList; } /** diff --git a/htdocs/categories/index.php b/htdocs/categories/index.php index d96fddca150..54a4ff9f1d2 100644 --- a/htdocs/categories/index.php +++ b/htdocs/categories/index.php @@ -40,6 +40,7 @@ $id = GETPOST('id', 'int'); $type = (GETPOST('type', 'aZ09') ? GETPOST('type', 'aZ09') : Categorie::TYPE_PRODUCT); $catname = GETPOST('catname', 'alpha'); +$categstatic = new Categorie($db); if (is_numeric($type)) $type = Categorie::$MAP_ID_TO_CODE[$type]; // For backward compatibility @@ -47,25 +48,13 @@ if (is_numeric($type)) $type = Categorie::$MAP_ID_TO_CODE[$type]; // For backwar * View */ -$categstatic = new Categorie($db); $form = new Form($db); -if ($type == Categorie::TYPE_PRODUCT) { $title=$langs->trans("ProductsCategoriesArea"); $typetext='product'; } -elseif ($type == Categorie::TYPE_SUPPLIER) { $title=$langs->trans("SuppliersCategoriesArea"); $typetext='supplier'; } -elseif ($type == Categorie::TYPE_CUSTOMER) { $title=$langs->trans("CustomersCategoriesArea"); $typetext='customer'; } -elseif ($type == Categorie::TYPE_MEMBER) { $title=$langs->trans("MembersCategoriesArea"); $typetext='member'; } -elseif ($type == Categorie::TYPE_CONTACT) { $title=$langs->trans("ContactsCategoriesArea"); $typetext='contact'; } -elseif ($type == Categorie::TYPE_ACCOUNT) { $title=$langs->trans("AccountsCategoriesArea"); $typetext='bank_account'; } -elseif ($type == Categorie::TYPE_PROJECT) { $title=$langs->trans("ProjectsCategoriesArea"); $typetext='project'; } -elseif ($type == Categorie::TYPE_USER) { $title=$langs->trans("UsersCategoriesArea"); $typetext='user'; } -elseif ($type == Categorie::TYPE_WAREHOUSE) { $title=$langs->trans("StocksCategoriesArea"); $typetext='warehouse'; } -elseif ($type == Categorie::TYPE_ACTIONCOMM) { - $title = $langs->trans("ActionCommCategoriesArea"); - $typetext = 'actioncomm'; -} else { - $title = $langs->trans("CategoriesArea"); - $typetext = 'unknown'; -} +$typetext = $type; +if ($type == Categorie::TYPE_ACCOUNT) $title = $langs->trans('AccountsCategoriesArea'); +elseif ($type == Categorie::TYPE_WAREHOUSE) $title = $langs->trans('StocksCategoriesArea'); +elseif ($type == Categorie::TYPE_ACTIONCOMM) $title = $langs->trans('ActionCommCategoriesArea'); +else $title = $langs->trans(ucfirst($type). 'sCategoriesArea'); $arrayofjs=array('/includes/jquery/plugins/jquerytreeview/jquery.treeview.js', '/includes/jquery/plugins/jquerytreeview/lib/jquery.cookie.js'); $arrayofcss=array('/includes/jquery/plugins/jquerytreeview/jquery.treeview.css'); diff --git a/htdocs/categories/photos.php b/htdocs/categories/photos.php index ed6091e3568..b9fd23c1a3d 100644 --- a/htdocs/categories/photos.php +++ b/htdocs/categories/photos.php @@ -36,15 +36,13 @@ require_once DOL_DOCUMENT_ROOT.'/core/lib/categories.lib.php'; $langs->loadlangs(array('categories', 'bills')); -$id = GETPOST('id', 'int'); -$ref = GETPOST('ref'); -$type = GETPOST('type'); -$action = GETPOST('action', 'aZ09'); +$id = GETPOST('id', 'int'); +$label = GETPOST('label', 'alpha'); +$type = GETPOST('type'); +$action = GETPOST('action', 'aZ09'); $confirm = GETPOST('confirm'); -if (is_numeric($type)) $type = Categorie::$MAP_ID_TO_CODE[$type]; // For backward compatibility - -if ($id == "") +if ($id == '' && $label == '') { dol_print_error('', 'Missing parameter id'); exit(); @@ -54,13 +52,17 @@ if ($id == "") $result = restrictedArea($user, 'categorie', $id, '&category'); $object = new Categorie($db); -if ($id > 0) -{ - $result = $object->fetch($id); - - $upload_dir = $conf->categorie->multidir_output[$object->entity]; +$result = $object->fetch($id, $label, $type); +if ($result <= 0) { + dol_print_error($db, $object->error); exit; } +$object->fetch_optionals(); +if ($result <= 0) { + dol_print_error($db, $object->error); exit; +} +$upload_dir = $conf->categorie->multidir_output[$object->entity]; +if (is_numeric($type)) $type = Categorie::$MAP_ID_TO_CODE[$type]; // For backward compatibility /* * Actions @@ -126,7 +128,7 @@ if ($object->id) dol_fiche_head($head, 'photos', $title, -1, 'category'); $linkback = ''.$langs->trans("BackToList").''; - + $object->next_prev_filter = ' type = ' . $object->type; $object->ref = $object->label; $morehtmlref='
'.$langs->trans("Root").' >> '; $ways = $object->print_all_ways(" >> ", '', 1); @@ -136,7 +138,7 @@ if ($object->id) } $morehtmlref.='
'; - dol_banner_tab($object, 'ref', $linkback, ($user->socid?0:1), 'ref', 'ref', $morehtmlref, '', 0, '', '', 1); + dol_banner_tab($object, 'label', $linkback, ($user->socid?0:1), 'label', 'label', $morehtmlref, '&type=' . $type, 0, '', '', 1); /* * Confirmation de la suppression de photo diff --git a/htdocs/categories/traduction.php b/htdocs/categories/traduction.php index 03ca6e977bd..697db116881 100644 --- a/htdocs/categories/traduction.php +++ b/htdocs/categories/traduction.php @@ -36,18 +36,12 @@ require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php'; $langs->loadLangs(array('categories', 'languages')); $id = GETPOST('id', 'int'); -$ref = GETPOST('ref', 'alpha'); +$label = GETPOST('label', 'alpha'); $action = GETPOST('action', 'alpha'); $cancel = GETPOST('cancel', 'alpha'); $type = GETPOST('type', 'aZ09'); -if (is_numeric($type)) $type = Categorie::$MAP_ID_TO_CODE[$type]; // For backward compatibility - -// Security check -$fieldvalue = (!empty($id) ? $id : (!empty($ref) ? $ref : '')); -$fieldtype = (!empty($ref) ? 'ref' : 'rowid'); - -if ($id == "") +if ($id == '' && $label == '') { dol_print_error('', 'Missing parameter id'); exit(); @@ -57,7 +51,16 @@ if ($id == "") $result = restrictedArea($user, 'categorie', $id, '&category'); $object = new Categorie($db); +$result = $object->fetch($id, $label, $type); +if ($result <= 0) { + dol_print_error($db, $object->error); exit; +} +$object->fetch_optionals(); +if ($result <= 0) { + dol_print_error($db, $object->error); exit; +} +if (is_numeric($type)) $type = Categorie::$MAP_ID_TO_CODE[$type]; // For backward compatibility /* * Actions @@ -159,8 +162,6 @@ $cancel != $langs->trans("Cancel") && } } -$result = $object->fetch($id, $ref); - /* * View @@ -197,7 +198,7 @@ if (!empty($object->multilangs)) dol_fiche_head($head, 'translation', $title, -1, 'category'); $linkback = ''.$langs->trans("BackToList").''; - +$object->next_prev_filter = ' type = ' . $object->type; $object->ref = $object->label; $morehtmlref = '
'.$langs->trans("Root").' >> '; $ways = $object->print_all_ways(" >> ", '', 1); @@ -207,7 +208,7 @@ foreach ($ways as $way) } $morehtmlref .= '
'; -dol_banner_tab($object, 'ref', $linkback, ($user->socid ? 0 : 1), 'ref', 'ref', $morehtmlref, '', 0, '', '', 1); +dol_banner_tab($object, 'label', $linkback, ($user->socid ? 0 : 1), 'label', 'label', $morehtmlref, '&type=' . $type, 0, '', '', 1); print '
'; diff --git a/htdocs/categories/viewcat.php b/htdocs/categories/viewcat.php index 62538da0273..727ef8b0610 100644 --- a/htdocs/categories/viewcat.php +++ b/htdocs/categories/viewcat.php @@ -71,7 +71,7 @@ if ($id == "" && $label == "") $result = restrictedArea($user, 'categorie', $id, '&category'); $object = new Categorie($db); -$result = $object->fetch($id, $label); +$result = $object->fetch($id, $label, $type); if ($result <= 0) { dol_print_error($db, $object->error); exit; } @@ -80,7 +80,6 @@ if ($result <= 0) { dol_print_error($db, $object->error); exit; } -$type = $object->type; if (is_numeric($type)) $type = Categorie::$MAP_ID_TO_CODE[$type]; // For backward compatibility $extrafields = new ExtraFields($db); @@ -222,8 +221,8 @@ $head = categories_prepare_head($object, $type); dol_fiche_head($head, 'card', $title, -1, 'category'); $backtolist = (GETPOST('backtolist') ? GETPOST('backtolist') : DOL_URL_ROOT.'/categories/index.php?leftmenu=cat&type='.$type); -$linkback = ''.$langs->trans("BackToList").''; -$object->next_prev_filter=" type = ".$object->type; +$linkback = ''.$langs->trans("BackToList").''; +$object->next_prev_filter = ' type = ' . $object->type; $object->ref = $object->label; $morehtmlref='
'.$langs->trans("Root").' >> '; $ways = $object->print_all_ways(" >> ", '', 1); @@ -233,7 +232,7 @@ foreach ($ways as $way) } $morehtmlref.='
'; -dol_banner_tab($object, 'label', $linkback, ($user->socid?0:1), 'label', 'label', $morehtmlref, '', 0, '', '', 1); +dol_banner_tab($object, 'label', $linkback, ($user->socid?0:1), 'label', 'label', $morehtmlref, '&type=' . $type, 0, '', '', 1); /* diff --git a/htdocs/conf/conf.php.example b/htdocs/conf/conf.php.example index a742c5c45fd..32c37301a0e 100644 --- a/htdocs/conf/conf.php.example +++ b/htdocs/conf/conf.php.example @@ -218,7 +218,7 @@ $dolibarr_main_authentication='dolibarr'; // 0 = No forced redirect // 1 = Force redirect to https, until SCRIPT_URI start with https into response // 2 = Force redirect to https, until SERVER["HTTPS"] is 'on' into response -// 'https://my.domain.com' = Force reditect to https using this domain name. +// 'https://my.domain.com' = Force redirect to https using this domain name. // Warning: If you enable this parameter, your web server must be configured to // respond URL with https protocol. // According to your web server setup, some values may works and other not. Try @@ -226,7 +226,7 @@ $dolibarr_main_authentication='dolibarr'; // Default value: 0 // Possible values: 0, 1, 2 or 'https://my.domain.com' // Examples: -// $dolibarr_main_force_https='0'; +// $dolibarr_main_force_https='1'; // $dolibarr_main_force_https='0'; diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index 2c22e83f786..f3615d4180f 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -316,6 +316,33 @@ class Form return $ret; } + /** + * Output edit in place form + * + * @param string $fieldname Name of the field + * @param object $object Object + * @param boolean $perm Permission to allow button to edit parameter. Set it to 0 to have a not edited field. + * @param string $typeofdata Type of data ('string' by default, 'email', 'amount:99', 'numeric:99', 'text' or 'textarea:rows:cols', 'datepicker' ('day' do not work, don't know why), 'ckeditor:dolibarr_zzz:width:height:savemethod:1:rows:cols', 'select;xxx[:class]'...) + * @return string HTML code for the edit of alternative language + */ + public function widgetForTranslation($fieldname, $object, $perm, $typeofdata = 'string') + { + global $conf, $langs; + + $result = ''; + + if (! empty($conf->global->PDF_USE_ALSO_LANGUAGE_CODE)) { + $result ='
'; + + $s=picto_from_langcode($conf->global->PDF_USE_ALSO_LANGUAGE_CODE); + $result .= $s; + + $result .= '
'; + } + + return $result; + } + /** * Output edit in place form * @@ -3514,11 +3541,11 @@ class Form * Return list of payment methods * Constant MAIN_DEFAULT_PAYMENT_TYPE_ID can used to set default value but scope is all application, probably not what you want. * - * @param string $selected Id du mode de paiement pre-selectionne - * @param string $htmlname Nom de la zone select + * @param string $selected Id or code or preselected payment mode + * @param string $htmlname Name of select field * @param string $filtertype To filter on field type in llx_c_paiement ('CRDT' or 'DBIT' or array('code'=>xx,'label'=>zz)) - * @param int $format 0=id+libelle, 1=code+code, 2=code+libelle, 3=id+code - * @param int $empty 1=peut etre vide, 0 sinon + * @param int $format 0=id+label, 1=code+code, 2=code+label, 3=id+code + * @param int $empty 1=can be empty, 0 otherwise * @param int $noadmininfo 0=Add admin info, 1=Disable admin info * @param int $maxlength Max length of label * @param int $active Active or not, -1 = all @@ -3559,9 +3586,12 @@ class Form elseif ($format == 1) print ''; print '
'.$langs->trans("Name").'
'; } - - - -/** - * Return HTML content to add structured data for an article, news or Blog Post. - * - * @return string HTML content - */ -function getRSSForBlogPosts() -{ - global $conf, $db, $hookmanager, $langs, $mysoc, $user, $website, $websitepage, $weblangs; // Very important. Required to have var available when running inluded containers. - - - - return $out; -} - - diff --git a/htdocs/core/lib/xcal.lib.php b/htdocs/core/lib/xcal.lib.php index 4aba32007bf..ef81ecda5bf 100644 --- a/htdocs/core/lib/xcal.lib.php +++ b/htdocs/core/lib/xcal.lib.php @@ -336,7 +336,7 @@ function build_calfile($format, $title, $desc, $events_array, $outputfile) * @param string $url Url * @return int < 0 if ko, Nb of events in file if ok */ -function build_rssfile($format, $title, $desc, $events_array, $outputfile, $filter = "", $url="") +function build_rssfile($format, $title, $desc, $events_array, $outputfile, $filter = '', $url = '') { global $user, $conf, $langs; global $dolibarr_main_url_root; @@ -534,7 +534,7 @@ function calEncode($line) // Take char at position $j $char = substr($line, $j, 1); - if ((dol_strlen($newpara) + dol_strlen($char)) >= 75 ) + if ((dol_strlen($newpara) + dol_strlen($char)) >= 75) { // CRLF + Space for cal $out .= $newpara . "\r\n "; diff --git a/htdocs/fourn/commande/card.php b/htdocs/fourn/commande/card.php index c8706d1b22e..302cf3b47b7 100644 --- a/htdocs/fourn/commande/card.php +++ b/htdocs/fourn/commande/card.php @@ -55,7 +55,7 @@ if (!empty($conf->variants->enabled)) { require_once DOL_DOCUMENT_ROOT.'/variants/class/ProductCombination.class.php'; } -$langs->loadLangs(array('admin', 'orders', 'sendings', 'companies', 'bills', 'propal', 'supplier_proposal', 'deliveries', 'products', 'stocks', 'productbatch')); +$langs->loadLangs(array('admin', 'orders', 'sendings', 'companies', 'bills', 'propal', 'receptions', 'supplier_proposal', 'deliveries', 'products', 'stocks', 'productbatch')); if (!empty($conf->incoterm->enabled)) $langs->load('incoterm'); $id = GETPOST('id', 'int'); @@ -2483,11 +2483,14 @@ elseif (!empty($object->id)) if (!empty($conf->stock->enabled) && (!empty($conf->global->STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER) || !empty($conf->global->STOCK_CALCULATE_ON_RECEPTION) || !empty($conf->global->STOCK_CALCULATE_ON_RECEPTION_CLOSE))) { + $labelofbutton = $langs->trans('ReceiveProducts'); + if ($conf->reception->enabled) $labelofbutton = $langs->trans("CreateReception"); + if (in_array($object->statut, array(3, 4, 5))) { if ($conf->fournisseur->enabled && $user->rights->fournisseur->commande->receptionner) { - print '
'.$langs->trans('ReceiveProducts').'
'; + print '
'.$labelofbutton.'
'; } else { - print '
'.$langs->trans('ReceiveProducts').'
'; + print '
'.$labelofbutton.'
'; } } } diff --git a/htdocs/fourn/commande/dispatch.php b/htdocs/fourn/commande/dispatch.php index dd55bb36ffb..cc38abfc935 100644 --- a/htdocs/fourn/commande/dispatch.php +++ b/htdocs/fourn/commande/dispatch.php @@ -379,7 +379,7 @@ $warehouse_static = new Entrepot($db); $supplierorderdispatch = new CommandeFournisseurDispatch($db); $help_url = 'EN:Module_Suppliers_Orders|FR:CommandeFournisseur|ES:Módulo_Pedidos_a_proveedores'; -llxHeader('', $langs->trans("Order"), $help_url, '', 0, 0, array('/fourn/js/lib_dispatch.js')); +llxHeader('', $langs->trans("Order"), $help_url, '', 0, 0, array('/fourn/js/lib_dispatch.js.php')); if ($id > 0 || !empty($ref)) { $soc = new Societe($db); @@ -807,15 +807,13 @@ if ($id > 0 || !empty($ref)) { print ''; if (! empty($conf->productbatch->enabled) && $objp->tobatch == 1) { $type = 'batch'; - //print img_picto($langs->trans('AddDispatchBatchLine'), 'split.png', 'class="splitbutton" onClick="addDispatchLine(' . $i . ',\'' . $type . '\')"'); - print img_picto($langs->trans('AddStockLocationLine'), 'split.png', 'class="splitbutton" onClick="addDispatchLine(' . $i . ',\'' . $type . '\')"'); + print img_picto($langs->trans('AddStockLocationLine'), 'split.png', 'class="splitbutton" onClick="addDispatchLine('.$i.', \''.$type.'\')"'); } else { $type = 'dispatch'; - print img_picto($langs->trans('AddStockLocationLine'), 'split.png', 'class="splitbutton" onClick="addDispatchLine(' . $i . ',\'' . $type . '\')"'); + print img_picto($langs->trans('AddStockLocationLine'), 'split.png', 'class="splitbutton" onClick="addDispatchLine('.$i.', \''.$type.'\')"'); } - print ''; if (! empty($conf->global->SUPPLIER_ORDER_CAN_UPDATE_BUYINGPRICE_DURING_RECEIPT)) { @@ -894,7 +892,8 @@ if ($id > 0 || !empty($ref)) { print ' '.$checkboxlabel; } - empty($conf->reception->enabled) ? $dispatchBt = $langs->trans("DispatchVerb") : $dispatchBt = $langs->trans("Receive"); + + $dispatchBt = empty($conf->reception->enabled) ? $langs->trans("Receive") : $langs->trans("CreateReception"); print '
// Copyright (C) 2017 Francis Appels // @@ -15,14 +16,33 @@ // along with this program. If not, see . // or see https://www.gnu.org/ -// -// \file htdocs/core/js/lib_dispatch.js -// \brief File that include javascript functions used dispatch.php -// +/** + * \file htdocs/fourn/js/lib_dispatch.js.php + * \brief File that include javascript functions used for dispatching qty/stock/lot + */ +if (! defined('NOREQUIRESOC')) define('NOREQUIRESOC', '1'); +if (! defined('NOCSRFCHECK')) define('NOCSRFCHECK', 1); +if (! defined('NOTOKENRENEWAL')) define('NOTOKENRENEWAL', 1); +if (! defined('NOLOGIN')) define('NOLOGIN', 1); +if (! defined('NOREQUIREMENU')) define('NOREQUIREMENU', 1); +if (! defined('NOREQUIREHTML')) define('NOREQUIREHTML', 1); +if (! defined('NOREQUIREAJAX')) define('NOREQUIREAJAX', '1'); + +session_cache_limiter('public'); + +require_once '../../main.inc.php'; + +// Define javascript type +top_httphead('text/javascript; charset=UTF-8'); +// Important: Following code is to avoid page request by browser and PHP CPU at each Dolibarr page access. +if (empty($dolibarr_nocache)) header('Cache-Control: max-age=10800, public, must-revalidate'); +else header('Cache-Control: no-cache'); + +?> /** * addDispatchLine - * Adds new table row for dispatching to multiple stock locations + * Adds new table row for dispatching to multiple stock locations or multiple lot/serial * * @param index int index of product line. 0 = first product line * @param type string type of dispatch (batch = batch dispatch, dispatch = non batch dispatch) @@ -32,12 +52,12 @@ function addDispatchLine(index, type, mode) { mode = mode || 'qtymissing' - console.log("fourn/js/lib_dispatch.js Split line type="+type+" index="+index+" mode="+mode); - var $row = $("tr[name='"+type+'_0_'+index+"']").clone(true), // clone first batch line to jQuery object - nbrTrs = $("tr[name^='"+type+"_'][name$='_"+index+"']").length, // position of line for batch - qtyOrdered = parseFloat($("#qty_ordered_0_"+index).val()), // Qty ordered is same for all rows - qty = parseFloat($("#qty_"+(nbrTrs - 1)+"_"+index).val()), - qtyDispatched; + console.log("fourn/js/lib_dispatch.js.php Split line type="+type+" index="+index+" mode="+mode); + var $row = $("tr[name='"+type+'_0_'+index+"']").clone(true); // clone first batch line to jQuery object + var nbrTrs = $("tr[name^='"+type+"_'][name$='_"+index+"']").length; // position of line for batch + var qtyOrdered = parseFloat($("#qty_ordered_0_"+index).val()); // Qty ordered is same for all rows + var qty = parseFloat($("#qty_"+(nbrTrs - 1)+"_"+index).val()); + var qtyDispatched; if (mode === 'lessone') { @@ -46,8 +66,17 @@ function addDispatchLine(index, type, mode) else { qtyDispatched = parseFloat($("#qty_dispatched_0_"+index).val()) + qty; + // If user did not reduced the qty to dispatch on old line, we keep only 1 on old line and the rest on new line + if (qtyDispatched == qtyOrdered && qtyDispatched > 1) { + qtyDispatched = parseFloat($("#qty_dispatched_0_"+index).val()) + 1; + mode = 'lessone'; + } } + console.log("qtyDispatched="+qtyDispatched+" qtyOrdered="+qtyOrdered); + if (qtyOrdered <= 1) { + window.alert("Quantity can't be split"); + } if (qtyDispatched < qtyOrdered) { //replace tr suffix nbr @@ -97,7 +126,7 @@ function addDispatchLine(index, type, mode) * * Change event handler for dispatch qty input field, * recalculate qty dispatched when qty input has changed. - * If qty is more then qty ordered reset input qty to max qty to dispatch. + * If qty is more than qty ordered reset input qty to max qty to dispatch. * * element requires arbitrary data qty (value before change), type (type of dispatch) and index (index of product line) */ diff --git a/htdocs/install/mysql/migration/11.0.0-12.0.0.sql b/htdocs/install/mysql/migration/11.0.0-12.0.0.sql index b2d0b9b0bd1..dfbbc4d2e19 100644 --- a/htdocs/install/mysql/migration/11.0.0-12.0.0.sql +++ b/htdocs/install/mysql/migration/11.0.0-12.0.0.sql @@ -193,8 +193,9 @@ ALTER TABLE llx_accounting_account DROP COLUMN pcg_subtype; ALTER TABLE llx_product ADD COLUMN accountancy_code_buy_intra varchar(32) AFTER accountancy_code_buy; ALTER TABLE llx_product ADD COLUMN accountancy_code_buy_export varchar(32) AFTER accountancy_code_buy_intra; -ALTER TABLE llx_entrepot ADD COLUMN fax varchar(20) DEFAULT NULL AFTER fk_pays; -ALTER TABLE llx_entrepot ADD COLUMN phone varchar(20) DEFAULT NULL AFTER fk_pays; +ALTER TABLE llx_entrepot ADD COLUMN fax varchar(20) DEFAULT NULL; +ALTER TABLE llx_entrepot ADD COLUMN phone varchar(20) DEFAULT NULL; ALTER TABLE llx_accounting_account ADD COLUMN reconcilable tinyint DEFAULT 0 NOT NULL after active; +ALTER TABLE llx_categorie MODIFY type integer NOT NULL DEFAULT 1; diff --git a/htdocs/install/mysql/tables/llx_categorie.sql b/htdocs/install/mysql/tables/llx_categorie.sql index ed1cb828363..c57c2adaa10 100644 --- a/htdocs/install/mysql/tables/llx_categorie.sql +++ b/htdocs/install/mysql/tables/llx_categorie.sql @@ -26,7 +26,7 @@ create table llx_categorie fk_parent integer DEFAULT 0 NOT NULL, label varchar(180) NOT NULL, -- category ref/name ref_ext varchar(255), -- reference into an external system (not used by dolibarr) - type tinyint DEFAULT 1 NOT NULL, -- category type (product, supplier, customer, member) + type integer DEFAULT 1 NOT NULL, -- category type (product, supplier, customer, member) description text, -- description of the category color varchar(8), -- color fk_soc integer DEFAULT NULL, -- not used by default. Used when option CATEGORY_ASSIGNED_TO_A_CUSTOMER is set. diff --git a/htdocs/langs/en_US/admin.lang b/htdocs/langs/en_US/admin.lang index 62119428b9a..7e46cdefbad 100644 --- a/htdocs/langs/en_US/admin.lang +++ b/htdocs/langs/en_US/admin.lang @@ -1108,8 +1108,8 @@ Delays_MAIN_DELAY_EXPENSEREPORTS=Expense report to approve Delays_MAIN_DELAY_HOLIDAYS=Leave requests to approve SetupDescription1=Before starting to use Dolibarr some initial parameters must be defined and modules enabled/configured. SetupDescription2=The following two sections are mandatory (the two first entries in the Setup menu): -SetupDescription3=%s -> %s
Basic parameters used to customize the default behavior of your application (e.g for country-related features). -SetupDescription4=%s -> %s
This software is a suite of many modules/applications, all more or less independent. The modules relevant to your needs must be enabled and configured. New items/options are added to menus with the activation of a module. +SetupDescription3=%s -> %s

Basic parameters used to customize the default behavior of your application (e.g for country-related features). +SetupDescription4=%s -> %s

This software is a suite of many modules/applications, all more or less independent. The modules relevant to your needs must be enabled and configured. New items/options are added to menus with the activation of a module. SetupDescription5=Other Setup menu entries manage optional parameters. LogEvents=Security audit events Audit=Audit @@ -1264,6 +1264,8 @@ RuleForGeneratedPasswords=Rules to generate and validate passwords DisableForgetPasswordLinkOnLogonPage=Do not show the "Password Forgotten" link on the Login page UsersSetup=Users module setup UserMailRequired=Email required to create a new user +UsersDocModules=Document templates for documents generated from user record +GroupsDocModules=Document templates for documents generated from a group record ##### HRM setup ##### HRMSetup=HRM module setup ##### Company setup ##### @@ -1980,5 +1982,5 @@ MakeAnonymousPing=Make an anonymous Ping '+1' to the Dolibarr foundation server FeatureNotAvailableWithReceptionModule=Feature not available when module Reception is enabled EmailTemplate=Template for email EMailsWillHaveMessageID=Emails will have a tag 'References' matching this syntax -PDF_USE_ALSO_LANGUAGE_CODE=If you want to have some text title in your PDF duplicated in 2 different languages in the same generate PDF, you must set here this second language so generated PDF will contains 2 different languages in same page, the one chosen when generating PDF and this one (only few PDF templates support this). Keep empty for 1 language per PDF. +PDF_USE_ALSO_LANGUAGE_CODE=If you want to have some texts in your PDF duplicated in 2 different languages in the same generated PDF, you must set here this second language so generated PDF will contains 2 different languages in same page, the one chosen when generating PDF and this one (only few PDF templates support this). Keep empty for 1 language per PDF. FafaIconSocialNetworksDesc=Enter here the code of a FontAwesome icon. If you don't know what is FontAwesome, you can use the generic value fa-address-book. diff --git a/htdocs/main.inc.php b/htdocs/main.inc.php index 1cea53ae2a7..8d3812d5553 100644 --- a/htdocs/main.inc.php +++ b/htdocs/main.inc.php @@ -210,7 +210,7 @@ $sessionname = 'DOLSESSID_'.$prefix; $sessiontimeout = 'DOLSESSTIMEOUT_'.$prefix; if (!empty($_COOKIE[$sessiontimeout])) ini_set('session.gc_maxlifetime', $_COOKIE[$sessiontimeout]); session_name($sessionname); -session_set_cookie_params(0, '/', null, false, true); // Add tag httponly on session cookie (same as setting session.cookie_httponly into php.ini). Must be called before the session_start. +session_set_cookie_params(0, '/', null, (empty($dolibarr_main_force_https) ? false : true), true); // Add tag secure and httponly on session cookie (same as setting session.cookie_httponly into php.ini). Must be called before the session_start. // This create lock, released when session_write_close() or end of page. // We need this lock as long as we read/write $_SESSION ['vars']. We can remove lock when finished. if (!defined('NOSESSION')) @@ -257,7 +257,7 @@ if (isset($_SERVER["HTTP_USER_AGENT"])) } -// Force HTTPS if required ($conf->file->main_force_https is 0/1 or https dolibarr root url) +// Force HTTPS if required ($conf->file->main_force_https is 0/1 or 'https dolibarr root url') // $_SERVER["HTTPS"] is 'on' when link is https, otherwise $_SERVER["HTTPS"] is empty or 'off' if (!empty($conf->file->main_force_https) && (empty($_SERVER["HTTPS"]) || $_SERVER["HTTPS"] != 'on')) { @@ -284,6 +284,7 @@ if (!empty($conf->file->main_force_https) && (empty($_SERVER["HTTPS"]) || $_SERV // Start redirect if ($newurl) { + header_remove(); // Clean header already set to be sure to remove any header like "Set-Cookie: DOLSESSID_..." from non HTTPS answers dol_syslog("main.inc: dolibarr_main_force_https is on, we make a redirect to ".$newurl); header("Location: ".$newurl); exit; @@ -625,7 +626,7 @@ if (!defined('NOLOGIN')) dol_syslog('User not found, connexion refused'); session_destroy(); session_name($sessionname); - session_set_cookie_params(0, '/', null, false, true); // Add tag httponly on session cookie + session_set_cookie_params(0, '/', null, (empty($dolibarr_main_force_https) ? false : true), true); // Add tag secure and httponly on session cookie session_start(); if ($resultFetchUser == 0) @@ -682,7 +683,7 @@ if (!defined('NOLOGIN')) dol_syslog("Can't load user even if session logged. _SESSION['dol_login']=".$login, LOG_WARNING); session_destroy(); session_name($sessionname); - session_set_cookie_params(0, '/', null, false, true); // Add tag httponly on session cookie + session_set_cookie_params(0, '/', null, (empty($dolibarr_main_force_https) ? false : true), true); // Add tag secure and httponly on session cookie session_start(); if ($resultFetchUser == 0) diff --git a/htdocs/mrp/js/lib_dispatch.js.php b/htdocs/mrp/js/lib_dispatch.js.php new file mode 100644 index 00000000000..dc7c079a024 --- /dev/null +++ b/htdocs/mrp/js/lib_dispatch.js.php @@ -0,0 +1,136 @@ + +// Copyright (C) 2017 Francis Appels +// +// 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 . +// or see https://www.gnu.org/ + +/** + * \file htdocs/mrp/js/lib_dispatch.js.php + * \brief File that include javascript functions used for dispatching qty/stock/lot + */ + +if (! defined('NOREQUIRESOC')) define('NOREQUIRESOC', '1'); +if (! defined('NOCSRFCHECK')) define('NOCSRFCHECK', 1); +if (! defined('NOTOKENRENEWAL')) define('NOTOKENRENEWAL', 1); +if (! defined('NOLOGIN')) define('NOLOGIN', 1); +if (! defined('NOREQUIREMENU')) define('NOREQUIREMENU', 1); +if (! defined('NOREQUIREHTML')) define('NOREQUIREHTML', 1); +if (! defined('NOREQUIREAJAX')) define('NOREQUIREAJAX', '1'); + +session_cache_limiter('public'); + +require_once '../../main.inc.php'; + +// Define javascript type +top_httphead('text/javascript; charset=UTF-8'); +// Important: Following code is to avoid page request by browser and PHP CPU at each Dolibarr page access. +if (empty($dolibarr_nocache)) header('Cache-Control: max-age=10800, public, must-revalidate'); +else header('Cache-Control: no-cache'); + +?> +/** + * addDispatchLine + * Adds new table row for dispatching to multiple stock locations or multiple lot/serial + * + * @param index int index of product line. 0 = first product line + * @param type string type of dispatch (batch = batch dispatch, dispatch = non batch dispatch) + * @param mode string 'qtymissing' will create new line with qty missing, 'lessone' will keep 1 in old line and the rest in new one + */ +function addDispatchLine(index, type, mode) +{ + mode = mode || 'qtymissing' + + console.log("fourn/js/lib_dispatch.js.php Split line type="+type+" index="+index+" mode="+mode); + var nbrTrs = $("tr[name^='"+type+"_"+index+"']").length; // position of line for batch + var $row = $("tr[name='"+type+'_'+index+"_1']").clone(true); // clone last batch line to jQuery object + var qtyOrdered = parseFloat($("#qty_ordered_"+index).val()); // Qty ordered is same for all rows + var qty = parseFloat($("#qtytoproduce-"+index+"-"+nbrTrs).val()); + var qtyDispatched; + + if (mode === 'lessone') + { + qtyDispatched = parseFloat($("#qty_dispatched_"+index).val()) + 1; + } + else + { + qtyDispatched = parseFloat($("#qty_dispatched_"+index).val()) + qty; + console.log(qty); + // If user did not reduced the qty to dispatch on old line, we keep only 1 on old line and the rest on new line + if (qtyDispatched == qtyOrdered && qtyDispatched > 1) { + qtyDispatched = parseFloat($("#qty_dispatched_"+index).val()) + 1; + mode = 'lessone'; + } + } + console.log("qtyDispatched="+qtyDispatched+" qtyOrdered="+qtyOrdered); + + if (qtyOrdered <= 1) { + window.alert("Quantity can't be split"); + } + if (qtyDispatched < qtyOrdered) + { + //replace tr suffix nbr + var re1 = new RegExp('_'+index+'_1', 'g'); + var re2 = new RegExp('-'+index+'-1', 'g'); + $row.html($row.html().replace(re1, '_'+index+'_'+(nbrTrs+1))); + $row.html($row.html().replace(re2, '-'+index+'-'+(nbrTrs+1))); + //create new select2 to avoid duplicate id of cloned one + $row.find("select[name='"+'idwarehousetoproduce-'+index+'-'+(nbrTrs+1)+"']").select2(); + // TODO find solution to copy selected option to new select + // TODO find solution to keep new tr's after page refresh + //clear value + $row.find("input[name^='qtytoproduce']").val(''); + //change name of new row + $row.attr('name',type+'_'+index+'_'+(nbrTrs+1)); + //insert new row before last row + $("tr[name^='"+type+"_"+index+"_"+nbrTrs+"']:last").after($row); + + //remove cloned select2 with duplicate id. + $("#s2id_entrepot_"+nbrTrs+'_'+index).detach(); // old way to find duplicated select2 component + $(".csswarehouse_"+index+"_"+(nbrTrs+1)+":first-child").parent("span.selection").parent(".select2").detach(); + + /* Suffix of lines are: index _ trs.length */ + $("#qtytoproduce-"+index+"-"+(nbrTrs+1)).focus(); + if ($("#qtytoproduce-"+index+"-"+(nbrTrs)).val() == 0) { + $("#qtytoproduce-"+index+"-"+(nbrTrs)).val(1); + } + var totalonallines = 0; + for (let i = 1; i <= nbrTrs; i++) { + console.log(i+" = "+parseFloat($("#qtytoproduce-"+index+"-"+i).val())); + totalonallines = totalonallines + parseFloat($("#qtytoproduce-"+index+"-"+i).val()); + } + console.log("totalonallines="+totalonallines); + if (totalonallines == qtyOrdered && qtyOrdered > 1) { + var prevouslineqty = $("#qtytoproduce-"+index+"-"+nbrTrs).val(); + $("#qtytoproduce-"+index+"-"+(nbrTrs)).val(1); + $("#qtytoproduce-"+index+"-"+(nbrTrs+1)).val(prevouslineqty - 1); + } + $("#qty_dispatched_"+index).val(qtyDispatched); + + //hide all buttons then show only the last one + $("tr[name^='"+type+"_'][name$='_"+index+"'] .splitbutton").hide(); + $("tr[name^='"+type+"_'][name$='_"+index+"']:last .splitbutton").show(); + + if (mode === 'lessone') + { + qty = 1; // keep 1 in old line + $("#qty_"+(nbrTrs-1)+"_"+index).val(qty); + } + // Store arbitrary data for dispatch qty input field change event + $("#qtytoproduce-"+index+(nbrTrs)).data('qty', qty); + $("#qtytoproduce-"+index+(nbrTrs)).data('type', type); + $("#qtytoproduce-"+index+(nbrTrs)).data('index', index); + } +} + diff --git a/htdocs/mrp/mo_production.php b/htdocs/mrp/mo_production.php index a065cc922fe..b25f5093cb9 100644 --- a/htdocs/mrp/mo_production.php +++ b/htdocs/mrp/mo_production.php @@ -57,7 +57,7 @@ dol_include_once('/mrp/class/mo.class.php'); dol_include_once('/mrp/lib/mrp_mo.lib.php'); // Load translation files required by the page -$langs->loadLangs(array("mrp", "stocks", "other")); +$langs->loadLangs(array("mrp", "stocks", "other", "productbatch")); // Get parameters $id = GETPOST('id', 'int'); @@ -397,7 +397,8 @@ $formproduct = new FormProduct($db); $tmpwarehouse = new Entrepot($db); $tmpbatch = new Productlot($db); -llxHeader('', $langs->trans('Mo'), ''); +$help_url = 'EN:Module_Manufacturing_Orders|FR:Module_Ordres_de_Fabrication'; +llxHeader('', $langs->trans('Mo'), $help_url, '', 0, 0, array('/mrp/js/lib_dispatch.js.php')); // Part to show record if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'create'))) @@ -621,11 +622,12 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea if (in_array($action, array('consumeorproduce', 'consumeandproduceall', 'addconsumeline'))) { - print '
'; + print ''; print ''; print ''; print ''; print ''; + // Note: closing form is add end of page if (in_array($action, array('consumeorproduce', 'consumeandproduceall'))) { $defaultstockmovementlabel = GETPOST('inventorylabel', 'alphanohtml') ? GETPOST('inventorylabel', 'alphanohtml') : $langs->trans("ProductionForRef", $object->ref); @@ -686,7 +688,7 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea print ''; print $form->select_produits('', 'productidtoadd', '', 0, 0, -1, 2, '', 0, array(), 0, '1', 0, 'maxwidth300'); print ''; - print ''; + print ''; print ''; print ''; print ''; @@ -773,8 +775,8 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea print ''.$line2['qty'].''; print ''; if ($line2['fk_warehouse'] > 0) { - $tmpwarehouse->fetch($line2['fk_warehouse']); - print $tmpwarehouse->getNomUrl(1); + $result = $tmpwarehouse->fetch($line2['fk_warehouse']); + if ($result > 0) print $tmpwarehouse->getNomUrl(1); } print ''; // Lot Batch @@ -793,7 +795,7 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea print ''.$langs->trans("ToConsume").''; $preselected = (GETPOSTISSET('qty-'.$line->id.'-'.$i) ? GETPOST('qty-'.$line->id.'-'.$i) : max(0, $line->qty - $alreadyconsumed)); if ($action == 'consumeorproduce' && !GETPOSTISSET('qty-'.$line->id.'-'.$i)) $preselected = 0; - print ''; + print ''; print ''; print ''; if ($tmpproduct->type == Product::TYPE_PRODUCT || !empty($conf->global->STOCK_SUPPORTS_SERVICES)) { @@ -845,6 +847,7 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea print ''; if ($collapse || in_array($action, array('consumeorproduce', 'consumeandproduceall'))) print $langs->trans("Batch"); print ''; + print ''; } print ''; @@ -860,6 +863,8 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea $nblinetoproducecursor = 0; foreach ($object->lines as $line) { if ($line->role == 'toproduce') { + $i=1; + $nblinetoproducecursor++; $tmpproduct = new Product($db); @@ -871,6 +876,12 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea $alreadyproduced += $line2['qty']; } + $suffix = '_'.$line->id; + print ''."\n"; + // hidden fields for js function + print ''; + print ''; + print ''; print ''.$tmpproduct->getNomUrl(1).''; print ''.$line->qty.''; @@ -898,6 +909,7 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea print ''; if ($conf->productbatch->enabled) { print ''; // Lot + print ''; } print ''; @@ -911,30 +923,33 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea print ''.$line2['qty'].''; print ''; if ($line2['fk_warehouse'] > 0) { - $tmpwarehouse->fetch($line2['fk_warehouse']); - print $tmpwarehouse->getNomUrl(1); + $result = $tmpwarehouse->fetch($line2['fk_warehouse']); + if ($result > 0) print $tmpwarehouse->getNomUrl(1); } print ''; - print ''; - if ($line2['batch'] != '') { - $tmpbatch->fetch(0, $line2['fk_product'], $line2['batch']); - print $tmpbatch->getNomUrl(1); + if ($conf->productbatch->enabled) { + print ''; + if ($line2['batch'] != '') { + $tmpbatch->fetch(0, $line2['fk_product'], $line2['batch']); + print $tmpbatch->getNomUrl(1); + } + print ''; + print ''; } - print ''; print ''; } if (in_array($action, array('consumeorproduce', 'consumeandproduceall'))) { - print ''; + print ''; print ''.$langs->trans("ToProduce").''; $preselected = (GETPOSTISSET('qtytoproduce-'.$line->id.'-'.$i) ? GETPOST('qtytoproduce-'.$line->id.'-'.$i) : max(0, $line->qty - $alreadyproduced)); if ($action == 'consumeorproduce' && !GETPOSTISSET('qtytoproduce-'.$line->id.'-'.$i)) $preselected = 0; - print ''; + print ''; print ''; print ''; if ($tmpproduct->type == Product::TYPE_PRODUCT || !empty($conf->global->STOCK_SUPPORTS_SERVICES)) { $preselected = (GETPOSTISSET('idwarehousetoproduce-'.$line->id.'-'.$i) ? GETPOST('idwarehousetoproduce-'.$line->id.'-'.$i) : ($object->fk_warehouse > 0 ? $object->fk_warehouse : 'ifone')); - print $formproduct->selectWarehouses($preselected, 'idwarehousetoproduce-'.$line->id.'-'.$i, '', 1, 0, $line->fk_product, '', 1); + print $formproduct->selectWarehouses($preselected, 'idwarehousetoproduce-'.$line->id.'-'.$i, '', 1, 0, $line->fk_product, '', 1, 0, null, 'csswarehouse_'.$line->id.'_'.$i); } else { print ''.$langs->trans("NoStockChangeOnServices").''; } @@ -946,6 +961,12 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea print ''; } print ''; + print ''; + if ($tmpproduct->status_batch) { + $type = 'batch'; + print img_picto($langs->trans('AddStockLocationLine'), 'split.png', 'class="splitbutton" onClick="addDispatchLine('.$line->id.', \''.$type.'\', \'qtymissing\')"'); + } + print ''; } print ''; } diff --git a/htdocs/product/class/product.class.php b/htdocs/product/class/product.class.php index 405583ea314..96b2165c65a 100644 --- a/htdocs/product/class/product.class.php +++ b/htdocs/product/class/product.class.php @@ -4381,6 +4381,12 @@ class Product extends CommonObject if (!empty($this->label)) { $label .= '
'.$langs->trans('ProductLabel').': '.$this->label; } + if ($this->type == Product::TYPE_PRODUCT || !empty($conf->global->STOCK_SUPPORTS_SERVICES)) { + if (!empty($conf->productbatch->enabled)) { + $langs->load("productbatch"); + $label .= "
".$langs->trans("ManageLotSerial").': '.$this->getLibStatut(0, 2); + } + } if (!empty($conf->barcode->enabled)) { $label .= '
'.$langs->trans('BarCode').': '.$this->barcode; } @@ -4390,28 +4396,26 @@ class Product extends CommonObject if ($this->weight) { $label .= "
".$langs->trans("Weight").': '.$this->weight.' '.measuringUnitString(0, "weight", $this->weight_units); } + $labelsize = ""; if ($this->length) { - $label .= "
".$langs->trans("Length").': '.$this->length.' '.measuringUnitString(0, 'size', $this->length_units); + $labelsize .= ($labelsize ? " - ": "")."".$langs->trans("Length").': '.$this->length.' '.measuringUnitString(0, 'size', $this->length_units); } if ($this->width) { - $label .= "
".$langs->trans("Width").': '.$this->width.' '.measuringUnitString(0, 'size', $this->width_units); + $labelsize .= ($labelsize ? " - ": "")."".$langs->trans("Width").': '.$this->width.' '.measuringUnitString(0, 'size', $this->width_units); } if ($this->height) { - $label .= "
".$langs->trans("Height").': '.$this->height.' '.measuringUnitString(0, 'size', $this->height_units); + $labelsize .= ($labelsize ? " - ": "")."".$langs->trans("Height").': '.$this->height.' '.measuringUnitString(0, 'size', $this->height_units); } + if ($labelsize) $label .= "
".$labelsize; + + $labelsurfacevolume = ""; if ($this->surface) { - $label .= "
".$langs->trans("Surface").': '.$this->surface.' '.measuringUnitString(0, 'surface', $this->surface_units); + $labelsurfacevolume .= ($labelsurfacevolume ? " - " : "")."".$langs->trans("Surface").': '.$this->surface.' '.measuringUnitString(0, 'surface', $this->surface_units); } if ($this->volume) { - $label .= "
".$langs->trans("Volume").': '.$this->volume.' '.measuringUnitString(0, 'volume', $this->volume_units); - } - } - - if ($this->type == Product::TYPE_PRODUCT || !empty($conf->global->STOCK_SUPPORTS_SERVICES)) { - if (!empty($conf->productbatch->enabled)) { - $langs->load("productbatch"); - $label .= "
".$langs->trans("ManageLotSerial").': '.$this->getLibStatut(0, 2); + $labelsurfacevolume .= ($labelsurfacevolume ? " - " : "")."".$langs->trans("Volume").': '.$this->volume.' '.measuringUnitString(0, 'volume', $this->volume_units); } + if ($labelsurfacevolume) $label .= "
".$labelsurfacevolume; } if (!empty($conf->accounting->enabled) && $this->status) { diff --git a/htdocs/reception/class/reception.class.php b/htdocs/reception/class/reception.class.php index 595100b771c..0381892d9e3 100644 --- a/htdocs/reception/class/reception.class.php +++ b/htdocs/reception/class/reception.class.php @@ -47,7 +47,7 @@ class Reception extends CommonObject public $fk_element = "fk_reception"; public $table_element = "reception"; public $table_element_line = "commande_fournisseur_dispatch"; - protected $ismultientitymanaged = 1; // 0=No test on entity, 1=Test with field entity, 2=Test with link by societe + public $ismultientitymanaged = 1; // 0=No test on entity, 1=Test with field entity, 2=Test with link by societe /** * @var string String with name of icon for myobject. Must be the part after the 'object_' into object_myobject.png diff --git a/htdocs/societe/card.php b/htdocs/societe/card.php index edc00088c39..22da0cd0545 100644 --- a/htdocs/societe/card.php +++ b/htdocs/societe/card.php @@ -98,6 +98,13 @@ if (!empty($canvas)) // Security check $result = restrictedArea($user, 'societe', $socid, '&societe', '', 'fk_soc', 'rowid', $objcanvas); +$permissiontoread = $user->rights->societe->lire; +$permissiontoadd = $user->rights->societe->creer; // Used by the include of actions_addupdatedelete.inc.php and actions_lineupdown.inc.php +$permissiontodelete = $user->rights->societe->delete || ($permissiontoadd && isset($object->status) && $object->status == 0); +$permissionnote = $user->rights->societe->creer; // Used by the include of actions_setnotes.inc.php +$permissiondellink = $user->rights->societe->creer; // Used by the include of actions_dellink.inc.php +$upload_dir = $conf->societe->multidir_output[isset($object->entity) ? $object->entity : 1]; + /* * Actions @@ -1186,7 +1193,7 @@ else print ''; // Name, firstname - print 'global->SOCIETE_USEPREFIX) ? ' colspan="3"' : '').'>'; - print ''; + print ''; + print $form->widgetForTranslation("name", $object, $permissiontoadd); + print ''; if (!empty($conf->global->SOCIETE_USEPREFIX)) // Old not used prefix field { print ''; @@ -1286,16 +1295,20 @@ else // Barcode if (!empty($conf->barcode->enabled)) { - print ''; + print ''; print ''; } // Address - print ''; + print ''; print ''; + print ''; + print $form->widgetForTranslation("address", $object, $permissiontoadd); + print ''; // Zip / Town print ''; print ''; // Country diff --git a/htdocs/societe/class/societe.class.php b/htdocs/societe/class/societe.class.php index ad5c66a50b8..e61c98e3267 100644 --- a/htdocs/societe/class/societe.class.php +++ b/htdocs/societe/class/societe.class.php @@ -712,6 +712,7 @@ class Societe extends CommonObject */ public $multicurrency_code; + /** * Constructor * diff --git a/htdocs/societe/list.php b/htdocs/societe/list.php index 04ad577bff9..63641f27625 100644 --- a/htdocs/societe/list.php +++ b/htdocs/societe/list.php @@ -228,7 +228,7 @@ $arrayfields = dol_sort_array($arrayfields, 'position'); if ($action == "change") // Change customer for TakePOS { $idcustomer = GETPOST('idcustomer', 'int'); - $place = (GETPOST('place', 'int') > 0 ? GETPOST('place', 'int') : 0); // $place is id of table for Ba or Restaurant + $place = (GETPOST('place', 'alpha') ? GETPOST('place', 'alpha') : 0); // $place is id of table for Ba or Restaurant // Check if draft invoice already exists, if not create it $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."facture where ref='(PROV-POS".$_SESSION["takeposterminal"]."-".$place.")' AND entity IN (".getEntity('invoice').")"; @@ -1031,7 +1031,7 @@ while ($i < min($num, $limit)) print ' 0 ? GETPOST('place', 'int') : 0); // $place is id of table for Bar or Restaurant + $place = (GETPOST('place', 'alpha') > 0 ? GETPOST('place', 'alpha') : 0); // $place is id of table for Bar or Restaurant print ' onclick="location.href=\'list.php?action=change&contextpage=poslist&idcustomer='.$obj->rowid.'&place='.$place.'\'"'; } print '>'; diff --git a/htdocs/takepos/admin/receipt.php b/htdocs/takepos/admin/receipt.php index 7b412cfe610..d50faa480cb 100644 --- a/htdocs/takepos/admin/receipt.php +++ b/htdocs/takepos/admin/receipt.php @@ -83,7 +83,6 @@ $linkback = ''.$langs->trans("BackT print load_fiche_titre($langs->trans("CashDeskSetup").' (TakePOS)', $linkback, 'title_setup'); $head = takepos_prepare_head(); dol_fiche_head($head, 'receipt', 'TakePOS', -1); -print '
'; print ''; print ''; diff --git a/htdocs/takepos/admin/setup.php b/htdocs/takepos/admin/setup.php index a7967169db8..d21936bdaef 100644 --- a/htdocs/takepos/admin/setup.php +++ b/htdocs/takepos/admin/setup.php @@ -71,20 +71,12 @@ if ($action == 'set') $db->begin(); if (GETPOST('socid', 'int') < 0) $_POST["socid"] = ''; - $res = dolibarr_set_const($db, "CASHDESK_SERVICES", GETPOST('CASHDESK_SERVICES', 'alpha'), 'chaine', 0, '', $conf->entity); $res = dolibarr_set_const($db, "TAKEPOS_ROOT_CATEGORY_ID", GETPOST('TAKEPOS_ROOT_CATEGORY_ID', 'alpha'), 'chaine', 0, '', $conf->entity); - $res = dolibarr_set_const($db, "TAKEPOS_BAR_RESTAURANT", GETPOST('TAKEPOS_BAR_RESTAURANT', 'alpha'), 'chaine', 0, '', $conf->entity); - $res = dolibarr_set_const($db, "TAKEPOS_TICKET_VAT_GROUPPED", GETPOST('TAKEPOS_TICKET_VAT_GROUPPED', 'alpha'), 'chaine', 0, '', $conf->entity); - $res = dolibarr_set_const($db, "TAKEPOS_ORDER_PRINTERS", GETPOST('TAKEPOS_ORDER_PRINTERS', 'alpha'), 'chaine', 0, '', $conf->entity); - $res = dolibarr_set_const($db, "TAKEPOS_ORDER_NOTES", GETPOST('TAKEPOS_ORDER_NOTES', 'alpha'), 'chaine', 0, '', $conf->entity); - $res = dolibarr_set_const($db, "TAKEPOS_PHONE_BASIC_LAYOUT", GETPOST('TAKEPOS_PHONE_BASIC_LAYOUT', 'alpha'), 'chaine', 0, '', $conf->entity); - $res = dolibarr_set_const($db, "TAKEPOS_SUPPLEMENTS", GETPOST('TAKEPOS_SUPPLEMENTS', 'alpha'), 'chaine', 0, '', $conf->entity); $res = dolibarr_set_const($db, "TAKEPOS_SUPPLEMENTS_CATEGORY", GETPOST('TAKEPOS_SUPPLEMENTS_CATEGORY', 'alpha'), 'chaine', 0, '', $conf->entity); $res = dolibarr_set_const($db, "TAKEPOS_NUMPAD", GETPOST('TAKEPOS_NUMPAD', 'alpha'), 'chaine', 0, '', $conf->entity); $res = dolibarr_set_const($db, "TAKEPOS_SORTPRODUCTFIELD", GETPOST('TAKEPOS_SORTPRODUCTFIELD', 'alpha'), 'chaine', 0, '', $conf->entity); $res = dolibarr_set_const($db, "TAKEPOS_COLOR_THEME", GETPOST('TAKEPOS_COLOR_THEME', 'alpha'), 'chaine', 0, '', $conf->entity); $res = dolibarr_set_const($db, "TAKEPOS_NUM_TERMINALS", GETPOST('TAKEPOS_NUM_TERMINALS', 'alpha'), 'chaine', 0, '', $conf->entity); - $res = dolibarr_set_const($db, "TAKEPOS_DIRECT_PAYMENT", GETPOST('TAKEPOS_DIRECT_PAYMENT', 'int'), 'int', 0, '', $conf->entity); $res = dolibarr_set_const($db, "TAKEPOS_ADDON", GETPOST('TAKEPOS_ADDON', 'alpha'), 'int', 0, '', $conf->entity); $res = dolibarr_set_const($db, "TAKEPOS_EMAIL_TEMPLATE_INVOICE", GETPOST('TAKEPOS_EMAIL_TEMPLATE_INVOICE', 'alpha'), 'chaine', 0, '', $conf->entity); if (!empty($conf->global->TAKEPOS_ENABLE_SUMUP)) { @@ -142,7 +134,6 @@ $linkback = '
'.$langs->trans("BackT print load_fiche_titre($langs->trans("CashDeskSetup").' (TakePOS)', $linkback, 'title_setup'); $head = takepos_prepare_head(); dol_fiche_head($head, 'setup', 'TakePOS', -1); -print '
'; // Numbering modules $now = dol_now(); diff --git a/htdocs/takepos/floors.php b/htdocs/takepos/floors.php index 260813dd3b6..ac74a8d2203 100644 --- a/htdocs/takepos/floors.php +++ b/htdocs/takepos/floors.php @@ -42,7 +42,7 @@ $action = GETPOST('action', 'alpha'); $left = GETPOST('left', 'alpha'); $top = GETPOST('top', 'alpha'); -$place = (GETPOST('place', 'int') > 0 ? GETPOST('place', 'int') : 0); // $place is id of table for Ba or Restaurant +$place = (GETPOST('place', 'alpha') ? GETPOST('place', 'alpha') : 0); // $place is id of table for Ba or Restaurant $newname = GETPOST('newname', 'alpha'); $mode = GETPOST('mode', 'alpha'); diff --git a/htdocs/takepos/freezone.php b/htdocs/takepos/freezone.php index 1d4e0dfc7be..ee9b61581e2 100644 --- a/htdocs/takepos/freezone.php +++ b/htdocs/takepos/freezone.php @@ -40,7 +40,7 @@ global $mysoc; $langs->loadLangs(array("bills", "cashdesk")); -$place = (GETPOST('place', 'int') > 0 ? GETPOST('place', 'int') : 0); // $place is id of table for Ba or Restaurant +$place = (GETPOST('place', 'alpha') > 0 ? GETPOST('place', 'alpha') : 0); // $place is id of table for Ba or Restaurant $idline = GETPOST('idline', 'int'); $action = GETPOST('action', 'alpha'); diff --git a/htdocs/takepos/index.php b/htdocs/takepos/index.php index 9615f90d539..03f90e7bd96 100644 --- a/htdocs/takepos/index.php +++ b/htdocs/takepos/index.php @@ -39,7 +39,7 @@ require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php'; require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/hookmanager.class.php'; -$place = (GETPOST('place', 'int') > 0 ? GETPOST('place', 'int') : 0); // $place is id of table for Bar or Restaurant +$place = (GETPOST('place', 'alpha') ? GETPOST('place', 'alpha') : 0); // $place is id of table for Bar or Restaurant or multiple sales $action = GETPOST('action', 'alpha'); $setterminal = GETPOST('setterminal', 'int'); @@ -732,7 +732,9 @@ if (empty($conf->global->TAKEPOS_HIDE_HEAD_BAR)) { echo ' - '.dol_print_date(dol_now(), "day").''; ?>
-
+
+ +
diff --git a/htdocs/takepos/invoice.php b/htdocs/takepos/invoice.php index 683b74edc4b..501984d9460 100644 --- a/htdocs/takepos/invoice.php +++ b/htdocs/takepos/invoice.php @@ -44,7 +44,7 @@ $langs->loadLangs(array("companies", "commercial", "bills", "cashdesk", "stocks" $id = GETPOST('id', 'int'); $action = GETPOST('action', 'alpha'); $idproduct = GETPOST('idproduct', 'int'); -$place = (GETPOST('place', 'int') > 0 ? GETPOST('place', 'int') : 0); // $place is id of table for Bar or Restaurant +$place = (GETPOST('place', 'alpha') ? GETPOST('place', 'alpha') : 0); // $place is id of table for Bar or Restaurant $placeid = 0; // $placeid is ID of invoice if (empty($user->rights->takepos->run)) { @@ -713,9 +713,28 @@ $( document ).ready(function() { } ?> - $("a#customer").html(''); + $("#customerandsales").html(''); query($sql); + if ($resql) { + while ($obj = $db->fetch_object($resql)) { + echo '$("#customerandsales").append(\''; + if ($placeid==$obj->rowid) echo ""; + echo 'ref)); + echo $num_sale; + if (str_replace("-", "", $num_sale)>$max_sale) $max_sale=str_replace("-", "", $num_sale); + echo '\\\'">'.date('H:i', strtotime($obj->datec)); + if ($placeid==$obj->rowid) echo ""; + echo '\');'; + } + echo '$("#customerandsales").append(\'\');'; + } + $s = ''; $constantforkey = 'CASHDESK_NO_DECREASE_STOCK'.$_SESSION["takeposterminal"]; diff --git a/htdocs/takepos/pay.php b/htdocs/takepos/pay.php index f79e310f36b..a3bac766aaf 100644 --- a/htdocs/takepos/pay.php +++ b/htdocs/takepos/pay.php @@ -34,7 +34,7 @@ if (!defined('NOREQUIREAJAX')) define('NOREQUIREAJAX', '1'); require '../main.inc.php'; // Load $user and permissions require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php'; -$place = (GETPOST('place', 'int') > 0 ? GETPOST('place', 'int') : 0); // $place is id of table for Ba or Restaurant +$place = (GETPOST('place', 'alpha') ? GETPOST('place', 'alpha') : 0); // $place is id of table for Ba or Restaurant $invoiceid = GETPOST('invoiceid', 'int'); diff --git a/htdocs/takepos/phone.php b/htdocs/takepos/phone.php index c32561d3f52..424282d27cf 100644 --- a/htdocs/takepos/phone.php +++ b/htdocs/takepos/phone.php @@ -37,7 +37,7 @@ require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php'; require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/hookmanager.class.php'; -$place = (GETPOST('place', 'int') > 0 ? GETPOST('place', 'int') : 0); // $place is id of table for Ba or Restaurant +$place = (GETPOST('place', 'alpha') ? GETPOST('place', 'alpha') : 0); // $place is id of table for Ba or Restaurant $action = GETPOST('action', 'alpha'); $setterminal = GETPOST('setterminal', 'int'); diff --git a/htdocs/takepos/receipt.php b/htdocs/takepos/receipt.php index 31390c347bd..50010cf1712 100644 --- a/htdocs/takepos/receipt.php +++ b/htdocs/takepos/receipt.php @@ -30,7 +30,7 @@ include_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php'; $langs->loadLangs(array("main", "cashdesk", "companies")); -$place = (GETPOST('place', 'int') > 0 ? GETPOST('place', 'int') : 0); // $place is id of table for Ba or Restaurant +$place = (GETPOST('place', 'alpha') ? GETPOST('place', 'alpha') : 0); // $place is id of table for Ba or Restaurant $facid = GETPOST('facid', 'int'); diff --git a/htdocs/takepos/reduction.php b/htdocs/takepos/reduction.php index 7ad3e88d2b5..f4a83a09c52 100644 --- a/htdocs/takepos/reduction.php +++ b/htdocs/takepos/reduction.php @@ -34,7 +34,7 @@ if (!defined('NOREQUIREAJAX')) define('NOREQUIREAJAX', '1'); require '../main.inc.php'; // Load $user and permissions require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php'; -$place = (GETPOST('place', 'int') > 0 ? GETPOST('place', 'int') : 0); // $place is id of table for Ba or Restaurant +$place = (GETPOST('place', 'alpha') ? GETPOST('place', 'alpha') : 0); // $place is id of table for Ba or Restaurant $invoiceid = GETPOST('invoiceid', 'int'); diff --git a/htdocs/website/samples/wrapper.php b/htdocs/website/samples/wrapper.php index 8615d2db803..24d32bdf281 100644 --- a/htdocs/website/samples/wrapper.php +++ b/htdocs/website/samples/wrapper.php @@ -71,10 +71,10 @@ if (GETPOSTISSET('type')) $type=GETPOST('type', 'alpha'); else $type=dol_mimetype($original_file); // Security: Delete string ../ into $original_file -$original_file=str_replace("../","/", $original_file); +$original_file = str_replace("../", "/", $original_file); // Cache or not -if (GETPOST("cache",'none') || image_format_supported($original_file) >= 0) +if (GETPOST("cache", 'none') || image_format_supported($original_file) >= 0) { // Important: Following code is to avoid page request by browser and PHP CPU at // each Dolibarr page access. @@ -257,4 +257,4 @@ else readfile($fullpath_original_file_osencoded); } if (is_object($db)) $db->close(); -// END PHP ?> +// END PHP diff --git a/scripts/emailings/mailing-send.php b/scripts/emailings/mailing-send.php index 4e5069b4fdc..eb5b794d3d1 100755 --- a/scripts/emailings/mailing-send.php +++ b/scripts/emailings/mailing-send.php @@ -328,7 +328,7 @@ if ($resql) { dol_syslog("error for emailing id " . $id . " #" . $i . ($mail->error ? ' - ' . $mail->error : ''), LOG_DEBUG); $sqlerror = "UPDATE " . MAIN_DB_PREFIX . "mailing_cibles"; - $sqlerror .= " SET statut=-1, date_envoi=" . $db->idate($now) . " WHERE rowid=" . $obj->rowid; + $sqlerror .= " SET statut=-1, date_envoi='" . $db->idate($now) . "' WHERE rowid=" . $obj->rowid; $resqlerror = $db->query($sqlerror); if (! $resqlerror) { dol_print_error($db);
'; + print '
'; if ($object->particulier || $private) { print ''.$langs->trans('ThirdPartyName').' / '.$langs->trans('LastName', 'name').''; @@ -1196,7 +1203,9 @@ else print ''.$form->editfieldkey('ThirdPartyName', 'name', '', $object, 0).''; } print ''.$langs->trans('Prefix').'
'.$form->editfieldkey('Gencod', 'barcode', '', $object, 0).'
'.$form->editfieldkey('Gencod', 'barcode', '', $object, 0).''; print '
'.$form->editfieldkey('Address', 'address', '', $object, 0).'
'; + print $form->editfieldkey('Address', 'address', '', $object, 0); + print '
'.$form->editfieldkey('Zip', 'zipcode', '', $object, 0).''; @@ -1304,6 +1317,7 @@ else if ($conf->browser->layout == 'phone') print '
'.$form->editfieldkey('Town', 'town', '', $object, 0).''; print $formcompany->select_ziptown($object->town, 'town', array('zipcode', 'selectcountry_id', 'state_id'), 0, 0, '', 'maxwidth100 quatrevingtpercent'); + print $form->widgetForTranslation("town", $object, $permissiontoadd); print '