Merge branch '14.0' into 14p24

This commit is contained in:
Alexandre SPANGARO 2021-10-20 07:38:54 +02:00
commit bee6abd6fc
13 changed files with 98 additions and 43 deletions

View File

@ -358,6 +358,37 @@ Following changes may create regressions for some external modules, but were nec
* v14 seems to work correctly on PHP v8 but it generates a lot of verbose warnings. Currently, v14 i snot yet officialy supported with PHP 8.
***** ChangeLog for 13.0.5 compared to 13.0.4 *****
FIX: 13.0: class CommandeFournisseurDispatch provides trigger for UPDATE but not for CREATE / DELETE
FIX: #18389 Accountancy - Bug on LDcompta10 export for supplier invoice
FIX: #18591 : Remove double quotes of SQL Queries for postgresql compatibility
FIX: Accountancy - Debug Export Sage50 / CIEL Compta / CIEL Compta Evo (Format XIMPORT)
FIX: Accountancy - Some problems of length with general & subledger account
FIX: add DISTINCT
FIX: an approved holiday can be canceled by an admin.
FIX: autocalculation of the supplier price in main currency.
FIX: better sql request
FIX: cannot add time spend when column ref is not displayed
FIX: compatibility postgre sql
FIX: holiday card: hooks uninitialized
FIX: Invoice - Missing button to reopen an abandoned situation invoice
FIX: invoice validation: when checking if any VAT rate has a negative amount, prevent false positives with -1.0E-14 amounts
FIX: list of categories in stats of supplier invoices
FIX: Manage credit note on situation invoice for calculate margin
FIX: method_exists needs object at first param
FIX: move fetch_optionnal into $ac_static->fetch()
FIX: multicompany transverse mode compatibility
FIX: on supplier order, JOIN with product fourn price table must be done with fk_soc too to avoid display several times a same line (because of same supplier product ref)
FIX: postgre filter select search extrafield
FIX: products/services card: hidden extrafields were overridden
FIX: shipping validation workflow: 'ORDER_NEW' trigger called from wrong object
FIX: task time: can't filter by user with pgsql + show error message
FIX: task time: keep on using natural_search
FIX: wrong users count in multicompany transverse mode
***** ChangeLog for 13.0.4 compared to 13.0.3 *****
FIX: Allow disabling of a module (not a dangerous action) even if there is problem with token (due to bugged modules).

View File

@ -1,6 +1,6 @@
<?php
/* Copyright (C) 2004-2017 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2011-2017 Alexandre Spangaro <aspangaro@open-dsi.fr>
* Copyright (C) 2011-2021 Alexandre Spangaro <aspangaro@open-dsi.fr>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -91,19 +91,19 @@ $tabsql[32] = "SELECT a.rowid as rowid, a.code as code, a.label, a.range_account
$tabsqlsort = array();
$tabsqlsort[32] = "position ASC";
// Nom des champs en resultat de select pour affichage du dictionnaire
// Name of the fields in the result of select to display the dictionary
$tabfield = array();
$tabfield[32] = "code,label,range_account,category_type,formula,position,country";
// Nom des champs d'edition pour modification d'un enregistrement
// Name of editing fields for record modification
$tabfieldvalue = array();
$tabfieldvalue[32] = "code,label,range_account,category_type,formula,position,country_id";
// Nom des champs dans la table pour insertion d'un enregistrement
// Name of the fields in the table for inserting a record
$tabfieldinsert = array();
$tabfieldinsert[32] = "code,label,range_account,category_type,formula,position,fk_country";
// Nom du rowid si le champ n'est pas de type autoincrement
// Name of the rowid if the field is not of type autoincrement
// Example: "" if id field is "rowid" and has autoincrement on
// "nameoffield" if id field is not "rowid" or has not autoincrement on
$tabrowid = array();
@ -151,7 +151,7 @@ if (GETPOST('actionadd', 'alpha') || GETPOST('actionmodify', 'alpha')) {
if ($value == 'range_account' && empty($_POST['range_account'])) {
continue;
}
if ($value == 'country' || $value == 'country_id') {
if (($value == 'country' || $value == 'country_id') && (!empty($_POST['country_id']))) {
continue;
}
if (!GETPOSTISSET($value) || GETPOST($value) == '') {
@ -176,6 +176,9 @@ if (GETPOST('actionadd', 'alpha') || GETPOST('actionmodify', 'alpha')) {
if ($fieldnamekey == 'category_type') {
$fieldnamekey = 'Calculated';
}
if ($fieldnamekey == 'country') {
$fieldnamekey = 'Country';
}
setEventMessages($langs->transnoentities("ErrorFieldRequired", $langs->transnoentities($fieldnamekey)), null, 'errors');
}
@ -263,7 +266,7 @@ if (GETPOST('actionadd', 'alpha') || GETPOST('actionmodify', 'alpha')) {
}
}
// Si verif ok et action modify, on modifie la ligne
// If check ok and action modify, we modify the line
if ($ok && GETPOST('actionmodify', 'alpha')) {
if ($tabrowid[$id]) {
$rowidcol = $tabrowid[$id];
@ -430,12 +433,12 @@ print load_fiche_titre($titre, $linkback, $titlepicto);
print '<span class="opacitymedium">'.$langs->trans("AccountingAccountGroupsDesc", $langs->transnoentitiesnoconv("ByPersonalizedAccountGroups")).'</span><br><br>';
// Confirmation de la suppression de la ligne
// Confirmation of the deletion of the line
if ($action == 'delete') {
print $form->formconfirm($_SERVER["PHP_SELF"].'?'.($page ? 'page='.$page.'&' : '').'sortfield='.$sortfield.'&sortorder='.$sortorder.'&rowid='.$rowid.'&code='.$code.'&id='.$id.($search_country_id > 0 ? '&search_country_id='.$search_country_id : ''), $langs->trans('DeleteLine'), $langs->trans('ConfirmDeleteLine'), 'confirm_delete', '', 0, 1);
}
// Complete requete recherche valeurs avec critere de tri
// Complete search query with sorting criteria
$sql = $tabsql[$id];
if ($search_country_id > 0) {
@ -634,14 +637,14 @@ if ($resql) {
// Title of lines
print '<tr class="liste_titre">';
foreach ($fieldlist as $field => $value) {
// Determine le nom du champ par rapport aux noms possibles
// dans les dictionnaires de donnees
$showfield = 1; // By defaut
// Determines the name of the field in relation to the possible names
// in data dictionaries
$showfield = 1; // By default
$class = "left";
$sortable = 1;
$valuetoshow = '';
$valuetoshow = ucfirst($fieldlist[$field]); // By defaut
$valuetoshow = ucfirst($fieldlist[$field]); // By default
$valuetoshow = $langs->trans($valuetoshow); // try to translate
if ($fieldlist[$field] == 'source') {
$valuetoshow = $langs->trans("Contact");

View File

@ -913,7 +913,7 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) {
$object->state_id = GETPOST('state_id', 'int');
// We set country_id, country_code and country for the selected country
$object->country_id = GETPOST('country_id', 'int') ?GETPOST('country_id', 'int') : $mysoc->country_id;
$object->country_id = GETPOST('country_id', 'int') ? GETPOST('country_id', 'int') : $mysoc->country_id;
if ($object->country_id) {
$tmparray = getCountry($object->country_id, 'all');
$object->country_code = $tmparray['code'];
@ -921,12 +921,12 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) {
}
if (!empty($socid)) {
$object = new Societe($db);
$soc = new Societe($db);
if ($socid > 0) {
$object->fetch($socid);
$soc->fetch($socid);
}
if (!($object->id > 0)) {
if (!($soc->id > 0)) {
$langs->load("errors");
print($langs->trans('ErrorRecordNotFound'));
exit;
@ -1009,7 +1009,7 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) {
print "</td>\n";
// Company
print '<tr><td id="tdcompany">'.$langs->trans("Company").'</td><td><input type="text" name="societe" class="minwidth300" maxlength="128" value="'.(GETPOSTISSET('societe') ? GETPOST('societe', 'alphanohtml') : $object->company).'"></td></tr>';
print '<tr><td id="tdcompany">'.$langs->trans("Company").'</td><td><input type="text" name="societe" class="minwidth300" maxlength="128" value="'.(GETPOSTISSET('societe') ? GETPOST('societe', 'alphanohtml') : $soc->name).'"></td></tr>';
// Civility
print '<tr><td>'.$langs->trans("UserTitle").'</td><td>';
@ -1033,7 +1033,7 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) {
// EMail
print '<tr><td>'.($conf->global->ADHERENT_MAIL_REQUIRED ? '<span class="fieldrequired">' : '').$langs->trans("EMail").($conf->global->ADHERENT_MAIL_REQUIRED ? '</span>' : '').'</td>';
print '<td>'.img_picto('', 'object_email').' <input type="text" name="member_email" class="minwidth300" maxlength="255" value="'.(GETPOSTISSET('member_email') ? GETPOST('member_email', 'alpha') : $object->email).'"></td></tr>';
print '<td>'.img_picto('', 'object_email').' <input type="text" name="member_email" class="minwidth300" maxlength="255" value="'.(GETPOSTISSET('member_email') ? GETPOST('member_email', 'alpha') : $soc->email).'"></td></tr>';
// Website
print '<tr><td>'.$form->editfieldkey('Web', 'member_url', '', $object, 0).'</td>';
@ -1041,21 +1041,25 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) {
// Address
print '<tr><td class="tdtop">'.$langs->trans("Address").'</td><td>';
print '<textarea name="address" wrap="soft" class="quatrevingtpercent" rows="2">'.(GETPOSTISSET('address') ?GETPOST('address', 'alphanohtml') : $object->address).'</textarea>';
print '<textarea name="address" wrap="soft" class="quatrevingtpercent" rows="2">'.(GETPOSTISSET('address') ?GETPOST('address', 'alphanohtml') : $soc->address).'</textarea>';
print '</td></tr>';
// Zip / Town
print '<tr><td>'.$langs->trans("Zip").' / '.$langs->trans("Town").'</td><td>';
print $formcompany->select_ziptown((GETPOSTISSET('zipcode') ? GETPOST('zipcode', 'alphanohtml') : $object->zip), 'zipcode', array('town', 'selectcountry_id', 'state_id'), 6);
print $formcompany->select_ziptown((GETPOSTISSET('zipcode') ? GETPOST('zipcode', 'alphanohtml') : $soc->zip), 'zipcode', array('town', 'selectcountry_id', 'state_id'), 6);
print ' ';
print $formcompany->select_ziptown((GETPOSTISSET('town') ? GETPOST('town', 'alphanohtml') : $object->town), 'town', array('zipcode', 'selectcountry_id', 'state_id'));
print $formcompany->select_ziptown((GETPOSTISSET('town') ? GETPOST('town', 'alphanohtml') : $soc->town), 'town', array('zipcode', 'selectcountry_id', 'state_id'));
print '</td></tr>';
// Country
$object->country_id = $object->country_id ? $object->country_id : $mysoc->country_id;
print '<tr><td width="25%">'.$langs->trans('Country').'</td><td>';
if (empty($soc->country_id)) {
$soc->country_id = $mysoc->country_id;
$soc->country_code = $mysoc->country_code;
$soc->state_id = $mysoc->state_id;
}
print '<tr><td>'.$langs->trans('Country').'</td><td>';
print img_picto('', 'country', 'class="pictofixedwidth"');
print $form->select_country(GETPOSTISSET('country_id') ? GETPOST('country_id', 'alpha') : $object->country_id, 'country_id');
print $form->select_country(GETPOSTISSET('country_id') ? GETPOST('country_id', 'alpha') : $soc->country_id, 'country_id');
if ($user->admin) {
print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
}
@ -1064,9 +1068,9 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) {
// State
if (empty($conf->global->MEMBER_DISABLE_STATE)) {
print '<tr><td>'.$langs->trans('State').'</td><td>';
if ($object->country_id) {
if ($soc->country_id) {
print img_picto('', 'state', 'class="pictofixedwidth"');
print $formcompany->select_state(GETPOSTISSET('state_id') ? GETPOST('state_id', 'int') : $object->state_id, $object->country_code);
print $formcompany->select_state(GETPOSTISSET('state_id') ? GETPOST('state_id', 'int') : $soc->state_id, $soc->country_code);
} else {
print $countrynotdefined;
}
@ -1075,7 +1079,7 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) {
// Pro phone
print '<tr><td>'.$langs->trans("PhonePro").'</td>';
print '<td>'.img_picto('', 'object_phoning').' <input type="text" name="phone" size="20" value="'.(GETPOSTISSET('phone') ? GETPOST('phone', 'alpha') : $object->phone).'"></td></tr>';
print '<td>'.img_picto('', 'object_phoning').' <input type="text" name="phone" size="20" value="'.(GETPOSTISSET('phone') ? GETPOST('phone', 'alpha') : $soc->phone).'"></td></tr>';
// Personal phone
print '<tr><td>'.$langs->trans("PhonePerso").'</td>';

View File

@ -961,7 +961,7 @@ while ($i < min($num, $limit)) {
// Firstname
if (!empty($arrayfields['d.firstname']['checked'])) {
print '<td class="tdoverflowmax150" title="'.dol_escape_htmltag($obj->firstname).'">';
print $memberstatic->getNomUrl(0, 0, 'card', 'fistname');
print $memberstatic->getNomUrl(0, 0, 'card', 'firstname');
//print $obj->firstname;
print "</td>\n";
if (!$i) {

View File

@ -2563,8 +2563,13 @@ class Propal extends CommonObject
$outputlangs->setDefaultLang($newlang);
}
// PDF
$hidedetails = (!empty($conf->global->MAIN_GENERATE_DOCUMENTS_HIDE_DETAILS) ? 1 : 0);
$hidedesc = (!empty($conf->global->MAIN_GENERATE_DOCUMENTS_HIDE_DESC) ? 1 : 0);
$hideref = (!empty($conf->global->MAIN_GENERATE_DOCUMENTS_HIDE_REF) ? 1 : 0);
//$ret=$object->fetch($id); // Reload to get new records
$this->generateDocument($modelpdf, $outputlangs);
$this->generateDocument($modelpdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
}
if (!$error) {
@ -2651,8 +2656,13 @@ class Propal extends CommonObject
$outputlangs->setDefaultLang($newlang);
}
// PDF
$hidedetails = (!empty($conf->global->MAIN_GENERATE_DOCUMENTS_HIDE_DETAILS) ? 1 : 0);
$hidedesc = (!empty($conf->global->MAIN_GENERATE_DOCUMENTS_HIDE_DESC) ? 1 : 0);
$hideref = (!empty($conf->global->MAIN_GENERATE_DOCUMENTS_HIDE_REF) ? 1 : 0);
//$ret=$object->fetch($id); // Reload to get new records
$this->generateDocument($modelpdf, $outputlangs);
$this->generateDocument($modelpdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
}
$this->oldcopy = clone $this;

View File

@ -309,7 +309,7 @@ class FormActions
$tmpa = dol_getdate($actioncomm->datep);
$tmpb = dol_getdate($actioncomm->datef);
if ($tmpa['mday'] == $tmpb['mday'] && $tmpa['mon'] == $tmpb['mon'] && $tmpa['year'] == $tmpb['year']) {
if ($tmpa['hours'] != $tmpb['hours'] || $tmpa['minutes'] != $tmpb['minutes'] && $tmpa['seconds'] != $tmpb['seconds']) {
if ($tmpa['hours'] != $tmpb['hours'] || $tmpa['minutes'] != $tmpb['minutes']) {
print '-'.dol_print_date($actioncomm->datef, 'hour', 'tzuserrel');
}
} else {

View File

@ -133,7 +133,7 @@ class ActionsDatapolicy
header('Content-Disposition: attachment; filename=datapolicy_portabilite.csv');
header('Pragma: no-cache');
$object->fetch(GETPOST('socid'));
echo 'Name;Fistname;Civility;Thirdparty;Function;Address;ZipCode;City;Department;Country;Email;Pro Phone;Perso Phone;Mobile Phone;Instant Mail;Birthday;'.PHP_EOL;
echo 'Name;Firstname;Civility;Thirdparty;Function;Address;ZipCode;City;Department;Country;Email;Pro Phone;Perso Phone;Mobile Phone;Instant Mail;Birthday;'.PHP_EOL;
echo $object->name.';';
echo ';';
echo ';';
@ -157,7 +157,7 @@ class ActionsDatapolicy
header('Pragma: no-cache');
$soc = $object->fetch_thirdparty();
echo 'Name;Fistname;Civility;Thirdparty;Function;Address;ZipCode;City;Department;Country;Email;Pro Phone;Perso Phone;Mobile Phone;Instant Mail;Birthday;'.PHP_EOL;
echo 'Name;Firstname;Civility;Thirdparty;Function;Address;ZipCode;City;Department;Country;Email;Pro Phone;Perso Phone;Mobile Phone;Instant Mail;Birthday;'.PHP_EOL;
echo $object->lastname.';';
echo $object->firstname.';';
echo $object->getCivilityLabel().';';
@ -181,7 +181,7 @@ class ActionsDatapolicy
header('Content-Disposition: attachment; filename=datapolicy_portabilite.csv');
header('Pragma: no-cache');
$soc = $object->fetch_thirdparty();
echo 'Name;Fistname;Civility;Thirdparty;Function;Address;ZipCode;City;Department;Country;Email;Pro Phone;Perso Phone;Mobile Phone;Instant Mail;Birthday;'.PHP_EOL;
echo 'Name;Firstname;Civility;Thirdparty;Function;Address;ZipCode;City;Department;Country;Email;Pro Phone;Perso Phone;Mobile Phone;Instant Mail;Birthday;'.PHP_EOL;
echo $object->lastname.';';
echo $object->firstname.';';
echo $object->getCivilityLabel().';';

View File

@ -565,7 +565,7 @@ if ($ok && GETPOST('restore_user_pictures', 'alpha')) {
$filetotestsmall = $dolibarr_main_data_root.'/users/'.substr(sprintf('%08d', $obj->rowid), -1, 1).'/'.substr(sprintf('%08d', $obj->rowid), -2, 1).'/thumbs/'.$name.'_small'.$ext;
$filetotestmini = $dolibarr_main_data_root.'/users/'.substr(sprintf('%08d', $obj->rowid), -1, 1).'/'.substr(sprintf('%08d', $obj->rowid), -2, 1).'/thumbs/'.$name.'_mini'.$ext;
$exists = dol_is_file($filetotest);
print 'Check user '.$obj->rowid.' lastname='.$obj->lastname.' fistname='.$obj->firstname.' photo='.$obj->photo.' file '.$filetotest." exists=".$exists."<br>\n";
print 'Check user '.$obj->rowid.' lastname='.$obj->lastname.' firstname='.$obj->firstname.' photo='.$obj->photo.' file '.$filetotest." exists=".$exists."<br>\n";
if ($exists) {
$filetarget = $dolibarr_main_data_root.'/users/'.$obj->rowid.'/'.$name.$ext;
$filetargetsmall = $dolibarr_main_data_root.'/users/'.$obj->rowid.'/thumbs/'.$name.'_small'.$ext;

View File

@ -523,6 +523,7 @@ print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST" name="newmember">'.
print '<input type="hidden" name="token" value="'.newToken().'" / >';
print '<input type="hidden" name="entity" value="'.$entity.'" />';
print '<input type="hidden" name="action" value="add" />';
print '<input type="hidden" name="page_y" value="" />';
print '<br>';
@ -563,7 +564,7 @@ jQuery(document).ready(function () {
print '<table class="border" summary="form to subscribe" id="tablesubscribe">'."\n";
// Type
// Type
if (empty($conf->global->MEMBER_NEWFORM_FORCETYPE)) {
$listoftype = $adht->liste_array();
$tmp = array_keys($listoftype);
@ -596,7 +597,7 @@ if (empty($conf->global->MEMBER_NEWFORM_FORCEMORPHY)) {
// Company
print '<tr id="trcompany" class="trcompany"><td>'.$langs->trans("Company").'</td><td>';
print img_picto('', 'company', 'class="pictofixedwidth"');
print '<input type="text" name="societe" class="minwidth150" value="'.dol_escape_htmltag(GETPOST('societe')).'"></td></tr>'."\n";
print '<input type="text" name="societe" class="minwidth150 widthcentpercentminusx" value="'.dol_escape_htmltag(GETPOST('societe')).'"></td></tr>'."\n";
// Title
print '<tr><td class="titlefield">'.$langs->trans('UserTitle').'</td><td>';
print $formcompany->select_civility(GETPOST('civility_id'), 'civility_id').'</td></tr>'."\n";
@ -625,7 +626,7 @@ print '<tr><td>'.$langs->trans("Address").'</td><td>'."\n";
print '<textarea name="address" id="address" wrap="soft" class="quatrevingtpercent" rows="'.ROWS_3.'">'.dol_escape_htmltag(GETPOST('address', 'restricthtml'), 0, 1).'</textarea></td></tr>'."\n";
// Zip / Town
print '<tr><td>'.$langs->trans('Zip').' / '.$langs->trans('Town').'</td><td>';
print $formcompany->select_ziptown(GETPOST('zipcode'), 'zipcode', array('town', 'selectcountry_id', 'state_id'), 6, 1);
print $formcompany->select_ziptown(GETPOST('zipcode'), 'zipcode', array('town', 'selectcountry_id', 'state_id'), 0, 1, '', 'width75');
print ' / ';
print $formcompany->select_ziptown(GETPOST('town'), 'town', array('zipcode', 'selectcountry_id', 'state_id'), 0, 1);
print '</td></tr>';

View File

@ -698,8 +698,14 @@ class RecruitmentJobPosition extends CommonObject
$newlang = (GETPOST('lang_id', 'aZ09') ? GETPOST('lang_id', 'aZ09') : $this->thirdparty->default_lang);
$outputlangs->setDefaultLang($newlang);
}
// PDF
$hidedetails = (!empty($conf->global->MAIN_GENERATE_DOCUMENTS_HIDE_DETAILS) ? 1 : 0);
$hidedesc = (!empty($conf->global->MAIN_GENERATE_DOCUMENTS_HIDE_DESC) ? 1 : 0);
$hideref = (!empty($conf->global->MAIN_GENERATE_DOCUMENTS_HIDE_REF) ? 1 : 0);
//$ret=$object->fetch($id); // Reload to get new records
$this->generateDocument($modelpdf, $outputlangs);
$this->generateDocument($modelpdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
}
if (!$error) {

View File

@ -1549,7 +1549,7 @@ select.widthcentpercentminusxx, span.widthcentpercentminusxx:not(.select2-select
height: 64px !important;
}
.divmainbodylarge { margin-left: 20px !important; margin-right: 20px !important; }
.divmainbodylarge { margin-left: 10px !important; margin-right: 10px !important; }
.tdoverflowonsmartphone {
max-width: 0;

View File

@ -1576,7 +1576,7 @@ table[summary="list_of_modules"] .fa-cog {
min-width: 150px !important;
}
.divmainbodylarge { margin-left: 20px; margin-right: 20px; }
.divmainbodylarge { margin-left: 10px; margin-right: 10px; }
.tdoverflowonsmartphone {
max-width: 0;

View File

@ -1671,7 +1671,7 @@ class Ticket extends CommonObject
$actioncomm->userassigned = array($user->id);
$actioncomm->userownerid = $user->id;
$actioncomm->datep = $now;
$actioncomm->percentage = 100;
$actioncomm->percentage = -1; // percentage is not relevant for punctual events
$actioncomm->elementtype = 'ticket';
$actioncomm->fk_element = $this->id;