Merge branch '20.0' of https://github.com/Dolibarr/dolibarr into fix_v20_pdf_space_lost_with_images
This commit is contained in:
commit
377d211535
10 changed files with 141 additions and 33 deletions
11
.github/workflows/windows-ci.yml
vendored
11
.github/workflows/windows-ci.yml
vendored
|
|
@ -36,11 +36,6 @@ jobs:
|
|||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
- name: Setup MariaDB
|
||||
uses: frederic34/setup-mariadb@v1
|
||||
with:
|
||||
# mariadb-version: ${{ matrix.mariadb-version }}
|
||||
database: travis # Specify your database name
|
||||
- name: Setup PHP
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
|
|
@ -79,6 +74,12 @@ jobs:
|
|||
${{ env.KEY_ROOT }}-${{ env.HASH }}-
|
||||
${{ env.KEY_ROOT }}-
|
||||
|
||||
- name: Setup MariaDB
|
||||
uses: frederic34/setup-mariadb@v1
|
||||
with:
|
||||
# mariadb-version: ${{ matrix.mariadb-version }}
|
||||
database: travis # Specify your database name
|
||||
|
||||
- name: Create local php.ini with open_basedir restrictions
|
||||
shell: cmd
|
||||
# Objective: separate step, and before database initialisation to verify open_basedir restrictions
|
||||
|
|
|
|||
50
ChangeLog
50
ChangeLog
|
|
@ -2,6 +2,56 @@
|
|||
English Dolibarr ChangeLog
|
||||
--------------------------------------------------------------
|
||||
|
||||
***** ChangeLog for 20.0.1 compared to 20.0.0 *****
|
||||
|
||||
FIX: #30960 show and search extrafields (#31026)
|
||||
FIX: #31076 Bad position of hooks
|
||||
FIX: #31152
|
||||
FIX: #31237 (#31239)
|
||||
FIX: #31241 (#31245)
|
||||
FIX: accounting transfer when nb of lines is not zero but amount is zero
|
||||
FIX: Add same security test when nuploading files from API than from GUI (#31114)
|
||||
FIX: allow "class" into search string in website module
|
||||
FIX: autoselect the fiscal period by default
|
||||
FIX: avoid odt errors (#31126)
|
||||
FIX: Backport fix fatal error on price with some truncating setup
|
||||
FIX: better compatibility with some old extrafield syntax filter
|
||||
FIX: box_actions.php still uses fk_user_done which no longer exists (#31190)
|
||||
FIX: Browser Notification ko with firefox
|
||||
FIX: custom CSS for WebPortal (#31022)
|
||||
FIX: Debug calculation of the delay of purchase order
|
||||
FIX: Debug option WORKFLOW_TICKET_LINK_CONTRACT. Bad id stored. Bad
|
||||
FIX: dolFICalculatePaymentReference for Finland in functions_fi.lib.php (#31281)
|
||||
FIX: Duplicate trigger printFieldPreListTitle
|
||||
FIX: edit contract of intervention broken by CSRF protection
|
||||
FIX: error return missing in mo creation when qty to consume is <= 0 (#31134)
|
||||
FIX: Extrafields does not appear on form
|
||||
FIX: FATAL ERROR abusively triggered due to incomplete regex (#31052)
|
||||
FIX: if you call fetchLines several times, your $object->lines contains duplicates (#31167)
|
||||
FIX: late order search option (v18+) (#30692)
|
||||
FIX: late propal search option (v18+) (#30687)
|
||||
FIX: Maxi debug edit/delete accounting transaction
|
||||
FIX: member must be found to search the linked partnership (WebPortal) (#30977)
|
||||
FIX: Missing picto on user link
|
||||
FIX: mysql error during dump for enable sandbox M999999 (#31116)
|
||||
FIX: OAuth generation of token for Microsoft, Stripe and Generic
|
||||
FIX: param id in website account list from third-party card (#30975)
|
||||
FIX: Position of box for shipping address in PDF
|
||||
FIX: Protection to avoid an extrafield to be mandatory if computed
|
||||
FIX: removed unreachable code (#31141)
|
||||
FIX: Remove wrong button
|
||||
FIX: retrieving user specific constant
|
||||
FIX: Revert storing of ticket files into event dir, too many troubles.
|
||||
FIX: Selection of country - state in resource
|
||||
FIX: State dropdown is not working on User card #31198 (#31205)
|
||||
FIX: Tool to convert into utf8 or utf8mb4
|
||||
FIX: use price() to display qty on a product's stats tab to avoid showing too many decimals when rounding errors are possible (#31165)
|
||||
FIX: Warning visible when it should not
|
||||
FIX: webhook must send POST in body. Add WEBHOOK_POST_SEND_DATA_IN_BODY
|
||||
FIX: when qty is not an integer, apply price() (#31138)
|
||||
FIX: Wrong price for BOM with workstation (#31142)
|
||||
FIX: determine multi-currency price on object line create tpl (#28021)
|
||||
|
||||
|
||||
***** ChangeLog for 20.0.0 compared to 19.0 *****
|
||||
|
||||
|
|
|
|||
|
|
@ -278,8 +278,8 @@ class Categories extends DolibarrApi
|
|||
throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
|
||||
}
|
||||
|
||||
if (!$this->category->delete(DolibarrApiAccess::$user)) {
|
||||
throw new RestException(500, 'error when delete category');
|
||||
if ($this->category->delete(DolibarrApiAccess::$user) <= 0) {
|
||||
throw new RestException(500, 'Error when delete category : ' . $this->category->error);
|
||||
}
|
||||
|
||||
return array(
|
||||
|
|
|
|||
|
|
@ -2492,9 +2492,11 @@ if ($id > 0) {
|
|||
}
|
||||
|
||||
// Priority
|
||||
print '<tr><td class="nowrap" class="titlefield">'.$langs->trans("Priority").'</td><td>';
|
||||
print($object->priority ? $object->priority : '');
|
||||
print '</td></tr>';
|
||||
if (getDolGlobalString('AGENDA_SUPPORT_PRIORITY_IN_EVENTS')) {
|
||||
print '<tr><td class="nowrap" class="titlefield">' . $langs->trans("Priority") . '</td><td>';
|
||||
print($object->priority ? $object->priority : '');
|
||||
print '</td></tr>';
|
||||
}
|
||||
|
||||
// Object linked (if link is for thirdparty, contact, project it is a recording error. We should not have links in link table
|
||||
// for such objects because there is already a dedicated field into table llx_actioncomm.
|
||||
|
|
|
|||
|
|
@ -3514,7 +3514,7 @@ class Form
|
|||
|
||||
if (isModEnabled('stock') && isset($objp->stock) && ($objp->fk_product_type == Product::TYPE_PRODUCT || getDolGlobalString('STOCK_SUPPORTS_SERVICES'))) {
|
||||
if ($user->hasRight('stock', 'lire')) {
|
||||
$opt .= ' - ' . $langs->trans("Stock") . ': ' . price(price2num($objp->stock, 'MS'));
|
||||
$opt .= ' - ' . $langs->trans("Stock") . ': ' . price(price2num($objp->stock, 'MS'), 0, $langs, 0, 0);
|
||||
|
||||
if ($objp->stock > 0) {
|
||||
$outval .= ' - <span class="product_line_stock_ok">';
|
||||
|
|
|
|||
|
|
@ -603,8 +603,12 @@ function getBrowserInfo($user_agent)
|
|||
$version = end($reg);
|
||||
} elseif (preg_match('/l[iy]n(x|ks)(\(|\/|\s)*([\d\.]+)/i', $user_agent, $reg)) {
|
||||
// MS products at end
|
||||
$name = 'lynxlinks';
|
||||
$name = 'textbrowser';
|
||||
$version = empty($reg[3]) ? '' : $reg[3];
|
||||
} elseif (preg_match('/w3m\/([\d\.]+)/i', $user_agent, $reg)) {
|
||||
// MS products at end
|
||||
$name = 'textbrowser';
|
||||
$version = empty($reg[1]) ? '' : $reg[1];
|
||||
}
|
||||
|
||||
if ($tablet) {
|
||||
|
|
@ -6612,10 +6616,11 @@ function price($amount, $form = 0, $outlangs = '', $trunc = 1, $rounding = -1, $
|
|||
if (dol_strlen($decpart) > $nbdecimal) {
|
||||
$nbdecimal = dol_strlen($decpart);
|
||||
}
|
||||
// Si on depasse max
|
||||
$max_nbdecimal = (int) str_replace('...', '', getDolGlobalString('MAIN_MAX_DECIMALS_SHOWN'));
|
||||
if ($trunc && $nbdecimal > $max_nbdecimal) {
|
||||
$nbdecimal = $max_nbdecimal;
|
||||
|
||||
// If nbdecimal is higher than max to show
|
||||
$nbdecimalmaxshown = (int) str_replace('...', '', getDolGlobalString('MAIN_MAX_DECIMALS_SHOWN'));
|
||||
if ($trunc && $nbdecimal > $nbdecimalmaxshown) {
|
||||
$nbdecimal = $nbdecimalmaxshown;
|
||||
if (preg_match('/\.\.\./i', getDolGlobalString('MAIN_MAX_DECIMALS_SHOWN'))) {
|
||||
// If output is truncated, we show ...
|
||||
$end = '...';
|
||||
|
|
@ -12263,6 +12268,7 @@ function dolGetStatus($statusLabel = '', $statusLabelShort = '', $html = '', $st
|
|||
* $arrayforbutaction = array(
|
||||
* 10 => array('attr' => array('class'=>''), 'lang'=>'propal', 'enabled'=>isModEnabled("propal"), 'perm'=>$user->hasRight('propal', 'creer'), 'label' => 'AddProp', 'url'=>'/comm/propal/card.php?action=create&projectid='.$object->id.'&socid='.$object->socid),
|
||||
* 20 => array('attr' => array('class'=>''), 'lang'=>'mymodule', 'enabled'=>isModEnabled("mymodule"), 'perm'=>$user->hasRight('mymodule', 'write'), 'label' => 'MyModuleAction', 'urlroot'=>dol_build_patch('/mymodule/mypage.php?action=create')),
|
||||
* 30 => array('attr' => array('class'=>''), 'lang'=>'mymodule', 'enabled'=>isModEnabled("mymodule"), 'perm'=>$user->hasRight('mymodule', 'write'), 'label' => 'MyModuleOtherAction', 'urlraw' => '# || external Url || javascript: || tel: || mailto:' ),
|
||||
* ); );
|
||||
* @param string $id Attribute id of action button. Example 'action-delete'. This can be used for full ajax confirm if this code is reused into the ->formconfirm() method.
|
||||
* @param int|boolean $userRight User action right
|
||||
|
|
@ -12328,17 +12334,18 @@ function dolGetButtonAction($label, $text = '', $actionType = 'default', $url =
|
|||
$langs->load($subbutton['lang']);
|
||||
}
|
||||
|
||||
if (!empty($subbutton['urlroot'])) {
|
||||
$tmpurl = $subbutton['urlroot'].(empty($params['backtopage']) ? '' : '&backtopage='.urlencode($params['backtopage']));
|
||||
if (!empty($subbutton['urlraw'])) {
|
||||
$tmpurl = $subbutton['urlraw']; // Use raw url, no url completion, use only what developer send
|
||||
} else {
|
||||
$tmpurl = DOL_URL_ROOT.$subbutton['url'].(empty($params['backtopage']) ? '' : '&backtopage='.urlencode($params['backtopage']));
|
||||
$tmpurl = !empty($subbutton['urlroot']) ? $subbutton['urlroot'] : $subbutton['url'];
|
||||
$tmpurl = dolCompletUrlForDropdownButton($tmpurl, $params, empty($subbutton['urlroot']));
|
||||
}
|
||||
|
||||
$subbuttonparam = array();
|
||||
if (!empty($subbutton['attr'])) {
|
||||
$subbuttonparam['attr'] = $subbutton['attr'];
|
||||
}
|
||||
$subbuttonparam['isDropDown'] = (empty($params['isDropDown']) ? $subbutton['isDropDown'] : $params['isDropDown']);
|
||||
$subbuttonparam['isDropDown'] = (empty($params['isDropDown']) ? ($subbutton['isDropDown']??false) : $params['isDropDown']);
|
||||
|
||||
$out .= dolGetButtonAction('', $langs->trans($subbutton['label']), 'default', $tmpurl, $subbutton['id'] ?? '', $subbutton['perm'], $subbuttonparam);
|
||||
}
|
||||
|
|
@ -12350,10 +12357,11 @@ function dolGetButtonAction($label, $text = '', $actionType = 'default', $url =
|
|||
$langs->load($subbutton['lang']);
|
||||
}
|
||||
|
||||
if (!empty($subbutton['urlroot'])) {
|
||||
$tmpurl = $subbutton['urlroot'].(empty($params['backtopage']) ? '' : '&backtopage='.urlencode($params['backtopage']));
|
||||
if (!empty($subbutton['urlraw'])) {
|
||||
$tmpurl = $subbutton['urlraw']; // Use raw url, no url completion, use only what developer send
|
||||
} else {
|
||||
$tmpurl = DOL_URL_ROOT.$subbutton['url'].(empty($params['backtopage']) ? '' : '&backtopage='.urlencode($params['backtopage']));
|
||||
$tmpurl = !empty($subbutton['urlroot']) ? $subbutton['urlroot'] : $subbutton['url'];
|
||||
$tmpurl = dolCompletUrlForDropdownButton($tmpurl, $params, empty($subbutton['urlroot']));
|
||||
}
|
||||
|
||||
$out .= dolGetButtonAction('', $langs->trans($subbutton['label']), 'default', $tmpurl, '', $subbutton['perm'], $params);
|
||||
|
|
@ -12488,6 +12496,42 @@ function dolGetButtonAction($label, $text = '', $actionType = 'default', $url =
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* An function to complete dropdown url in dolGetButtonAction
|
||||
*
|
||||
* @param string $url the Url to complete
|
||||
* @param array|array<string> $params params of dolGetButtonAction function
|
||||
* @param bool $addDolUrlRoot to add root url
|
||||
* @return string
|
||||
*/
|
||||
function dolCompletUrlForDropdownButton(string $url, array $params, bool $addDolUrlRoot = true)
|
||||
{
|
||||
if (empty($url)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$parsedUrl = parse_url($url);
|
||||
if ((isset($parsedUrl['scheme']) && in_array($parsedUrl['scheme'], ['javascript', 'mailto', 'tel'])) || strpos($url, '#') === 0) {
|
||||
return $url;
|
||||
}
|
||||
|
||||
if (!empty($parsedUrl['query'])) {
|
||||
// Use parse_str() function to parse the string passed via URL
|
||||
parse_str($parsedUrl['query'], $urlQuery);
|
||||
if (!isset($urlQuery['backtopage']) && isset($params['backtopage'])) {
|
||||
$url.= '&backtopage='.urlencode($params['backtopage']);
|
||||
}
|
||||
}
|
||||
|
||||
if (!isset($parsedUrl['scheme']) && $addDolUrlRoot) {
|
||||
$url = DOL_URL_ROOT.$url;
|
||||
}
|
||||
|
||||
return $url;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add space between dolGetButtonTitle
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
<?php
|
||||
/* Copyright (C) 2010 Laurent Destailleur <eldy@users.sourceforge.net>
|
||||
* Copyright (C) 2024 Mikko Virtanen
|
||||
*
|
||||
* 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
|
||||
|
|
@ -37,16 +38,16 @@ function dolFICalculatePaymentReference($invoice_number, $statut, $use_rf)
|
|||
{
|
||||
if ($statut >= 1) {
|
||||
$invoice_number = preg_replace('/[^0-9]/', '', $invoice_number); // Keep only numbers
|
||||
$invoice_number = ltrim($invoice_number, '0'); //Remove any leading zero or zeros
|
||||
$invoice_number = strrev($invoice_number); // Reverse the reference number
|
||||
$coefficients = array(7, 3, 1, 7, 3); // Define the coefficient numbers
|
||||
$invoice_number = ltrim($invoice_number, '0'); // Remove leading zeros
|
||||
$coefficients = array(7, 3, 1); // Define the coefficient numbers (rotating 7, 3, 1)
|
||||
$sum = 0;
|
||||
$stlen_invoice_number = (int) strlen($invoice_number);
|
||||
for ($i = 0; $i < $stlen_invoice_number; $i++) { // Calculate the sum using coefficients
|
||||
$sum += (int) $invoice_number[$i] * $coefficients[$i % 5];
|
||||
// Calculate the weighted sum from right to left
|
||||
for ($i = 0; $i < $stlen_invoice_number; $i++) {
|
||||
$sum += (int) $invoice_number[$stlen_invoice_number - $i - 1] * $coefficients[$i % 3];
|
||||
}
|
||||
$check_digit = (10 - ($sum % 10)) % 10; // Calculate the check digit
|
||||
$bank_reference_fi = strrev($invoice_number) . $check_digit; // Concatenate the Reversed reference number and the check digit
|
||||
$bank_reference_fi = $invoice_number . $check_digit; // Concatenate the reference number and the check digit
|
||||
if ($use_rf) { // SEPA RF creditor reference
|
||||
$reference_with_suffix = $bank_reference_fi . "271500"; // Append "271500" to the end of the payment reference number
|
||||
$remainder = (int) bcmod($reference_with_suffix, '97'); // Calculate the remainder when dividing by 97
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ if (!defined('DOL_APPLICATION_TITLE')) {
|
|||
define('DOL_APPLICATION_TITLE', 'Dolibarr');
|
||||
}
|
||||
if (!defined('DOL_VERSION')) {
|
||||
define('DOL_VERSION', '20.0.0'); // a.b.c-alpha, a.b.c-beta, a.b.c-rcX or a.b.c
|
||||
define('DOL_VERSION', '20.0.1'); // a.b.c-alpha, a.b.c-beta, a.b.c-rcX or a.b.c
|
||||
}
|
||||
|
||||
if (!defined('EURO')) {
|
||||
|
|
|
|||
|
|
@ -510,7 +510,7 @@ if (GETPOST('theme', 'aZ09')) {
|
|||
}
|
||||
|
||||
// Set global MAIN_OPTIMIZEFORTEXTBROWSER (must be before login part)
|
||||
if (GETPOSTINT('textbrowser') || (!empty($conf->browser->name) && $conf->browser->name == 'lynxlinks')) { // If we must enable text browser
|
||||
if (GETPOSTINT('textbrowser') || (!empty($conf->browser->name) && $conf->browser->name == 'textbrowser')) { // If we must enable text browser
|
||||
$conf->global->MAIN_OPTIMIZEFORTEXTBROWSER = 2;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -369,7 +369,7 @@ class Contacts extends DolibarrApi
|
|||
* Delete contact
|
||||
*
|
||||
* @param int $id Contact ID
|
||||
* @return integer
|
||||
* @return array[]
|
||||
*/
|
||||
public function delete($id)
|
||||
{
|
||||
|
|
@ -385,7 +385,17 @@ class Contacts extends DolibarrApi
|
|||
throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
|
||||
}
|
||||
$this->contact->oldcopy = clone $this->contact;
|
||||
return $this->contact->delete(DolibarrApiAccess::$user);
|
||||
|
||||
if ($this->contact->delete(DolibarrApiAccess::$user) <= 0) {
|
||||
throw new RestException(500, 'Error when delete contact ' . $this->contact->error);
|
||||
}
|
||||
|
||||
return array(
|
||||
'success' => array(
|
||||
'code' => 200,
|
||||
'message' => 'Contact deleted'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Reference in a new issue