diff --git a/htdocs/accountancy/class/accountancyexport.class.php b/htdocs/accountancy/class/accountancyexport.class.php index f1815386624..f007208cf57 100644 --- a/htdocs/accountancy/class/accountancyexport.class.php +++ b/htdocs/accountancy/class/accountancyexport.class.php @@ -561,9 +561,9 @@ class AccountancyExport $Tab['contrepartie'] = str_repeat(' ', 8); // Force date format : %d%m%y - if (!empty($data->date_echeance)) { - //$Tab['date_echeance'] = dol_print_date($data->date_echeance, $conf->global->ACCOUNTING_EXPORT_DATE); - $Tab['date_echeance'] = dol_print_date($data->date_echeance, '%d%m%y'); // Format must be ddmmyy + if (!empty($data->date_lim_reglement)) { + //$Tab['date_echeance'] = dol_print_date($data->date_lim_reglement, $conf->global->ACCOUNTING_EXPORT_DATE); + $Tab['date_echeance'] = dol_print_date($data->date_lim_reglement, '%d%m%y'); // Format must be ddmmyy } else { $Tab['date_echeance'] = '000000'; } @@ -660,9 +660,9 @@ class AccountancyExport $Tab['code_stat'] = str_repeat(' ', 4); - if (!empty($data->date_echeance)) { - //$Tab['date_echeance'] = dol_print_date($data->date_echeance, $conf->global->ACCOUNTING_EXPORT_DATE); - $Tab['date_echeance'] = dol_print_date($data->date_echeance, '%d%m%Y'); + if (!empty($data->date_lim_reglement)) { + //$Tab['date_echeance'] = dol_print_date($data->date_lim_reglement, $conf->global->ACCOUNTING_EXPORT_DATE); + $Tab['date_echeance'] = dol_print_date($data->date_lim_reglement, '%d%m%Y'); } else { $Tab['date_echeance'] = dol_print_date($data->doc_date, '%d%m%Y'); } diff --git a/htdocs/admin/pdf_other.php b/htdocs/admin/pdf_other.php index acf1dfe707e..03c27fd3721 100644 --- a/htdocs/admin/pdf_other.php +++ b/htdocs/admin/pdf_other.php @@ -91,7 +91,9 @@ print '
'; print ''; print ''; -print ''; + $entrepot_id = !empty($detail_batch->entrepot_id)?$detail_batch->entrepot_id:$lines[$i]->entrepot_id; + print ''; print ''; } // add a 0 qty lot row to be able to add a lot diff --git a/htdocs/fichinter/card.php b/htdocs/fichinter/card.php index 88c5a1cefc0..e138c8ed6fe 100644 --- a/htdocs/fichinter/card.php +++ b/htdocs/fichinter/card.php @@ -1546,8 +1546,9 @@ if ($action == 'create') { // Validate if ($object->statut == Fichinter::STATUS_DRAFT && (count($object->lines) > 0 || !empty($conf->global->FICHINTER_DISABLE_DETAILS))) { if ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && $user->rights->ficheinter->creer) || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && $user->rights->ficheinter->ficheinter_advance->validate)) { - print '
'.$langs->trans("Validate").'
'; + print '
'.$langs->trans("Validate").'
'; + } else { + print '
'.$langs->trans("Validate").'
'; } } @@ -1582,7 +1583,7 @@ if ($action == 'create') { } } - // create intervention model + // Create intervention model if ($conf->global->MAIN_FEATURES_LEVEL >= 1 && $object->statut == Fichinter::STATUS_DRAFT && $user->rights->ficheinter->creer && (count($object->lines) > 0)) { print '
'; print ''.$langs->trans("ChangeIntoRepeatableIntervention").''; diff --git a/htdocs/holiday/list.php b/htdocs/holiday/list.php index b00abadb9c3..224e3583bbd 100644 --- a/htdocs/holiday/list.php +++ b/htdocs/holiday/list.php @@ -117,7 +117,7 @@ $search_month_end = GETPOST('search_month_end', 'int'); $search_year_end = GETPOST('search_year_end', 'int'); $search_employee = GETPOST('search_employee', 'int'); $search_valideur = GETPOST('search_valideur', 'int'); -$search_status = GETPOST('search_statut', 'int'); +$search_status = GETPOST('search_status', 'int'); $search_type = GETPOST('search_type', 'int'); // Initialize technical objects diff --git a/htdocs/holiday/month_report.php b/htdocs/holiday/month_report.php index 966dd7e8dee..eef3ca0dcbe 100644 --- a/htdocs/holiday/month_report.php +++ b/htdocs/holiday/month_report.php @@ -144,17 +144,17 @@ $sql .= " FROM ".MAIN_DB_PREFIX."holiday cp"; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."user u ON cp.fk_user = u.rowid"; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_holiday_types ct ON cp.fk_type = ct.rowid"; $sql .= " WHERE cp.rowid > 0"; -$sql .= " AND cp.statut = 3"; // 3 = Approved +$sql .= " AND cp.statut = ".Holiday::STATUS_APPROVED; $sql .= " AND (date_format(cp.date_debut, '%Y-%m') = '".$db->escape($year_month)."' OR date_format(cp.date_fin, '%Y-%m') = '".$db->escape($year_month)."')"; if (!empty($search_ref)) { $sql .= natural_search('cp.ref', $search_ref); } -if (!empty($search_employee)) { - $sql .= " AND cp.fk_user = '".$db->escape($search_employee)."'"; +if (!empty($search_employee) && $search_employee > 0) { + $sql .= " AND cp.fk_user = ".((int) $search_employee); } -if (!empty($search_type)) { - $sql .= ' AND cp.fk_type IN ('.$db->sanitize($search_type).')'; +if (!empty($search_type) && $search_type != '-1') { + $sql .= ' AND cp.fk_type IN ('.$db->escape($search_type).')'; } if (!empty($search_description)) { $sql .= natural_search('cp.description', $search_description); diff --git a/htdocs/langs/en_US/admin.lang b/htdocs/langs/en_US/admin.lang index 2eaba13de3c..b7618f64739 100644 --- a/htdocs/langs/en_US/admin.lang +++ b/htdocs/langs/en_US/admin.lang @@ -1987,7 +1987,7 @@ MAIN_PDF_MARGIN_RIGHT=Right margin on PDF MAIN_PDF_MARGIN_TOP=Top margin on PDF MAIN_PDF_MARGIN_BOTTOM=Bottom margin on PDF MAIN_DOCUMENTS_LOGO_HEIGHT=Height for logo on PDF -MAIN_GENERATE_PROPOSALS_WITH_PICTURE=Add picture on proposal ligne +MAIN_GENERATE_PROPOSALS_WITH_PICTURE=Add picture on proposal line MAIN_PDF_PROPAL_USE_ELECTRONIC_SIGNING=Add electronic sign in PDF NothingToSetup=There is no specific setup required for this module. SetToYesIfGroupIsComputationOfOtherGroups=Set this to yes if this group is a computation of other groups @@ -2140,4 +2140,5 @@ CheckForModuleUpdateHelp=This action will connect to editors of external modules ModuleUpdateAvailable=An update is available NoExternalModuleWithUpdate=No updates found for external modules SwaggerDescriptionFile=Swagger API description file (for use with redoc for example) -YouEnableDeprecatedWSAPIsUseRESTAPIsInstead=You enabled deprecated WS API. You should use REST API instead. \ No newline at end of file +YouEnableDeprecatedWSAPIsUseRESTAPIsInstead=You enabled deprecated WS API. You should use REST API instead. +RandomlySelectedIfSeveral=Randomly selected if several pictures are available \ No newline at end of file diff --git a/htdocs/product/class/product.class.php b/htdocs/product/class/product.class.php index 2ccc5e63c8f..f76a6fec0ad 100644 --- a/htdocs/product/class/product.class.php +++ b/htdocs/product/class/product.class.php @@ -5422,11 +5422,11 @@ class Product extends CommonObject // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps /** - * Retourne tableau de toutes les photos du produit + * Return an array with all photos of product found on disk. There is no sorting criteria. * - * @param string $dir Repertoire a scanner - * @param int $nbmax Nombre maximum de photos (0=pas de max) - * @return array Tableau de photos + * @param string $dir Directory to scan + * @param int $nbmax Number maxium of photos (0=no maximum) + * @return array Array of photos */ public function liste_photos($dir, $nbmax = 0) { @@ -5447,9 +5447,10 @@ class Product extends CommonObject if (dol_is_file($dir.$file) && image_format_supported($file) >= 0) { $nbphoto++; - // On determine nom du fichier vignette + // We forge name of thumb. $photo = $file; $photo_vignette = ''; + $regs = array(); if (preg_match('/('.$this->regeximgext.')$/i', $photo, $regs)) { $photo_vignette = preg_replace('/'.$regs[0].'/i', '', $photo).'_small'.$regs[0]; } @@ -5467,7 +5468,7 @@ class Product extends CommonObject $tabobj[$nbphoto - 1] = $obj; - // On continue ou on arrete de boucler ? + // Do we have to continue with next photo ? if ($nbmax && $nbphoto >= $nbmax) { break; } @@ -5482,9 +5483,9 @@ class Product extends CommonObject // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps /** - * Efface la photo du produit et sa vignette + * Delete a photo and its thumbs * - * @param string $file Chemin de l'image + * @param string $file Path to image file * @return void */ public function delete_photo($file) diff --git a/htdocs/product/stock/class/mouvementstock.class.php b/htdocs/product/stock/class/mouvementstock.class.php index 959336c1671..5e609bbe301 100644 --- a/htdocs/product/stock/class/mouvementstock.class.php +++ b/htdocs/product/stock/class/mouvementstock.class.php @@ -370,8 +370,12 @@ class MouvementStock extends CommonObject if (!empty($conf->productbatch->enabled) && $product->hasbatch() && !$skip_batch) { $foundforbatch = 0; $qtyisnotenough = 0; + foreach ($product->stock_warehouse[$entrepot_id]->detail_batch as $batchcursor => $prodbatch) { - if ($batch != $batchcursor) continue; + if ((string) $batch != (string) $batchcursor) { // Lot '59' must be different than lot '59c' + continue; + } + $foundforbatch = 1; if ($prodbatch->qty < abs($qty)) $qtyisnotenough = $prodbatch->qty; break; diff --git a/htdocs/product/stock/stockatdate.php b/htdocs/product/stock/stockatdate.php index b36d530d624..52addeba637 100644 --- a/htdocs/product/stock/stockatdate.php +++ b/htdocs/product/stock/stockatdate.php @@ -45,7 +45,7 @@ if ($user->socid) { $result = restrictedArea($user, 'produit|service'); // Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context -$hookmanager->initHooks(array('stockreplenishlist')); +$hookmanager->initHooks(array('stockatdate')); //checks if a product has been ordered diff --git a/htdocs/reception/card.php b/htdocs/reception/card.php index 493a400c891..cd34b0f916f 100644 --- a/htdocs/reception/card.php +++ b/htdocs/reception/card.php @@ -1045,10 +1045,7 @@ if ($action == 'create') { print ''; // Show product and description - $product_static->type = $line->fk_product_type; - $product_static->id = $line->fk_product; - $product_static->ref = $line->ref; - $product_static->status_batch = $line->product_tobatch; + $product_static = $product; $text = $product_static->getNomUrl(1); $text .= ' - '.(!empty($line->label) ? $line->label : $line->product_label); diff --git a/htdocs/societe/list.php b/htdocs/societe/list.php index 48cc882c052..b8bef7cad9a 100644 --- a/htdocs/societe/list.php +++ b/htdocs/societe/list.php @@ -508,6 +508,10 @@ if ($search_sale == -2) { } elseif (!empty($search_sale) && $search_sale != '-1' || (empty($user->rights->societe->client->voir) && !$socid)) { $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; } +// Add table from hooks +$parameters = array(); +$reshook = $hookmanager->executeHooks('printFieldListFrom', $parameters, $object); // Note that $action and $object may have been modified by hook +$sql .= $hookmanager->resPrint; $sql .= " WHERE s.entity IN (".getEntity('societe').")"; //if (empty($user->rights->societe->client->voir) && (empty($conf->global->MAIN_USE_ADVANCED_PERMS) || empty($user->rights->societe->client->readallthirdparties_advance)) && !$socid) $sql .= " AND s.rowid = sc.fk_soc AND sc.fk_user = ".$user->id; if (empty($user->rights->societe->client->voir) && !$socid) { @@ -667,6 +671,10 @@ if (empty($reshook)) { } } $sql .= $hookmanager->resPrint; +// Add GroupBy from hooks +$parameters = array('all' => $all, 'fieldstosearchall' => $fieldstosearchall); +$reshook = $hookmanager->executeHooks('printFieldListGroupBy', $parameters, $object); // Note that $action and $object may have been modified by hook +$sql .= $hookmanager->resPrint; $sql .= $db->order($sortfield, $sortorder);
'.$langs->trans("Parameter").''.$langs->trans("Value").'
'.$langs->trans("MAIN_GENERATE_PROPOSALS_WITH_PICTURE").''; +print '
'.$langs->trans("MAIN_GENERATE_PROPOSALS_WITH_PICTURE"); +print ' ('.$langs->trans("RandomlySelectedIfSeveral").')'; +print ''; if ($conf->use_javascript_ajax) { print ajax_constantonoff('MAIN_GENERATE_PROPOSALS_WITH_PICTURE'); } else { diff --git a/htdocs/commande/class/commandestats.class.php b/htdocs/commande/class/commandestats.class.php index 85036543e18..6bd6067dcf7 100644 --- a/htdocs/commande/class/commandestats.class.php +++ b/htdocs/commande/class/commandestats.class.php @@ -44,7 +44,10 @@ class CommandeStats extends Stats public $userid; public $from; + public $from_line; public $field; + public $field_line; + public $categ_link; public $where; public $join; @@ -77,6 +80,7 @@ class CommandeStats extends Stats $this->field = 'total_ht'; $this->field_line = 'total_ht'; //$this->where .= " c.fk_statut > 0"; // Not draft and not cancelled + $this->categ_link = MAIN_DB_PREFIX.'categorie_societe'; } elseif ($mode == 'supplier') { $object = new CommandeFournisseur($this->db); $this->from = MAIN_DB_PREFIX.$object->table_element." as c"; @@ -84,6 +88,7 @@ class CommandeStats extends Stats $this->field = 'total_ht'; $this->field_line = 'total_ht'; //$this->where .= " c.fk_statut > 2"; // Only approved & ordered + $this->categ_link = MAIN_DB_PREFIX.'categorie_fournisseur'; } //$this->where.= " AND c.fk_soc = s.rowid AND c.entity = ".$conf->entity; $this->where .= ($this->where ? ' AND ' : '').'c.entity IN ('.getEntity('commande').')'; @@ -104,7 +109,7 @@ class CommandeStats extends Stats } if ($categid) { - $this->join .= ' LEFT JOIN '.MAIN_DB_PREFIX.'categorie_societe as cats ON cats.fk_soc = c.fk_soc'; + $this->join .= ' LEFT JOIN '.$this->categ_link.' as cats ON cats.fk_soc = c.fk_soc'; $this->join .= ' LEFT JOIN '.MAIN_DB_PREFIX.'categorie as cat ON cat.rowid = cats.fk_categorie'; $this->where .= ' AND cat.rowid = '.((int) $categid); } diff --git a/htdocs/core/actions_massactions.inc.php b/htdocs/core/actions_massactions.inc.php index 72279faf16b..f39c73b5bf0 100644 --- a/htdocs/core/actions_massactions.inc.php +++ b/htdocs/core/actions_massactions.inc.php @@ -1,6 +1,6 @@ - * Copyright (C) 2018 Nicolas ZABOURI + * Copyright (C) 2018-2021 Nicolas ZABOURI * Copyright (C) 2018 Juanjo Menent * Copyright (C) 2019 Ferran Marcet * Copyright (C) 2019-2021 Frédéric France @@ -1267,7 +1267,7 @@ if (!$error && $massaction == 'validate' && $permissiontoadd) { if ($nbok > 1) { setEventMessages($langs->trans("RecordsModified", $nbok), null, 'mesgs'); } else { - setEventMessages($langs->trans("RecordsModified", $nbok), null, 'mesgs'); + setEventMessages($langs->trans("RecordModifiedSuccessfully"), null, 'mesgs'); } $db->commit(); } else { @@ -1330,7 +1330,7 @@ if (!$error && ($massaction == 'delete' || ($action == 'delete' && $confirm == ' if ($nbok > 1) { setEventMessages($langs->trans("RecordsDeleted", $nbok), null, 'mesgs'); } else { - setEventMessages($langs->trans("RecordDeleted", $nbok), null, 'mesgs'); + setEventMessages($langs->trans("RecordDeleted"), null, 'mesgs'); } $db->commit(); } else { diff --git a/htdocs/core/modules/propale/doc/pdf_cyan.modules.php b/htdocs/core/modules/propale/doc/pdf_cyan.modules.php index 0aed96df0e5..f75f5ecab56 100644 --- a/htdocs/core/modules/propale/doc/pdf_cyan.modules.php +++ b/htdocs/core/modules/propale/doc/pdf_cyan.modules.php @@ -434,13 +434,12 @@ class pdf_cyan extends ModelePDFPropales if (!empty($conf->global->MAIN_ADD_CREATOR_IN_NOTE) && $object->user_author_id > 0) { $tmpuser = new User($this->db); $tmpuser->fetch($object->user_author_id); - $notetoshow .= $langs->trans("CaseFollowedBy").' '.$tmpuser->getFullName($langs); - if ($tmpuser->email) { - $notetoshow .= ', Mail: '.$tmpuser->email; - } - if ($tmpuser->office_phone) { - $notetoshow .= ', Tel: '.$tmpuser->office_phone; - } + + $creator_info = $langs->trans("CaseFollowedBy").' '.$tmpuser->getFullName($langs); + if ($tmpuser->email) $creator_info .= ', '.$langs->trans("EMail").': '.$tmpuser->email; + if ($tmpuser->office_phone) $creator_info .= ', '.$langs->trans("Phone").': '.$tmpuser->office_phone; + + $notetoshow = dol_concatdesc($notetoshow, $creator_info); } $tab_height = $this->page_hauteur - $tab_top_newpage - $heightforinfotot - $heightforfreetext - $heightforsignature - $heightforfooter; diff --git a/htdocs/core/modules/supplier_proposal/doc/pdf_aurore.modules.php b/htdocs/core/modules/supplier_proposal/doc/pdf_aurore.modules.php index b471f65add6..cbcec7cfdd9 100644 --- a/htdocs/core/modules/supplier_proposal/doc/pdf_aurore.modules.php +++ b/htdocs/core/modules/supplier_proposal/doc/pdf_aurore.modules.php @@ -245,7 +245,7 @@ class pdf_aurore extends ModelePDFSupplierProposal $pdir = get_exdir($object->lines[$i]->fk_product, 2, 0, 0, $objphoto, 'product').$object->lines[$i]->fk_product."/photos/"; $dir = $conf->product->dir_output.'/'.$pdir; } else { - $pdir = get_exdir(0, 2, 0, 0, $objphoto, 'product').dol_sanitizeFileName($objphoto->ref).'/'; + $pdir = get_exdir(0, 0, 0, 0, $objphoto, 'product'); $dir = $conf->product->dir_output.'/'.$pdir; } diff --git a/htdocs/core/triggers/interface_50_modLdap_Ldapsynchro.class.php b/htdocs/core/triggers/interface_50_modLdap_Ldapsynchro.class.php index 28565114a21..81054338b88 100644 --- a/htdocs/core/triggers/interface_50_modLdap_Ldapsynchro.class.php +++ b/htdocs/core/triggers/interface_50_modLdap_Ldapsynchro.class.php @@ -125,6 +125,52 @@ class InterfaceLdapsynchro extends DolibarrTriggers $newparent = $object->_load_ldap_dn($info, 1); $result = $ldap->update($dn, $info, $user, $olddn, $newrdn, $newparent); + + if ($result > 0 && !empty($object->context['newgroupid'])) { // We are in context of adding a new group to user + $usergroup = new Usergroup($this->db); + + $usergroup->fetch($object->context['newgroupid']); + + $oldinfo = $usergroup->_load_ldap_info(); + $olddn = $usergroup->_load_ldap_dn($oldinfo); + + // Verify if entry exist + $container = $usergroup->_load_ldap_dn($oldinfo, 1); + $search = "(".$usergroup->_load_ldap_dn($oldinfo, 2).")"; + $records = $ldap->search($container, $search); + if (count($records) && $records['count'] == 0) + { + $olddn = ''; + } + + $info = $usergroup->_load_ldap_info(); // Contains all members, included the new one (insert already done before trigger call) + $dn = $usergroup->_load_ldap_dn($info); + + $result = $ldap->update($dn, $info, $user, $olddn); + } + + if ($result > 0 && !empty($object->context['oldgroupid'])) { // We are in context of removing a group from user + $usergroup = new Usergroup($this->db); + + $usergroup->fetch($object->context['oldgroupid']); + + $oldinfo = $usergroup->_load_ldap_info(); + $olddn = $usergroup->_load_ldap_dn($oldinfo); + + // Verify if entry exist + $container = $usergroup->_load_ldap_dn($oldinfo, 1); + $search = "(".$usergroup->_load_ldap_dn($oldinfo, 2).")"; + $records = $ldap->search($container, $search); + if (count($records) && $records['count'] == 0) + { + $olddn = ''; + } + + $info = $usergroup->_load_ldap_info(); // Contains all members, except the old one (remove already done before trigger call) + $dn = $usergroup->_load_ldap_dn($info); + + $result = $ldap->update($dn, $info, $user, $olddn); + } } if ($result < 0) { diff --git a/htdocs/expedition/card.php b/htdocs/expedition/card.php index cc441d9f50f..ae643ee688a 100644 --- a/htdocs/expedition/card.php +++ b/htdocs/expedition/card.php @@ -2138,7 +2138,8 @@ if ($action == 'create') { // only show lot numbers from src warehouse when shipping from multiple warehouses $line->fetch($detail_batch->fk_expeditiondet); } - print ''.$formproduct->selectLotStock($detail_batch->fk_origin_stock, 'batchl'.$detail_batch->fk_expeditiondet.'_'.$detail_batch->fk_origin_stock, '', 1, 0, $lines[$i]->fk_product, $line->entrepot_id).''.$formproduct->selectLotStock($detail_batch->fk_origin_stock, 'batchl'.$detail_batch->fk_expeditiondet.'_'.$detail_batch->fk_origin_stock, '', 1, 0, $lines[$i]->fk_product, $entrepot_id).'