diff --git a/.travis.yml b/.travis.yml index 84342c3e55c..7cfc506c609 100644 --- a/.travis.yml +++ b/.travis.yml @@ -85,6 +85,9 @@ before_install: if [ "$TRAVIS_PHP_VERSION" = '7.1' ]; then sudo apt install unzip apache2 php7.1 php7.1-cli php7.1-curl php7.1-mysql php7.1-pgsql php7.1-gd php7.1-imap php7.1-intl php7.1-ldap php7.1-xml php7.1-mbstring php7.1-xml php7.1-zip libapache2-mod-php7.1 fi + if [ "$TRAVIS_PHP_VERSION" = '7.1' ]; then + sudo apt install unzip apache2 php7.1 php7.1-cli php7.1-curl php7.1-mysql php7.1-pgsql php7.1-gd php7.1-imap php7.1-intl php7.1-ldap php7.1-xml php7.1-mbstring php7.1-xml php7.1-zip libapache2-mod-php7.1 + fi if [ "$TRAVIS_PHP_VERSION" = '8.1' ]; then sudo apt install unzip apache2 php8.1 php8.1-cli php8.1-curl php8.1-mysql php8.1-pgsql php8.1-gd php8.1-imap php8.1-intl php8.1-ldap php8.1-xml php8.1-mbstring php8.1-xml php8.1-zip libapache2-mod-php8.1 fi @@ -122,6 +125,9 @@ before_install: install: - | + if [ "$TRAVIS_PHP_VERSION" = '7.0' ]; then + sudo update-alternatives --set php /usr/bin/php7.0 + fi if [ "$TRAVIS_PHP_VERSION" = '7.1' ]; then sudo update-alternatives --set php /usr/bin/php7.1 fi diff --git a/ChangeLog b/ChangeLog index 7fe56e48177..4f94f4a4d00 100644 --- a/ChangeLog +++ b/ChangeLog @@ -2117,7 +2117,7 @@ Following changes may create regressions for some external modules, but were nec ***** ChangeLog for 17.0.4 compared to 17.0.3 ***** -FIX: $this->newref already exists and could have been modified by trigger but we still use a local variable for the filesystem-based renaming +FIX: $this->newref already exists and could have been modified by a trigger but we still use a local variable for the filesystem-based renaming FIX: 16.0 only, backport fix for SQL error on global search product FIX: 17.0: deprecated field should only be a fallback FIX: 17.0 PHP8: supplier invoice class: diff --git a/build/makepack-dolibarr.pl b/build/makepack-dolibarr.pl index 1c4ed9efbbf..88005007fbe 100755 --- a/build/makepack-dolibarr.pl +++ b/build/makepack-dolibarr.pl @@ -845,6 +845,7 @@ if ($nboftargetok) { print "Compress $FILENAMETGZ2 into $FILENAMETGZ2.tgz...\n"; $ret=`tar --exclude-from "$SOURCE/build/tgz/tar_exclude.txt" --directory "$BUILDROOT" -czvf "$BUILDROOT/$FILENAMETGZ2.tgz" $FILENAMETGZ2`; + if (! -d $RPMDIR . '/SOURCES') { mkdir($RPMDIR . '/SOURCES'); } print "Move $BUILDROOT/$FILENAMETGZ2.tgz to $RPMDIR/SOURCES/$FILENAMETGZ2.tgz\n"; $cmd="mv $BUILDROOT/$FILENAMETGZ2.tgz $RPMDIR/SOURCES/$FILENAMETGZ2.tgz"; $ret=`$cmd`; diff --git a/build/makepack-howto.txt b/build/makepack-howto.txt index f152282f143..59b1e8a795f 100644 --- a/build/makepack-howto.txt +++ b/build/makepack-howto.txt @@ -6,7 +6,7 @@ of Dolibarr. There is a chapter for BETA version and a chapter for RELEASE versi ***** Prerequisites For Linux ***** Prerequisites to build tgz, debian and rpm packages: -> apt-get install perl tar dpkg dpatch p7zip-full rpm zip php-cli +> apt-get install perl tar dpkg p7zip-full rpm zip php-cli debhelper po-debconf Prerequisites to build autoexe DoliWamp package from Linux (solution seems broken since Ubuntu 20.04): > apt-get install wine q4wine @@ -45,7 +45,7 @@ Prerequisites to build autoexe DoliWamp package from Windows: ***** Actions to do a BETA ***** -This files describe steps made by Dolibarr packaging team to make a beta version of Dolibarr, step by step. +This section describes steps made by Dolibarr packaging team to make a beta version of Dolibarr, step by step. - Check all files are committed. - Update version/info in ChangeLog, for this you can: @@ -66,7 +66,7 @@ Recopy the content of the output file into the file ChangeLog. ***** Actions to do a RELEASE ***** -This files describe steps made by Dolibarr packaging team to make a complete release of Dolibarr, step by step. +This section describes steps made by Dolibarr packaging team to make a complete release of Dolibarr, step by step. We suppose the branch x.y has already been created during the beta (see previous step). - Check all files are committed. diff --git a/htdocs/accountancy/class/bookkeeping.class.php b/htdocs/accountancy/class/bookkeeping.class.php index e63334650fd..825664d99e9 100644 --- a/htdocs/accountancy/class/bookkeeping.class.php +++ b/htdocs/accountancy/class/bookkeeping.class.php @@ -3009,7 +3009,7 @@ class BookKeeping extends CommonObject $error++; } $objtmp = $this->db->fetch_object($result); - $bookkeeping->subledger_label = $objtmp->subledger_label; // latest subledger label used + $bookkeeping->subledger_label = $objtmp->subledger_label ?? null; // latest subledger label used } else { $bookkeeping->subledger_account = null; $bookkeeping->subledger_label = null; diff --git a/htdocs/compta/facture/class/api_invoices.class.php b/htdocs/compta/facture/class/api_invoices.class.php index 1476eb8e764..8e9acda1c24 100644 --- a/htdocs/compta/facture/class/api_invoices.class.php +++ b/htdocs/compta/facture/class/api_invoices.class.php @@ -1590,8 +1590,8 @@ class Invoices extends DolibarrApi * Warning: Take care that all invoices are owned by the same customer. * Example of value for parameter arrayofamounts: {"1": {"amount": "99.99", "multicurrency_amount": ""}, "2": {"amount": "", "multicurrency_amount": "10"}} * - * @param array $arrayofamounts {@from body} Array with id of invoices with amount to pay for each invoice - * @param string $datepaye {@from body} Payment date + * @param array $arrayofamounts {@from body} Array with id of invoices with amount to pay for each invoice + * @param string $datepaye {@from body} Payment date {@type timestamp} * @param int $paymentid {@from body} Payment mode Id {@min 1} * @param string $closepaidinvoices {@from body} Close paid invoices {@choice yes,no} * @param int $accountid {@from body} Account Id {@min 1} @@ -1676,13 +1676,13 @@ class Invoices extends DolibarrApi $amount = price2num($amountarray["multicurrency_amount"], 'MT'); } - if ($amount > $remainstopay && !$accepthigherpayment) { + if (abs($amount) > abs($remainstopay) && !$accepthigherpayment) { $this->db->rollback(); throw new RestException(400, 'Payment amount on invoice ID '.$id.' ('.$amount.') is higher than remain to pay ('.$remainstopay.')'); } if ($this->invoice->type == Facture::TYPE_CREDIT_NOTE) { - $amount = price2num(-1 * (float) $amount, 'MT'); + $amount = price2num(-1 * abs((float) $amount), 'MT'); } if ($is_multicurrency) { diff --git a/htdocs/product/ajax/products.php b/htdocs/product/ajax/products.php index a0337a75a49..4823ddddf4d 100644 --- a/htdocs/product/ajax/products.php +++ b/htdocs/product/ajax/products.php @@ -183,7 +183,7 @@ if ($action == 'fetch' && !empty($id)) { $sql .= " WHERE fk_product = ".((int) $id); $sql .= " AND entity IN (".getEntity('productprice').")"; $sql .= " AND price_level = ".((int) $price_level); - $sql .= " ORDER BY date_price"; + $sql .= " ORDER BY date_price DESC, rowid"; $sql .= " DESC LIMIT 1"; $result = $db->query($sql); diff --git a/htdocs/projet/tasks/time.php b/htdocs/projet/tasks/time.php index 23dd03b9a96..92822e76c21 100644 --- a/htdocs/projet/tasks/time.php +++ b/htdocs/projet/tasks/time.php @@ -282,6 +282,9 @@ if (($action == 'updateline' || $action == 'updatesplitline') && !$cancel && $us $error++; } + //If timespent date is not provided in POST (for eg, because in list the column date is hidden) we keep the actual date + $timespent_date = dol_mktime(12, 0, 0, GETPOSTINT("timelinemonth"), GETPOSTINT("timelineday"), GETPOSTINT("timelineyear")); + if (!$error) { if (GETPOSTINT('taskid') != $id) { // GETPOST('taskid') is id of new task $id_temp = GETPOSTINT('taskid'); // should not overwrite $id @@ -297,11 +300,11 @@ if (($action == 'updateline' || $action == 'updatesplitline') && !$cancel && $us $object->timespent_old_duration = GETPOSTINT("old_duration"); $object->timespent_duration = GETPOSTINT("new_durationhour") * 60 * 60; // We store duration in seconds $object->timespent_duration += (GETPOSTINT("new_durationmin") ? GETPOSTINT('new_durationmin') : 0) * 60; // We store duration in seconds - if (GETPOST("timelinehour") != '' && GETPOST("timelinehour") >= 0) { // If hour was entered + if (GETPOST("timelinehour") != '' && GETPOST("timelinehour") >= 0 && !empty($timespent_date)) { // If hour was entered $object->timespent_date = dol_mktime(GETPOSTINT("timelinehour"), GETPOSTINT("timelinemin"), 0, GETPOSTINT("timelinemonth"), GETPOSTINT("timelineday"), GETPOSTINT("timelineyear")); $object->timespent_withhour = 1; - } else { - $object->timespent_date = dol_mktime(12, 0, 0, GETPOSTINT("timelinemonth"), GETPOSTINT("timelineday"), GETPOSTINT("timelineyear")); + } elseif (!empty($timespent_date)) { + $object->timespent_date = $timespent_date; $object->timespent_withhour = 0; } $object->timespent_fk_user = GETPOSTINT("userid_line"); @@ -322,7 +325,8 @@ if (($action == 'updateline' || $action == 'updatesplitline') && !$cancel && $us } else { $object->fetch($id, $ref); - $object->timespent_id = GETPOSTINT("lineid"); + $object->fetchTimeSpent(GETPOSTINT('lineid')); + $object->timespent_note = GETPOST("timespent_note_line", "alphanohtml"); $object->timespent_old_duration = GETPOSTINT("old_duration"); $object->timespent_duration = GETPOSTINT("new_durationhour") * 60 * 60; // We store duration in seconds @@ -330,8 +334,8 @@ if (($action == 'updateline' || $action == 'updatesplitline') && !$cancel && $us if (GETPOST("timelinehour") != '' && GETPOST("timelinehour") >= 0) { // If hour was entered $object->timespent_date = dol_mktime(GETPOSTINT("timelinehour"), GETPOSTINT("timelinemin"), 0, GETPOSTINT("timelinemonth"), GETPOSTINT("timelineday"), GETPOSTINT("timelineyear")); $object->timespent_withhour = 1; - } else { - $object->timespent_date = dol_mktime(12, 0, 0, GETPOSTINT("timelinemonth"), GETPOSTINT("timelineday"), GETPOSTINT("timelineyear")); + } elseif (!empty($timespent_date)) { + $object->timespent_date = $timespent_date; $object->timespent_withhour = 0; } $object->timespent_fk_user = GETPOSTINT("userid_line");