diff --git a/build/docker/Dockerfile b/build/docker/Dockerfile index dca74e9e720..e39f96b0b27 100644 --- a/build/docker/Dockerfile +++ b/build/docker/Dockerfile @@ -39,15 +39,13 @@ RUN chmod +x /usr/local/bin/docker-run.sh RUN pecl install xdebug && docker-php-ext-enable xdebug RUN echo 'zend_extension="/usr/local/lib/php/extensions/no-debug-non-zts-20180731/xdebug.so"' >> ${PHP_INI_DIR}/php.ini -RUN echo 'xdebug.remote_autostart=1' >> ${PHP_INI_DIR}/php.ini -RUN echo 'xdebug.remote_enable=1' >> ${PHP_INI_DIR}/php.ini -RUN echo 'xdebug.default_enable=1' >> ${PHP_INI_DIR}/php.ini -#RUN echo 'xdebug.remote_host=docker.host' >> ${PHP_INI_DIR}/php.ini -RUN echo 'xdebug.remote_port=9000' >> ${PHP_INI_DIR}/php.ini -RUN echo 'xdebug.remote_connect_back=1' >> ${PHP_INI_DIR}/php.ini -RUN echo 'xdebug.profiler_enable=0' >> ${PHP_INI_DIR}/php.ini -RUN echo 'xdebug.remote_log="/tmp/xdebug.log"' >> ${PHP_INI_DIR}/php.ini -#RUN echo 'localhost docker.host' >> /etc/hosts +RUN echo 'xdebug.mode=debug' >> ${PHP_INI_DIR}/php.ini +RUN echo 'xdebug.start_with_request=yes' >> ${PHP_INI_DIR}/php.ini +RUN echo 'xdebug.client_host=host.docker.internal' >> ${PHP_INI_DIR}/php.ini +RUN echo 'xdebug.client_port=9003' >> ${PHP_INI_DIR}/php.ini +RUN echo 'xdebug.discover_client_host=true' >> ${PHP_INI_DIR}/php.ini +#RUN echo 'xdebug.log="/tmp/xdebug.log"' >> ${PHP_INI_DIR}/php.ini +RUN echo 'xdebug.idekey="netbeans-xdebug"' >> ${PHP_INI_DIR}/php.ini # set up sendmail config, to use maildev RUN echo "account default" > /etc/msmtprc diff --git a/build/docker/docker-compose.yml b/build/docker/docker-compose.yml index 2167f069f25..8994043cd8a 100644 --- a/build/docker/docker-compose.yml +++ b/build/docker/docker-compose.yml @@ -46,6 +46,9 @@ services: networks: - internal-pod - external-pod + extra_hosts: + - "localhost.localdomain:127.0.0.1" + - "host.docker.internal:host-gateway" mail: image: maildev/maildev diff --git a/htdocs/accountancy/class/accountancyimport.class.php b/htdocs/accountancy/class/accountancyimport.class.php index ece843515e2..ea88534b6ed 100644 --- a/htdocs/accountancy/class/accountancyimport.class.php +++ b/htdocs/accountancy/class/accountancyimport.class.php @@ -55,8 +55,8 @@ class AccountancyImport $fieldname = $fieldArr[1]; } - $debit = trim($arrayrecord[11]['val']); - $credit = trim($arrayrecord[12]['val']); + $debit = floatval(trim($arrayrecord[11]['val'])); + $credit = floatval(trim($arrayrecord[12]['val'])); if (!empty($debit)) { $amount = $debit; } else { @@ -86,7 +86,7 @@ class AccountancyImport $fieldname = $fieldArr[1]; } - $debit = trim($arrayrecord[11]['val']); + $debit = floatval(trim($arrayrecord[11]['val'])); if (!empty($debit)) { $sens = 'D'; } else { diff --git a/htdocs/accountancy/class/bookkeeping.class.php b/htdocs/accountancy/class/bookkeeping.class.php index 43dcce8c646..5635df3c8e7 100644 --- a/htdocs/accountancy/class/bookkeeping.class.php +++ b/htdocs/accountancy/class/bookkeeping.class.php @@ -331,7 +331,7 @@ class BookKeeping extends CommonObject if (empty($this->piece_num)) { $sqlnum = "SELECT MAX(piece_num)+1 as maxpiecenum"; $sqlnum .= " FROM ".MAIN_DB_PREFIX.$this->table_element; - $sqlnum .= " WHERE entity = ".$conf->entity; // Do not use getEntity for accounting features + $sqlnum .= " WHERE entity = " . ((int) $conf->entity); // Do not use getEntity for accounting features $resqlnum = $this->db->query($sqlnum); if ($resqlnum) { @@ -736,7 +736,7 @@ class BookKeeping extends CommonObject $sql .= " t.date_validated as date_validation"; $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.$mode.' as t'; $sql .= ' WHERE 1 = 1'; - $sql .= " AND entity IN (".getEntity('accountancy').")"; + $sql .= " AND entity = " . ((int) $conf->entity); // Do not use getEntity for accounting features if (null !== $ref) { $sql .= " AND t.ref = '".$this->db->escape($ref)."'"; } else { @@ -881,7 +881,7 @@ class BookKeeping extends CommonObject } $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t'; $sql .= ' WHERE 1 = 1'; - $sql .= " AND entity IN (".getEntity('accountancy').")"; + $sql .= " AND entity = " . ((int) $conf->entity); // Do not use getEntity for accounting features if (count($sqlwhere) > 0) { $sql .= ' AND '.implode(' '.$filtermode.' ', $sqlwhere); } @@ -1037,7 +1037,7 @@ class BookKeeping extends CommonObject } } } - $sql .= ' WHERE t.entity IN ('.getEntity('accountancy').')'; + $sql .= ' WHERE t.entity = ' . ((int) $conf->entity); // Do not use getEntity for accounting features if ($showAlreadyExportMovements == 0) { $sql .= " AND t.date_export IS NULL"; } @@ -1157,7 +1157,7 @@ class BookKeeping extends CommonObject } } } - $sql .= ' WHERE entity IN ('.getEntity('accountancy').')'; + $sql .= ' WHERE entity = ' . ((int) $conf->entity); // Do not use getEntity for accounting features if (count($sqlwhere) > 0) { $sql .= ' AND '.implode(' '.$filtermode.' ', $sqlwhere); } @@ -1454,7 +1454,7 @@ class BookKeeping extends CommonObject */ public function deleteByYearAndJournal($delyear = 0, $journal = '', $mode = '', $delmonth = 0) { - global $langs; + global $conf, $langs; if (empty($delyear) && empty($journal)) { $this->error = 'ErrorOneFieldRequired'; @@ -1475,7 +1475,7 @@ class BookKeeping extends CommonObject if (!empty($journal)) { $sql .= " AND code_journal = '".$this->db->escape($journal)."'"; } - $sql .= " AND entity IN (".getEntity('accountancy').")"; + $sql .= " AND entity = " . ((int) $conf->entity); // Do not use getEntity for accounting features // Exclusion of validated entries at the time of deletion $sql .= " AND date_validated IS NULL"; @@ -1514,7 +1514,7 @@ class BookKeeping extends CommonObject $sql .= " FROM ".MAIN_DB_PREFIX.$this->table_element; $sql .= " WHERE piece_num = ".(int) $piecenum; $sql .= " AND date_validated IS NULL"; // For security, exclusion of validated entries at the time of deletion - $sql .= " AND entity IN (".getEntity('accountancy').")"; + $sql .= " AND entity = " . ((int) $conf->entity); // Do not use getEntity for accounting features $resql = $this->db->query($sql); @@ -1636,7 +1636,7 @@ class BookKeeping extends CommonObject } $sql .= " FROM ".MAIN_DB_PREFIX.$this->table_element.$mode; $sql .= " WHERE piece_num = ".$piecenum; - $sql .= " AND entity IN (".getEntity('accountancy').")"; + $sql .= " AND entity = " . ((int) $conf->entity); // Do not use getEntity for accounting features dol_syslog(__METHOD__, LOG_DEBUG); $result = $this->db->query($sql); @@ -1674,9 +1674,9 @@ class BookKeeping extends CommonObject global $conf; $sql = "SELECT MAX(piece_num)+1 as max FROM ".MAIN_DB_PREFIX.$this->table_element.$mode; - $sql .= " WHERE entity IN (".getEntity('accountancy').")"; + $sql .= " WHERE entity = " . ((int) $conf->entity); // Do not use getEntity for accounting features - dol_syslog(get_class($this)."getNextNumMvt sql=".$sql, LOG_DEBUG); + dol_syslog(get_class($this)."::getNextNumMvt sql=".$sql, LOG_DEBUG); $result = $this->db->query($sql); if ($result) { @@ -1717,7 +1717,7 @@ class BookKeeping extends CommonObject } $sql .= " FROM ".MAIN_DB_PREFIX.$this->table_element.$mode; $sql .= " WHERE piece_num = ".$piecenum; - $sql .= " AND entity IN (".getEntity('accountancy').")"; + $sql .= " AND entity = " . ((int) $conf->entity); // Do not use getEntity for accounting features dol_syslog(__METHOD__, LOG_DEBUG); $result = $this->db->query($sql); @@ -1780,7 +1780,7 @@ class BookKeeping extends CommonObject $sql .= " montant as amount, sens, fk_user_author, import_key, code_journal, piece_num,"; $sql .= " date_validated as date_validation"; $sql .= " FROM ".MAIN_DB_PREFIX.$this->table_element; - $sql .= " WHERE entity IN (".getEntity('accountancy').")"; + $sql .= " WHERE entity = " . ((int) $conf->entity); // Do not use getEntity for accounting features dol_syslog(get_class($this)."::export_bookkeeping", LOG_DEBUG); @@ -1836,6 +1836,8 @@ class BookKeeping extends CommonObject */ public function transformTransaction($direction = 0, $piece_num = '') { + global $conf; + $error = 0; $this->db->begin(); @@ -1855,14 +1857,14 @@ class BookKeeping extends CommonObject $sql .= ' doc_ref, fk_doc, fk_docdet, entity, thirdparty_code, subledger_account, subledger_label,'; $sql .= ' numero_compte, label_compte, label_operation, debit, credit,'; $sql .= ' montant, sens, fk_user_author, import_key, code_journal, journal_label, '.$next_piecenum.", '".$this->db->idate($now)."'"; - $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.'_tmp WHERE piece_num = '.((int) $piece_num); + $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.'_tmp WHERE piece_num = '.((int) $piece_num).' AND entity = ' .((int) $conf->entity); $resql = $this->db->query($sql); if (!$resql) { $error++; $this->errors[] = 'Error '.$this->db->lasterror(); dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR); } - $sql = 'DELETE FROM '.MAIN_DB_PREFIX.$this->table_element.'_tmp WHERE piece_num = '.((int) $piece_num); + $sql = 'DELETE FROM '.MAIN_DB_PREFIX.$this->table_element.'_tmp WHERE piece_num = '.((int) $piece_num).' AND entity = ' .((int) $conf->entity); $resql = $this->db->query($sql); if (!$resql) { $error++; @@ -1870,7 +1872,7 @@ class BookKeeping extends CommonObject dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR); } } elseif ($direction == 1) { - $sql = 'DELETE FROM '.MAIN_DB_PREFIX.$this->table_element.'_tmp WHERE piece_num = '.((int) $piece_num); + $sql = 'DELETE FROM '.MAIN_DB_PREFIX.$this->table_element.'_tmp WHERE piece_num = '.((int) $piece_num).' AND entity = ' .((int) $conf->entity); $resql = $this->db->query($sql); if (!$resql) { $error++; @@ -1885,14 +1887,14 @@ class BookKeeping extends CommonObject $sql .= ' doc_ref, fk_doc, fk_docdet, thirdparty_code, subledger_account, subledger_label,'; $sql .= ' numero_compte, label_compte, label_operation, debit, credit,'; $sql .= ' montant, sens, fk_user_author, import_key, code_journal, journal_label, piece_num'; - $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' WHERE piece_num = '.((int) $piece_num); + $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' WHERE piece_num = '.((int) $piece_num).' AND entity = ' .((int) $conf->entity); $resql = $this->db->query($sql); if (!$resql) { $error++; $this->errors[] = 'Error '.$this->db->lasterror(); dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR); } - $sql = 'DELETE FROM '.MAIN_DB_PREFIX.$this->table_element.'_tmp WHERE piece_num = '.((int) $piece_num); + $sql = 'DELETE FROM '.MAIN_DB_PREFIX.$this->table_element.'_tmp WHERE piece_num = '.((int) $piece_num).' AND entity = ' .((int) $conf->entity); $resql = $this->db->query($sql); if (!$resql) { $error++; @@ -1947,7 +1949,7 @@ class BookKeeping extends CommonObject $sql .= " AND aa.active = 1"; $sql .= " INNER JOIN ".MAIN_DB_PREFIX."accounting_system as asy ON aa.fk_pcg_version = asy.pcg_version"; $sql .= " AND asy.rowid = ".((int) $pcgver); - $sql .= " AND ab.entity IN (".getEntity('accountancy').")"; + $sql .= " AND ab.entity = " . ((int) $conf->entity); // Do not use getEntity for accounting features $sql .= " ORDER BY account_number ASC"; dol_syslog(get_class($this)."::select_account", LOG_DEBUG); @@ -2011,7 +2013,7 @@ class BookKeeping extends CommonObject $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as parent ON aa.account_parent = parent.rowid AND parent.active = 1"; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as root ON parent.account_parent = root.rowid AND root.active = 1"; $sql .= " WHERE aa.account_number = '".$this->db->escape($account)."'"; - $sql .= " AND aa.entity IN (".getEntity('accountancy').")"; + $sql .= " AND aa.entity = " . ((int) $conf->entity); // Do not use getEntity for accounting features dol_syslog(get_class($this)."::select_account sql=".$sql, LOG_DEBUG); $resql = $this->db->query($sql); @@ -2051,7 +2053,7 @@ class BookKeeping extends CommonObject $sql .= " AND asy.rowid = ".((int) $pcgver); $sql .= " AND aa.active = 1"; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_accounting_category as cat ON aa.fk_accounting_category = cat.rowid"; - $sql .= " WHERE aa.entity IN (".getEntity('accountancy').")"; + $sql .= " WHERE aa.entity = " . ((int) $conf->entity); // Do not use getEntity for accounting features dol_syslog(get_class($this)."::select_account sql=".$sql, LOG_DEBUG); $resql = $this->db->query($sql); diff --git a/htdocs/accountancy/customer/index.php b/htdocs/accountancy/customer/index.php index a88524ec5d4..c233134f562 100644 --- a/htdocs/accountancy/customer/index.php +++ b/htdocs/accountancy/customer/index.php @@ -403,6 +403,7 @@ if (!empty($conf->global->FACTURE_DEPOSITS_ARE_JUST_PAYMENTS)) { } $sql .= " AND aa.account_number IS NOT NULL"; $sql .= " GROUP BY fd.fk_code_ventilation,aa.account_number,aa.label"; +$sql .= ' ORDER BY aa.account_number'; dol_syslog('htdocs/accountancy/customer/index.php'); $resql = $db->query($sql); diff --git a/htdocs/accountancy/expensereport/index.php b/htdocs/accountancy/expensereport/index.php index 0e3bda39521..2d9c8ac4f1c 100644 --- a/htdocs/accountancy/expensereport/index.php +++ b/htdocs/accountancy/expensereport/index.php @@ -188,6 +188,7 @@ $sql .= " AND er.fk_statut IN (".ExpenseReport::STATUS_APPROVED.", ".ExpenseRepo $sql .= " AND er.entity IN (".getEntity('expensereport', 0).")"; // We don't share object for accountancy $sql .= " AND aa.account_number IS NULL"; $sql .= " GROUP BY erd.fk_code_ventilation,aa.account_number,aa.label"; +$sql .= ' ORDER BY aa.account_number'; dol_syslog('/accountancy/expensereport/index.php:: sql='.$sql); $resql = $db->query($sql); diff --git a/htdocs/accountancy/supplier/index.php b/htdocs/accountancy/supplier/index.php index 585121f7c36..9ea8fd0a307 100644 --- a/htdocs/accountancy/supplier/index.php +++ b/htdocs/accountancy/supplier/index.php @@ -300,6 +300,7 @@ $sql .= " AND ffd.product_type <= 2"; $sql .= " AND ff.entity IN (".getEntity('facture_fourn', 0).")"; // We don't share object for accountancy $sql .= " AND aa.account_number IS NULL"; $sql .= " GROUP BY ffd.fk_code_ventilation,aa.account_number,aa.label"; +$sql .= ' ORDER BY aa.account_number'; dol_syslog('htdocs/accountancy/supplier/index.php'); $resql = $db->query($sql); diff --git a/htdocs/admin/dolistore/class/dolistore.class.php b/htdocs/admin/dolistore/class/dolistore.class.php index 546ef1d57a6..f672cf05a52 100644 --- a/htdocs/admin/dolistore/class/dolistore.class.php +++ b/htdocs/admin/dolistore/class/dolistore.class.php @@ -267,9 +267,9 @@ class Dolistore // add image or default ? if ($product->id_default_image != '') { - $image_url = DOL_URL_ROOT.'/admin/dolistore/ajax/image.php?id_product='.((int) $product->id).'&id_image='.((int) $product->id_default_image); - $images = ''; - $images .= ''; + $image_url = DOL_URL_ROOT.'/admin/dolistore/ajax/image.php?id_product='.urlencode(((int) $product->id)).'&id_image='.urlencode(((int) $product->id_default_image)); + $images = ''; + $images .= ''; } else { $images = ''; } @@ -277,11 +277,11 @@ class Dolistore // free or pay ? if ($product->price > 0) { $price = '

'.price(price2num($product->price, 'MT'), 0, $langs, 1, -1, -1, 'EUR').' '.$langs->trans("HT").'

'; - $download_link = ''; + $download_link = ''; } else { $price = '

'.$langs->trans('Free').'

'; - $download_link = ''; - $download_link .= '

'; + $download_link = ''; + $download_link .= '

'; } // Set and check version diff --git a/htdocs/admin/tools/dolibarr_export.php b/htdocs/admin/tools/dolibarr_export.php index 4f6977ffb41..092f3a57170 100644 --- a/htdocs/admin/tools/dolibarr_export.php +++ b/htdocs/admin/tools/dolibarr_export.php @@ -546,6 +546,7 @@ print ''; print ''; +$title = $langs->trans("BackupZipWizard"); print "
\n"; print "\n"; @@ -564,7 +565,7 @@ print ''; print '
'; -print load_fiche_titre($title ? $title : $langs->trans("BackupZipWizard")); +print load_fiche_titre($title); print '
'; $prefix = 'documents'; diff --git a/htdocs/admin/tools/export_files.php b/htdocs/admin/tools/export_files.php index 384b08e19cf..4bae5f4862d 100644 --- a/htdocs/admin/tools/export_files.php +++ b/htdocs/admin/tools/export_files.php @@ -126,8 +126,10 @@ $utils = new Utils($db); if ($compression == 'zip') { $file .= '.zip'; - $excludefiles = '/(\.back|\.old|\.log|[\/\\\]temp[\/\\\]|documents[\/\\\]admin[\/\\\]documents[\/\\\])/i'; + + $excludefiles = '/(\.back|\.old|\.log|\.pdf_preview-.*\.png|[\/\\\]temp[\/\\\]|[\/\\\]admin[\/\\\]documents[\/\\\])/i'; $ret = dol_compress_dir(DOL_DATA_ROOT, $outputdir."/".$file, $compression, $excludefiles); + if ($ret < 0) { if ($ret == -2) { $langs->load("errors"); diff --git a/htdocs/api/class/api.class.php b/htdocs/api/class/api.class.php index 0a84de7b7c1..e4f093be87f 100644 --- a/htdocs/api/class/api.class.php +++ b/htdocs/api/class/api.class.php @@ -348,6 +348,9 @@ class DolibarrApi $operand = preg_replace('/[^a-z0-9\._]/i', '', trim($tmp[0])); $operator = strtoupper(preg_replace('/[^a-z<>=]/i', '', trim($tmp[1]))); + if ($operator == 'NOTLIKE') { + $operator = 'NOT LIKE'; + } $tmpescaped = trim($tmp[2]); $regbis = array(); diff --git a/htdocs/api/class/api_setup.class.php b/htdocs/api/class/api_setup.class.php index 9856acfacdc..2572899e467 100644 --- a/htdocs/api/class/api_setup.class.php +++ b/htdocs/api/class/api_setup.class.php @@ -1041,7 +1041,7 @@ class Setup extends DolibarrApi * @param int $page Page number (starting from zero) * @param string $zipcode To filter on zipcode * @param string $town To filter on city name - * @param int $active Payment term is active or not {@min 0} {@max 1} + * @param int $active Town is active or not {@min 0} {@max 1} * @param string $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.code:like:'A%') and (t.active:>=:0)" * @return array List of towns * @@ -1055,7 +1055,7 @@ class Setup extends DolibarrApi $sql = "SELECT rowid AS id, zip, town, fk_county, fk_pays AS fk_country"; $sql .= " FROM ".MAIN_DB_PREFIX."c_ziptown as t"; - $sql .= " AND t.active = ".((int) $active); + $sql .= " WHERE t.active = ".((int) $active); if ($zipcode) { $sql .= " AND t.zip LIKE '%".$this->db->escape($zipcode)."%'"; } diff --git a/htdocs/api/index.php b/htdocs/api/index.php index d19754f9c35..869dacc5cc0 100644 --- a/htdocs/api/index.php +++ b/htdocs/api/index.php @@ -55,12 +55,27 @@ if (!empty($_SERVER['HTTP_DOLAPIENTITY'])) { define("DOLENTITY", (int) $_SERVER['HTTP_DOLAPIENTITY']); } +// Response for preflight requests (used by browser when into a CORS context) +if (!empty($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] == 'OPTIONS' && !empty($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS'])) { + header('Access-Control-Allow-Origin: *'); + header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE'); + header('Access-Control-Allow-Headers: Content-Type, Authorization, api_key, DOLAPIKEY'); + http_response_code(204); + exit; +} + // When we request url to get the json file, we accept Cross site so we can include the descriptor into an external tool. if (preg_match('/\/explorer\/swagger\.json/', $_SERVER["PHP_SELF"])) { header('Access-Control-Allow-Origin: *'); header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE'); header('Access-Control-Allow-Headers: Content-Type, Authorization, api_key, DOLAPIKEY'); } +// When we request url to get an API, we accept Cross site so we can make js API call inside another website +if (preg_match('/\/api\/index\.php/', $_SERVER["PHP_SELF"])) { + header('Access-Control-Allow-Origin: *'); + header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE'); + header('Access-Control-Allow-Headers: Content-Type, Authorization, api_key, DOLAPIKEY'); +} $res = 0; if (!$res && file_exists("../main.inc.php")) { @@ -304,7 +319,7 @@ if (!empty($reg[1]) && ($reg[1] != 'explorer' || ($reg[2] != '/swagger.json' && foreach ($listofendpoints as $endpointrule) { $tmparray = explode(':', $endpointrule); - if ($classfile == $tmparray[0] && $tmparray[1] == 1) { + if (($classfile == $tmparray[0] || $classfile.'api' == $tmparray[0]) && $tmparray[1] == 1) { $endpointisallowed = true; break; } diff --git a/htdocs/bookmarks/bookmarks.lib.php b/htdocs/bookmarks/bookmarks.lib.php index d24ba63ef55..f8daff1cd14 100644 --- a/htdocs/bookmarks/bookmarks.lib.php +++ b/htdocs/bookmarks/bookmarks.lib.php @@ -66,7 +66,7 @@ function printDropdownBookmarksList() // Url to list bookmark - $listbtn = ''; + $listbtn = ''; $listbtn .= img_picto('', 'bookmark', 'class="paddingright"').$langs->trans('Bookmarks').''; // Url to go on create new bookmark page diff --git a/htdocs/comm/propal/card.php b/htdocs/comm/propal/card.php index c96f24760c0..63f2977acdb 100644 --- a/htdocs/comm/propal/card.php +++ b/htdocs/comm/propal/card.php @@ -1944,7 +1944,7 @@ if ($action == 'create') { // We verify whether the object is provisionally numbering $ref = substr($object->ref, 1, 4); - if ($ref == 'PROV') { + if ($ref == 'PROV' || $ref == '') { $numref = $object->getNextNumRef($soc); if (empty($numref)) { $error++; diff --git a/htdocs/commande/card.php b/htdocs/commande/card.php index ba96725ddbd..3ed5ede556c 100644 --- a/htdocs/commande/card.php +++ b/htdocs/commande/card.php @@ -1877,8 +1877,12 @@ if ($action == 'create' && $usercancreate) { if ($action == 'validate') { // We check that object has a temporary ref $ref = substr($object->ref, 1, 4); - if ($ref == 'PROV') { + if ($ref == 'PROV' || $ref == '') { $numref = $object->getNextNumRef($soc); + if (empty($numref)) { + $error++; + setEventMessages($object->error, $object->errors, 'errors'); + } } else { $numref = $object->ref; } @@ -1915,7 +1919,9 @@ if ($action == 'create' && $usercancreate) { ); } - $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('ValidateOrder'), $text, 'confirm_validate', $formquestion, 0, 1, 220); + if (!$error) { + $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('ValidateOrder'), $text, 'confirm_validate', $formquestion, 0, 1, 220); + } } // Confirm back to draft status diff --git a/htdocs/compta/bank/card.php b/htdocs/compta/bank/card.php index 989ab236a1c..62b97f6d100 100644 --- a/htdocs/compta/bank/card.php +++ b/htdocs/compta/bank/card.php @@ -326,7 +326,7 @@ if ($action == 'create') { if ($conf->use_javascript_ajax) { print "\n".''."\n"; } else { dol_syslog("Warning: module ".$modjs." declared a js path file for a file we can't find.", LOG_WARNING); diff --git a/htdocs/modulebuilder/template/myobject_card.php b/htdocs/modulebuilder/template/myobject_card.php index b074412b6b3..346e9d907e6 100644 --- a/htdocs/modulebuilder/template/myobject_card.php +++ b/htdocs/modulebuilder/template/myobject_card.php @@ -132,7 +132,7 @@ $upload_dir = $conf->mymodule->multidir_output[isset($object->entity) ? $object- // Security check (enable the most restrictive one) //if ($user->socid > 0) accessforbidden(); //if ($user->socid > 0) $socid = $user->socid; -//$isdraft = (($object->status == $object::STATUS_DRAFT) ? 1 : 0); +//$isdraft = (isset($object->status) && ($object->status == $object::STATUS_DRAFT) ? 1 : 0); //restrictedArea($user, $object->element, $object->id, $object->table_element, '', 'fk_soc', 'rowid', $isdraft); //if (empty($conf->mymodule->enabled)) accessforbidden(); //if (!$permissiontoread) accessforbidden(); diff --git a/htdocs/mrp/class/mo.class.php b/htdocs/mrp/class/mo.class.php index d4abe482a88..97ac9adb6a3 100644 --- a/htdocs/mrp/class/mo.class.php +++ b/htdocs/mrp/class/mo.class.php @@ -112,8 +112,8 @@ class Mo extends CommonObject 'date_creation' => array('type'=>'datetime', 'label'=>'DateCreation', 'enabled'=>1, 'visible'=>-2, 'position'=>500, 'notnull'=>1,), 'tms' => array('type'=>'timestamp', 'label'=>'DateModification', 'enabled'=>1, 'visible'=>-2, 'position'=>501, 'notnull'=>1,), 'date_valid' => array('type'=>'datetime', 'label'=>'DateValidation', 'enabled'=>1, 'visible'=>-2, 'position'=>502,), - 'fk_user_creat' => array('type'=>'integer', 'label'=>'UserAuthor', 'enabled'=>1, 'visible'=>-2, 'position'=>510, 'notnull'=>1, 'foreignkey'=>'user.rowid', 'csslist'=>'tdoverflowmax100'), - 'fk_user_modif' => array('type'=>'integer', 'label'=>'UserModif', 'enabled'=>1, 'visible'=>-2, 'position'=>511, 'notnull'=>-1, 'csslist'=>'tdoverflowmax100'), + 'fk_user_creat' => array('type'=>'integer:User:user/class/user.class.php', 'label'=>'UserAuthor', 'enabled'=>1, 'visible'=>-2, 'position'=>510, 'notnull'=>1, 'foreignkey'=>'user.rowid', 'csslist'=>'tdoverflowmax100'), + 'fk_user_modif' => array('type'=>'integer:User:user/class/user.class.php', 'label'=>'UserModif', 'enabled'=>1, 'visible'=>-2, 'position'=>511, 'notnull'=>-1, 'csslist'=>'tdoverflowmax100'), 'date_start_planned' => array('type'=>'datetime', 'label'=>'DateStartPlannedMo', 'enabled'=>1, 'visible'=>1, 'position'=>55, 'notnull'=>-1, 'index'=>1, 'help'=>'KeepEmptyForAsap'), 'date_end_planned' => array('type'=>'datetime', 'label'=>'DateEndPlannedMo', 'enabled'=>1, 'visible'=>1, 'position'=>56, 'notnull'=>-1, 'index'=>1,), 'import_key' => array('type'=>'varchar(14)', 'label'=>'ImportId', 'enabled'=>1, 'visible'=>-2, 'position'=>1000, 'notnull'=>-1,), diff --git a/htdocs/product/admin/product.php b/htdocs/product/admin/product.php index fa75a20277f..ab54e292215 100644 --- a/htdocs/product/admin/product.php +++ b/htdocs/product/admin/product.php @@ -148,25 +148,8 @@ if ($action == 'other') { $value = GETPOST('activate_FillProductDescAuto', 'alpha'); $res = dolibarr_set_const($db, "PRODUIT_AUTOFILL_DESC", $value, 'chaine', 0, '', $conf->entity); - if ($value) { - $sql_test = "SELECT count(desc_fourn) as cpt FROM ".MAIN_DB_PREFIX."product_fournisseur_price WHERE 1"; - $resql = $db->query($sql_test); - if (!$resql && $db->lasterrno == 'DB_ERROR_NOSUCHFIELD') { // if the field does not exist, we create it - $sql_new = "ALTER TABLE ".MAIN_DB_PREFIX."product_fournisseur_price ADD COLUMN desc_fourn text"; - $resql_new = $db->query($sql_new); - } - } - $value = GETPOST('activate_useProdSupplierPackaging', 'alpha'); $res = dolibarr_set_const($db, "PRODUCT_USE_SUPPLIER_PACKAGING", $value, 'chaine', 0, '', $conf->entity); - if ($value) { - $sql_test = "SELECT count(packaging) as cpt FROM ".MAIN_DB_PREFIX."product_fournisseur_price WHERE 1"; - $resql = $db->query($sql_test); - if (!$resql && $db->lasterrno == 'DB_ERROR_NOSUCHFIELD') { // if the field does not exist, we create it - $sql_new = "ALTER TABLE ".MAIN_DB_PREFIX."product_fournisseur_price ADD COLUMN packaging double(24,8) DEFAULT 1"; - $resql_new = $db->query($sql_new); - } - } } if ($action == 'specimen') { // For products diff --git a/htdocs/product/class/product.class.php b/htdocs/product/class/product.class.php index 55c48be5088..f72642c249a 100644 --- a/htdocs/product/class/product.class.php +++ b/htdocs/product/class/product.class.php @@ -1947,7 +1947,10 @@ class Product extends CommonObject $sql .= " pfp.multicurrency_price, pfp.multicurrency_unitprice, pfp.multicurrency_tx, pfp.fk_multicurrency, pfp.multicurrency_code,"; $sql .= " pfp.packaging"; $sql .= " FROM ".MAIN_DB_PREFIX."product_fournisseur_price as pfp"; - $sql .= " WHERE pfp.fk_product = ".((int) $product_id); + $sql .= " WHERE 1 = 1"; + if ($product_id > 0) { + $sql .= " AND pfp.fk_product = ".((int) $product_id); + } if ($fourn_ref != 'none') { $sql .= " AND pfp.ref_fourn = '".$this->db->escape($fourn_ref)."'"; } @@ -5281,7 +5284,20 @@ class Product extends CommonObject } $stock_commande_fournisseur = $this->stats_commande_fournisseur['qty']; } + if (((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled) || !empty($conf->supplier_invoice->enabled)) && empty($conf->reception->enabled)) { + // Case module reception is not used + $filterStatus = '4'; + if (isset($includedraftpoforvirtual)) { + $filterStatus = '0,'.$filterStatus; + } + $result = $this->load_stats_reception(0, $filterStatus, 1); + if ($result < 0) { + dol_print_error($this->db, $this->error); + } + $stock_reception_fournisseur = $this->stats_reception['qty']; + } if (((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled) || !empty($conf->supplier_invoice->enabled)) && !empty($conf->reception->enabled)) { + // Case module reception is used $filterStatus = '4'; if (isset($includedraftpoforvirtual)) { $filterStatus = '0,'.$filterStatus; diff --git a/htdocs/product/reassort.php b/htdocs/product/reassort.php index c327b24e8f0..a711c630414 100644 --- a/htdocs/product/reassort.php +++ b/htdocs/product/reassort.php @@ -146,11 +146,11 @@ if (!empty($conf->global->PRODUCT_USE_UNITS)) { $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'c_units as u on p.fk_unit = u.rowid'; } // We'll need this table joined to the select in order to filter by categ -if ($search_categ) { +if ($search_categ > 0) { $sql .= ", ".MAIN_DB_PREFIX."categorie_product as cp"; } $sql .= " WHERE p.entity IN (".getEntity('product').")"; -if ($search_categ) { +if ($search_categ > 0) { $sql .= " AND p.rowid = cp.fk_product"; // Join for the needed table to filter by categ } if ($sall) { @@ -267,7 +267,7 @@ if ($resql) { if ($search_sale) { $param .= "&search_sale=".urlencode($search_sale); } - if ($search_categ) { + if ($search_categ > 0) { $param .= "&search_categ=".urlencode($search_categ); } if ($toolowstock) { @@ -344,7 +344,7 @@ if ($resql) { if ($toolowstock) { $param .= "&toolowstock=".urlencode($toolowstock); } - if ($search_categ) { + if ($search_categ > 0) { $param .= "&search_categ=".urlencode($search_categ); } diff --git a/htdocs/product/reassortlot.php b/htdocs/product/reassortlot.php index 65e69b91384..21bca9c4aa8 100644 --- a/htdocs/product/reassortlot.php +++ b/htdocs/product/reassortlot.php @@ -135,11 +135,11 @@ $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'entrepot as e on ps.fk_entrepot = e.rowid' $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'product_batch as pb on pb.fk_product_stock = ps.rowid'; // Detail for each lot on each warehouse $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'product_lot as pl on pl.fk_product = p.rowid AND pl.batch = pb.batch'; // Link on unique key // We'll need this table joined to the select in order to filter by categ -if ($search_categ) { +if ($search_categ > 0) { $sql .= ", ".MAIN_DB_PREFIX."categorie_product as cp"; } $sql .= " WHERE p.entity IN (".getEntity('product').")"; -if ($search_categ) { +if ($search_categ > 0) { $sql .= " AND p.rowid = cp.fk_product"; // Join for the needed table to filter by categ } if ($sall) { @@ -178,7 +178,7 @@ if ($fourn_id > 0) { $sql .= " AND p.rowid = pf.fk_product AND pf.fk_soc = ".((int) $fourn_id); } // Insert categ filter -if ($search_categ) { +if ($search_categ > 0) { $sql .= " AND cp.fk_categorie = ".((int) $search_categ); } if ($search_warehouse) { @@ -277,7 +277,7 @@ if ($resql) { if ($search_sale) { $param .= "&search_sale=".urlencode($search_sale); } - if ($search_categ) { + if ($search_categ > 0) { $param .= "&search_categ=".urlencode($search_categ); } /*if ($eatby) $param.="&eatby=".$eatby; diff --git a/htdocs/product/stock/card.php b/htdocs/product/stock/card.php index 440e082e8ff..80be3c923ec 100644 --- a/htdocs/product/stock/card.php +++ b/htdocs/product/stock/card.php @@ -944,7 +944,7 @@ if ($action != 'create' && $action != 'edit' && $action != 'delete') { $delallowed = $usercancreate; $modulepart = 'stock'; - print $formfile->showdocuments($modulepart, $object->ref, $filedir, $urlsource, $genallowed, $delallowed, $object->model_pdf, 0, 0, 0, 28, 0, '', 0, '', $object->default_lang, '', $object); + print $formfile->showdocuments($modulepart, $objectref, $filedir, $urlsource, $genallowed, $delallowed, $object->model_pdf, 0, 0, 0, 28, 0, '', 0, '', $object->default_lang, '', $object); $somethingshown = $formfile->numoffiles; print '
'; diff --git a/htdocs/product/stock/class/mouvementstock.class.php b/htdocs/product/stock/class/mouvementstock.class.php index 8a66e535ca2..4976530eb5e 100644 --- a/htdocs/product/stock/class/mouvementstock.class.php +++ b/htdocs/product/stock/class/mouvementstock.class.php @@ -842,7 +842,9 @@ class MouvementStock extends CommonObject */ private function createBatch($dluo, $qty) { - global $user; + global $user, $langs; + + $langs->load('productbatch'); $pdluo = new Productbatch($this->db); @@ -853,7 +855,7 @@ class MouvementStock extends CommonObject $result = $pdluo->fetch($dluo); if (empty($pdluo->id)) { // We didn't find the line. May be it was deleted before by a previous move in same transaction. - $this->error = 'Error. You ask a move on a record for a serial that does not exists anymore. May be you take the same serial on same warehouse several times in same shipment or it was used by another shipment. Remove this shipment and prepare another one.'; + $this->error = $langs->trans('CantMoveNonExistantSerial'); $this->errors[] = $this->error; $result = -2; } diff --git a/htdocs/public/ticket/create_ticket.php b/htdocs/public/ticket/create_ticket.php index b911e7480d3..d653f835616 100644 --- a/htdocs/public/ticket/create_ticket.php +++ b/htdocs/public/ticket/create_ticket.php @@ -249,7 +249,7 @@ if (empty($reshook) && $action == 'create_ticket' && GETPOST('add', 'alpha')) { $message = ($conf->global->TICKET_MESSAGE_MAIL_NEW ? $conf->global->TICKET_MESSAGE_MAIL_NEW : $langs->transnoentities('TicketNewEmailBody')).'

'; $message .= $langs->transnoentities('TicketNewEmailBodyInfosTicket').'
'; - $url_public_ticket = ($conf->global->TICKET_URL_PUBLIC_INTERFACE ? $conf->global->TICKET_URL_PUBLIC_INTERFACE.'/' : dol_buildpath('/public/ticket/view.php', 2)).'?track_id='.$object->track_id; + $url_public_ticket = ($conf->global->TICKET_URL_PUBLIC_INTERFACE ? $conf->global->TICKET_URL_PUBLIC_INTERFACE.'/view.php' : dol_buildpath('/public/ticket/view.php', 2)).'?track_id='.$object->track_id; $infos_new_ticket = $langs->transnoentities('TicketNewEmailBodyInfosTrackId', ''.$object->track_id.'').'
'; $infos_new_ticket .= $langs->transnoentities('TicketNewEmailBodyInfosTrackUrl').'

'; diff --git a/htdocs/reception/card.php b/htdocs/reception/card.php index e0f84f24df4..e5f5fccffad 100644 --- a/htdocs/reception/card.php +++ b/htdocs/reception/card.php @@ -1031,9 +1031,17 @@ if ($action == 'create') { print "\n"; } + // $objectsrc->lines contains the line of the purchase order + // $dispatchLines is list of lines with dispatching detail (with product, qty and warehouse). One purchase order line may have n of this dispatch lines. + + $arrayofpurchaselinealreadyoutput= array(); + + // $_POST contains fk_commandefourndet_X_Y where Y is num of product line and X is number of splitted line $indiceAsked = 1; - while ($indiceAsked <= $numAsked) { + while ($indiceAsked <= $numAsked) { // Loop on $dispatchLines. Warning: $dispatchLines must be sorted by fk_commandefourndet (it is a regroupment key on output) $product = new Product($db); + + // We search the purchase order line that is linked to the dispatchLines foreach ($objectsrc->lines as $supplierLine) { if ($dispatchLines[$indiceAsked]['fk_commandefourndet'] == $supplierLine->id) { $line = $supplierLine; @@ -1055,7 +1063,6 @@ if ($action == 'create') { print ''."\n"; print ''."\n"; - // Product label if ($line->fk_product > 0) { // If predefined product $product->fetch($line->fk_product); @@ -1064,42 +1071,45 @@ if ($action == 'create') { print ''; print ''; // ancre pour retourner sur la ligne - print ''; + if (! array_key_exists($line->id, $arrayofpurchaselinealreadyoutput)) { // Add test to avoid to show qty twice + print ''; - // Show product and description - $product_static = $product; + // Show product and description + $product_static = $product; - $text = $product_static->getNomUrl(1); - $text .= ' - '.(!empty($line->label) ? $line->label : $line->product_label); - $description = ($conf->global->PRODUIT_DESC_IN_FORM ? '' : dol_htmlentitiesbr($line->desc)); - print $form->textwithtooltip($text, $description, 3, '', '', $i); + $text = $product_static->getNomUrl(1); + $text .= ' - '.(!empty($line->label) ? $line->label : $line->product_label); + $description = ($conf->global->PRODUIT_DESC_IN_FORM ? '' : dol_htmlentitiesbr($line->desc)); + print $form->textwithtooltip($text, $description, 3, '', '', $i); - // Show range - print_date_range($db->jdate($line->date_start), $db->jdate($line->date_end)); + // Show range + print_date_range($db->jdate($line->date_start), $db->jdate($line->date_end)); - // Add description in form - if (!empty($conf->global->PRODUIT_DESC_IN_FORM)) { - print ($line->desc && $line->desc != $line->product_label) ? '
'.dol_htmlentitiesbr($line->desc) : ''; + // Add description in form + if (!empty($conf->global->PRODUIT_DESC_IN_FORM)) { + print ($line->desc && $line->desc != $line->product_label) ? '
'.dol_htmlentitiesbr($line->desc) : ''; + } } - print ''; } else { print ""; - if ($type == 1) { - $text = img_object($langs->trans('Service'), 'service'); - } else { - $text = img_object($langs->trans('Product'), 'product'); - } + if (! array_key_exists($line->id, $arrayofpurchaselinealreadyoutput)) { // Add test to avoid to show qty twice + if ($type == 1) { + $text = img_object($langs->trans('Service'), 'service'); + } else { + $text = img_object($langs->trans('Product'), 'product'); + } - if (!empty($line->label)) { - $text .= ' '.$line->label.''; - print $form->textwithtooltip($text, $line->desc, 3, '', '', $i); - } else { - print $text.' '.nl2br($line->desc); - } + if (!empty($line->label)) { + $text .= ' '.$line->label.''; + print $form->textwithtooltip($text, $line->desc, 3, '', '', $i); + } else { + print $text.' '.nl2br($line->desc); + } - // Show range - print_date_range($db->jdate($line->date_start), $db->jdate($line->date_end)); + // Show range + print_date_range($db->jdate($line->date_start), $db->jdate($line->date_end)); + } print "\n"; } @@ -1110,8 +1120,11 @@ if ($action == 'create') { print ''; print ''; - // Qty - print ''.$line->qty; + // Qty in source purchase order line + print ''; + if (! array_key_exists($line->id, $arrayofpurchaselinealreadyoutput)) { // Add test to avoid to show qty twice + print $line->qty; + } print ''; print ''; print ''; @@ -1121,7 +1134,9 @@ if ($action == 'create') { // Qty already received print ''; $quantityDelivered = $objectsrc->receptions[$line->id]; - print $quantityDelivered; + if (! array_key_exists($line->id, $arrayofpurchaselinealreadyoutput)) { // Add test to avoid to show qty twice + print $quantityDelivered; + } print ''; print ''; @@ -1190,6 +1205,9 @@ if ($action == 'create') { } } } + + $arrayofpurchaselinealreadyoutput[$line->id] = $line->id; + print "\n"; $extralabelslines = $extrafields->attributes[$line->table_element]; @@ -1756,7 +1774,9 @@ if ($action == 'create') { //var_dump($alreadysent); } - // Loop on each product to send/sent + $arrayofpurchaselinealreadyoutput = array(); + + // Loop on each product to send/sent. Warning: $lines must be sorted by ->fk_commandefourndet (it is a regroupment key on output) for ($i = 0; $i < $num_prod; $i++) { print ''; // id of order line print ''; @@ -1778,32 +1798,35 @@ if ($action == 'create') { } print ''; - - $text = $lines[$i]->product->getNomUrl(1); - $text .= ' - '.$label; - $description = (!empty($conf->global->PRODUIT_DESC_IN_FORM) ? '' : dol_htmlentitiesbr($lines[$i]->product->description)); - print $form->textwithtooltip($text, $description, 3, '', '', $i); - print_date_range($lines[$i]->date_start, $lines[$i]->date_end); - if (!empty($conf->global->PRODUIT_DESC_IN_FORM)) { - print (!empty($lines[$i]->product->description) && $lines[$i]->description != $lines[$i]->product->description) ? '
'.dol_htmlentitiesbr($lines[$i]->description) : ''; + if (!array_key_exists($lines[$i]->fk_commandefourndet, $arrayofpurchaselinealreadyoutput)) { + $text = $lines[$i]->product->getNomUrl(1); + $text .= ' - '.$label; + $description = (!empty($conf->global->PRODUIT_DESC_IN_FORM) ? '' : dol_htmlentitiesbr($lines[$i]->product->description)); + print $form->textwithtooltip($text, $description, 3, '', '', $i); + print_date_range($lines[$i]->date_start, $lines[$i]->date_end); + if (!empty($conf->global->PRODUIT_DESC_IN_FORM)) { + print (!empty($lines[$i]->product->description) && $lines[$i]->description != $lines[$i]->product->description) ? '
'.dol_htmlentitiesbr($lines[$i]->description) : ''; + } } print "\n"; } else { print ""; - if ($lines[$i]->product_type == Product::TYPE_SERVICE) { - $text = img_object($langs->trans('Service'), 'service'); - } else { - $text = img_object($langs->trans('Product'), 'product'); - } + if (!array_key_exists($lines[$i]->fk_commandefourndet, $arrayofpurchaselinealreadyoutput)) { + if ($lines[$i]->product_type == Product::TYPE_SERVICE) { + $text = img_object($langs->trans('Service'), 'service'); + } else { + $text = img_object($langs->trans('Product'), 'product'); + } - if (!empty($lines[$i]->label)) { - $text .= ' '.$lines[$i]->label.''; - print $form->textwithtooltip($text, $lines[$i]->description, 3, '', '', $i); - } else { - print $text.' '.nl2br($lines[$i]->description); - } + if (!empty($lines[$i]->label)) { + $text .= ' '.$lines[$i]->label.''; + print $form->textwithtooltip($text, $lines[$i]->description, 3, '', '', $i); + } else { + print $text.' '.nl2br($lines[$i]->description); + } - print_date_range($lines[$i]->date_start, $lines[$i]->date_end); + print_date_range($lines[$i]->date_start, $lines[$i]->date_end); + } print "\n"; } @@ -1815,33 +1838,39 @@ if ($action == 'create') { // Qty ordered - print ''.$lines[$i]->qty_asked.''; + print ''; + if (!array_key_exists($lines[$i]->fk_commandefourndet, $arrayofpurchaselinealreadyoutput)) { + print $lines[$i]->qty_asked; + } + print ''; // Qty in other receptions (with reception and warehouse used) if ($origin && $origin_id > 0) { print ''; - foreach ($alreadysent as $key => $val) { - if ($lines[$i]->fk_commandefourndet == $key) { - $j = 0; - foreach ($val as $receptionline_id => $receptionline_var) { - if ($receptionline_var['reception_id'] == $lines[$i]->fk_reception) { - continue; // We want to show only "other receptions" - } + if (!array_key_exists($lines[$i]->fk_commandefourndet, $arrayofpurchaselinealreadyoutput)) { + foreach ($alreadysent as $key => $val) { + if ($lines[$i]->fk_commandefourndet == $key) { + $j = 0; + foreach ($val as $receptionline_id => $receptionline_var) { + if ($receptionline_var['reception_id'] == $lines[$i]->fk_reception) { + continue; // We want to show only "other receptions" + } - $j++; - if ($j > 1) { - print '
'; - } - $reception_static->fetch($receptionline_var['reception_id']); - print $reception_static->getNomUrl(1); - print ' - '.$receptionline_var['qty']; + $j++; + if ($j > 1) { + print '
'; + } + $reception_static->fetch($receptionline_var['reception_id']); + print $reception_static->getNomUrl(1); + print ' - '.$receptionline_var['qty']; - $htmltext = $langs->trans("DateValidation").' : '.(empty($receptionline_var['date_valid']) ? $langs->trans("Draft") : dol_print_date($receptionline_var['date_valid'], 'dayhour')); - if (!empty($conf->stock->enabled) && $receptionline_var['warehouse'] > 0) { - $warehousestatic->fetch($receptionline_var['warehouse']); - $htmltext .= '
'.$langs->trans("From").' : '.$warehousestatic->getNomUrl(1, '', 0, 1); + $htmltext = $langs->trans("DateValidation").' : '.(empty($receptionline_var['date_valid']) ? $langs->trans("Draft") : dol_print_date($receptionline_var['date_valid'], 'dayhour')); + if (!empty($conf->stock->enabled) && $receptionline_var['warehouse'] > 0) { + $warehousestatic->fetch($receptionline_var['warehouse']); + $htmltext .= '
'.$langs->trans("From").' : '.$warehousestatic->getNomUrl(1, '', 0, 1); + } + print ' '.$form->textwithpicto('', $htmltext, 1); } - print ' '.$form->textwithpicto('', $htmltext, 1); } } } @@ -1971,6 +2000,8 @@ if ($action == 'create') { } print ""; + $arrayofpurchaselinealreadyoutput[$lines[$i]->fk_commandefourndet] = $lines[$i]->fk_commandefourndet; + // Display lines extrafields $extralabelslines = $extrafields->attributes[$lines[$i]->table_element]; if (is_array($extralabelslines) && count($extralabelslines) > 0) { diff --git a/htdocs/reception/list.php b/htdocs/reception/list.php index 8f07d1bede7..9f98202099a 100644 --- a/htdocs/reception/list.php +++ b/htdocs/reception/list.php @@ -491,6 +491,9 @@ $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."delivery as l ON l.rowid = ee.fk_target"; if (!$user->rights->societe->client->voir && !$socid) { // Internal user with no permission to see all $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; } +$parameters = array(); +$reshook = $hookmanager->executeHooks('printFieldListFrom', $parameters, $object); // Note that $action and $object may have been modified by hook +$sql .= $hookmanager->resPrint; $sql .= " WHERE e.entity IN (".getEntity('reception').")"; if (!$user->rights->societe->client->voir && !$socid) { // Internal user with no permission to see all $sql .= " AND e.fk_soc = sc.fk_soc"; @@ -976,6 +979,9 @@ while ($i < min($num, $limit)) { { }*/ print "\n"; + if (!$i) { + $totalarray['nbfield']++; + } } if (!empty($arrayfields['l.ref']['checked']) || !empty($arrayfields['l.date_delivery']['checked'])) { @@ -1071,6 +1077,13 @@ if ($num == 0) { print ''.$langs->trans("NoRecordFound").''; } +// Show total line +include DOL_DOCUMENT_ROOT.'/core/tpl/list_print_total.tpl.php'; + +$parameters = array('arrayfields'=>$arrayfields, 'sql'=>$sql); +$reshook = $hookmanager->executeHooks('printFieldListFooter', $parameters); // Note that $action and $object may have been modified by hook +print $hookmanager->resPrint; + print ""; print "
"; print ''; diff --git a/htdocs/societe/class/societe.class.php b/htdocs/societe/class/societe.class.php index c8b381280b1..3d1637019e9 100644 --- a/htdocs/societe/class/societe.class.php +++ b/htdocs/societe/class/societe.class.php @@ -875,8 +875,8 @@ class Societe extends CommonObject $sql .= ", name_alias"; $sql .= ", entity"; $sql .= ", datec"; - $sql .= ", fk_typent"; $sql .= ", fk_user_creat"; + $sql .= ", fk_typent"; $sql .= ", canvas"; $sql .= ", status"; $sql .= ", ref_ext"; diff --git a/htdocs/takepos/receipt.php b/htdocs/takepos/receipt.php index 627a6c99565..b834ff64d0a 100644 --- a/htdocs/takepos/receipt.php +++ b/htdocs/takepos/receipt.php @@ -48,7 +48,7 @@ if (!isset($action)) { } include_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php'; -$langs->loadLangs(array("main", "cashdesk", "companies")); +$langs->loadLangs(array("main", "bills", "cashdesk", "companies")); $place = (GETPOST('place', 'aZ09') ? GETPOST('place', 'aZ09') : 0); // $place is id of table for Bar or Restaurant @@ -68,7 +68,7 @@ if (empty($user->rights->takepos->run)) { top_httphead('text/html'); if ($place > 0) { - $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."facture where ref='(PROV-POS".$_SESSION["takeposterminal"]."-".$place.")'"; + $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."facture where ref='(PROV-POS".$db->escape($_SESSION["takeposterminal"]."-".$place).")'"; $resql = $db->query($sql); $obj = $db->fetch_object($resql); if ($obj) { @@ -79,6 +79,7 @@ $object = new Facture($db); $object->fetch($facid); // Call to external receipt modules if exist +$parameters = array(); $hookmanager->initHooks(array('takeposfrontend'), $facid); $reshook = $hookmanager->executeHooks('TakeposReceipt', $parameters, $object); if (!empty($hookmanager->resPrint)) { diff --git a/htdocs/ticket/list.php b/htdocs/ticket/list.php index 6991516ede8..4caffd173c3 100644 --- a/htdocs/ticket/list.php +++ b/htdocs/ticket/list.php @@ -391,7 +391,7 @@ foreach ($search as $key => $val) { continue; } $mode_search = (($object->isInt($object->fields[$key]) || $object->isFloat($object->fields[$key])) ? 1 : 0); - if ($search[$key] != '') { + if ($search[$key] != '' && !is_array($val)) { $sql .= natural_search($key, $search[$key], $mode_search); } } @@ -609,9 +609,9 @@ if ($limit > 0 && $limit != $conf->liste_limit) { $param .= '&limit='.urlencode($limit); } foreach ($search as $key => $val) { - if (is_array($search[$key]) && count($search[$key])) { - foreach ($search[$key] as $skey) { - $param .= '&search_'.$key.'[]='.urlencode($skey); + if (is_array($val) && count($val)) { + foreach ($val as $skey) { + $param .= (!empty($val)) ? '&search_'.$key.'[]='.urlencode($skey) : ""; } } else { $param .= '&search_'.$key.'='.urlencode($search[$key]); diff --git a/htdocs/ticket/messaging.php b/htdocs/ticket/messaging.php index 68615424abf..9d605a530b9 100644 --- a/htdocs/ticket/messaging.php +++ b/htdocs/ticket/messaging.php @@ -204,6 +204,7 @@ if (!empty($conf->projet->enabled)) { } } else { if (!empty($object->fk_project)) { + require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php'; $proj = new Project($db); $proj->fetch($object->fk_project); $morehtmlref .= $proj->getNomUrl(1); diff --git a/htdocs/user/param_ihm.php b/htdocs/user/param_ihm.php index 72f9b075be9..0d2729d904f 100644 --- a/htdocs/user/param_ihm.php +++ b/htdocs/user/param_ihm.php @@ -207,6 +207,9 @@ if (!empty($conf->adherent->enabled)) { if (!empty($conf->agenda->enabled)) { $tmparray['comm/action/index.php?mainmenu=agenda&leftmenu='] = 'Agenda'; } +if (!empty($conf->ticket->enabled)) { + $tmparray['ticket/list.php?mainmenu=ticket&leftmenu='] = 'Tickets'; +} $head = user_prepare_head($object); diff --git a/htdocs/variants/combinations.php b/htdocs/variants/combinations.php index c29fc519258..f8fb962e1ef 100644 --- a/htdocs/variants/combinations.php +++ b/htdocs/variants/combinations.php @@ -248,7 +248,7 @@ if (($action == 'add' || $action == 'create') && empty($massaction) && !GETPOST( exit(); } - $prodcomb->variation_weight = $weight_impact; + $prodcomb->variation_weight = price2num($weight_impact); // for conf PRODUIT_MULTIPRICES if ($conf->global->PRODUIT_MULTIPRICES) { diff --git a/htdocs/viewimage.php b/htdocs/viewimage.php index 0e91bd5bc9f..881f741650d 100644 --- a/htdocs/viewimage.php +++ b/htdocs/viewimage.php @@ -234,7 +234,7 @@ if (empty($modulepart)) { accessforbidden('Bad value for parameter modulepart', 0, 0, 1); } -$check_access = dol_check_secure_access_document($modulepart, $original_file, $entity, $refname); +$check_access = dol_check_secure_access_document($modulepart, $original_file, $entity, $user, $refname); $accessallowed = $check_access['accessallowed']; $sqlprotectagainstexternals = $check_access['sqlprotectagainstexternals']; $fullpath_original_file = $check_access['original_file']; // $fullpath_original_file is now a full path name diff --git a/test/phpunit/SecurityTest.php b/test/phpunit/SecurityTest.php index 6bece069cc9..2d14a35dce9 100644 --- a/test/phpunit/SecurityTest.php +++ b/test/phpunit/SecurityTest.php @@ -359,7 +359,7 @@ class SecurityTest extends PHPUnit\Framework\TestCase $_POST['param8b']='objnotdefined\''; @@ -501,6 +501,10 @@ class SecurityTest extends PHPUnit\Framework\TestCase print __METHOD__." result param7 = ".$result."\n"; $this->assertEquals('"c:\this is a path~1\aaan &#x;;;;" abcdef', $result); + $result=GETPOST("param8e", 'restricthtml'); + print __METHOD__." result param8e = ".$result."\n"; + $this->assertEquals('', $result); + $result=GETPOST("param12", 'restricthtml'); print __METHOD__." result=".$result."\n"; $this->assertEquals(trim($_POST["param12"]), $result, 'Test a string with DOCTYPE and restricthtml'); @@ -519,7 +523,7 @@ class SecurityTest extends PHPUnit\Framework\TestCase $result=GETPOST("param15", 'restricthtml'); // src=>0xbeefed print __METHOD__." result=".$result."\n"; - $this->assertEquals("0xbeefed", $result, 'Test 15a'); // The GETPOST return a harmull string + $this->assertEquals("0xbeefed", $result, 'Test 15'); // The GETPOST return a harmull string // Test with restricthtml + MAIN_RESTRICTHTML_REMOVE_ALSO_BAD_ATTRIBUTES to test disabling of bad atrributes $conf->global->MAIN_RESTRICTHTML_ONLY_VALID_HTML = 1; diff --git a/test/phpunit/testvirus.txt b/test/phpunit/testvirus.txt index a2463df6d64..86bb55dac62 100644 --- a/test/phpunit/testvirus.txt +++ b/test/phpunit/testvirus.txt @@ -1 +1,2 @@ -X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H* \ No newline at end of file +# Remove this line and replace the "AB" with "X5" at begin of line to get a file that is detected by antiviruses. +ABO!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*