diff --git a/README.md b/README.md index cf2de36b81d68b33078c45fbbf6a8333a763848f..eda6b8b642e8a8b77057d143f2531376944c737b 100644 --- a/README.md +++ b/README.md @@ -91,14 +91,15 @@ See the [ChangeLog](https://github.com/Dolibarr/dolibarr/blob/develop/ChangeLog) - Standing orders management (European SEPA) - Bank accounts management - Shared calendar/agenda (with ical and vcal export for third party tools integration) -- Opportunities and/or project management (following project benefit including invoices, expense reports, time spent, ...) +- Opportunities and/or project management - Projects management - Contracts management - Stock management - Shipping management - Interventions management - Employee's leave requests management -- Expense report management +- Expense reports +- Timesheets - Electronic Document Management (EDM) - Foundations members management - Mass emailing diff --git a/htdocs/accountancy/admin/index.php b/htdocs/accountancy/admin/index.php index 8f023432727d97b15af59169bc9a1bd19438ab0d..74479a9d39f62c9af8173311a8a5454180d3a1a2 100644 --- a/htdocs/accountancy/admin/index.php +++ b/htdocs/accountancy/admin/index.php @@ -1,7 +1,7 @@ <?php /* Copyright (C) 2013-2014 Olivier Geffroy <jeff@jeffinfo.com> * Copyright (C) 2013-2014 Florian Henry <florian.henry@open-concept.pro> - * Copyright (C) 2013-2016 Alexandre Spangaro <aspangaro.dolibarr@gmail.com> + * Copyright (C) 2013-2017 Alexandre Spangaro <aspangaro@zendsi.com> * Copyright (C) 2014-2015 Ari Elbaz (elarifr) <github@accedinfo.com> * Copyright (C) 2014 Marcos García <marcosgdf@gmail.com> * Copyright (C) 2014 Juanjo Menent <jmenent@2byte.es> @@ -87,7 +87,8 @@ if ($action == 'update') { setEventMessages($langs->trans("Error"), null, 'errors'); } - foreach ($list as $constname) { + foreach ($list as $constname) + { $constvalue = GETPOST($constname, 'alpha'); if (! dolibarr_set_const($db, $constname, $constvalue, 'chaine', 0, '', $conf->entity)) { @@ -278,13 +279,17 @@ foreach ($list as $key) $var = ! $var; print '<tr ' . $bc[$var] . ' class="value">'; + + if (! empty($conf->global->ACCOUNTING_MANAGE_ZERO) && ($key == 'ACCOUNTING_LENGTH_GACCOUNT' || $key == 'ACCOUNTING_LENGTH_AACCOUNT')) continue; + // Param $label = $langs->trans($key); print '<td>'.$label.'</td>'; // Value print '<td align="right">'; - print '<input type="text" size="20" id="' . $key . '" name="' . $key . '" value="' . $conf->global->$key . '">'; + print '<input type="text" class="maxwidth100" id="' . $key . '" name="' . $key . '" value="' . $conf->global->$key . '">'; print '</td>'; + print '</tr>'; } @@ -301,7 +306,7 @@ print '<div class="center"><input type="submit" class="button" value="' . $langs print '<br>'; print '<br>'; -print $langs->trans("AccountancySetupDoneFromAccountancyMenu", $langs->transnoentitiesnoconv("Home").'-'.$langs->transnoentitiesnoconv("Financial").'-'.$langs->transnoentitiesnoconv("Accountancy")); +print $langs->trans("AccountancySetupDoneFromAccountancyMenu", $langs->transnoentitiesnoconv("Home").'-'.$langs->transnoentitiesnoconv("MenuFinancial").'-'.$langs->transnoentitiesnoconv("MenuAccountancy")); print '<br>'; print '</form>'; diff --git a/htdocs/admin/index.php b/htdocs/admin/index.php index 6778f618265460ee6d79debea715fadd211416fc..e9d38ad37764eeee244cd5307cf19ecdc0bc8f28 100644 --- a/htdocs/admin/index.php +++ b/htdocs/admin/index.php @@ -1,7 +1,7 @@ <?php /* Copyright (C) 2001-2004 Rodolphe Quiedeville <rodolphe@quiedeville.org> * Copyright (C) 2004-2012 Laurent Destailleur <eldy@users.sourceforge.net> - * Copyright (C) 2015 Jean-François Ferry <jfefe@aternatik.fr> + * Copyright (C) 2015 Jean-François Ferry <jfefe@aternatik.fr> * * 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 diff --git a/htdocs/core/class/commondocgenerator.class.php b/htdocs/core/class/commondocgenerator.class.php index 75336e2a291bd09b7037c49d0e65d4eac90a1cbc..f338aca7be8125eac683d18dd5fe515b26b19dc1 100644 --- a/htdocs/core/class/commondocgenerator.class.php +++ b/htdocs/core/class/commondocgenerator.class.php @@ -304,11 +304,13 @@ abstract class CommonDocGenerator $now=dol_now('gmt'); // gmt $array_other = array( - 'current_date'=>dol_print_date($now,'day','tzuser'), - 'current_datehour'=>dol_print_date($now,'dayhour','tzuser'), + // Date in default language + 'current_date'=>dol_print_date($now,'day','tzuser'), + 'current_datehour'=>dol_print_date($now,'dayhour','tzuser'), 'current_server_date'=>dol_print_date($now,'day','tzserver'), 'current_server_datehour'=>dol_print_date($now,'dayhour','tzserver'), - 'current_date_locale'=>dol_print_date($now,'day','tzuser',$outputlangs), + // Date in requested output language + 'current_date_locale'=>dol_print_date($now,'day','tzuser',$outputlangs), 'current_datehour_locale'=>dol_print_date($now,'dayhour','tzuser',$outputlangs), 'current_server_date_locale'=>dol_print_date($now,'day','tzserver',$outputlangs), 'current_server_datehour_locale'=>dol_print_date($now,'dayhour','tzserver',$outputlangs), @@ -350,6 +352,7 @@ abstract class CommonDocGenerator $array_key.'_ref_customer'=>$object->ref_client, $array_key.'_ref_supplier'=>(! empty($object->ref_fournisseur)?$object->ref_fournisseur:''), $array_key.'_source_invoice_ref'=>$invoice_source->ref, + // Dates $array_key.'_hour'=>dol_print_date($object->date,'hour'), $array_key.'_date'=>dol_print_date($object->date,'day'), $array_key.'_date_rfc'=>dol_print_date($object->date,'dayrfc'), @@ -360,6 +363,7 @@ abstract class CommonDocGenerator $array_key.'_date_validation'=>(! empty($object->date_validation)?dol_print_date($object->date_validation,'dayhour'):''), $array_key.'_date_delivery_planed'=>(! empty($object->date_livraison)?dol_print_date($object->date_livraison,'day'):''), $array_key.'_date_close'=>(! empty($object->date_cloture)?dol_print_date($object->date_cloture,'dayhour'):''), + $array_key.'_payment_mode_code'=>$object->mode_reglement_code, $array_key.'_payment_mode'=>($outputlangs->transnoentitiesnoconv('PaymentType'.$object->mode_reglement_code)!='PaymentType'.$object->mode_reglement_code?$outputlangs->transnoentitiesnoconv('PaymentType'.$object->mode_reglement_code):$object->mode_reglement), $array_key.'_payment_term_code'=>$object->cond_reglement_code, @@ -444,10 +448,13 @@ abstract class CommonDocGenerator 'line_price_ht_locale'=>price($line->total_ht, 0, $outputlangs), 'line_price_ttc_locale'=>price($line->total_ttc, 0, $outputlangs), 'line_price_vat_locale'=>price($line->total_tva, 0, $outputlangs), - 'line_date_start'=>$line->date_start, - 'line_date_start_rfc'=>dol_print_date($line->date_start,'dayrfc'), - 'line_date_end'=>$line->date_end, - 'line_date_end_rfc'=>dol_print_date($line->date_end,'dayrfc') + // Dates + 'line_date_start'=>dol_print_date($line->date_start, 'day', 'tzuser'), + 'line_date_start_locale'=>dol_print_date($line->date_start, 'day', 'tzuser', $outputlangs), + 'line_date_start_rfc'=>dol_print_date($line->date_start, 'dayrfc', 'tzuser'), + 'line_date_end'=>dol_print_date($line->date_end, 'day', 'tzuser'), + 'line_date_end_locale'=>dol_print_date($line->date_end, 'day', 'tzuser', $outputlangs), + 'line_date_end_rfc'=>dol_print_date($line->date_end, 'dayrfc', 'tzuser'), ); // Retrieve extrafields diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index d6a1588acbebb21ffa05f6c6d5eb45ef48e8f2a4..e7ca48973c15c0083ab8947dbc68aea84090a126 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -1231,7 +1231,7 @@ abstract class CommonObject * @param int $id To force other object id (should not be used) * @param string $format Data format ('text', 'date'). 'text' is used if not defined * @param string $id_field To force rowid field name. 'rowid' is used if not defined - * @param User|string $user Update last update fields also if user object provided + * @param User|string $user Update last update fields also if user object provided. If not provided, current user is used. * @param string $trigkey Trigger key to run (in most cases something like 'XXX_MODIFY') * @return int <0 if KO, >0 if OK */ @@ -1255,7 +1255,7 @@ abstract class CommonObject if ($format == 'text') $sql.= $field." = '".$this->db->escape($value)."'"; else if ($format == 'int') $sql.= $field." = ".$this->db->escape($value); else if ($format == 'date') $sql.= $field." = ".($value ? "'".$this->db->idate($value)."'" : "null"); - if (is_object($user)) $sql.=", fk_user_modif = ".$user->id; + if (empty($user) && is_object($user)) $sql.=", fk_user_modif = ".$user->id; $sql.= " WHERE ".$id_field." = ".$id; dol_syslog(get_class($this)."::".__FUNCTION__."", LOG_DEBUG); diff --git a/htdocs/core/lib/accounting.lib.php b/htdocs/core/lib/accounting.lib.php index bb704ba5c2ee611f308a58f7b30209f719506e54..8ec0713b01a0a1802b08fd575dc8395c7f61c1a1 100644 --- a/htdocs/core/lib/accounting.lib.php +++ b/htdocs/core/lib/accounting.lib.php @@ -116,8 +116,9 @@ function length_accountg($account) if ($account < 0 || empty($account)) return ''; + if (! empty($conf->global->ACCOUNTING_MANAGE_ZERO)) return $account; + $g = $conf->global->ACCOUNTING_LENGTH_GACCOUNT; - if (! empty($g)) { // Clean parameters $i = strlen($account); @@ -150,8 +151,9 @@ function length_accounta($accounta) if ($accounta < 0 || empty($accounta)) return ''; + if (! empty($conf->global->ACCOUNTING_MANAGE_ZERO)) return $account; + $a = $conf->global->ACCOUNTING_LENGTH_AACCOUNT; - if (! empty($a)) { // Clean parameters $i = strlen($accounta); diff --git a/htdocs/core/lib/files.lib.php b/htdocs/core/lib/files.lib.php index a2d6da7bdc5c6fcee96dae41909309d73b773a27..ca140fbb29069ec34e0b90c77b98fa7e21152088 100644 --- a/htdocs/core/lib/files.lib.php +++ b/htdocs/core/lib/files.lib.php @@ -772,7 +772,7 @@ function dol_move_uploaded_file($src_file, $dest_file, $allowoverwrite, $disable } // Security: - // On interdit fichiers caches, remontees de repertoire ainsi que les pipes dans les noms de fichiers. + // We refuse cache files/dirs, upload using .. and pipes into filenames. if (preg_match('/^\./',$src_file) || preg_match('/\.\./',$src_file) || preg_match('/[<>|]/',$src_file)) { dol_syslog("Refused to deliver file ".$src_file, LOG_WARNING); @@ -845,6 +845,7 @@ function dol_move_uploaded_file($src_file, $dest_file, $allowoverwrite, $disable * @param int $nohook Disable all hooks * @param object $object Current object in use * @return boolean True if no error (file is deleted or if glob is used and there's nothing to delete), False if error + * @see dol_delete_dir */ function dol_delete_file($file,$disableglob=0,$nophperrors=0,$nohook=0,$object=null) { @@ -856,6 +857,14 @@ function dol_delete_file($file,$disableglob=0,$nophperrors=0,$nohook=0,$object=n dol_syslog("dol_delete_file file=".$file." disableglob=".$disableglob." nophperrors=".$nophperrors." nohook=".$nohook); + // Security: + // We refuse transversal using .. and pipes into filenames. + if (preg_match('/\.\./',$file) || preg_match('/[<>|]/',$file)) + { + dol_syslog("Refused to delete file ".$file, LOG_WARNING); + return False; + } + if (empty($nohook)) { $hookmanager->initHooks(array('fileslib')); @@ -943,9 +952,18 @@ function dol_delete_file($file,$disableglob=0,$nophperrors=0,$nohook=0,$object=n * @param string $dir Directory to delete * @param int $nophperrors Disable all PHP output errors * @return boolean True if success, false if error + * @see dol_delete_file */ function dol_delete_dir($dir,$nophperrors=0) { + // Security: + // We refuse transversal using .. and pipes into filenames. + if (preg_match('/\.\./',$dir) || preg_match('/[<>|]/',$dir)) + { + dol_syslog("Refused to delete dir ".$dir, LOG_WARNING); + return False; + } + $dir_osencoded=dol_osencode($dir); return ($nophperrors?@rmdir($dir_osencoded):rmdir($dir_osencoded)); } @@ -1568,141 +1586,140 @@ function dol_check_secure_access_document($modulepart,$original_file,$entity,$fu // find the subdirectory name as the reference if (empty($refname)) $refname=basename(dirname($original_file)."/"); + $relative_original_file = $original_file; + // Wrapping for some images - if ($modulepart == 'companylogo') + if ($modulepart == 'companylogo' && !empty($conf->mycompany->dir_output)) { $accessallowed=1; $original_file=$conf->mycompany->dir_output.'/logos/'.$original_file; } // Wrapping for users photos - elseif ($modulepart == 'userphoto') + elseif ($modulepart == 'userphoto' && !empty($conf->user->dir_output)) { $accessallowed=1; $original_file=$conf->user->dir_output.'/'.$original_file; } // Wrapping for members photos - elseif ($modulepart == 'memberphoto') + elseif ($modulepart == 'memberphoto' && !empty($conf->adherent->dir_output)) { $accessallowed=1; $original_file=$conf->adherent->dir_output.'/'.$original_file; } // Wrapping pour les apercu factures - elseif ($modulepart == 'apercufacture') + elseif ($modulepart == 'apercufacture' && !empty($conf->facture->dir_output)) { if ($fuser->rights->facture->lire) $accessallowed=1; $original_file=$conf->facture->dir_output.'/'.$original_file; } // Wrapping pour les apercu propal - elseif ($modulepart == 'apercupropal') + elseif ($modulepart == 'apercupropal' && !empty($conf->propal->dir_output)) { if ($fuser->rights->propale->lire) $accessallowed=1; $original_file=$conf->propal->dir_output.'/'.$original_file; } // Wrapping pour les apercu commande - elseif ($modulepart == 'apercucommande') + elseif ($modulepart == 'apercucommande' && !empty($conf->commande->dir_output)) { if ($fuser->rights->commande->lire) $accessallowed=1; $original_file=$conf->commande->dir_output.'/'.$original_file; } // Wrapping pour les apercu intervention - elseif ($modulepart == 'apercufichinter') + elseif ($modulepart == 'apercufichinter' && !empty($conf->ficheinter->dir_output)) { if ($fuser->rights->ficheinter->lire) $accessallowed=1; $original_file=$conf->ficheinter->dir_output.'/'.$original_file; } // Wrapping pour les images des stats propales - elseif ($modulepart == 'propalstats') + elseif ($modulepart == 'propalstats' && !empty($conf->propal->dir_temp)) { if ($fuser->rights->propale->lire) $accessallowed=1; $original_file=$conf->propal->dir_temp.'/'.$original_file; } // Wrapping pour les images des stats commandes - elseif ($modulepart == 'orderstats') + elseif ($modulepart == 'orderstats' && !empty($conf->commande->dir_temp)) { if ($fuser->rights->commande->lire) $accessallowed=1; $original_file=$conf->commande->dir_temp.'/'.$original_file; } - elseif ($modulepart == 'orderstatssupplier') + elseif ($modulepart == 'orderstatssupplier' && !empty($conf->fournisseur->dir_output)) { if ($fuser->rights->fournisseur->commande->lire) $accessallowed=1; $original_file=$conf->fournisseur->dir_output.'/commande/temp/'.$original_file; } // Wrapping pour les images des stats factures - elseif ($modulepart == 'billstats') + elseif ($modulepart == 'billstats' && !empty($conf->facture->dir_temp)) { if ($fuser->rights->facture->lire) $accessallowed=1; $original_file=$conf->facture->dir_temp.'/'.$original_file; } - elseif ($modulepart == 'billstatssupplier') + elseif ($modulepart == 'billstatssupplier' && !empty($conf->fournisseur->dir_output)) { if ($fuser->rights->fournisseur->facture->lire) $accessallowed=1; $original_file=$conf->fournisseur->dir_output.'/facture/temp/'.$original_file; } // Wrapping pour les images des stats expeditions - elseif ($modulepart == 'expeditionstats') + elseif ($modulepart == 'expeditionstats' && !empty($conf->expedition->dir_temp)) { if ($fuser->rights->expedition->lire) $accessallowed=1; $original_file=$conf->expedition->dir_temp.'/'.$original_file; } // Wrapping pour les images des stats expeditions - elseif ($modulepart == 'tripsexpensesstats') + elseif ($modulepart == 'tripsexpensesstats' && !empty($conf->deplacement->dir_temp)) { if ($fuser->rights->deplacement->lire) $accessallowed=1; $original_file=$conf->deplacement->dir_temp.'/'.$original_file; } // Wrapping pour les images des stats expeditions - elseif ($modulepart == 'memberstats') + elseif ($modulepart == 'memberstats' && !empty($conf->adherent->dir_temp)) { if ($fuser->rights->adherent->lire) $accessallowed=1; $original_file=$conf->adherent->dir_temp.'/'.$original_file; } // Wrapping pour les images des stats produits - elseif (preg_match('/^productstats_/i',$modulepart)) + elseif (preg_match('/^productstats_/i',$modulepart) && !empty($conf->product->dir_temp)) { if ($fuser->rights->produit->lire || $fuser->rights->service->lire) $accessallowed=1; $original_file=(!empty($conf->product->multidir_temp[$entity])?$conf->product->multidir_temp[$entity]:$conf->service->multidir_temp[$entity]).'/'.$original_file; } // Wrapping for products or services - elseif ($modulepart == 'tax') + elseif ($modulepart == 'tax' && !empty($conf->tax->dir_output)) { if ($fuser->rights->tax->charges->lire) $accessallowed=1; $original_file=$conf->tax->dir_output.'/'.$original_file; } // Wrapping for products or services - elseif ($modulepart == 'actions') + elseif ($modulepart == 'actions' && !empty($conf->agenda->dir_output)) { if ($fuser->rights->agenda->myactions->read) $accessallowed=1; $original_file=$conf->agenda->dir_output.'/'.$original_file; } // Wrapping for categories - elseif ($modulepart == 'category') + elseif ($modulepart == 'category' && !empty($conf->categorie->dir_output)) { if ($fuser->rights->categorie->lire) $accessallowed=1; $original_file=$conf->categorie->multidir_output[$entity].'/'.$original_file; } // Wrapping pour les prelevements - elseif ($modulepart == 'prelevement') + elseif ($modulepart == 'prelevement' && !empty($conf->prelevement->dir_output)) { - if ($fuser->rights->prelevement->bons->lire || preg_match('/^specimen/i',$original_file)) - { - $accessallowed=1; - } + if ($fuser->rights->prelevement->bons->lire || preg_match('/^specimen/i',$original_file)) $accessallowed=1; $original_file=$conf->prelevement->dir_output.'/'.$original_file; } // Wrapping pour les graph energie - elseif ($modulepart == 'graph_stock') + elseif ($modulepart == 'graph_stock' && !empty($conf->stock->dir_temp)) { $accessallowed=1; $original_file=$conf->stock->dir_temp.'/'.$original_file; } // Wrapping pour les graph fournisseurs - elseif ($modulepart == 'graph_fourn') + elseif ($modulepart == 'graph_fourn' && !empty($conf->fournisseur->dir_temp)) { $accessallowed=1; $original_file=$conf->fournisseur->dir_temp.'/'.$original_file; } // Wrapping pour les graph des produits - elseif ($modulepart == 'graph_product') + elseif ($modulepart == 'graph_product' && !empty($conf->product->dir_temp)) { $accessallowed=1; $original_file=$conf->product->multidir_temp[$entity].'/'.$original_file; @@ -1711,32 +1728,31 @@ function dol_check_secure_access_document($modulepart,$original_file,$entity,$fu elseif ($modulepart == 'barcode') { $accessallowed=1; - // If viewimage is called for barcode, we try to output an image on the fly, - // with not build of file on disk. + // If viewimage is called for barcode, we try to output an image on the fly, with no build of file on disk. //$original_file=$conf->barcode->dir_temp.'/'.$original_file; $original_file=''; } // Wrapping pour les icones de background des mailings - elseif ($modulepart == 'iconmailing') + elseif ($modulepart == 'iconmailing' && !empty($conf->mailing->dir_temp)) { $accessallowed=1; $original_file=$conf->mailing->dir_temp.'/'.$original_file; } - // Wrapping pour les icones de background des mailings - elseif ($modulepart == 'scanner_user_temp') + // Wrapping pour le scanner + elseif ($modulepart == 'scanner_user_temp' && !empty($conf->scanner->dir_temp)) { $accessallowed=1; $original_file=$conf->scanner->dir_temp.'/'.$fuser->id.'/'.$original_file; } // Wrapping pour les images fckeditor - elseif ($modulepart == 'fckeditor') + elseif ($modulepart == 'fckeditor' && !empty($conf->fckeditor->dir_output)) { $accessallowed=1; $original_file=$conf->fckeditor->dir_output.'/'.$original_file; } // Wrapping for third parties - else if ($modulepart == 'company' || $modulepart == 'societe') + else if (($modulepart == 'company' || $modulepart == 'societe') && !empty($conf->societe->dir_output)) { if ($fuser->rights->societe->lire || preg_match('/^specimen/i',$original_file)) { @@ -1747,7 +1763,7 @@ function dol_check_secure_access_document($modulepart,$original_file,$entity,$fu } // Wrapping for contact - else if ($modulepart == 'contact') + else if ($modulepart == 'contact' && !empty($conf->societe->dir_output)) { if ($fuser->rights->societe->lire) { @@ -1757,7 +1773,7 @@ function dol_check_secure_access_document($modulepart,$original_file,$entity,$fu } // Wrapping for invoices - else if ($modulepart == 'facture' || $modulepart == 'invoice') + else if (($modulepart == 'facture' || $modulepart == 'invoice') && !empty($conf->facture->dir_output)) { if ($fuser->rights->facture->lire || preg_match('/^specimen/i',$original_file)) { @@ -1766,7 +1782,7 @@ function dol_check_secure_access_document($modulepart,$original_file,$entity,$fu $original_file=$conf->facture->dir_output.'/'.$original_file; $sqlprotectagainstexternals = "SELECT fk_soc as fk_soc FROM ".MAIN_DB_PREFIX."facture WHERE ref='".$db->escape($refname)."' AND entity=".$conf->entity; } - else if ($modulepart == 'massfilesarea_proposals') + else if ($modulepart == 'massfilesarea_proposals' && !empty($conf->propal->dir_output)) { if ($fuser->rights->propal->lire || preg_match('/^specimen/i',$original_file)) { @@ -1791,8 +1807,8 @@ function dol_check_secure_access_document($modulepart,$original_file,$entity,$fu $original_file=$conf->facture->dir_output.'/temp/massgeneration/'.$user->id.'/'.$original_file; } - // Wrapping pour les fiches intervention - else if ($modulepart == 'ficheinter') + // Wrapping for interventions + else if (($modulepart == 'fichinter' || $modulepart == 'ficheinter') && !empty($conf->ficheinter->dir_output)) { if ($fuser->rights->ficheinter->lire || preg_match('/^specimen/i',$original_file)) { @@ -1803,7 +1819,7 @@ function dol_check_secure_access_document($modulepart,$original_file,$entity,$fu } // Wrapping pour les deplacements et notes de frais - else if ($modulepart == 'deplacement') + else if ($modulepart == 'deplacement' && !empty($conf->deplacement->dir_output)) { if ($fuser->rights->deplacement->lire || preg_match('/^specimen/i',$original_file)) { @@ -1813,7 +1829,7 @@ function dol_check_secure_access_document($modulepart,$original_file,$entity,$fu //$sqlprotectagainstexternals = "SELECT fk_soc as fk_soc FROM ".MAIN_DB_PREFIX."fichinter WHERE ref='".$db->escape($refname)."' AND entity=".$conf->entity; } // Wrapping pour les propales - else if ($modulepart == 'propal') + else if ($modulepart == 'propal' && !empty($conf->propal->dir_output)) { if ($fuser->rights->propale->lire || preg_match('/^specimen/i',$original_file)) { @@ -1825,7 +1841,7 @@ function dol_check_secure_access_document($modulepart,$original_file,$entity,$fu } // Wrapping pour les commandes - else if ($modulepart == 'commande' || $modulepart == 'order') + else if (($modulepart == 'commande' || $modulepart == 'order') && !empty($conf->commande->dir_output)) { if ($fuser->rights->commande->lire || preg_match('/^specimen/i',$original_file)) { @@ -1836,7 +1852,7 @@ function dol_check_secure_access_document($modulepart,$original_file,$entity,$fu } // Wrapping pour les projets - else if ($modulepart == 'project') + else if ($modulepart == 'project' && !empty($conf->projet->dir_output)) { if ($fuser->rights->projet->lire || preg_match('/^specimen/i',$original_file)) { @@ -1845,7 +1861,7 @@ function dol_check_secure_access_document($modulepart,$original_file,$entity,$fu $original_file=$conf->projet->dir_output.'/'.$original_file; $sqlprotectagainstexternals = "SELECT fk_soc as fk_soc FROM ".MAIN_DB_PREFIX."projet WHERE ref='".$db->escape($refname)."' AND entity IN (".getEntity('project', 1).")"; } - else if ($modulepart == 'project_task') + else if ($modulepart == 'project_task' && !empty($conf->projet->dir_output)) { if ($fuser->rights->projet->lire || preg_match('/^specimen/i',$original_file)) { @@ -1854,19 +1870,9 @@ function dol_check_secure_access_document($modulepart,$original_file,$entity,$fu $original_file=$conf->projet->dir_output.'/'.$original_file; $sqlprotectagainstexternals = "SELECT fk_soc as fk_soc FROM ".MAIN_DB_PREFIX."projet WHERE ref='".$db->escape($refname)."' AND entity IN (".getEntity('project', 1).")"; } - // Wrapping for interventions - else if ($modulepart == 'fichinter') - { - if ($fuser->rights->ficheinter->lire || preg_match('/^specimen/i',$original_file)) - { - $accessallowed=1; - } - $original_file=$conf->ficheinter->dir_output.'/'.$original_file; - $sqlprotectagainstexternals = "SELECT fk_soc as fk_soc FROM ".MAIN_DB_PREFIX."fichinter WHERE ref='".$db->escape($refname)."' AND entity=".$conf->entity; - } // Wrapping pour les commandes fournisseurs - else if ($modulepart == 'commande_fournisseur' || $modulepart == 'order_supplier') + else if (($modulepart == 'commande_fournisseur' || $modulepart == 'order_supplier') && !empty($conf->fournisseur->commande->dir_output)) { if ($fuser->rights->fournisseur->commande->lire || preg_match('/^specimen/i',$original_file)) { @@ -1877,7 +1883,7 @@ function dol_check_secure_access_document($modulepart,$original_file,$entity,$fu } // Wrapping pour les factures fournisseurs - else if ($modulepart == 'facture_fournisseur' || $modulepart == 'invoice_supplier') + else if (($modulepart == 'facture_fournisseur' || $modulepart == 'invoice_supplier') && !empty($conf->fournisseur->facture->dir_output)) { if ($fuser->rights->fournisseur->facture->lire || preg_match('/^specimen/i',$original_file)) { @@ -1898,7 +1904,7 @@ function dol_check_secure_access_document($modulepart,$original_file,$entity,$fu } // Wrapping pour les rapport de paiements - else if ($modulepart == 'facture_paiement') + else if ($modulepart == 'facture_paiement' && !empty($conf->facture->dir_output)) { if ($fuser->rights->facture->lire || preg_match('/^specimen/i',$original_file)) { @@ -1909,7 +1915,7 @@ function dol_check_secure_access_document($modulepart,$original_file,$entity,$fu } // Wrapping for accounting exports - else if ($modulepart == 'export_compta') + else if ($modulepart == 'export_compta' && !empty($conf->accounting->dir_output)) { if ($fuser->rights->accounting->bind->write || preg_match('/^specimen/i',$original_file)) { @@ -1919,7 +1925,7 @@ function dol_check_secure_access_document($modulepart,$original_file,$entity,$fu } // Wrapping pour les expedition - else if ($modulepart == 'expedition') + else if ($modulepart == 'expedition' && !empty($conf->expedition->dir_output)) { if ($fuser->rights->expedition->lire || preg_match('/^specimen/i',$original_file)) { @@ -1929,7 +1935,7 @@ function dol_check_secure_access_document($modulepart,$original_file,$entity,$fu } // Wrapping pour les bons de livraison - else if ($modulepart == 'livraison') + else if ($modulepart == 'livraison' && !empty($conf->livraison->dir_output)) { if ($fuser->rights->expedition->livraison->lire || preg_match('/^specimen/i',$original_file)) { @@ -1939,7 +1945,7 @@ function dol_check_secure_access_document($modulepart,$original_file,$entity,$fu } // Wrapping pour les actions - else if ($modulepart == 'actions') + else if ($modulepart == 'actions' && !empty($conf->agenda->dir_output)) { if ($fuser->rights->agenda->myactions->read || preg_match('/^specimen/i',$original_file)) { @@ -1949,7 +1955,7 @@ function dol_check_secure_access_document($modulepart,$original_file,$entity,$fu } // Wrapping pour les actions - else if ($modulepart == 'actionsreport') + else if ($modulepart == 'actionsreport' && !empty($conf->agenda->dir_temp)) { if ($fuser->rights->agenda->allactions->read || preg_match('/^specimen/i',$original_file)) { @@ -1970,7 +1976,7 @@ function dol_check_secure_access_document($modulepart,$original_file,$entity,$fu } // Wrapping pour les contrats - else if ($modulepart == 'contract') + else if ($modulepart == 'contract' && !empty($conf->contrat->dir_output)) { if ($fuser->rights->contrat->lire || preg_match('/^specimen/i',$original_file)) { @@ -1981,7 +1987,7 @@ function dol_check_secure_access_document($modulepart,$original_file,$entity,$fu } // Wrapping pour les dons - else if ($modulepart == 'donation') + else if ($modulepart == 'donation' && !empty($conf->donation->dir_output)) { if ($fuser->rights->don->lire || preg_match('/^specimen/i',$original_file)) { @@ -1991,7 +1997,7 @@ function dol_check_secure_access_document($modulepart,$original_file,$entity,$fu } // Wrapping pour les remises de cheques - else if ($modulepart == 'remisecheque') + else if ($modulepart == 'remisecheque' && !empty($conf->banque->dir_output)) { if ($fuser->rights->banque->lire || preg_match('/^specimen/i',$original_file)) { @@ -2002,7 +2008,7 @@ function dol_check_secure_access_document($modulepart,$original_file,$entity,$fu } // Wrapping for bank - else if ($modulepart == 'bank') + else if ($modulepart == 'bank' && !empty($conf->bank->dir_output)) { if ($fuser->rights->banque->lire) { @@ -2012,7 +2018,7 @@ function dol_check_secure_access_document($modulepart,$original_file,$entity,$fu } // Wrapping for export module - else if ($modulepart == 'export') + else if ($modulepart == 'export' && !empty($conf->export->dir_temp)) { // Aucun test necessaire car on force le rep de download sur // le rep export qui est propre a l'utilisateur @@ -2021,21 +2027,21 @@ function dol_check_secure_access_document($modulepart,$original_file,$entity,$fu } // Wrapping for import module - else if ($modulepart == 'import') + else if ($modulepart == 'import' && !empty($conf->import->dir_temp)) { $accessallowed=1; $original_file=$conf->import->dir_temp.'/'.$original_file; } // Wrapping pour l'editeur wysiwyg - else if ($modulepart == 'editor') + else if ($modulepart == 'editor' && !empty($conf->fckeditor->dir_output)) { $accessallowed=1; $original_file=$conf->fckeditor->dir_output.'/'.$original_file; } // Wrapping for miscellaneous medias files - elseif ($modulepart == 'medias') + elseif ($modulepart == 'medias' && !empty($dolibarr_main_data_root)) { $accessallowed=1; global $dolibarr_main_data_root; @@ -2043,25 +2049,21 @@ function dol_check_secure_access_document($modulepart,$original_file,$entity,$fu } // Wrapping for backups - else if ($modulepart == 'systemtools') + else if ($modulepart == 'systemtools' && !empty($conf->admin->dir_output)) { - if ($fuser->admin) - { - $accessallowed=1; - } + if ($fuser->admin) $accessallowed=1; $original_file=$conf->admin->dir_output.'/'.$original_file; } // Wrapping for upload file test - else if ($modulepart == 'admin_temp') + else if ($modulepart == 'admin_temp' && !empty($conf->admin->dir_temp)) { - if ($fuser->admin) - $accessallowed=1; + if ($fuser->admin) $accessallowed=1; $original_file=$conf->admin->dir_temp.'/'.$original_file; } // Wrapping pour BitTorrent - else if ($modulepart == 'bittorrent') + else if ($modulepart == 'bittorrent' && !empty($conf->bittorrent->dir_output)) { $accessallowed=1; $dir='files'; @@ -2070,7 +2072,7 @@ function dol_check_secure_access_document($modulepart,$original_file,$entity,$fu } // Wrapping pour Foundation module - else if ($modulepart == 'member') + else if ($modulepart == 'member' && !empty($conf->adherent->dir_output)) { if ($fuser->rights->adherent->lire || preg_match('/^specimen/i',$original_file)) { @@ -2080,7 +2082,7 @@ function dol_check_secure_access_document($modulepart,$original_file,$entity,$fu } // Wrapping for Scanner - else if ($modulepart == 'scanner_user_temp') + else if ($modulepart == 'scanner_user_temp' && !empty($conf->scanner->dir_temp)) { $accessallowed=1; $original_file=$conf->scanner->dir_temp.'/'.$fuser->id.'/'.$original_file; @@ -2093,20 +2095,38 @@ function dol_check_secure_access_document($modulepart,$original_file,$entity,$fu // If modulepart=module Allows any module to open a file if file is in directory called DOL_DATA_ROOT/modulepart else { + if (preg_match('/^specimen/i',$original_file)) $accessallowed=1; // If link to a file called specimen. Test must be done before changing $original_file int full path. + if ($fuser->admin) $accessallowed=1; // If user is admin + // Define $accessallowed if (preg_match('/^([a-z]+)_user_temp$/i',$modulepart,$reg)) { - if ($fuser->rights->{$reg[1]}->lire || $fuser->rights->{$reg[1]}->read || ($fuser->rights->{$reg[1]}->download)) $accessallowed=1; + if (empty($conf->{$reg[1]}->dir_temp)) // modulepart not supported + { + dol_print_error('','Error call dol_check_secure_access_document with not supported value for modulepart parameter ('.$modulepart.')'); + exit; + } + if ($fuser->rights->{$reg[1]}->lire || $fuser->rights->{$reg[1]}->read || ($fuser->rights->{$reg[1]}->download)) $accessallowed=1; $original_file=$conf->{$reg[1]}->dir_temp.'/'.$fuser->id.'/'.$original_file; } else if (preg_match('/^([a-z]+)_temp$/i',$modulepart,$reg)) { - if ($fuser->rights->{$reg[1]}->lire || $fuser->rights->{$reg[1]}->read || ($fuser->rights->{$reg[1]}->download)) $accessallowed=1; + if (empty($conf->{$reg[1]}->dir_temp)) // modulepart not supported + { + dol_print_error('','Error call dol_check_secure_access_document with not supported value for modulepart parameter ('.$modulepart.')'); + exit; + } + if ($fuser->rights->{$reg[1]}->lire || $fuser->rights->{$reg[1]}->read || ($fuser->rights->{$reg[1]}->download)) $accessallowed=1; $original_file=$conf->{$reg[1]}->dir_temp.'/'.$original_file; } else if (preg_match('/^([a-z]+)_user$/i',$modulepart,$reg)) { - if ($fuser->rights->{$reg[1]}->lire || $fuser->rights->{$reg[1]}->read || ($fuser->rights->{$reg[1]}->download)) $accessallowed=1; + if (empty($conf->{$reg[1]}->dir_output)) // modulepart not supported + { + dol_print_error('','Error call dol_check_secure_access_document with not supported value for modulepart parameter ('.$modulepart.')'); + exit; + } + if ($fuser->rights->{$reg[1]}->lire || $fuser->rights->{$reg[1]}->read || ($fuser->rights->{$reg[1]}->download)) $accessallowed=1; $original_file=$conf->{$reg[1]}->dir_output.'/'.$fuser->id.'/'.$original_file; } else @@ -2130,8 +2150,6 @@ function dol_check_secure_access_document($modulepart,$original_file,$entity,$fu $original_file=$conf->$modulepart->dir_output.'/'.$original_file; } } - if (preg_match('/^specimen/i',$original_file)) $accessallowed=1; // If link to a specimen - if ($fuser->admin) $accessallowed=1; // If user is admin // For modules who wants to manage different levels of permissions for documents $subPermCategoryConstName = strtoupper($modulepart).'_SUBPERMCATEGORY_FOR_DOCUMENTS'; @@ -2163,7 +2181,7 @@ function dol_check_secure_access_document($modulepart,$original_file,$entity,$fu } /** - * Store object in file + * Store object in file. * * @param string $directory Directory of cache * @param string $filename Name of filecache @@ -2179,7 +2197,7 @@ function dol_filecache($directory, $filename, $object) } /** - * Test if Refresh needed + * Test if Refresh needed. * * @param string $directory Directory of cache * @param string $filename Name of filecache @@ -2195,7 +2213,7 @@ function dol_cache_refresh($directory, $filename, $cachetime) } /** - * Read object from cachefile + * Read object from cachefile. * * @param string $directory Directory of cache * @param string $filename Name of filecache diff --git a/htdocs/core/login/functions_dolibarr.php b/htdocs/core/login/functions_dolibarr.php index ee162bd9cc802727e0c250ce12f140d7e6073539..daf82b2f9956a61b9ad8601f45647be55f63f168 100644 --- a/htdocs/core/login/functions_dolibarr.php +++ b/htdocs/core/login/functions_dolibarr.php @@ -47,7 +47,7 @@ function check_user_password_dolibarr($usertotest,$passwordtotest,$entitytotest= { dol_syslog("functions_dolibarr::check_user_password_dolibarr usertotest=".$usertotest." passwordtotest=".preg_replace('/./','*',$passwordtotest)." entitytotest=".$entitytotest); - // If test username/password asked, we define $test=false and $login var if ok, set $_SESSION["dol_loginmesg"] if ko + // If test username/password asked, we define $test=false if ko and $login var to login if ok, set also $_SESSION["dol_loginmesg"] if ko $table = MAIN_DB_PREFIX."user"; $usernamecol1 = 'login'; $usernamecol2 = 'email'; @@ -59,6 +59,9 @@ function check_user_password_dolibarr($usertotest,$passwordtotest,$entitytotest= if (preg_match('/@/',$usertotest)) $sql.=' OR '.$usernamecol2." = '".$db->escape($usertotest)."'"; $sql.=') AND '.$entitycol." IN (0," . ($entity ? $entity : 1) . ")"; $sql.=' AND statut = 1'; + // Required to first found the user into entity, then the superadmin. + // For the case (TODO and that we must avoid) a user has renamed its login with same value than a user in entity 0. + $sql.=' ORDER BY entity DESC'; $resql=$db->query($sql); if ($resql) diff --git a/htdocs/fourn/class/fournisseur.commande.class.php b/htdocs/fourn/class/fournisseur.commande.class.php index 053e5b314d640ef2d9d7f5710bab023e06042f9a..fb1a3168c3d9354f1038047c826e6e25877521ef 100644 --- a/htdocs/fourn/class/fournisseur.commande.class.php +++ b/htdocs/fourn/class/fournisseur.commande.class.php @@ -2957,7 +2957,8 @@ class CommandeFournisseurLigne extends CommonOrderLine $sql.= ' cd.info_bits, cd.total_ht, cd.total_tva, cd.total_ttc,'; $sql.= ' cd.total_localtax1, cd.total_localtax2,'; $sql.= ' p.ref as product_ref, p.label as product_libelle, p.description as product_desc,'; - $sql.= ' cd.date_start, cd.date_end, cd.fk_unit'; + $sql.= ' cd.date_start, cd.date_end, cd.fk_unit,'; + $sql.= ' cd.multicurrency_subprice, cd.multicurrency_total_ht, cd.multicurrency_total_tva, cd.multicurrency_total_ttc'; $sql.= ' FROM '.MAIN_DB_PREFIX.'commande_fournisseurdet as cd'; $sql.= ' LEFT JOIN '.MAIN_DB_PREFIX.'product as p ON cd.fk_product = p.rowid'; $sql.= ' WHERE cd.rowid = '.$rowid; @@ -2965,6 +2966,7 @@ class CommandeFournisseurLigne extends CommonOrderLine if ($result) { $objp = $this->db->fetch_object($result); + $this->rowid = $objp->rowid; $this->id = $objp->rowid; $this->fk_commande = $objp->fk_commande; @@ -2992,10 +2994,15 @@ class CommandeFournisseurLigne extends CommonOrderLine $this->product_libelle = $objp->product_libelle; $this->product_desc = $objp->product_desc; - $this->date_start = $this->db->jdate($objp->date_start); - $this->date_end = $this->db->jdate($objp->date_end); - $this->fk_unit = $objp->fk_unit; - + $this->date_start = $this->db->jdate($objp->date_start); + $this->date_end = $this->db->jdate($objp->date_end); + $this->fk_unit = $objp->fk_unit; + + $this->multicurrency_subprice = $objp->multicurrency_subprice; + $this->multicurrency_total_ht = $objp->multicurrency_total_ht; + $this->multicurrency_total_tva = $objp->multicurrency_total_tva; + $this->multicurrency_total_ttc = $objp->multicurrency_total_ttc; + $this->db->free($result); return 1; } diff --git a/htdocs/fourn/class/fournisseur.facture.class.php b/htdocs/fourn/class/fournisseur.facture.class.php index 5602f573e90c1b879dd42e00ed099ce24e13fdde..009f765e5cddce66a0bd2a597de843ed03f19a99 100644 --- a/htdocs/fourn/class/fournisseur.facture.class.php +++ b/htdocs/fourn/class/fournisseur.facture.class.php @@ -2385,8 +2385,9 @@ class SupplierInvoiceLine extends CommonObjectLine { $sql = 'SELECT f.rowid, f.ref as ref_supplier, f.description, f.pu_ht, f.pu_ttc, f.qty, f.remise_percent, f.tva_tx'; $sql.= ', f.localtax1_type, f.localtax2_type, f.localtax1_tx, f.localtax2_tx, f.total_localtax1, f.total_localtax2 '; - $sql.= ', f.total_ht, f.tva as total_tva, f.total_ttc, f.fk_product, f.product_type, f.info_bits, f.rang, f.special_code, f.fk_parent_line, f.fk_unit'; + $sql.= ', f.total_ht, f.tva as total_tva, f.total_ttc, f.fk_facture_fourn, f.fk_product, f.product_type, f.info_bits, f.rang, f.special_code, f.fk_parent_line, f.fk_unit'; $sql.= ', p.rowid as product_id, p.ref as product_ref, p.label as label, p.description as product_desc'; + $sql.= ', f.multicurrency_subprice, f.multicurrency_total_ht, f.multicurrency_total_tva, multicurrency_total_ttc'; $sql.= ' FROM '.MAIN_DB_PREFIX.'facture_fourn_det as f'; $sql.= ' LEFT JOIN '.MAIN_DB_PREFIX.'product as p ON f.fk_product = p.rowid'; $sql.= ' WHERE f.rowid = '.$rowid; @@ -2407,6 +2408,7 @@ class SupplierInvoiceLine extends CommonObjectLine $this->id = $obj->rowid; $this->rowid = $obj->rowid; + $this->fk_facture_fourn = $obj->fk_facture_fourn; $this->description = $obj->description; $this->product_ref = $obj->product_ref; $this->ref = $obj->product_ref; @@ -2439,6 +2441,11 @@ class SupplierInvoiceLine extends CommonObjectLine $this->rang = $obj->rang; $this->fk_unit = $obj->fk_unit; + $this->multicurrency_subprice = $obj->multicurrency_subprice; + $this->multicurrency_total_ht = $obj->multicurrency_total_ht; + $this->multicurrency_total_tva = $obj->multicurrency_total_tva; + $this->multicurrency_total_ttc = $obj->multicurrency_total_ttc; + return 1; } diff --git a/htdocs/fourn/commande/card.php b/htdocs/fourn/commande/card.php index 2a7744a97b7a1db54d0d8bb854b184b5d8f98788..b8ea51b85679ebcfbe749e76c1574cfb4636e402 100644 --- a/htdocs/fourn/commande/card.php +++ b/htdocs/fourn/commande/card.php @@ -1805,7 +1805,7 @@ elseif (! empty($object->id)) $morehtmlref.='<form method="post" action="'.$_SERVER['PHP_SELF'].'?id='.$object->id.'">'; $morehtmlref.='<input type="hidden" name="action" value="classin">'; $morehtmlref.='<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">'; - $morehtmlref.=$formproject->select_projects($object->socid, $object->fk_project, 'projectid', $maxlength, 0, 1, 0, 1, 0, 0, '', 1); + $morehtmlref.=$formproject->select_projects((empty($conf->global->PROJECT_CAN_ALWAYS_LINK_TO_ALL_SUPPLIERS)?$object->socid:-1), $object->fk_project, 'projectid', $maxlength, 0, 1, 0, 1, 0, 0, '', 1); $morehtmlref.='<input type="submit" class="button valignmiddle" value="'.$langs->trans("Modify").'">'; $morehtmlref.='</form>'; } else { diff --git a/htdocs/fourn/facture/card.php b/htdocs/fourn/facture/card.php index 9549cbd879db25725e2225b181e3921d1d9a3454..8a73f783642600d1505679cb583053a4f967083a 100644 --- a/htdocs/fourn/facture/card.php +++ b/htdocs/fourn/facture/card.php @@ -2053,7 +2053,7 @@ else $morehtmlref.='<form method="post" action="'.$_SERVER['PHP_SELF'].'?id='.$object->id.'">'; $morehtmlref.='<input type="hidden" name="action" value="classin">'; $morehtmlref.='<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">'; - $morehtmlref.=$formproject->select_projects($object->socid, $object->fk_project, 'projectid', $maxlength, 0, 1, 0, 1, 0, 0, '', 1); + $morehtmlref.=$formproject->select_projects((empty($conf->global->PROJECT_CAN_ALWAYS_LINK_TO_ALL_SUPPLIERS)?$object->socid:-1), $object->fk_project, 'projectid', $maxlength, 0, 1, 0, 1, 0, 0, '', 1); $morehtmlref.='<input type="submit" class="button valignmiddle" value="'.$langs->trans("Modify").'">'; $morehtmlref.='</form>'; } else { @@ -2454,6 +2454,7 @@ else print $langs->trans('AlreadyPaid'); print ' :</td><td align="right"'.(($totalpaye > 0)?' class="amountalreadypaid"':'').'>' . price($totalpaye) . '</td><td> </td></tr>'; + $resteapayer = $object->total_ttc - $totalpaye; $resteapayeraffiche = $resteapayer; $cssforamountpaymentcomplete = 'amountpaymentcomplete'; diff --git a/htdocs/langs/en_US/accountancy.lang b/htdocs/langs/en_US/accountancy.lang index f51493c276349390bec09850bd4495f8c944d1ca..d8313e2a11bbe22553d23734576192f11601f1a1 100644 --- a/htdocs/langs/en_US/accountancy.lang +++ b/htdocs/langs/en_US/accountancy.lang @@ -105,9 +105,9 @@ ACCOUNTING_LIST_SORT_VENTILATION_DONE=Begin the sorting of the page "Binding don ACCOUNTING_LENGTH_DESCRIPTION=Truncate product & services description in listings after x chars (Best = 50) ACCOUNTING_LENGTH_DESCRIPTION_ACCOUNT=Truncate product & services account description form in listings after x chars (Best = 50) -ACCOUNTING_LENGTH_GACCOUNT=Length of the general accounting accounts -ACCOUNTING_LENGTH_AACCOUNT=Length of the third party accounting accounts -ACCOUNTING_MANAGE_ZERO=Manage the zero at the end of an accounting account. Needed by some countries. Disabled by default. If set to on, you must also set the 2 following parameters (or it is ignored) +ACCOUNTING_LENGTH_GACCOUNT=Length of the general accounting accounts (If you set value to 6 here, the account '706' will appear like '706000' on screen) +ACCOUNTING_LENGTH_AACCOUNT=Length of the third party accounting accounts (If you set value to 6 here, the account '401' will appear like '401000' on screen) +ACCOUNTING_MANAGE_ZERO=Allow to manage different number of zero at the end of an accounting account. Needed by some countries (like switzerland). If keep to off (default), you can set the 2 following parameters to ask application to add virtual zero. BANK_DISABLE_DIRECT_INPUT=Disable direct recording of transaction in bank account ACCOUNTING_SELL_JOURNAL=Sell journal diff --git a/htdocs/product/stock/class/mouvementstock.class.php b/htdocs/product/stock/class/mouvementstock.class.php index e6631d4b716401974578579797997289e61dd46a..c90af069fdabc1be4a12a538879da845378bdd02 100644 --- a/htdocs/product/stock/class/mouvementstock.class.php +++ b/htdocs/product/stock/class/mouvementstock.class.php @@ -277,7 +277,7 @@ class MouvementStock extends CommonObject // Check if stock is enough when qty is < 0 // Note that qty should be > 0 with type 0 or 3, < 0 with type 1 or 2. - if ($qty < 0 && empty($conf->global->STOCK_ALLOW_NEGATIVE_TRANSFER)) + if ($movestock && $qty < 0 && empty($conf->global->STOCK_ALLOW_NEGATIVE_TRANSFER)) { if (! empty($conf->productbatch->enabled) && $product->hasbatch() && ! $skip_batch) { @@ -292,6 +292,7 @@ class MouvementStock extends CommonObject } if (! $foundforbatch || $qtyisnotenough) { + $langs->load("stocks"); $this->error = $langs->trans('qtyToTranferLotIsNotEnough'); $this->errors[] = $langs->trans('qtyToTranferLotIsNotEnough'); $this->db->rollback(); @@ -302,6 +303,7 @@ class MouvementStock extends CommonObject { if (empty($product->stock_warehouse[$entrepot_id]->real) || $product->stock_warehouse[$entrepot_id]->real < abs($qty)) { + $langs->load("stocks"); $this->error = $langs->trans('qtyToTranferIsNotEnough'); $this->errors[] = $langs->trans('qtyToTranferIsNotEnough'); $this->db->rollback();