diff --git a/ChangeLog b/ChangeLog index bef57215417..16811fd8f8b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -16,6 +16,7 @@ NEW: Accountancy - add options to disable binding on sales, purchases & expense NEW: Accountancy balance - add a menu entry to show subtotal by group NEW: Accountancy - move to real ledger, real journals, menu disposition NEW: Accountancy - on transfers, select the periodicity by default +NEW: Accountancy - Add export for Gestinum (v3 & v5) NEW: new currency rate editor NEW: add 2 rules for emailcollector: Message send/not sent from Dolibarr NEW: add a counter of number of words for pages in website module diff --git a/build/debian/copyright b/build/debian/copyright index 7b199adf693..d5fdf416a65 100644 --- a/build/debian/copyright +++ b/build/debian/copyright @@ -1,4 +1,4 @@ -Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ Upstream-Name: Dolibarr Upstream-Contact: Laurent Destailleur Source: https://www.dolibarr.org/files/stable/standard/ @@ -38,6 +38,7 @@ Copyright: 2002-2009, Rodolphe Quiedeville 2011, Herve Prot 2011, Remy Younes 2012-2013, Christophe Battarel + License: GPL-3+ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public @@ -56,7 +57,9 @@ License: GPL-3+ . On Debian systems, the full text of the GNU General Public License version 3 can be found in the file - `/usr/share/common-licenses/GPL-3'. + '/usr/share/common-licenses/GPL-3'. + +------------------------------------------------------------ Files: htdocs/includes/adodbtime/* Copyright: 2003-2005, John Lim @@ -80,6 +83,9 @@ Comment: Those files are not shipped in the binary package since we use the library as packaged in "libphp-adodb". + +------------------------------------------------------------ + Files: htdocs/includes/ckeditor/* Copyright: 2003-2012 CKSource - Frederico Knabben License: GPL-2+ @@ -109,6 +115,9 @@ Comment: Those files are not shipped in the binary package since we use the library as packaged in "ckeditor". + +------------------------------------------------------------ + Files: htdocs/includes/fonts/* Copyright: 2003, Bitstream Inc unknown, Gavin Graham @@ -158,7 +167,10 @@ License: other Comments: Those files are not shipped in the binary package as we configure Dolibarr to use Dejavu fonts from "fonts-dejavu-core". - + + +------------------------------------------------------------ + Files: doc/images/* Copyright: Laurent Destailleur License: CC-BY-SA-3.0 @@ -174,7 +186,10 @@ License: CC-BY-SA-3.0 distribute the resulting work only under the same, similar or a compatible license. . - For more information, see http://creativecommons.org/licenses/by-sa/3.0/ + For more information, see https://creativecommons.org/licenses/by-sa/3.0/ + + +------------------------------------------------------------ Files: htdocs/includes/fpdfi/* Copyright: 2004-2011 Setasign - Jan Slabon @@ -196,7 +211,10 @@ License: GPL-2+ . On Debian systems, the full text of the GNU General Public License version 2 can be found in the file - `/usr/share/common-licenses/GPL-2'. + '/usr/share/common-licenses/GPL-2'. + + +------------------------------------------------------------ Files: htdocs/includes/geoip/* Copyright: 2007 MaxMind LLC @@ -216,10 +234,14 @@ License: LGPL-2.1+ . On Debian systems, the full text of the GNU Lesser General Public License version 2.1 can be found in the file - `/usr/share/common-licenses/LGPL-2.1'. + '/usr/share/common-licenses/LGPL-2.1'. + + +------------------------------------------------------------ Files: htdocs/includes/jquery/* Copyright: JQuery team +https://www.jquery.com License: GPL-2+ or MIT === GPL-2+ LICENSE NOTICE === . @@ -240,7 +262,7 @@ License: GPL-2+ or MIT . On Debian systems, the full text of the GNU General Public License version 2 can be found in the file - `/usr/share/common-licenses/GPL-2'. + '/usr/share/common-licenses/GPL-2'. . === MIT LICENSE === . @@ -267,6 +289,8 @@ Comment: "libjs-jquery-ui". Most of the plugins are shipped though. +------------------------------------------------------------ + Files: htdocs/includes/jquery/plugins/flot/* Copyright: Flot team License: Public-Domain @@ -275,6 +299,9 @@ Comment: Those files are not shipped in the binary package because we configure Dolibarr to use the files provided by "libjs-flot". + +------------------------------------------------------------ + Files: htdocs/includes/jsgantt/* Copyright: JSGantt team License: GPL-2+ @@ -295,7 +322,10 @@ License: GPL-2+ . On Debian systems, the full text of the GNU General Public License version 2 can be found in the file - `/usr/share/common-licenses/GPL-2'. + '/usr/share/common-licenses/GPL-2'. + + +------------------------------------------------------------ Files: htdocs/includes/nusoap/* Copyright: 2002-2010 NuSphere Corporation @@ -315,11 +345,14 @@ License: LGPL-2.1+ . On Debian systems, the full text of the GNU Lesser General Public License version 2.1 can be found in the file - `/usr/share/common-licenses/LGPL-2.1'. + '/usr/share/common-licenses/LGPL-2.1'. Comment: Those files are not shipped in the binary package since we configure Dolibarr to use the library provided in "libnusoap-php". + +------------------------------------------------------------ + Files: htdocs/includes/odtphp/* Copyright: 2008, Julien Pauli 2008, Cyril PIERRE de GEYER @@ -342,7 +375,10 @@ License: GPL-2+ . On Debian systems, the full text of the GNU General Public License version 2 can be found in the file - `/usr/share/common-licenses/GPL-2'. + '/usr/share/common-licenses/GPL-2'. + + +------------------------------------------------------------ Files: htdocs/includes/phpexcel/* Copyright: 2006-2011 PHPExcel (http://www.codeplex.com/PHPExcel) @@ -362,7 +398,10 @@ License: LGPL-2.1+ . On Debian systems, the full text of the GNU Lesser General Public License version 2.1 can be found in the file - `/usr/share/common-licenses/LGPL-2.1'. + '/usr/share/common-licenses/LGPL-2.1'. + + +------------------------------------------------------------ Files: htdocs/includes/tcpdf/* Copyright: 2002-2013 Nicola Asuni - Tecnick.com LTD diff --git a/dev/translation/README b/dev/translation/README index 9727f91e2e6..8d6954878b5 100644 --- a/dev/translation/README +++ b/dev/translation/README @@ -2,13 +2,18 @@ README (English) -------------------------------- This directory contains tools to generate translation files for a new languages or to update translation files for existing languages. + See Dolibarr Wiki page: https://wiki.dolibarr.org/index.php/Translator_documentation For more information on how to use them. -for Linux OS: -To install transifex client: +Translation of Dolibarr Project at Transifex: +https://www.transifex.com/dolibarr-association/dolibarr/dashboard/ + + +Installation of Transifex Client: +--------------------------------- +for Linux OS +to install or to update transifex client: sudo pip install --upgrade transifex-client -To update transifex client: -sudo pip install --upgrade transifex-client diff --git a/doc/install/README-FR b/doc/install/README-FR index 2cee29cf2df..5872ec0e3d1 100644 --- a/doc/install/README-FR +++ b/doc/install/README-FR @@ -6,13 +6,14 @@ README (french) Téléchargement -------------------------------- -* Dolibarr ERP/CRM can be downloaded at sourceforge: -http://sourceforge.net/projects/dolibarr/files -or from Dolibarr official web site: +* Dolibarr ERP/CRM peut être téléchargé sur sourceforge: +https://sourceforge.net/projects/dolibarr/files + +ou sur le site officiel de Dolibarr: https://www.dolibarr.org -* Most external modules are only available on DoliStore: -https://www.dolistore.org +* La plupart des modules externes ne sont disponibles que sur le DoliStore officiel: +https://www.dolistore.com -------------------------------- @@ -24,4 +25,4 @@ README-FR à la racine. * Une documentation utilisateur francophone plus consistante est disponible en ligne sur le wiki de Dolibarr à l'adresse: -https://wiki.dolibarr.org +https://wiki.dolibarr.org/index.php/Accueil diff --git a/htdocs/accountancy/class/accountancyexport.class.php b/htdocs/accountancy/class/accountancyexport.class.php index c36a0c8f906..51e66f3360c 100644 --- a/htdocs/accountancy/class/accountancyexport.class.php +++ b/htdocs/accountancy/class/accountancyexport.class.php @@ -57,6 +57,8 @@ class AccountancyExport public static $EXPORT_TYPE_OPENCONCERTO = 100; public static $EXPORT_TYPE_LDCOMPTA = 110; public static $EXPORT_TYPE_LDCOMPTA10 = 120; + public static $EXPORT_TYPE_GESTINUMV3 = 130; + public static $EXPORT_TYPE_GESTINUMV5 = 135; public static $EXPORT_TYPE_FEC = 1000; @@ -113,10 +115,12 @@ class AccountancyExport self::$EXPORT_TYPE_AGIRIS => $langs->trans('Modelcsv_agiris'), self::$EXPORT_TYPE_OPENCONCERTO => $langs->trans('Modelcsv_openconcerto'), self::$EXPORT_TYPE_SAGE50_SWISS => $langs->trans('Modelcsv_Sage50_Swiss'), + self::$EXPORT_TYPE_CHARLEMAGNE => $langs->trans('Modelcsv_charlemagne'), self::$EXPORT_TYPE_LDCOMPTA => $langs->trans('Modelcsv_LDCompta'), self::$EXPORT_TYPE_LDCOMPTA10 => $langs->trans('Modelcsv_LDCompta10'), + self::$EXPORT_TYPE_GESTINUMV3 => $langs->trans('Modelcsv_Gestinum_v3'), + self::$EXPORT_TYPE_GESTINUMV5 => $langs->trans('Modelcsv_Gestinum_v5'), self::$EXPORT_TYPE_FEC => $langs->trans('Modelcsv_FEC'), - self::$EXPORT_TYPE_CHARLEMAGNE => $langs->trans('Modelcsv_charlemagne'), ); ksort($listofexporttypes, SORT_NUMERIC); @@ -144,9 +148,12 @@ class AccountancyExport self::$EXPORT_TYPE_COGILOG => 'cogilog', self::$EXPORT_TYPE_AGIRIS => 'agiris', self::$EXPORT_TYPE_OPENCONCERTO => 'openconcerto', - self::$EXPORT_TYPE_SAGE50_SWISS => 'sage50ch', - self::$EXPORT_TYPE_LDCOMPTA => 'ldcompta', - self::$EXPORT_TYPE_LDCOMPTA10 => 'ldcompta10', + self::$EXPORT_TYPE_SAGE50_SWISS => 'sage50ch', + self::$EXPORT_TYPE_CHARLEMAGNE => 'charlemagne', + self::$EXPORT_TYPE_LDCOMPTA => 'ldcompta', + self::$EXPORT_TYPE_LDCOMPTA10 => 'ldcompta10', + self::$EXPORT_TYPE_GESTINUMV3 => 'gestinumv3', + self::$EXPORT_TYPE_GESTINUMV5 => 'gestinumv5', self::$EXPORT_TYPE_FEC => 'fec', ); @@ -201,30 +208,32 @@ class AccountancyExport self::$EXPORT_TYPE_AGIRIS => array( 'label' => $langs->trans('Modelcsv_agiris'), ), - self::$EXPORT_TYPE_OPENCONCERTO => array( - 'label' => $langs->trans('Modelcsv_openconcerto'), - 'ACCOUNTING_EXPORT_FORMAT' => 'csv', - ), + self::$EXPORT_TYPE_OPENCONCERTO => array( + 'label' => $langs->trans('Modelcsv_openconcerto'), + ), self::$EXPORT_TYPE_SAGE50_SWISS => array( 'label' => $langs->trans('Modelcsv_Sage50_Swiss'), - 'ACCOUNTING_EXPORT_FORMAT' => 'csv', - ), - self::$EXPORT_TYPE_LDCOMPTA => array( - 'label' => $langs->trans('Modelcsv_LDCompta'), - 'ACCOUNTING_EXPORT_FORMAT' => 'csv', - ), - self::$EXPORT_TYPE_LDCOMPTA10 => array( - 'label' => $langs->trans('Modelcsv_LDCompta10'), - 'ACCOUNTING_EXPORT_FORMAT' => 'csv', - ), - self::$EXPORT_TYPE_FEC => array( - 'label' => $langs->trans('Modelcsv_FEC'), - 'ACCOUNTING_EXPORT_FORMAT' => 'txt', ), self::$EXPORT_TYPE_CHARLEMAGNE => array( 'label' => $langs->trans('Modelcsv_charlemagne'), 'ACCOUNTING_EXPORT_FORMAT' => 'txt', ), + self::$EXPORT_TYPE_LDCOMPTA => array( + 'label' => $langs->trans('Modelcsv_LDCompta'), + ), + self::$EXPORT_TYPE_LDCOMPTA10 => array( + 'label' => $langs->trans('Modelcsv_LDCompta10'), + ), + self::$EXPORT_TYPE_GESTINUMV3 => array( + 'label' => $langs->trans('Modelcsv_Gestinumv3'), + ), + self::$EXPORT_TYPE_GESTINUMV5 => array( + 'label' => $langs->trans('Modelcsv_Gestinumv5'), + ), + self::$EXPORT_TYPE_FEC => array( + 'label' => $langs->trans('Modelcsv_FEC'), + 'ACCOUNTING_EXPORT_FORMAT' => 'txt', + ), ), 'cr'=> array( '1' => $langs->trans("Unix"), @@ -295,18 +304,24 @@ class AccountancyExport case self::$EXPORT_TYPE_SAGE50_SWISS : $this->exportSAGE50SWISS($TData); break; - case self::$EXPORT_TYPE_LDCOMPTA : - $this->exportLDCompta($TData); - break; - case self::$EXPORT_TYPE_LDCOMPTA10 : - $this->exportLDCompta10($TData); - break; - case self::$EXPORT_TYPE_FEC : - $this->exportFEC($TData); - break; case self::$EXPORT_TYPE_CHARLEMAGNE : $this->exportCharlemagne($TData); break; + case self::$EXPORT_TYPE_LDCOMPTA : + $this->exportLDCompta($TData); + break; + case self::$EXPORT_TYPE_LDCOMPTA10 : + $this->exportLDCompta10($TData); + break; + case self::$EXPORT_TYPE_GESTINUMV3 : + $this->exportGestimumV3($TData); + break; + case self::$EXPORT_TYPE_GESTINUMV5 : + $this->exportGestimumV5($TData); + break; + case self::$EXPORT_TYPE_FEC : + $this->exportFEC($TData); + break; default: $this->errors[] = $langs->trans('accountancy_error_modelnotfound'); break; @@ -1469,6 +1484,136 @@ class AccountancyExport } } + /** + * Export format : Gestimum V3 + * + * @param array $objectLines data + * + * @return void + */ + public function exportGestimumV3($objectLines) + { + global $langs; + + $this->separator = ','; + + $invoices_infos = array(); + $supplier_invoices_infos = array(); + foreach ($objectLines as $line) { + $date = dol_print_date($line->doc_date, '%d/%m/%Y'); + + $invoice_ref = $line->doc_ref; + $company_name = ""; + + if (($line->doc_type == 'customer_invoice' || $line->doc_type == 'supplier_invoice') && $line->fk_doc > 0) { + if (($line->doc_type == 'customer_invoice' && !isset($invoices_infos[$line->fk_doc])) || + ($line->doc_type == 'supplier_invoice' && !isset($supplier_invoices_infos[$line->fk_doc]))) { + if ($line->doc_type == 'customer_invoice') { + // Get new customer invoice ref and company name + $sql = 'SELECT f.facnumber, s.nom FROM ' . MAIN_DB_PREFIX . 'facture as f'; + $sql .= ' LEFT JOIN ' . MAIN_DB_PREFIX . 'societe AS s ON f.fk_soc = s.rowid'; + $sql .= ' WHERE f.rowid = ' . $line->fk_doc; + $resql = $this->db->query($sql); + if ($resql) { + if ($obj = $this->db->fetch_object($resql)) { + // Save invoice infos + $invoices_infos[$line->fk_doc] = array('ref' => $obj->facnumber, 'company_name' => $obj->nom); + $invoice_ref = $obj->facnumber; + $company_name = $obj->nom; + } + } + } else { + // Get new supplier invoice ref and company name + $sql = 'SELECT ff.ref, s.nom FROM ' . MAIN_DB_PREFIX . 'facture_fourn as ff'; + $sql .= ' LEFT JOIN ' . MAIN_DB_PREFIX . 'societe AS s ON ff.fk_soc = s.rowid'; + $sql .= ' WHERE ff.rowid = ' . $line->fk_doc; + $resql = $this->db->query($sql); + if ($resql) { + if ($obj = $this->db->fetch_object($resql)) { + // Save invoice infos + $supplier_invoices_infos[$line->fk_doc] = array('ref' => $obj->ref, 'company_name' => $obj->nom); + $invoice_ref = $obj->ref; + $company_name = $obj->nom; + } + } + } + } elseif ($line->doc_type == 'customer_invoice') { + // Retrieve invoice infos + $invoice_ref = $invoices_infos[$line->fk_doc]['ref']; + $company_name = $invoices_infos[$line->fk_doc]['company_name']; + } else { + // Retrieve invoice infos + $invoice_ref = $supplier_invoices_infos[$line->fk_doc]['ref']; + $company_name = $supplier_invoices_infos[$line->fk_doc]['company_name']; + } + } + + print $line->id . $this->separator; + print $date . $this->separator; + print substr($line->code_journal, 0, 4) . $this->separator; + + if ((substr($line->numero_compte, 0, 3) == '411') || (substr($line->numero_compte, 0, 3) == '401')) { + print length_accountg($line->subledger_account) . $this->separator; + } else { + print substr(length_accountg($line->numero_compte), 0, 15) . $this->separator; + } + //Libellé Auto + print $this->separator; + //print '"'.dol_trunc(str_replace('"', '', $line->label_operation),40,'right','UTF-8',1).'"' . $this->separator; + //Libellé manuel + print dol_trunc(str_replace('"', '', $invoice_ref . (!empty($company_name) ? ' - ' : '') . $company_name), 40, 'right', 'UTF-8', 1) . $this->separator; + //Numéro de pièce + print dol_trunc(str_replace('"', '', $line->piece_num), 10, 'right', 'UTF-8', 1) . $this->separator; + //Devise + print 'EUR' . $this->separator; + //Montant + print price2num(abs($line->montant)) . $this->separator; + //Sens + print $line->sens . $this->separator; + //Code lettrage + print $this->separator; + //Date Echéance + print $date; + print $this->end_line; + } + } + + /** + * Export format : Gestimum V5 + * + * @param array $objectLines data + * + * @return void + */ + public function exportGestimumV5($objectLines) + { + + $this->separator = ','; + + foreach ($objectLines as $line) { + $date = dol_print_date($line->doc_date, '%d%m%Y'); + + print $line->id . $this->separator; + print $date . $this->separator; + print substr($line->code_journal, 0, 4) . $this->separator; + if ((substr($line->numero_compte, 0, 3) == '411') || (substr($line->numero_compte, 0, 3) == '401')) { + print length_accountg($line->subledger_account) . $this->separator; + } else { + print substr(length_accountg($line->numero_compte), 0, 15) . $this->separator; + } + print $this->separator; + //print '"'.dol_trunc(str_replace('"', '', $line->label_operation),40,'right','UTF-8',1).'"' . $this->separator; + print '"'.dol_trunc(str_replace('"', '', $line->doc_ref), 40, 'right', 'UTF-8', 1).'"' . $this->separator; + print '"'.dol_trunc(str_replace('"', '', $line->piece_num), 10, 'right', 'UTF-8', 1).'"'.$this->separator; + print price2num($line->montant).$this->separator; + print $line->sens.$this->separator; + print $date . $this->separator; + print $this->separator; + print $this->separator; + print 'EUR'; + print $this->end_line; + } + } /** * trunc diff --git a/htdocs/blockedlog/admin/blockedlog.php b/htdocs/blockedlog/admin/blockedlog.php index b6ce9cda1bc..39725eae3b7 100644 --- a/htdocs/blockedlog/admin/blockedlog.php +++ b/htdocs/blockedlog/admin/blockedlog.php @@ -35,6 +35,8 @@ if (!$user->admin || empty($conf->blockedlog->enabled)) accessforbidden(); $action = GETPOST('action', 'aZ09'); $backtopage = GETPOST('backtopage', 'alpha'); +$withtab = GETPOST('withtab', 'int'); + /* * Actions @@ -49,7 +51,7 @@ if (preg_match('/set_(.*)/', $action, $reg)) if (dolibarr_set_const($db, $code, $values, 'chaine', 0, '', $conf->entity) > 0) { - header("Location: ".$_SERVER["PHP_SELF"]); + header("Location: ".$_SERVER["PHP_SELF"].($withtab ? '?withtab='.$withtab : '')); exit; } else { dol_print_error($db); @@ -61,7 +63,7 @@ if (preg_match('/del_(.*)/', $action, $reg)) $code = $reg[1]; if (dolibarr_del_const($db, $code, 0) > 0) { - Header("Location: ".$_SERVER["PHP_SELF"]); + Header("Location: ".$_SERVER["PHP_SELF"].($withtab ? '?withtab='.$withtab : '')); exit; } else { dol_print_error($db); @@ -79,15 +81,13 @@ $block_static = new BlockedLog($db); llxHeader('', $langs->trans("BlockedLogSetup")); $linkback = ''; -if (GETPOST('withtab', 'alpha')) -{ +if ($withtab) { $linkback = ''.$langs->trans("BackToModuleList").''; } print load_fiche_titre($langs->trans("ModuleSetup").' '.$langs->trans('BlockedLog'), $linkback); -if (GETPOST('withtab', 'alpha')) -{ +if ($withtab) { $head = blockedlogadmin_prepare_head(); print dol_get_fiche_head($head, 'blockedlog', '', -1); } @@ -114,21 +114,26 @@ if (!empty($conf->global->BLOCKEDLOG_USE_REMOTE_AUTHORITY)) { print ''; print ''.$langs->trans("BlockedLogAuthorityUrl").img_info($langs->trans('BlockedLogAuthorityNeededToStoreYouFingerprintsInNonAlterableRemote')).''; print ''; + print '
'; print ''; print ''; + print ''; print ''; print ''; print '
'; + print ''; } print ''; print ''.$langs->trans("BlockedLogDisableNotAllowedForCountry").''; print ''; + print '
'; print ''; print ''; +print ''; $sql = "SELECT rowid, code as code_iso, code_iso as code_iso3, label, favorite"; $sql .= " FROM ".MAIN_DB_PREFIX."c_country"; @@ -168,7 +173,7 @@ print ''; print ''; -if (GETPOST('withtab', 'alpha')) +if ($withtab) { print dol_get_fiche_end(); } diff --git a/htdocs/bom/class/bom.class.php b/htdocs/bom/class/bom.class.php index 192acc22d83..2689a1a69e6 100644 --- a/htdocs/bom/class/bom.class.php +++ b/htdocs/bom/class/bom.class.php @@ -112,13 +112,31 @@ class BOM extends CommonObject 'model_pdf' =>array('type'=>'varchar(255)', 'label'=>'Model pdf', 'enabled'=>1, 'visible'=>0, 'position'=>1010), 'status' => array('type'=>'integer', 'label'=>'Status', 'enabled'=>1, 'visible'=>2, 'position'=>1000, 'notnull'=>1, 'default'=>0, 'index'=>1, 'arrayofkeyval'=>array(0=>'Draft', 1=>'Enabled', 9=>'Disabled')), ); + + /** + * @var int rowid + */ public $rowid; + + /** + * @var string ref + */ public $ref; + + /** + * @var string label + */ public $label; + + /** + * @var int bomtype + */ public $bomtype; + + /** + * @var string description + */ public $description; - public $note_public; - public $note_private; /** * @var integer|string date_creation @@ -127,10 +145,30 @@ class BOM extends CommonObject public $tms; + + /** + * @var int Id User creator + */ public $fk_user_creat; + + /** + * @var int Id User modifying + */ public $fk_user_modif; + + /** + * @var string import key + */ public $import_key; + + /** + * @var int status + */ public $status; + + /** + * @var int product Id + */ public $fk_product; public $qty; public $efficiency; @@ -1097,15 +1135,43 @@ class BOMLine extends CommonObjectLine 'position' => array('type'=>'integer', 'label'=>'Rank', 'enabled'=>1, 'visible'=>0, 'default'=>0, 'position'=>200, 'notnull'=>1,), 'import_key' => array('type'=>'varchar(14)', 'label'=>'ImportId', 'enabled'=>1, 'visible'=>-2, 'position'=>1000, 'notnull'=>-1,), ); + + /** + * @var int rowid + */ public $rowid; + + /** + * @var int fk_bom + */ public $fk_bom; + + /** + * @var int Id of product + */ public $fk_product; + + /** + * @var string description + */ public $description; public $qty; + + /** + * @var int qty frozen + */ public $qty_frozen; public $disable_stock_change; public $efficiency; + + /** + * @var int position of line + */ public $position; + + /** + * @var string import key + */ public $import_key; // END MODULEBUILDER PROPERTIES diff --git a/htdocs/bookmarks/class/bookmark.class.php b/htdocs/bookmarks/class/bookmark.class.php index 7f19b1bd21e..f7098f1d780 100644 --- a/htdocs/bookmarks/class/bookmark.class.php +++ b/htdocs/bookmarks/class/bookmark.class.php @@ -71,10 +71,16 @@ class Bookmark extends CommonObject */ public $datec; + /** + * @var string url + */ public $url; public $target; // 0=replace, 1=new window + /** + * @var string title + */ public $title; public $position; diff --git a/htdocs/comm/card.php b/htdocs/comm/card.php index 624526a9a5d..47c8431072d 100644 --- a/htdocs/comm/card.php +++ b/htdocs/comm/card.php @@ -170,6 +170,7 @@ if (empty($reshook)) $object->stcomm_id = dol_getIdFromCode($db, GETPOST('stcomm', 'alpha'), 'c_stcomm'); $result = $object->update($object->id, $user); if ($result < 0) setEventMessages($object->error, $object->errors, 'errors'); + else $result = $object->fetch($object->id); } // update outstandng limit diff --git a/htdocs/comm/propal/class/propal.class.php b/htdocs/comm/propal/class/propal.class.php index 4f2159a200e..c0b592c28f2 100644 --- a/htdocs/comm/propal/class/propal.class.php +++ b/htdocs/comm/propal/class/propal.class.php @@ -1322,7 +1322,6 @@ class Propal extends CommonObject // Load source object $object->fetch($this->id); - $object->fetch_lines(); $objsoc = new Societe($this->db); @@ -1708,7 +1707,7 @@ class Propal extends CommonObject $sql = 'SELECT d.rowid, d.fk_propal, d.fk_parent_line, d.label as custom_label, d.description, d.price, d.vat_src_code, d.tva_tx, d.localtax1_tx, d.localtax2_tx, d.localtax1_type, d.localtax2_type, d.qty, d.fk_remise_except, d.remise_percent, d.subprice, d.fk_product,'; $sql .= ' d.info_bits, d.total_ht, d.total_tva, d.total_localtax1, d.total_localtax2, d.total_ttc, d.fk_product_fournisseur_price as fk_fournprice, d.buy_price_ht as pa_ht, d.special_code, d.rang, d.product_type,'; $sql .= ' d.fk_unit,'; - $sql .= ' p.ref as product_ref, p.description as product_desc, p.fk_product_type, p.label as product_label, p.tobatch as product_batch,'; + $sql .= ' p.ref as product_ref, p.description as product_desc, p.fk_product_type, p.label as product_label, p.tobatch as product_tobatch, p.barcode as product_barcode,'; $sql .= ' p.weight, p.weight_units, p.volume, p.volume_units,'; $sql .= ' d.date_start, d.date_end,'; $sql .= ' d.fk_multicurrency, d.multicurrency_code, d.multicurrency_subprice, d.multicurrency_total_ht, d.multicurrency_total_tva, d.multicurrency_total_ttc'; @@ -1770,11 +1769,14 @@ class Propal extends CommonObject $line->fk_product = $objp->fk_product; $line->ref = $objp->product_ref; // deprecated - $line->product_ref = $objp->product_ref; $line->libelle = $objp->product_label; // deprecated + + $line->product_ref = $objp->product_ref; $line->product_label = $objp->product_label; $line->product_desc = $objp->product_desc; // Description produit $line->product_tobatch = $objp->product_tobatch; + $line->product_barcode = $objp->product_barcode; + $line->fk_product_type = $objp->fk_product_type; // deprecated $line->fk_unit = $objp->fk_unit; $line->weight = $objp->weight; @@ -3839,6 +3841,18 @@ class PropaleLigne extends CommonObjectLine */ public $product_desc; + /** + * Product use lot + * @var string + */ + public $product_tobatch; + + /** + * Product barcode + * @var string + */ + public $product_barcode; + public $localtax1_tx; // Local tax 1 public $localtax2_tx; // Local tax 2 public $localtax1_type; // Local tax 1 type diff --git a/htdocs/commande/card.php b/htdocs/commande/card.php index 22c512aa0ed..d38dd6d86ed 100644 --- a/htdocs/commande/card.php +++ b/htdocs/commande/card.php @@ -1709,7 +1709,7 @@ if ($action == 'create' && $usercancreate) $reshook = $hookmanager->executeHooks('formObjectOptions', $parameters, $object, $action); print $hookmanager->resPrint; if (empty($reshook)) { - if (!empty($conf->global->THIRDPARTY_PROPAGATE_EXTRAFIELDS_TO_ORDER)) { + if (!empty($conf->global->THIRDPARTY_PROPAGATE_EXTRAFIELDS_TO_ORDER) && !empty($soc->id)) { // copy from thirdparty $tpExtrafields = new Extrafields($db); $tpExtrafieldLabels = $tpExtrafields->fetch_name_optionals_label($soc->table_element); diff --git a/htdocs/commande/class/commande.class.php b/htdocs/commande/class/commande.class.php index ade778263e9..9de479dcb52 100644 --- a/htdocs/commande/class/commande.class.php +++ b/htdocs/commande/class/commande.class.php @@ -2014,7 +2014,7 @@ class Commande extends CommonOrder $sql .= ' l.total_ht, l.total_ttc, l.total_tva, l.total_localtax1, l.total_localtax2, l.date_start, l.date_end,'; $sql .= ' l.fk_unit,'; $sql .= ' l.fk_multicurrency, l.multicurrency_code, l.multicurrency_subprice, l.multicurrency_total_ht, l.multicurrency_total_tva, l.multicurrency_total_ttc,'; - $sql .= ' p.ref as product_ref, p.description as product_desc, p.fk_product_type, p.label as product_label, p.tosell as product_tosell, p.tobuy as product_tobuy, p.tobatch as product_tobatch,'; + $sql .= ' p.ref as product_ref, p.description as product_desc, p.fk_product_type, p.label as product_label, p.tosell as product_tosell, p.tobuy as product_tobuy, p.tobatch as product_tobatch, p.barcode as product_barcode,'; $sql .= ' p.weight, p.weight_units, p.volume, p.volume_units'; $sql .= ' FROM '.MAIN_DB_PREFIX.'commandedet as l'; $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'product as p ON (p.rowid = l.fk_product)'; @@ -2073,13 +2073,16 @@ class Commande extends CommonOrder $line->fk_parent_line = $objp->fk_parent_line; $line->ref = $objp->product_ref; - $line->product_ref = $objp->product_ref; $line->libelle = $objp->product_label; + + $line->product_ref = $objp->product_ref; $line->product_label = $objp->product_label; $line->product_desc = $objp->product_desc; $line->product_tosell = $objp->product_tosell; $line->product_tobuy = $objp->product_tobuy; $line->product_tobatch = $objp->product_tobatch; + $line->product_barcode = $objp->product_barcode; + $line->fk_product_type = $objp->fk_product_type; // Produit ou service $line->fk_unit = $objp->fk_unit; diff --git a/htdocs/compta/facture/card.php b/htdocs/compta/facture/card.php index 101b0aa82e6..a4def0c0b9b 100644 --- a/htdocs/compta/facture/card.php +++ b/htdocs/compta/facture/card.php @@ -3466,7 +3466,7 @@ if ($action == 'create') $reshook = $hookmanager->executeHooks('formObjectOptions', $parameters, $object, $action); // Note that $action and $object may have been modified by hook print $hookmanager->resPrint; if (empty($reshook)) { - if (!empty($conf->global->THIRDPARTY_PROPAGATE_EXTRAFIELDS_TO_INVOICE)) { + if (!empty($conf->global->THIRDPARTY_PROPAGATE_EXTRAFIELDS_TO_INVOICE) && !empty($soc->id)) { // copy from thirdparty $tpExtrafields = new Extrafields($db); $tpExtrafieldLabels = $tpExtrafields->fetch_name_optionals_label($soc->table_element); diff --git a/htdocs/compta/facture/list.php b/htdocs/compta/facture/list.php index 9e21c584678..b693238924f 100644 --- a/htdocs/compta/facture/list.php +++ b/htdocs/compta/facture/list.php @@ -307,12 +307,10 @@ if ($massaction == 'makepayment') { header('Location: '.$loc); exit; -} elseif ($massaction == 'withdrawrequest') -{ +} elseif ($massaction == 'withdrawrequest') { $langs->load("withdrawals"); - if (!$user->rights->prelevement->bons->creer) - { + if (!$user->rights->prelevement->bons->creer) { $error++; setEventMessages($langs->trans("NotEnoughPermissions"), null, 'errors'); } else { @@ -325,8 +323,7 @@ if ($massaction == 'makepayment') { { $objecttmp = new Facture($db); $result = $objecttmp->fetch($toselectid); - if ($result > 0) - { + if ($result > 0) { $totalpaye = $objecttmp->getSommePaiement(); $totalcreditnotes = $objecttmp->getSumCreditNotesUsed(); $totaldeposits = $objecttmp->getSumDepositsUsed(); @@ -667,7 +664,7 @@ if ($resql) 'presend'=>$langs->trans("SendByMail"), //'makepayment'=>$langs->trans("InvoicePaymentsLimits"), TODO Blank page when using this ); - if ($conf->prelevement->enabled) { + if ($conf->prelevement->enabled && !empty($user->rights->prelevement->bons->creer)) { $langs->load("withdrawals"); $arrayofmassactions['withdrawrequest'] = $langs->trans("MakeWithdrawRequest"); } diff --git a/htdocs/compta/facture/prelevement.php b/htdocs/compta/facture/prelevement.php index f6a00f606ba..792ff73bcd3 100644 --- a/htdocs/compta/facture/prelevement.php +++ b/htdocs/compta/facture/prelevement.php @@ -632,8 +632,10 @@ if ($object->id > 0) print "\n
\n"; $buttonlabel = $langs->trans("MakeWithdrawRequest"); + $user_perms=$user->rights->prelevement->bons->creer; if ($type == 'bank-transfer') { $buttonlabel = $langs->trans("MakeBankTransferOrder"); + $user_perms=$user->rights->paymentbybanktransfer->create; } // Add a transfer request @@ -641,7 +643,7 @@ if ($object->id > 0) { if ($resteapayer > 0) { - if ($user->rights->prelevement->bons->creer) + if ($user_perms) { $remaintopaylesspendingdebit = $resteapayer - $pending; diff --git a/htdocs/core/class/commondocgenerator.class.php b/htdocs/core/class/commondocgenerator.class.php index 6d1a6a57cba..1cd873c64c6 100644 --- a/htdocs/core/class/commondocgenerator.class.php +++ b/htdocs/core/class/commondocgenerator.class.php @@ -582,10 +582,13 @@ abstract class CommonDocGenerator $resarray = array( 'line_pos' => $linenumber, 'line_fulldesc'=>doc_getlinedesc($line, $outputlangs), - 'line_product_ref'=>$line->product_ref, - 'line_product_ref_fourn'=>$line->ref_fourn, // for supplier doc lines - 'line_product_label'=>$line->product_label, - 'line_product_type'=>$line->product_type, + + 'line_product_ref'=>(empty($line->product_ref) ? '' : $line->product_ref), + 'line_product_ref_fourn'=>(empty($line->ref_fourn) ? '' : $line->ref_fourn), // for supplier doc lines + 'line_product_label'=>(empty($line->product_label) ? '' :$line->product_label), + 'line_product_type'=>(empty($line->product_type) ? '' : $line->product_type), + 'line_product_barcode'=>(empty($line->product_barcode) ? '' : $line->product_barcode), + 'line_desc'=>$line->desc, 'line_vatrate'=>vatrate($line->tva_tx, true, $line->info_bits), 'line_localtax1_rate'=>vatrate($line->localtax1_tx), diff --git a/htdocs/core/class/commonorder.class.php b/htdocs/core/class/commonorder.class.php index 5062a7016bb..410bf41a601 100644 --- a/htdocs/core/class/commonorder.class.php +++ b/htdocs/core/class/commonorder.class.php @@ -78,6 +78,18 @@ abstract class CommonOrderLine extends CommonObjectLine */ public $product_desc; + /** + * Product use lot + * @var string + */ + public $product_tobatch; + + /** + * Product barcode + * @var string + */ + public $product_barcode; + /** * Quantity * @var float diff --git a/htdocs/core/class/smtps.class.php b/htdocs/core/class/smtps.class.php index e42622c4170..8254cc56ed2 100644 --- a/htdocs/core/class/smtps.class.php +++ b/htdocs/core/class/smtps.class.php @@ -1647,7 +1647,7 @@ class SMTPs * - [2] Private * - [3] Company Confidential * - * @return void + * @return string|boolean */ public function getSensitivity() { diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index bfa6ec798cd..f0d6ff9a53c 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -4748,19 +4748,19 @@ function price($amount, $form = 0, $outlangs = '', $trunc = 1, $rounding = -1, $ * Function to use on each input amount before any numeric test or database insert. A better name for this function * should be roundtext2num(). * - * @param float $amount Amount to convert/clean or round - * @param string $rounding ''=No rounding - * 'MU'=Round to Max unit price (MAIN_MAX_DECIMALS_UNIT) - * 'MT'=Round to Max for totals with Tax (MAIN_MAX_DECIMALS_TOT) - * 'MS'=Round to Max for stock quantity (MAIN_MAX_DECIMALS_STOCK) - * 'CR'=Currency rate - * Numeric = Nb of digits for rounding - * @param int $alreadysqlnb Put 1 if you know that content is already universal format number - * @return string Amount with universal numeric format (Example: '99.99999'). - * If conversion fails, it return text unchanged if $rounding = '' or '0' if $rounding is defined. - * If amount is null or '', it returns '' if $rounding = '' or '0' if $rounding is defined.. + * @param string|float $amount Amount to convert/clean or round + * @param string $rounding ''=No rounding + * 'MU'=Round to Max unit price (MAIN_MAX_DECIMALS_UNIT) + * 'MT'=Round to Max for totals with Tax (MAIN_MAX_DECIMALS_TOT) + * 'MS'=Round to Max for stock quantity (MAIN_MAX_DECIMALS_STOCK) + * 'CR'=Currency rate + * Numeric = Nb of digits for rounding + * @param int $alreadysqlnb Put 1 if you know that content is already universal format number + * @return string Amount with universal numeric format (Example: '99.99999'). + * If conversion fails, it return text unchanged if $rounding = '' or '0' if $rounding is defined. + * If amount is null or '', it returns '' if $rounding = '' or '0' if $rounding is defined.. * - * @see price() Opposite function of price2num + * @see price() Opposite function of price2num */ function price2num($amount, $rounding = '', $alreadysqlnb = 0) { @@ -4777,15 +4777,14 @@ function price2num($amount, $rounding = '', $alreadysqlnb = 0) //print "amount=".$amount." html=".$form." trunc=".$trunc." nbdecimal=".$nbdecimal." dec='".$dec."' thousand='".$thousand."'
"; // Convert value to universal number format (no thousand separator, '.' as decimal separator) - if ($alreadysqlnb != 1) // If not a PHP number or unknown, we change format - { + if ($alreadysqlnb != 1) { // If not a PHP number or unknown, we change or clean format //print 'PP'.$amount.' - '.$dec.' - '.$thousand.' - '.intval($amount).'
'; + if ($thousand == '.' && preg_match('/\.(\d\d\d)$/', (string) $amount)) { // It means the . is used as a thousand separator, not as a decimal separator + $amount = str_replace($thousand, '', $amount); // Replace of thousand before test of is_numeric to avoid pb if thousand is . and there is 3 numbers after + } // Convert amount to format with dolibarr dec and thousand (this is because PHP convert a number // to format defined by LC_NUMERIC after a calculation and we want source format to be like defined by Dolibarr setup. - if ($thousand == '.') { - $amount = str_replace($thousand, '', $amount); // Replace of thousand before test of is_numeric to avoid pb if thousand is . - } if (is_numeric($amount)) { // We put in temps value of decimal ("0.00001"). Works with 0 and 2.0E-5 and 9999.10 @@ -4795,7 +4794,7 @@ function price2num($amount, $rounding = '', $alreadysqlnb = 0) $amount = number_format($amount, $nbofdec, $dec, $thousand); } //print "QQ".$amount.'
'; - + // Now make replace (the main goal of function) if ($thousand != ',' && $thousand != '.') { $amount = str_replace(',', '.', $amount); // To accept 2 notations for french users diff --git a/htdocs/core/lib/phpsessionindb.lib.php b/htdocs/core/lib/phpsessionindb.lib.php new file mode 100644 index 00000000000..585967965dc --- /dev/null +++ b/htdocs/core/lib/phpsessionindb.lib.php @@ -0,0 +1,166 @@ + + * + * 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/core/lib/phpsessionindb.lib.php + * \ingroup core + * \brief Set function handlers for PHP session management in DB + */ + +// The session handler file must be included just after the call of the master.inc.php into main.inc.php +// The $conf is already defined from conf.php file. +// To use it set in your PHP.ini: session.save_handler = user + +/** + * The session open handler called by PHP whenever a session is initialized. + * + * @param string $database_name Database NamedConstraint + * @param string $table_name Table name + * @return boolean Always true + */ +function dolSessionOpen($database_name, $table_name) +{ + global $conf, $dbsession; + + $dbsession = getDoliDBInstance($conf->db->type, $conf->db->host, $conf->db->user, $conf->db->pass, $conf->db->name, $conf->db->port); + + return true; +} + +/** + * This function is called whenever a session_start() call is made and reads the session variables. + * + * @param string $sess_id Session ID + * @return string Returns "" when a session is not found or (serialized)string if session exists + */ +function dolSessionRead($sess_id) +{ + global $dbsession; + + $sql = "SELECT session_variable FROM ".MAIN_DB_PREFIX."session"; + $sql .= " WHERE session_id = '".$dbsession->escape($sess_id)."'"; + + // Execute the query + $resql = $dbsession->query($sql); + $num_rows = $dbsession->num_rows($resql); + if ($num_rows == 0) { + // No session found - return an empty string + return ''; + } else { + // Found a session - return the serialized string + $obj = $dbsession->fetch_object($resql); + return $obj->session_variable; + } +} + +/** + * This function is called when a session is initialized with a session_start( ) call, when variables are registered or unregistered, + * and when session variables are modified. Returns true on success. + * + * @param string $sess_id Session iDecodeStream + * @param string $val Content of session + * @return boolean Always true + */ +function dolSessionWrite($sess_id, $val) +{ + global $dbsession; + + $time_stamp = dol_now(); + + $sql = "SELECT session_id FROM ".MAIN_DB_PREFIX."session"; + $sql .= " WHERE session_id = '".$dbsession->escape($sess_id)."'"; + + // Execute the query + $resql = $dbsession->query($sql); + $num_rows = $dbsession->num_rows($resql); + if ($num_rows == 0) { + // No session found, insert a new one + $insert_query = "INSERT INTO ".MAIN_DB_PREFIX."session"; + $insert_query .= "(session_id, session_variable, last_accessed)"; + $insert_query .= " VALUES ('".$dbsession->escape($sess_id)."', '".$dbsession->escape($val)."', '".$dbsession->idate($time_stamp)."')"; + $dbsession->query($insert_query); + } else { + // Existing session found - Update the session variables + $update_query = "UPDATE ".MAIN_DB_PREFIX."session"; + $update_query .= "SET session_variable = '".$dbsession->escape($val)."',"; + $update_query .= " last_accessed = '".$dbsession->idate($time_stamp)."'"; + $update_query .= " WHERE session_id = '".$dbsession->escape($sess_id)."'"; + $dbsession->query($update_query); + } + return true; +} + +/** + * This function is executed on shutdown of the session. + * + * @param string $sess_id Session ID + * @return boolean Always returns true. + */ +function dolSessionClose($sess_id) +{ + global $dbsession; + + $dbsession->close(); + + return true; +} + +/** + * This is called whenever the session_destroy() function call is made. Returns true if the session has successfully been deleted. + * + * @param string $sess_id Session iDecodeStream + * @return boolean Always true + */ +function dolSessionDestroy($sess_id) +{ + global $dbsession; + + $delete_query = "DELETE FROM ".MAIN_DB_PREFIX."session"; + $delete_query .= " WHERE session_id = '".$dbsession->escape($sess_id)."'"; + $dbsession->query($delete_query); + + return true; +} + +/** + * This function is called on a session's start up with the probability specified in session.gc_probability. + * Performs garbage collection by removing all sessions that haven't been updated in the last $max_lifetime seconds as set in session.gc_maxlifetime. + * + * @param int $max_lifetime Max lifetime + * @return boolean true if the DELETE query succeeded. + */ +function dolSessionGC($max_lifetime) +{ + global $dbsession; + + $time_stamp = dol_now(); + + $delete_query = "DELETE FROM ".MAIN_DB_PREFIX."session"; + $delete_query .= " WHERE last_accessed < '".$dbsession->idate($time_stamp - $max_lifetime)."'"; + + $resql = $dbsession->query($delete_query); + if ($resql) { + return true; + } else { + return false; + } +} + +// Call to register user call back functions. +session_set_save_handler("dolSessionOpen", "dolSessionClose", "dolSessionRead", "dolSessionWrite", "dolSessionDestroy", "dolSessionGC"); + diff --git a/htdocs/core/modules/commande/doc/pdf_eratosthene.modules.php b/htdocs/core/modules/commande/doc/pdf_eratosthene.modules.php index 46409b362af..36374ce66b7 100644 --- a/htdocs/core/modules/commande/doc/pdf_eratosthene.modules.php +++ b/htdocs/core/modules/commande/doc/pdf_eratosthene.modules.php @@ -1756,7 +1756,6 @@ class pdf_eratosthene extends ModelePDFCommandes $this->cols['photo']['status'] = true; } - $rank = $rank + 10; $this->cols['vat'] = array( 'rank' => $rank, @@ -1784,6 +1783,17 @@ class pdf_eratosthene extends ModelePDFCommandes 'border-left' => true, // add left line separator ); + // Adapt dynamically the width of subprice, if text is too long. + $tmpwidth = 0; + $nblines = count($object->lines); + for ($i = 0; $i < $nblines; $i++) { + $tmpwidth2 = dol_strlen(dol_string_nohtmltag(pdf_getlineupexcltax($object, $i, $outputlangs, $hidedetails))); + $tmpwidth = max($tmpwidth, $tmpwidth2); + } + if ($tmpwidth > 10) { + $this->cols['subprice']['width'] += (2 * ($tmpwidth - 10)); + } + $rank = $rank + 10; $this->cols['qty'] = array( 'rank' => $rank, diff --git a/htdocs/core/modules/facture/doc/pdf_sponge.modules.php b/htdocs/core/modules/facture/doc/pdf_sponge.modules.php index 4107e25ca03..646b4831697 100644 --- a/htdocs/core/modules/facture/doc/pdf_sponge.modules.php +++ b/htdocs/core/modules/facture/doc/pdf_sponge.modules.php @@ -304,7 +304,7 @@ class pdf_sponge extends ModelePDFFactures $file = $dir."/SPECIMEN.pdf"; } else { $objectref = dol_sanitizeFileName($object->ref); - $dir = $conf->facture->multidir_output[$conf->entity]."/".$objectref; + $dir = $conf->facture->multidir_output[$object->entity]."/".$objectref; $file = $dir."/".$objectref.".pdf"; } if (!file_exists($dir)) @@ -443,7 +443,7 @@ class pdf_sponge extends ModelePDFFactures } } - // Display notes + // Displays notes $notetoshow = empty($object->note_public) ? '' : $object->note_public; if (!empty($conf->global->MAIN_ADD_SALE_REP_SIGNATURE_IN_NOTE)) { @@ -608,6 +608,7 @@ class pdf_sponge extends ModelePDFFactures $showpricebeforepagebreak = 1; $posYAfterImage = 0; + $posYAfterDescription = 0; if ($this->getColumnStatus('photo')) { @@ -671,6 +672,7 @@ class pdf_sponge extends ModelePDFFactures { $pdf->commitTransaction(); } + $posYAfterDescription = $pdf->GetY(); } $nexY = $pdf->GetY(); @@ -684,7 +686,7 @@ class pdf_sponge extends ModelePDFFactures $pdf->setPage($pageposafter); $curY = $tab_top_newpage; } - $pdf->SetFont('', '', $default_font_size - 1); // On repositionne la police par defaut + $pdf->SetFont('', '', $default_font_size - 1); // We reposition the default font // VAT Rate if ($this->getColumnStatus('vat')) @@ -1233,7 +1235,7 @@ class pdf_sponge extends ModelePDFFactures /** * Show total to pay * - * @param TCPDI $pdf Object PDF + * @param TCPDF $pdf Object PDF * @param Facture $object Object invoice * @param int $deja_regle Amount already paid (in the currency of invoice) * @param int $posy Position depart @@ -1658,8 +1660,6 @@ class pdf_sponge extends ModelePDFFactures $pdf->MultiCell($largcol2, $tab2_hl, price($sign * $total_ttc, 0, $outputlangs), $useborder, 'R', 1); - - // Retained warranty if ($object->displayRetainedWarranty()) { @@ -1720,7 +1720,7 @@ class pdf_sponge extends ModelePDFFactures $pdf->MultiCell($largcol2, $tab2_hl, price($creditnoteamount, 0, $outputlangs), 0, 'R', 0); } - // Escompte + /* if ($object->close_code == Facture::CLOSECODE_DISCOUNTVAT) { $index++; @@ -1733,6 +1733,7 @@ class pdf_sponge extends ModelePDFFactures $resteapayer = 0; } + */ $index++; $pdf->SetTextColor(0, 0, 60); @@ -1847,7 +1848,7 @@ class pdf_sponge extends ModelePDFFactures pdf_pagehead($pdf, $outputlangs, $this->page_hauteur); // Show Draft Watermark - if ($object->statut == Facture::STATUS_DRAFT && (!empty($conf->global->FACTURE_DRAFT_WATERMARK))) + if ($object->statut == $object::STATUS_DRAFT && (!empty($conf->global->FACTURE_DRAFT_WATERMARK))) { pdf_watermark($pdf, $outputlangs, $this->page_hauteur, $this->page_largeur, 'mm', $conf->global->FACTURE_DRAFT_WATERMARK); } @@ -1875,8 +1876,7 @@ class pdf_sponge extends ModelePDFFactures } else { $logo = $logodir.'/logos/'.$this->emetteur->logo; } - if (is_readable($logo)) - { + if (is_readable($logo)) { $height = pdf_getHeightForLogo($logo); $pdf->Image($logo, $this->marge_gauche, $posy, 0, $height); // width=0 (auto) } else { @@ -1918,7 +1918,7 @@ class pdf_sponge extends ModelePDFFactures $pdf->SetXY($posx, $posy); $pdf->SetTextColor(0, 0, 60); $textref = $outputlangs->transnoentities("Ref")." : ".$outputlangs->convToOutputCharset($object->ref); - if ($object->statut == Facture::STATUS_DRAFT) + if ($object->statut == $object::STATUS_DRAFT) { $pdf->SetTextColor(128, 0, 0); $textref .= ' - '.$outputlangs->transnoentities("NotValidated"); @@ -2092,7 +2092,7 @@ class pdf_sponge extends ModelePDFFactures $pdf->SetFont('', '', $default_font_size - 1); $pdf->MultiCell($widthrecbox - 2, 4, $carac_emetteur, 0, 'L'); - // If BILLING contact defined on invoice, we use it + // If BILLING contact defined, we use it $usecontact = false; $arrayidcontact = $object->getIdContact('external', 'BILLING'); if (count($arrayidcontact) > 0) @@ -2273,6 +2273,17 @@ class pdf_sponge extends ModelePDFFactures 'border-left' => true, // add left line separator ); + // Adapt dynamically the width of subprice, if text is too long. + $tmpwidth = 0; + $nblines = count($object->lines); + for ($i = 0; $i < $nblines; $i++) { + $tmpwidth2 = dol_strlen(dol_string_nohtmltag(pdf_getlineupexcltax($object, $i, $outputlangs, $hidedetails))); + $tmpwidth = max($tmpwidth, $tmpwidth2); + } + if ($tmpwidth > 10) { + $this->cols['subprice']['width'] += (2 * ($tmpwidth - 10)); + } + $rank = $rank + 10; $this->cols['qty'] = array( 'rank' => $rank, diff --git a/htdocs/core/modules/modHRM.class.php b/htdocs/core/modules/modHRM.class.php index 484564b7066..ad36253fe22 100644 --- a/htdocs/core/modules/modHRM.class.php +++ b/htdocs/core/modules/modHRM.class.php @@ -49,7 +49,7 @@ class modHRM extends DolibarrModules $this->description = "Management of employees carrier and feelings (department, employment contract)"; // Possible values for version are: 'development', 'experimental', 'dolibarr' or version - $this->version = 'development'; + $this->version = 'experimental'; $this->const_name = 'MAIN_MODULE_'.strtoupper($this->name); // Name of image file used for this module. diff --git a/htdocs/core/modules/propale/doc/pdf_cyan.modules.php b/htdocs/core/modules/propale/doc/pdf_cyan.modules.php index ac83d194749..91aaa9de4a4 100644 --- a/htdocs/core/modules/propale/doc/pdf_cyan.modules.php +++ b/htdocs/core/modules/propale/doc/pdf_cyan.modules.php @@ -200,6 +200,8 @@ class pdf_cyan extends ModelePDFPropales // phpcs:enable global $user, $langs, $conf, $mysoc, $db, $hookmanager, $nblines; + dol_syslog("write_file outputlangs->defaultlang=".(is_object($outputlangs) ? $outputlangs->defaultlang : 'null')); + if (!is_object($outputlangs)) $outputlangs = $langs; // For backward compatibility with FPDF, force output charset to ISO, because FPDF expect text to be encoded in ISO if (!empty($conf->global->MAIN_USE_FPDF)) $outputlangs->charset_output = 'ISO-8859-1'; @@ -320,6 +322,10 @@ class pdf_cyan extends ModelePDFPropales global $action; $reshook = $hookmanager->executeHooks('beforePDFCreation', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks + // Set nblines with the new facture lines content after hook + $nblines = count($object->lines); + //$nbpayments = count($object->getListOfPayments()); + // Create pdf instance $pdf = pdf_getInstance($this->format); $default_font_size = pdf_getPDFFontSize($outputlangs); // Must be after pdf_getInstance @@ -393,7 +399,7 @@ class pdf_cyan extends ModelePDFPropales $pdf->SetFont('', '', $default_font_size - 1); $pdf->writeHTMLCell(190, 3, $this->posxdesc - 1, $tab_top - 1, dol_htmlentitiesbr($desc_incoterms), 0, 1); - $nexY = $pdf->GetY(); + $nexY = max($pdf->GetY(), $nexY); $height_incoterms = $nexY - $tab_top; // Rect takes a length in 3rd parameter @@ -420,8 +426,7 @@ class pdf_cyan extends ModelePDFPropales // Extrafields in note $extranote = $this->getExtrafieldsInHtml($object, $outputlangs); - if (!empty($extranote)) - { + if (!empty($extranote)) { $notetoshow = dol_concatdesc($notetoshow, $extranote); } @@ -554,7 +559,7 @@ class pdf_cyan extends ModelePDFPropales // Use new auto column system $this->prepareArrayColumnField($object, $outputlangs, $hidedetails, $hidedesc, $hideref); - // tab simulation to know line height + // Table simulation to know the height of the title line $pdf->startTransaction(); $this->pdfTabTitles($pdf, $tab_top, $tab_height, $outputlangs, $hidetop); $pdf->rollbackTransaction(true); @@ -633,7 +638,6 @@ class pdf_cyan extends ModelePDFPropales { $pdf->AddPage('', '', true); if (!empty($tplidx)) $pdf->useTemplate($tplidx); - //if (empty($conf->global->MAIN_PDF_DONOTREPEAT_HEAD)) $this->_pagehead($pdf, $object, 0, $outputlangs); $pdf->setPage($pageposafter + 1); } } else { @@ -773,20 +777,21 @@ class pdf_cyan extends ModelePDFPropales } // retrieve global local tax - if ($localtax1_type && $localtax1ligne != 0) + if ($localtax1_type && $localtax1ligne != 0) { $this->localtax1[$localtax1_type][$localtax1_rate] += $localtax1ligne; - if ($localtax2_type && $localtax2ligne != 0) + } + if ($localtax2_type && $localtax2ligne != 0) { $this->localtax2[$localtax2_type][$localtax2_rate] += $localtax2ligne; + } if (($object->lines[$i]->info_bits & 0x01) == 0x01) $vatrate .= '*'; if (!isset($this->tva[$vatrate])) $this->tva[$vatrate] = 0; $this->tva[$vatrate] += $tvaligne; - if ($posYAfterImage > $posYAfterDescription) $nexY = $posYAfterImage; + if ($posYAfterImage > $posYAfterDescription) $nexY = max($nexY, $posYAfterImage); // Add line - if (!empty($conf->global->MAIN_PDF_DASH_BETWEEN_LINES) && $i < ($nblines - 1)) - { + if (!empty($conf->global->MAIN_PDF_DASH_BETWEEN_LINES) && $i < ($nblines - 1)) { $pdf->setPage($pageposafter); $pdf->SetLineStyle(array('dash'=>'1,1', 'color'=>array(80, 80, 80))); //$pdf->SetDrawColor(190,190,200); @@ -797,14 +802,12 @@ class pdf_cyan extends ModelePDFPropales // Detect if some page were added automatically and output _tableau for past pages - while ($pagenb < $pageposafter) - { + while ($pagenb < $pageposafter) { $pdf->setPage($pagenb); - if ($pagenb == $pageposbeforeprintlines) - { - $this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforfooter, 0, $outputlangs, $hidetop, 1, $object->multicurrency_code); + if ($pagenb == $pageposbeforeprintlines) { + $this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforfooter, 0, $outputlangs, $hidetop, 1, $object->multicurrency_code, $outputlangsbis); } else { - $this->_tableau($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforfooter, 0, $outputlangs, 1, 1, $object->multicurrency_code); + $this->_tableau($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforfooter, 0, $outputlangs, 1, 1, $object->multicurrency_code, $outputlangsbis); } $this->_pagefoot($pdf, $object, $outputlangs, 1); $pagenb++; @@ -812,13 +815,12 @@ class pdf_cyan extends ModelePDFPropales $pdf->setPageOrientation('', 1, 0); // The only function to edit the bottom margin of current page to set it. if (empty($conf->global->MAIN_PDF_DONOTREPEAT_HEAD)) $this->_pagehead($pdf, $object, 0, $outputlangs); } - if (isset($object->lines[$i + 1]->pagebreak) && $object->lines[$i + 1]->pagebreak) - { - if ($pagenb == $pageposafter) - { - $this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforfooter, 0, $outputlangs, $hidetop, 1, $object->multicurrency_code); + + if (isset($object->lines[$i + 1]->pagebreak) && $object->lines[$i + 1]->pagebreak) { + if ($pagenb == $pageposafter) { + $this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforfooter, 0, $outputlangs, $hidetop, 1, $object->multicurrency_code, $outputlangsbis); } else { - $this->_tableau($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforfooter, 0, $outputlangs, 1, 1, $object->multicurrency_code); + $this->_tableau($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforfooter, 0, $outputlangs, 1, 1, $object->multicurrency_code, $outputlangsbis); } $this->_pagefoot($pdf, $object, $outputlangs, 1); // New page @@ -832,10 +834,10 @@ class pdf_cyan extends ModelePDFPropales // Show square if ($pagenb == $pageposbeforeprintlines) { - $this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforinfotot - $heightforfreetext - $heightforsignature - $heightforfooter, 0, $outputlangs, $hidetop, 0, $object->multicurrency_code); + $this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforinfotot - $heightforfreetext - $heightforsignature - $heightforfooter, 0, $outputlangs, $hidetop, 0, $object->multicurrency_code, $outputlangsbis); $bottomlasttab = $this->page_hauteur - $heightforinfotot - $heightforfreetext - $heightforsignature - $heightforfooter + 1; } else { - $this->_tableau($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforinfotot - $heightforfreetext - $heightforsignature - $heightforfooter, 0, $outputlangs, 1, 0, $object->multicurrency_code); + $this->_tableau($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforinfotot - $heightforfreetext - $heightforsignature - $heightforfooter, 0, $outputlangs, 1, 0, $object->multicurrency_code, $outputlangsbis); $bottomlasttab = $this->page_hauteur - $heightforinfotot - $heightforfreetext - $heightforsignature - $heightforfooter + 1; } @@ -859,7 +861,7 @@ class pdf_cyan extends ModelePDFPropales $posy = $this->drawSignatureArea($pdf, $object, $posy, $outputlangs); } - // Pied de page + // Pagefoot $this->_pagefoot($pdf, $object, $outputlangs); if (method_exists($pdf, 'AliasNbPages')) $pdf->AliasNbPages(); @@ -1160,7 +1162,7 @@ class pdf_cyan extends ModelePDFPropales * * @param TCPDF $pdf Object PDF * @param Propal $object Object proposal - * @param int $deja_regle Montant deja regle + * @param int $deja_regle Amount already paid (in the currency of invoice) * @param int $posy Position depart * @param Translate $outputlangs Objet langs * @return int Position pour suite @@ -1417,7 +1419,7 @@ class pdf_cyan extends ModelePDFPropales $pdf->SetFillColor(255,255,255); $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index); - $pdf->MultiCell($col2x-$col1x, $tab2_hl, $outputlangs->transnoentities("EscompteOfferedShort"), $useborder, 'L', 1); + $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities("EscompteOfferedShort"), $useborder, 'L', 1); $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); $pdf->MultiCell($largcol2, $tab2_hl, price($object->total_ttc - $deja_regle, 0, $outputlangs), $useborder, 'R', 1); @@ -1525,7 +1527,7 @@ class pdf_cyan extends ModelePDFPropales pdf_pagehead($pdf, $outputlangs, $this->page_hauteur); // Show Draft Watermark - if ($object->statut == 0 && (!empty($conf->global->PROPALE_DRAFT_WATERMARK))) + if ($object->statut == $object::STATUS_DRAFT && (!empty($conf->global->PROPALE_DRAFT_WATERMARK))) { pdf_watermark($pdf, $outputlangs, $this->page_hauteur, $this->page_largeur, 'mm', $conf->global->PROPALE_DRAFT_WATERMARK); } @@ -1579,7 +1581,13 @@ class pdf_cyan extends ModelePDFPropales $posy += 5; $pdf->SetXY($posx, $posy); $pdf->SetTextColor(0, 0, 60); - $pdf->MultiCell(100, 4, $outputlangs->transnoentities("Ref")." : ".$outputlangs->convToOutputCharset($object->ref), '', 'R'); + $textref = $outputlangs->transnoentities("Ref")." : ".$outputlangs->convToOutputCharset($object->ref); + if ($object->statut == $object::STATUS_DRAFT) + { + $pdf->SetTextColor(128, 0, 0); + $textref .= ' - '.$outputlangs->transnoentities("NotValidated"); + } + $pdf->MultiCell($w, 4, $textref, '', 'R'); $posy += 1; $pdf->SetFont('', '', $default_font_size - 2); @@ -1624,7 +1632,12 @@ class pdf_cyan extends ModelePDFPropales $posy += 4; $pdf->SetXY($posx, $posy); $pdf->SetTextColor(0, 0, 60); - $pdf->MultiCell(100, 3, $outputlangs->transnoentities("DateEndPropal")." : ".dol_print_date($object->fin_validite, "day", false, $outputlangs, true), '', 'R'); + + $title = $outputlangs->transnoentities("DateEndPropal"); + if (!empty($conf->global->PDF_USE_ALSO_LANGUAGE_CODE) && is_object($outputlangsbis)) { + $title .= ' - '.$outputlangsbis->transnoentities("DateEndPropal"); + } + $pdf->MultiCell($w, 3, $title." : ".dol_print_date($object->fin_validite, "day", false, $outputlangs, true), '', 'R'); if ($object->thirdparty->code_client) { @@ -1676,10 +1689,13 @@ class pdf_cyan extends ModelePDFPropales $carac_emetteur .= pdf_build_address($outputlangs, $this->emetteur, $object->thirdparty, '', 0, 'source', $object); // Show sender - $posy = 42 + $top_shift; + $posy = !empty($conf->global->MAIN_PDF_USE_ISO_LOCATION) ? 40 : 42; + $posy += $top_shift; $posx = $this->marge_gauche; if (!empty($conf->global->MAIN_INVERT_SENDER_RECIPIENT)) $posx = $this->page_largeur - $this->marge_droite - 80; - $hautcadre = 40; + + $hautcadre = !empty($conf->global->MAIN_PDF_USE_ISO_LOCATION) ? 38 : 40; + $widthrecbox = !empty($conf->global->MAIN_PDF_USE_ISO_LOCATION) ? 92 : 82; // Show sender frame $pdf->SetTextColor(0, 0, 0); @@ -1688,19 +1704,19 @@ class pdf_cyan extends ModelePDFPropales $pdf->MultiCell(66, 5, $outputlangs->transnoentities("BillFrom").":", 0, 'L'); $pdf->SetXY($posx, $posy); $pdf->SetFillColor(230, 230, 230); - $pdf->MultiCell(82, $hautcadre, "", 0, 'R', 1); + $pdf->MultiCell($widthrecbox, $hautcadre, "", 0, 'R', 1); $pdf->SetTextColor(0, 0, 60); // Show sender name $pdf->SetXY($posx + 2, $posy + 3); $pdf->SetFont('', 'B', $default_font_size); - $pdf->MultiCell(80, 4, $outputlangs->convToOutputCharset($this->emetteur->name), 0, 'L'); + $pdf->MultiCell($widthrecbox - 2, 4, $outputlangs->convToOutputCharset($this->emetteur->name), 0, 'L'); $posy = $pdf->getY(); // Show sender information $pdf->SetXY($posx + 2, $posy); $pdf->SetFont('', '', $default_font_size - 1); - $pdf->MultiCell(80, 4, $carac_emetteur, 0, 'L'); + $pdf->MultiCell($widthrecbox - 2, 4, $carac_emetteur, 0, 'L'); // If CUSTOMER contact defined, we use it @@ -1920,6 +1936,17 @@ class pdf_cyan extends ModelePDFPropales 'border-left' => true, // add left line separator ); + // Adapt dynamically the width of subprice, if text is too long. + $tmpwidth = 0; + $nblines = count($object->lines); + for ($i = 0; $i < $nblines; $i++) { + $tmpwidth2 = dol_strlen(dol_string_nohtmltag(pdf_getlineupexcltax($object, $i, $outputlangs, $hidedetails))); + $tmpwidth = max($tmpwidth, $tmpwidth2); + } + if ($tmpwidth > 10) { + $this->cols['subprice']['width'] += (2 * ($tmpwidth - 10)); + } + $rank = $rank + 10; $this->cols['qty'] = array( 'rank' => $rank, diff --git a/htdocs/ecm/class/ecmfiles.class.php b/htdocs/ecm/class/ecmfiles.class.php index 136a3ebc7e2..665da0c6ce6 100644 --- a/htdocs/ecm/class/ecmfiles.class.php +++ b/htdocs/ecm/class/ecmfiles.class.php @@ -60,15 +60,29 @@ class EcmFiles extends CommonObject */ public $label; - public $share; // hash for file sharing, empty by default (example: getRandomPassword(true)) + /** + * @var string hash for file sharing, empty by default (example: getRandomPassword(true)) + */ + public $share; /** * @var int Entity */ public $entity; - public $filename; // Note: Into ecm database record, the entry $filename never ends with .noexe + /** + * @var string filename, Note: Into ecm database record, the entry $filename never ends with .noexe + */ + public $filename; + + /** + * @var string filepath + */ public $filepath; + + /** + * @var string fullpath origin + */ public $fullpath_orig; /** @@ -76,12 +90,31 @@ class EcmFiles extends CommonObject */ public $description; + /** + * @var string keywords + */ public $keywords; public $cover; public $position; - public $gen_or_uploaded; // can be 'generated', 'uploaded', 'unknown' + + /** + * @var string can be 'generated', 'uploaded', 'unknown' + */ + public $gen_or_uploaded; + + /** + * @var string extraparams + */ public $extraparams; + + /** + * @var int|string date create + */ public $date_c = ''; + + /** + * @var int|string date modify + */ public $date_m = ''; /** @@ -94,6 +127,9 @@ class EcmFiles extends CommonObject */ public $fk_user_m; + /** + * @var string acl + */ public $acl; public $src_object_type; public $src_object_id; @@ -135,7 +171,7 @@ class EcmFiles extends CommonObject $this->share = trim($this->share); } if (isset($this->entity)) { - $this->entity = trim($this->entity); + $this->entity = (int) $this->entity; } if (isset($this->filename)) { $this->filename = preg_replace('/\.noexe$/', '', trim($this->filename)); @@ -163,10 +199,10 @@ class EcmFiles extends CommonObject $this->extraparams = trim($this->extraparams); } if (isset($this->fk_user_c)) { - $this->fk_user_c = trim($this->fk_user_c); + $this->fk_user_c = (int) $this->fk_user_c; } if (isset($this->fk_user_m)) { - $this->fk_user_m = trim($this->fk_user_m); + $this->fk_user_m = (int) $this->fk_user_m; } if (isset($this->acl)) { $this->acl = trim($this->acl); @@ -174,13 +210,16 @@ class EcmFiles extends CommonObject if (isset($this->src_object_type)) { $this->src_object_type = trim($this->src_object_type); } - if (empty($this->date_c)) $this->date_c = dol_now(); - if (empty($this->date_m)) $this->date_m = dol_now(); + if (empty($this->date_c)) { + $this->date_c = dol_now(); + } + if (empty($this->date_m)) { + $this->date_m = dol_now(); + } // If ref not defined $ref = ''; - if (!empty($this->ref)) - { + if (!empty($this->ref)) { $ref = $this->ref; } else { include_once DOL_DOCUMENT_ROOT.'/core/lib/security.lib.php'; @@ -188,8 +227,8 @@ class EcmFiles extends CommonObject } $maxposition = 0; - if (empty($this->position)) // Get max used - { + if (empty($this->position)) { + // Get max used $sql = "SELECT MAX(position) as maxposition FROM ".MAIN_DB_PREFIX.$this->table_element; $sql .= " WHERE filepath ='".$this->db->escape($this->filepath)."'"; diff --git a/htdocs/fourn/facture/list.php b/htdocs/fourn/facture/list.php index 39b91f42b09..d0dce03c87f 100644 --- a/htdocs/fourn/facture/list.php +++ b/htdocs/fourn/facture/list.php @@ -272,6 +272,96 @@ if (empty($reshook)) $permissiontodelete = $user->rights->fournisseur->facture->supprimer; $uploaddir = $conf->fournisseur->facture->dir_output; include DOL_DOCUMENT_ROOT.'/core/actions_massactions.inc.php'; + + if ($massaction == 'banktransfertrequest') + { + $langs->load("withdrawals"); + + if (!$user->rights->paymentbybanktransfer->create) + { + $error++; + setEventMessages($langs->trans("NotEnoughPermissions"), null, 'errors'); + } else { + //Checking error + $error = 0; + + $arrayofselected = is_array($toselect) ? $toselect : array(); + $listofbills = array(); + foreach ($arrayofselected as $toselectid) + { + $objecttmp = new FactureFournisseur($db); + $result = $objecttmp->fetch($toselectid); + if ($result > 0) + { + $totalpaye = $objecttmp->getSommePaiement(); + $totalcreditnotes = $objecttmp->getSumCreditNotesUsed(); + $totaldeposits = $objecttmp->getSumDepositsUsed(); + $objecttmp->resteapayer = price2num($objecttmp->total_ttc - $totalpaye - $totalcreditnotes - $totaldeposits, 'MT'); + if ($objecttmp->paye || $objecttmp->resteapayer == 0) { + $error++; + setEventMessages($objecttmp->ref.' '.$langs->trans("AlreadyPaid"), $objecttmp->errors, 'errors'); + } elseif ($objecttmp->resteapayer < 0) { + $error++; + setEventMessages($objecttmp->ref.' '.$langs->trans("AmountMustBePositive"), $objecttmp->errors, 'errors'); + } + if (!($objecttmp->statut > FactureFournisseur::STATUS_DRAFT)) { + $error++; + setEventMessages($objecttmp->ref.' '.$langs->trans("Draft"), $objecttmp->errors, 'errors'); + } + + $rsql = "SELECT pfd.rowid, pfd.traite, pfd.date_demande as date_demande"; + $rsql .= " , pfd.date_traite as date_traite"; + $rsql .= " , pfd.amount"; + $rsql .= " , u.rowid as user_id, u.lastname, u.firstname, u.login"; + $rsql .= " FROM ".MAIN_DB_PREFIX."prelevement_facture_demande as pfd"; + $rsql .= " , ".MAIN_DB_PREFIX."user as u"; + $rsql .= " WHERE fk_facture_fourn = ".$objecttmp->id; + $rsql .= " AND pfd.fk_user_demande = u.rowid"; + $rsql .= " AND pfd.traite = 0"; + $rsql .= " ORDER BY pfd.date_demande DESC"; + + $result_sql = $db->query($rsql); + if ($result_sql) + { + $numprlv = $db->num_rows($result_sql); + } + + if ($numprlv > 0) { + $error++; + setEventMessages($objecttmp->ref.' '.$langs->trans("RequestAlreadyDone"), $objecttmp->errors, 'warnings'); + } elseif (!empty($objecttmp->mode_reglement_code) && $objecttmp->mode_reglement_code != 'PRE') { + $error++; + setEventMessages($objecttmp->ref.' '.$langs->trans("BadPaymentMethod"), $objecttmp->errors, 'errors'); + } else { + $listofbills[] = $objecttmp; // $listofbills will only contains invoices with good payment method and no request already done + } + } + } + + //Massive withdraw request for request with no errors + if (!empty($listofbills)) + { + $nbwithdrawrequestok = 0; + foreach ($listofbills as $aBill) + { + $db->begin(); + $result = $aBill->demande_prelevement($user, $aBill->resteapayer, 'bank-transfer', 'supplier_invoice'); + if ($result > 0) + { + $db->commit(); + $nbwithdrawrequestok++; + } else { + $db->rollback(); + setEventMessages($aBill->error, $aBill->errors, 'errors'); + } + } + if ($nbwithdrawrequestok > 0) + { + setEventMessages($langs->trans("WithdrawRequestsDone", $nbwithdrawrequestok), null, 'mesgs'); + } + } + } + } } @@ -517,6 +607,10 @@ if ($resql) //'presend'=>$langs->trans("SendByMail"), ); //if($user->rights->fournisseur->facture->creer) $arrayofmassactions['createbills']=$langs->trans("CreateInvoiceForThisCustomer"); + if (!empty($conf->paymentbybanktransfer->enabled) && !empty($user->rights->paymentbybanktransfer->create)) { + $langs->load('withdrawals'); + $arrayofmassactions['banktransfertrequest'] = $langs->trans("MakeBankTransferOrder"); + } if ($user->rights->fournisseur->facture->supprimer) $arrayofmassactions['predelete'] = ''.$langs->trans("Delete"); if (in_array($massaction, array('presend', 'predelete', 'createbills'))) $arrayofmassactions = array(); $massactionbutton = $form->selectMassAction('', $arrayofmassactions); diff --git a/htdocs/install/mysql/data/llx_c_forme_juridique.sql b/htdocs/install/mysql/data/llx_c_forme_juridique.sql index a51b2bbd70f..7b02ee60ffa 100644 --- a/htdocs/install/mysql/data/llx_c_forme_juridique.sql +++ b/htdocs/install/mysql/data/llx_c_forme_juridique.sql @@ -84,6 +84,8 @@ insert into llx_c_forme_juridique (fk_pays, code, libelle) values (1,'19','Perso insert into llx_c_forme_juridique (fk_pays, code, libelle) values (1,'21','Indivision'); insert into llx_c_forme_juridique (fk_pays, code, libelle) values (1,'22','Société créée de fait'); insert into llx_c_forme_juridique (fk_pays, code, libelle) values (1,'23','Société en participation'); +insert into llx_c_forme_juridique (fk_pays, code, libelle) values (1,'24','Société coopérative d''interet collectif (SCIC)'); +insert into llx_c_forme_juridique (fk_pays, code, libelle) values (1,'25','Société coopérative de production à responsabilité limitée (SCOP)'); insert into llx_c_forme_juridique (fk_pays, code, libelle) values (1,'27','Paroisse hors zone concordataire'); insert into llx_c_forme_juridique (fk_pays, code, libelle) values (1,'29','Groupement de droit privé non doté de la personnalité morale'); insert into llx_c_forme_juridique (fk_pays, code, libelle) values (1,'31','Personne morale de droit étranger, immatriculée au RCS'); diff --git a/htdocs/install/mysql/migration/12.0.0-13.0.0.sql b/htdocs/install/mysql/migration/12.0.0-13.0.0.sql index a9f5a3fed37..1778646ffe4 100644 --- a/htdocs/install/mysql/migration/12.0.0-13.0.0.sql +++ b/htdocs/install/mysql/migration/12.0.0-13.0.0.sql @@ -533,3 +533,13 @@ CREATE TABLE llx_zapier_hook( import_key varchar(14) ) ENGINE=innodb; + +CREATE TABLE llx_session( + session_id varchar(50) PRIMARY KEY, + session_variable text, + last_accessed datetime NOT NULL, + fk_user integer NOT NULL, + remote_ip varchar(64) NULL, + user_agent varchar(128) NULL +)ENGINE=innodb; + diff --git a/htdocs/install/mysql/tables/llx_session.sql b/htdocs/install/mysql/tables/llx_session.sql new file mode 100644 index 00000000000..5be31733c22 --- /dev/null +++ b/htdocs/install/mysql/tables/llx_session.sql @@ -0,0 +1,28 @@ +-- ======================================================================== +-- Copyright (C) 2020 Laurent Destailleur +-- +-- This program is free software; you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- 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 . +-- +-- This table can be used for user defined session management +-- ======================================================================== + +create table llx_session +( + session_id varchar(50) PRIMARY KEY, + session_variable text, + last_accessed datetime NOT NULL, + fk_user integer NOT NULL, + remote_ip varchar(64) NULL, + user_agent varchar(128) NULL +)ENGINE=innodb; diff --git a/htdocs/langs/en_US/accountancy.lang b/htdocs/langs/en_US/accountancy.lang index 1d75fa153e8..3211a0b62df 100644 --- a/htdocs/langs/en_US/accountancy.lang +++ b/htdocs/langs/en_US/accountancy.lang @@ -339,6 +339,8 @@ Modelcsv_configurable=Export CSV Configurable Modelcsv_FEC=Export FEC Modelcsv_Sage50_Swiss=Export for Sage 50 Switzerland Modelcsv_winfic=Export Winfic - eWinfic - WinSis Compta +Modelcsv_Gestinumv3=Export for Gestinum (v3) +Modelcsv_Gestinumv5Export for Gestinum (v5) ChartofaccountsId=Chart of accounts Id ## Tools - Init accounting account on product / service diff --git a/htdocs/langs/en_US/hrm.lang b/htdocs/langs/en_US/hrm.lang index 6cc7f6bef24..3b8f137e103 100644 --- a/htdocs/langs/en_US/hrm.lang +++ b/htdocs/langs/en_US/hrm.lang @@ -16,3 +16,4 @@ DictionaryFunction=HRM - Job positions Employees=Employees Employee=Employee NewEmployee=New employee +ListOfEmployees=List of employees diff --git a/htdocs/langs/en_US/languages.lang b/htdocs/langs/en_US/languages.lang index 574ac2146dd..015e6dcfa25 100644 --- a/htdocs/langs/en_US/languages.lang +++ b/htdocs/langs/en_US/languages.lang @@ -40,6 +40,7 @@ Language_es_PA=Spanish (Panama) Language_es_PY=Spanish (Paraguay) Language_es_PE=Spanish (Peru) Language_es_PR=Spanish (Puerto Rico) +Language_es_US=Spanish (USA) Language_es_UY=Spanish (Uruguay) Language_es_GT=Spanish (USA) Language_es_VE=Spanish (Venezuela) diff --git a/htdocs/main.inc.php b/htdocs/main.inc.php index d6999dba6e7..c7468e4c7c6 100644 --- a/htdocs/main.inc.php +++ b/htdocs/main.inc.php @@ -229,6 +229,11 @@ if (!empty($_POST["DOL_AUTOSET_COOKIE"])) // Init the 5 global objects, this include will make the 'new Xxx()' and set properties for: $conf, $db, $langs, $user, $mysoc require_once 'master.inc.php'; +// Set the handler of session +if (ini_get('session.save_handler') == 'user') { + require_once 'core/lib/phpsessionindb.lib.php'; +} + // Init session. Name of session is specific to Dolibarr instance. // Must be done after the include of master.inc.php so $conf file is loaded and vars like $dolibarr_main_force_https are set. // Note: the function dol_getprefix may have been redefined to return a different key to manage another area to protect. diff --git a/htdocs/opensurvey/wizard/choix_autre.php b/htdocs/opensurvey/wizard/choix_autre.php index 248c44aeddd..42213af2ae2 100644 --- a/htdocs/opensurvey/wizard/choix_autre.php +++ b/htdocs/opensurvey/wizard/choix_autre.php @@ -43,10 +43,10 @@ $arrayoftypecolumn = GETPOST('typecolonne', 'array'); if (isset($_SESSION["nbrecases"])) { for ($i = 0; $i < $_SESSION["nbrecases"]; $i++) { if (isset($arrayofchoices[$i])) { - $_SESSION["choix$i"] = $arrayofchoices[$i]; + $_SESSION["choix".$i] = $arrayofchoices[$i]; } if (isset($arrayoftypecolumn[$i])) { - $_SESSION["typecolonne$i"] = $arrayoftypecolumn[$i]; + $_SESSION["typecolonne".$i] = $arrayoftypecolumn[$i]; } } } else { //nombre de cases par défaut @@ -97,9 +97,6 @@ if (GETPOSTISSET("confirmecreation")) } } -var_dump($_SESSION); exit; - - /* * View */ diff --git a/htdocs/opensurvey/wizard/create_survey.php b/htdocs/opensurvey/wizard/create_survey.php index 1ae5699500b..e2c3ddc67fd 100644 --- a/htdocs/opensurvey/wizard/create_survey.php +++ b/htdocs/opensurvey/wizard/create_survey.php @@ -40,7 +40,7 @@ $langs->load("opensurvey"); $post_var = array('title', 'description', 'mailsonde', 'creation_sondage_date', 'creation_sondage_autre'); foreach ($post_var as $var) { - $$var = GETPOST($var); + ${$var} = GETPOST($var); } // On initialise egalement la session car sinon bonjour les warning :-) diff --git a/htdocs/product/list.php b/htdocs/product/list.php index b69786cca30..12a6c807515 100644 --- a/htdocs/product/list.php +++ b/htdocs/product/list.php @@ -59,7 +59,6 @@ $search_ref = GETPOST("search_ref", 'alpha'); $search_barcode = GETPOST("search_barcode", 'alpha'); $search_label = GETPOST("search_label", 'alpha'); $search_type = GETPOST("search_type", 'int'); -$search_sale = GETPOST("search_sale", 'int'); $search_vatrate = GETPOST("search_vatrate", 'alpha'); $searchCategoryProductOperator = (GETPOST('search_category_product_operator', 'int') ? GETPOST('search_category_product_operator', 'int') : 0); $searchCategoryProductList = GETPOST('search_category_product_list', 'array'); @@ -278,10 +277,10 @@ if (empty($reshook)) $searchCategoryProductList = array(); $search_tosell = ""; $search_tobuy = ""; + $search_tobatch = ''; $search_country = ""; $search_state = ""; $search_vatrate = ""; - $search_tobatch = ''; $search_finished = ''; //$search_type=''; // There is 2 types of list: a list of product and a list of services. No list with both. So when we clear search criteria, we must keep the filter on type. @@ -373,8 +372,9 @@ if (!empty($conf->variants->enabled) && (!empty($conf->global->PRODUIT_ATTRIBUTE if ($search_ref) $sql .= natural_search('p.ref', $search_ref); if ($search_label) $sql .= natural_search('p.label', $search_label); if ($search_barcode) $sql .= natural_search('p.barcode', $search_barcode); -if (isset($search_tosell) && dol_strlen($search_tosell) > 0 && $search_tosell != -1) $sql .= " AND p.tosell = ".$db->escape($search_tosell); -if (isset($search_tobuy) && dol_strlen($search_tobuy) > 0 && $search_tobuy != -1) $sql .= " AND p.tobuy = ".$db->escape($search_tobuy); +if (isset($search_tosell) && dol_strlen($search_tosell) > 0 && $search_tosell != -1) $sql .= " AND p.tosell = ".((int) $search_tosell); +if (isset($search_tobuy) && dol_strlen($search_tobuy) > 0 && $search_tobuy != -1) $sql .= " AND p.tobuy = ".((int) $search_tobuy); +if (isset($search_tobatch) && dol_strlen($search_tobatch) > 0 && $search_tobatch != -1) $sql .= " AND p.tobatch = ".((int) $search_tobatch); if ($search_vatrate) $sql .= natural_search('p.tva_tx', $search_vatrate); if (dol_strlen($canvas) > 0) $sql .= " AND p.canvas = '".$db->escape($canvas)."'"; if ($catid > 0) $sql .= " AND cp.fk_categorie = ".$catid; @@ -403,8 +403,7 @@ if ($searchCategoryProductOperator == 1) { $sql .= " AND (".implode(' AND ', $searchCategoryProductSqlList).")"; } } -if ($fourn_id > 0) $sql .= " AND pfp.fk_soc = ".$fourn_id; -if ($search_tobatch != '' && $search_tobatch >= 0) $sql .= " AND p.tobatch = ".$db->escape($search_tobatch); +if ($fourn_id > 0) $sql .= " AND pfp.fk_soc = ".((int) $fourn_id); if ($search_country) $sql .= " AND p.fk_country = ".$search_country; if ($search_state) $sql .= " AND p.fk_state = ".$search_state; if ($search_finished >= 0 && $search_finished !== '') $sql .= " AND p.finished = ".$search_finished; @@ -505,16 +504,16 @@ if ($resql) if ($search_label) $param .= "&search_label=".urlencode($search_label); if ($search_tosell != '') $param .= "&search_tosell=".urlencode($search_tosell); if ($search_tobuy != '') $param .= "&search_tobuy=".urlencode($search_tobuy); + if ($search_tobatch) $param = "&search_tobatch=".urlencode($search_tobatch); if ($search_country != '') $param .= "&search_country=".urlencode($search_country); if ($search_state != '') $param .= "&search_state=".urlencode($search_state); - if ($search_vatrate) $sql .= natural_search('p.tva_tx', $search_vatrate); + if ($search_vatrate) $param = "&search_vatrate=".urlencode($search_vatrate); if ($fourn_id > 0) $param .= ($fourn_id ? "&fourn_id=".$fourn_id : ""); //if ($seach_categ) $param.=($search_categ?"&search_categ=".urlencode($search_categ):""); if ($show_childproducts) $param .= ($show_childproducts ? "&search_show_childproducts=".urlencode($show_childproducts) : ""); if ($type != '') $param .= '&type='.urlencode($type); if ($search_type != '') $param .= '&search_type='.urlencode($search_type); if ($optioncss != '') $param .= '&optioncss='.urlencode($optioncss); - if ($search_tobatch) $param = "&search_ref_supplier=".urlencode($search_ref_supplier); if ($search_accountancy_code_sell) $param = "&search_accountancy_code_sell=".urlencode($search_accountancy_code_sell); if ($search_accountancy_code_sell_intra) $param = "&search_accountancy_code_sell_intra=".urlencode($search_accountancy_code_sell_intra); if ($search_accountancy_code_sell_export) $param = "&search_accountancy_code_sell_export=".urlencode($search_accountancy_code_sell_export); @@ -826,7 +825,7 @@ if ($resql) // Stock if (!empty($arrayfields['stock_virtual']['checked'])) print ' '; // To batch - if (!empty($arrayfields['p.tobatch']['checked'])) print ''.$form->selectyesno($search_tobatch, '', '', '', 1).''; + if (!empty($arrayfields['p.tobatch']['checked'])) print ''.$form->selectyesno('search_tobatch', $search_tobatch, 1, false, 1).''; // Country if (!empty($arrayfields['p.fk_country']['checked'])) print ''.$form->select_country($search_country, 'search_country', '', 0).''; // State @@ -1283,31 +1282,59 @@ if ($resql) // Multiprices - if ($conf->global->PRODUIT_MULTIPRICES) { + if (! empty($conf->global->PRODUIT_MULTIPRICES)) { + if (! isset($productpricescache)) { + $productpricescache=array(); + } + if (! isset($productpricescache[$obj->rowid])) { + $productpricescache[$obj->rowid] = array(); + } + + if ($obj->tosell) + { + // Make 1 request for all price levels (without filter on price_level) and saved result into an cache array + // then reuse the cache array if we need prices for other price levels + $sqlp = "SELECT p.rowid, p.fk_product, p.price, p.price_ttc, p.price_level, p.date_price, p.price_base_type"; + $sqlp .= " FROM ".MAIN_DB_PREFIX."product_price as p"; + $sqlp .= " WHERE fk_product = ".$obj->rowid; + $sqlp .= " ORDER BY p.date_price DESC, p.rowid DESC, p.price_level ASC"; + $resultp = $db->query($sqlp); + if ($resultp) + { + $nump = $db->num_rows($resultp); + $j = 0; + while ($j < $nump) + { + $objp = $db->fetch_object($resultp); + + if (empty($productpricescache[$obj->rowid][$objp->price_level])) + { + $productpricescache[$obj->rowid][$objp->price_level]['price'] = $objp->price; + $productpricescache[$obj->rowid][$objp->price_level]['price_ttc'] = $objp->price_ttc; + $productpricescache[$obj->rowid][$objp->price_level]['price_base_type'] = $objp->price_base_type; + } + + $j++; + } + + $db->free($resultp); + } else { + dol_print_error($db); + } + } + foreach ($arraypricelevel as $key => $value) { if (!empty($arrayfields['p.sellprice'.$key]['checked'])) { print ''; - if ($obj->tosell) + if (! empty($productpricescache[$obj->rowid])) { - // TODO Make 1 request for all price levels (without filter on price_level) and saved result into an cache array - // then reuse the cache array if we need prices for other price levels - $resultp = "SELECT p.rowid, p.fk_product, p.price, p.price_ttc, p.price_level, p.date_price"; - $resultp .= " FROM ".MAIN_DB_PREFIX."product_price as p"; - $resultp .= " WHERE fk_product = ".$obj->rowid; - $resultp .= " AND p.price_level = ".$key; - $resultp .= " ORDER BY p.date_price DESC, p.rowid DESC, p.price_level ASC"; - $resultp = $db->query($resultp); - if ($resultp) - { - $objp = $db->fetch_object($resultp); - if ($obj->price_base_type == 'TTC') print price($objp->price_ttc).' '.$langs->trans("TTC"); - else print price($objp->price).' '.$langs->trans("HT"); - $db->free($resultp); - } else { - dol_print_error($db); - } + if ($productpricescache[$obj->rowid][$key]['price_base_type'] == 'TTC') { + print price($productpricescache[$obj->rowid][$key]['price_ttc']).' '.$langs->trans("TTC"); + } else { + print price($productpricescache[$obj->rowid][$key]['price']).' '.$langs->trans("HT"); + } } print ''; if (!$i) $totalarray['nbfield']++; diff --git a/htdocs/projet/card.php b/htdocs/projet/card.php index 94a7b772fac..771998fbb6c 100644 --- a/htdocs/projet/card.php +++ b/htdocs/projet/card.php @@ -126,7 +126,7 @@ if (empty($reshook)) } if (!GETPOST('title')) { - setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Label")), null, 'errors'); + setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("ProjectLabel")), null, 'errors'); $error++; } @@ -236,7 +236,7 @@ if (empty($reshook)) { $error++; //$_GET["id"]=$_POST["id"]; // We return on the project card - setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Label")), null, 'errors'); + setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("ProjectLabel")), null, 'errors'); } $db->begin(); @@ -529,7 +529,7 @@ if ($action == 'create' && $user->rights->projet->creer) print ''; // Label - print ''.$langs->trans("Label").''; + print ''.$langs->trans("ProjectLabel").''; // Usage (opp, task, bill time, ...) print ''; @@ -804,10 +804,9 @@ if ($action == 'create' && $user->rights->projet->creer) print ''; // Label - print ''.$langs->trans("Label").''; + print ''.$langs->trans("ProjectLabel").''; print ''; - // Status print ''.$langs->trans("Status").''; print ''; print $ldap_phone; } else { - print ''; + print ''; } print ''; // Tel portable - print ''.img_picto('', 'object_phoning_mobile').' '.$langs->trans("PhoneMobile").''; + print ''.$langs->trans("PhoneMobile").''; print ''; + print img_picto('', 'object_phoning_mobile'); if (!empty($ldap_mobile)) { print ''; print $ldap_mobile; } else { - print ''; + print ''; } print ''; // Fax - print ''.img_picto('', 'object_phoning_fax').' '.$langs->trans("Fax").''; + print ''.$langs->trans("Fax").''; print ''; + print img_picto('', 'object_phoning_fax'); if (!empty($ldap_fax)) { print ''; print $ldap_fax; } else { - print ''; + print ''; } print ''; // EMail - print 'global->USER_MAIL_REQUIRED) ? ' class="fieldrequired"' : '').'>'.img_picto('', 'object_email').' '.$langs->trans("EMail").''; + print 'global->USER_MAIL_REQUIRED) ? ' class="fieldrequired"' : '').'>'.$langs->trans("EMail").''; print ''; + print img_picto('', 'object_email'); if (!empty($ldap_mail)) { print ''; print $ldap_mail; } else { - print ''; + print ''; } print ''; @@ -1093,7 +1097,7 @@ if ($action == 'create' || $action == 'adduserldap') { print ''.$langs->trans("AccountancyCode").''; print ''; - print ''; + print ''; print ''; } @@ -2357,11 +2361,12 @@ if ($action == 'create' || $action == 'adduserldap') } // Tel pro - print "".''.img_picto('', 'object_phoning').' '.$langs->trans("PhonePro").''; + print "".''.$langs->trans("PhonePro").''; print ''; + print img_picto('', 'object_phoning'); if ($caneditfield && empty($object->ldap_sid)) { - print ''; + print ''; } else { print ''; print $object->office_phone; @@ -2369,11 +2374,12 @@ if ($action == 'create' || $action == 'adduserldap') print ''; // Tel mobile - print "".''.img_picto('', 'object_phoning_mobile').' '.$langs->trans("PhoneMobile").''; + print "".''.$langs->trans("PhoneMobile").''; print ''; + print img_picto('', 'object_phoning_mobile'); if ($caneditfield && empty($object->ldap_sid)) { - print ''; + print ''; } else { print ''; print $object->user_mobile; @@ -2381,11 +2387,12 @@ if ($action == 'create' || $action == 'adduserldap') print ''; // Fax - print "".''.img_picto('', 'object_phoning_fax').' '.$langs->trans("Fax").''; + print "".''.$langs->trans("Fax").''; print ''; + print img_picto('', 'object_phoning_fax'); if ($caneditfield && empty($object->ldap_sid)) { - print ''; + print ''; } else { print ''; print $object->office_fax; @@ -2393,11 +2400,12 @@ if ($action == 'create' || $action == 'adduserldap') print ''; // EMail - print "".'global->USER_MAIL_REQUIRED) ? ' class="fieldrequired"' : '').'>'.img_picto('', 'object_email').' '.$langs->trans("EMail").''; + print "".'global->USER_MAIL_REQUIRED) ? ' class="fieldrequired"' : '').'>'.$langs->trans("EMail").''; print ''; + print img_picto('', 'object_email'); if ($caneditfield && empty($object->ldap_sid)) { - print ''; + print ''; } else { print ''; print $object->email; diff --git a/htdocs/user/hierarchy.php b/htdocs/user/hierarchy.php index a27946e7474..1a6a630d27c 100644 --- a/htdocs/user/hierarchy.php +++ b/htdocs/user/hierarchy.php @@ -43,6 +43,9 @@ if ($user->socid > 0) $sall = trim((GETPOST('search_all', 'alphanohtml') != '') ?GETPOST('search_all', 'alphanohtml') : GETPOST('sall', 'alphanohtml')); $search_user = GETPOST('search_user', 'alpha'); +// Load mode employee +$mode = GETPOST("mode", 'alpha'); + $userstatic = new User($db); $search_statut = GETPOST('search_statut', 'int'); @@ -143,10 +146,7 @@ if (!is_array($user_arbo) && $user_arbo < 0) $param = "search_statut=".urlencode($search_statut); $newcardbutton = ''; - if ($canadduser) - { - $newcardbutton .= dolGetButtonTitle($langs->trans('NewUser'), '', 'fa fa-plus-circle', DOL_URL_ROOT.'/user/card.php?action=create'.($mode == 'employee' ? '&employee=1' : '').'&leftmenu='); - } + $newcardbutton .= dolGetButtonTitle($langs->trans('NewUser'), '', 'fa fa-plus-circle', DOL_URL_ROOT.'/user/card.php?action=create'.($mode == 'employee' ? '&employee=1' : '').'&leftmenu=', '', $canadduser); $morehtmlright .= dolGetButtonTitle($langs->trans("List"), '', 'fa fa-list paddingleft imgforviewmode', DOL_URL_ROOT.'/user/list.php'.(($search_statut != '' && $search_statut >= 0) ? '?search_statut='.$search_statut : '')); $param = array('morecss'=>'marginleftonly btnTitleSelected'); diff --git a/htdocs/user/list.php b/htdocs/user/list.php index a6237f47052..257bcd4c6be 100644 --- a/htdocs/user/list.php +++ b/htdocs/user/list.php @@ -299,7 +299,11 @@ $formother = new FormOther($db); //$help_url="EN:Module_MyObject|FR:Module_MyObject_FR|ES:Módulo_MyObject"; $help_url = ''; -$text = $langs->trans("ListOfUsers"); +if ($contextpage == 'employeelist' && $search_employee == 1) { + $text = $langs->trans("ListOfEmployees"); +} else { + $text = $langs->trans("ListOfUsers"); +} $user2 = new User($db); diff --git a/htdocs/website/class/website.class.php b/htdocs/website/class/website.class.php index bd25ad54898..631de0a5fa8 100644 --- a/htdocs/website/class/website.class.php +++ b/htdocs/website/class/website.class.php @@ -99,6 +99,10 @@ class Website extends CommonObject * @var integer */ public $fk_default_home; + + /** + * @var int User Create Id + */ public $fk_user_creat; /** @@ -878,13 +882,13 @@ class Website extends CommonObject global $user; $this->id = 0; - + $this->specimen =1; $this->entity = 1; $this->ref = 'myspecimenwebsite'; $this->description = 'A specimen website'; $this->lang = 'en'; $this->otherlang = 'fr,es'; - $this->status = ''; + $this->status = 1; $this->fk_default_home = null; $this->virtualhost = 'http://myvirtualhost'; $this->fk_user_creat = $user->id; @@ -1349,8 +1353,7 @@ class Website extends CommonObject $i++; } - if ($error) - { + if ($error) { return -1; } else { return $num; diff --git a/test/phpunit/CodingPhpTest.php b/test/phpunit/CodingPhpTest.php index 52c00978c54..727f8cc0ee3 100644 --- a/test/phpunit/CodingPhpTest.php +++ b/test/phpunit/CodingPhpTest.php @@ -281,7 +281,7 @@ class CodingPhpTest extends PHPUnit\Framework\TestCase preg_match_all('/sql.+\s*\'"\s*\.\s*\$(.........)/', $filecontent, $matches, PREG_SET_ORDER); foreach ($matches as $key => $val) { - if (! in_array($val[1], array('this->db-', 'this->esc', 'db->escap', 'db->idate', 'excludeGr', 'includeGr'))) { + if (! in_array($val[1], array('this->db-', 'this->esc', 'db->escap', 'dbsession->escap', 'db->idate', 'excludeGr', 'includeGr'))) { $ok=false; break; } diff --git a/test/phpunit/FunctionsLibTest.php b/test/phpunit/FunctionsLibTest.php index e24abcf4c0f..f757b00944f 100644 --- a/test/phpunit/FunctionsLibTest.php +++ b/test/phpunit/FunctionsLibTest.php @@ -1260,10 +1260,18 @@ class FunctionsLibTest extends PHPUnit\Framework\TestCase $newlangs2->load("main"); $langs = $newlangs2; - $this->assertEquals(1000, price2num('1.000'), 'Test 1.000 give 1000 with spanish language'); - $this->assertEquals(1000, price2num('1 000'), 'Test 1 000 give 1000 with spanish language'); + // Test with 3 chars after . or , + // If a . is used and there is 3 digits after, it is a thousand separator + $this->assertEquals(1234, price2num('1.234'), 'Test 1.234 give 1234 with spanish language'); + $this->assertEquals(1234, price2num('1 234'), 'Test 1 234 give 1234 with spanish language'); $this->assertEquals(1234, price2num('1.234'), 'Test 1.234 give 1234 with spanish language'); $this->assertEquals(1.234, price2num('1,234'), 'Test 1,234 give 1.234 with spanish language'); + $this->assertEquals(21500123, price2num('21.500.123'), 'Test 21.500.123 give 21500123 with spanish language'); + $this->assertEquals(21500123, price2num('21500.123'), 'Test 21500.123 give 21500123 with spanish language'); + $this->assertEquals(21500.123, price2num('21500,123'), 'Test 21500,123 give 21500.123 with spanish language'); + // Test with 2 digits + $this->assertEquals(21500.12, price2num('21500.12'), 'Test 21500.12 give 21500.12 with spanish language'); + $this->assertEquals(21500.12, price2num('21500,12'), 'Test 21500,12 give 21500.12 with spanish language'); // For french language $newlangs3 = new Translate('', $conf); @@ -1275,6 +1283,10 @@ class FunctionsLibTest extends PHPUnit\Framework\TestCase $this->assertEquals(1000, price2num('1 000'), 'Test 1.000 give 1 with french language'); $this->assertEquals(1.234, price2num('1.234'), 'Test 1.234 give 1.234 with french language'); $this->assertEquals(1.234, price2num('1,234'), 'Test 1,234 give 1.234 with french language'); + $this->assertEquals(21500000, price2num('21500 000'), 'Test 21500 000 give 21500000 with french language'); + $this->assertEquals(21500000, price2num('21 500 000'), 'Test 21 500 000 give 21500000 with french language'); + $this->assertEquals(21500, price2num('21500.00'), 'Test 21500.00 give 21500 with french language'); + $this->assertEquals(21500, price2num('21500,00'), 'Test 21500,00 give 21500 with french language'); $langs = $oldlangs;