Merge branch '14.0' of git@github.com:Dolibarr/dolibarr.git into develop

This commit is contained in:
Laurent Destailleur 2021-06-30 17:27:20 +02:00
commit 6cb5ea6ec2
24 changed files with 142 additions and 262 deletions

View File

@ -1013,7 +1013,7 @@ class Setup extends DolibarrApi
$list[$tab->elementtype][$tab->name]['computed'] = $tab->fieldcomputed; $list[$tab->elementtype][$tab->name]['computed'] = $tab->fieldcomputed;
$list[$tab->elementtype][$tab->name]['unique'] = $tab->fieldunique; $list[$tab->elementtype][$tab->name]['unique'] = $tab->fieldunique;
$list[$tab->elementtype][$tab->name]['required'] = $tab->fieldrequired; $list[$tab->elementtype][$tab->name]['required'] = $tab->fieldrequired;
$list[$tab->elementtype][$tab->name]['param'] = ($tab->param ? unserialize($tab->param) : ''); $list[$tab->elementtype][$tab->name]['param'] = ($tab->param ? jsonOrUnserialize($tab->param) : ''); // This may be a string encoded with serialise() or json_encode()
$list[$tab->elementtype][$tab->name]['pos'] = $tab->pos; $list[$tab->elementtype][$tab->name]['pos'] = $tab->pos;
$list[$tab->elementtype][$tab->name]['alwayseditable'] = $tab->alwayseditable; $list[$tab->elementtype][$tab->name]['alwayseditable'] = $tab->alwayseditable;
$list[$tab->elementtype][$tab->name]['perms'] = $tab->perms; $list[$tab->elementtype][$tab->name]['perms'] = $tab->perms;

View File

@ -777,10 +777,8 @@ class BlockedLog
public function dolDecodeBlockedData($data, $mode = 0) public function dolDecodeBlockedData($data, $mode = 0)
{ {
try { try {
//include_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
//include_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php'; //include_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
$aaa = unserialize($data); $aaa = unserialize($data);
//$aaa = unserialize($data);
} catch (Exception $e) { } catch (Exception $e) {
//print $e->getErrs); //print $e->getErrs);
} }

View File

@ -163,8 +163,8 @@ if (GETPOST("account") || GETPOST("ref")) {
$sqls[] = $sql; $sqls[] = $sql;
// Social contributions // Social contributions
$sql = " SELECT 'social_contribution' as family, cs.rowid as objid, cs.libelle as ref, (-1*cs.amount) as total_ttc, ccs.libelle as type, cs.date_ech as dlr"; $sql = " SELECT 'social_contribution' as family, cs.rowid as objid, cs.libelle as ref, (-1*cs.amount) as total_ttc, ccs.libelle as type, cs.date_ech as dlr,";
$sql .= ", cs.fk_account"; $sql .= " 0 as socid, 'noname' as name, 0 as fournisseur";
$sql .= " FROM ".MAIN_DB_PREFIX."chargesociales as cs"; $sql .= " FROM ".MAIN_DB_PREFIX."chargesociales as cs";
$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_chargesociales as ccs ON cs.fk_type = ccs.id"; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_chargesociales as ccs ON cs.fk_type = ccs.id";
$sql .= " WHERE cs.entity = ".$conf->entity; $sql .= " WHERE cs.entity = ".$conf->entity;
@ -188,7 +188,18 @@ if (GETPOST("account") || GETPOST("ref")) {
$resql = $db->query($sql); $resql = $db->query($sql);
if ($resql) { if ($resql) {
while ($sqlobj = $db->fetch_object($resql)) { while ($sqlobj = $db->fetch_object($resql)) {
$tab_sqlobj[] = $sqlobj; $tmpobj = new stdClass();
$tmpobj->family = $sqlobj->family;
$tmpobj->objid = $sqlobj->objid;
$tmpobj->ref = $sqlobj->ref;
$tmpobj->total_ttc = $sqlobj->total_ttc;
$tmpobj->type = $sqlobj->type;
$tmpobj->dlt = $sqlobj->dlr;
$tmpobj->socid = $sqlobj->socid;
$tmpobj->name = $sqlobj->name;
$tmpobj->fournisseur = $sqlobj->fournisseur;
$tab_sqlobj[] = $tmpobj;
$tab_sqlobjOrder[] = $db->jdate($sqlobj->dlr); $tab_sqlobjOrder[] = $db->jdate($sqlobj->dlr);
} }
$db->free($resql); $db->free($resql);
@ -201,15 +212,6 @@ if (GETPOST("account") || GETPOST("ref")) {
if (!$error) { if (!$error) {
array_multisort($tab_sqlobjOrder, $tab_sqlobj); array_multisort($tab_sqlobjOrder, $tab_sqlobj);
// Apply distinct filter
foreach ($tab_sqlobj as $key => $value) {
$tab_sqlobj[$key] = "'".serialize($value)."'";
}
$tab_sqlobj = array_unique($tab_sqlobj);
foreach ($tab_sqlobj as $key => $value) {
$tab_sqlobj[$key] = unserialize(trim($value, "'"));
}
$num = count($tab_sqlobj); $num = count($tab_sqlobj);
$i = 0; $i = 0;

View File

@ -3296,11 +3296,11 @@ if ($action == 'create') {
if (is_array($facids)) { if (is_array($facids)) {
foreach ($facids as $facparam) { foreach ($facids as $facparam) {
$options .= '<option value="'.$facparam ['id'].'"'; $options .= '<option value="'.$facparam ['id'].'"';
if ($facparam ['id'] == $_POST['fac_replacement']) { if ($facparam['id'] == GETPOST('fac_replacement', 'int')) {
$options .= ' selected'; $options .= ' selected';
} }
$options .= '>'.$facparam['ref']; $options .= '>'.$facparam['ref'];
$options .= ' ('.$facturestatic->LibStatut(0, $facparam ['status']).')'; $options .= ' ('.$facturestatic->LibStatut($facparam['paid'], $facparam['status'], 0, $facparam['alreadypaid']).')';
$options .= '</option>'; $options .= '</option>';
} }
} }

View File

@ -4100,28 +4100,34 @@ class Facture extends CommonInvoice
$return = array(); $return = array();
$sql = "SELECT f.rowid as rowid, f.ref, f.fk_statut,"; $sql = "SELECT f.rowid as rowid, f.ref, f.fk_statut as status, f.paye as paid,";
$sql .= " ff.rowid as rowidnext"; $sql .= " ff.rowid as rowidnext";
//$sql .= ", SUM(pf.amount) as alreadypaid";
$sql .= " FROM ".MAIN_DB_PREFIX."facture as f"; $sql .= " FROM ".MAIN_DB_PREFIX."facture as f";
$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."paiement_facture as pf ON f.rowid = pf.fk_facture"; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."paiement_facture as pf ON f.rowid = pf.fk_facture";
$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."facture as ff ON f.rowid = ff.fk_facture_source"; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."facture as ff ON f.rowid = ff.fk_facture_source";
$sql .= " WHERE (f.fk_statut = ".self::STATUS_VALIDATED." OR (f.fk_statut = ".self::STATUS_ABANDONED." AND f.close_code = '".self::CLOSECODE_ABANDONED."'))"; $sql .= " WHERE (f.fk_statut = ".self::STATUS_VALIDATED." OR (f.fk_statut = ".self::STATUS_ABANDONED." AND f.close_code = '".self::CLOSECODE_ABANDONED."'))";
$sql .= " AND f.entity IN (".getEntity('invoice').")"; $sql .= " AND f.entity IN (".getEntity('invoice').")";
$sql .= " AND f.paye = 0"; // Pas classee payee completement $sql .= " AND f.paye = 0"; // Not paid completely
$sql .= " AND pf.fk_paiement IS NULL"; // Aucun paiement deja fait $sql .= " AND pf.fk_paiement IS NULL"; // No payment already done
$sql .= " AND ff.fk_statut IS NULL"; // Renvoi vrai si pas facture de remplacement $sql .= " AND ff.fk_statut IS NULL"; // Return true if it is not a replacement invoice
if ($socid > 0) { if ($socid > 0) {
$sql .= " AND f.fk_soc = ".((int) $socid); $sql .= " AND f.fk_soc = ".((int) $socid);
} }
//$sql .= " GROUP BY f.rowid, f.ref, f.fk_statut, f.paye, ff.rowid";
$sql .= " ORDER BY f.ref"; $sql .= " ORDER BY f.ref";
dol_syslog(get_class($this)."::list_replacable_invoices", LOG_DEBUG); dol_syslog(get_class($this)."::list_replacable_invoices", LOG_DEBUG);
$resql = $this->db->query($sql); $resql = $this->db->query($sql);
if ($resql) { if ($resql) {
while ($obj = $this->db->fetch_object($resql)) { while ($obj = $this->db->fetch_object($resql)) {
$return[$obj->rowid] = array('id' => $obj->rowid, $return[$obj->rowid] = array(
'id' => $obj->rowid,
'ref' => $obj->ref, 'ref' => $obj->ref,
'status' => $obj->fk_statut); 'status' => $obj->status,
'paid' => $obj->paid,
'alreadypaid' => 0
);
} }
//print_r($return); //print_r($return);
return $return; return $return;

View File

@ -8167,15 +8167,6 @@ abstract class CommonObject
} else { } else {
$queryarray[$field] = $this->db->idate($this->{$field}); $queryarray[$field] = $this->db->idate($this->{$field});
} }
} elseif ($this->isArray($info)) {
if (!empty($this->{$field})) {
if (!is_array($this->{$field})) {
$this->{$field} = array($this->{$field});
}
$queryarray[$field] = serialize($this->{$field});
} else {
$queryarray[$field] = null;
}
} elseif ($this->isDuration($info)) { } elseif ($this->isDuration($info)) {
// $this->{$field} may be null, '', 0, '0', 123, '123' // $this->{$field} may be null, '', 0, '0', 123, '123'
if ((isset($this->{$field}) && $this->{$field} != '') || !empty($info['notnull'])) { if ((isset($this->{$field}) && $this->{$field} != '') || !empty($info['notnull'])) {
@ -8236,16 +8227,6 @@ abstract class CommonObject
} else { } else {
$this->{$field} = $db->jdate($obj->{$field}); $this->{$field} = $db->jdate($obj->{$field});
} }
} elseif ($this->isArray($info)) {
if (!empty($obj->{$field})) {
$this->{$field} = @unserialize($obj->{$field});
// Hack for data not in UTF8
if ($this->{$field } === false) {
@unserialize(utf8_decode($obj->{$field}));
}
} else {
$this->{$field} = array();
}
} elseif ($this->isInt($info)) { } elseif ($this->isInt($info)) {
if ($field == 'rowid') { if ($field == 'rowid') {
$this->id = (int) $obj->{$field}; $this->id = (int) $obj->{$field};

View File

@ -936,7 +936,7 @@ class ExtraFields
$this->attribute_computed[$tab->name] = $tab->fieldcomputed; $this->attribute_computed[$tab->name] = $tab->fieldcomputed;
$this->attribute_unique[$tab->name] = $tab->fieldunique; $this->attribute_unique[$tab->name] = $tab->fieldunique;
$this->attribute_required[$tab->name] = $tab->fieldrequired; $this->attribute_required[$tab->name] = $tab->fieldrequired;
$this->attribute_param[$tab->name] = ($tab->param ? unserialize($tab->param) : ''); $this->attribute_param[$tab->name] = ($tab->param ? jsonOrUnserialize($tab->param) : '');
$this->attribute_pos[$tab->name] = $tab->pos; $this->attribute_pos[$tab->name] = $tab->pos;
$this->attribute_alwayseditable[$tab->name] = $tab->alwayseditable; $this->attribute_alwayseditable[$tab->name] = $tab->alwayseditable;
$this->attribute_perms[$tab->name] = (strlen($tab->perms) == 0 ? 1 : $tab->perms); $this->attribute_perms[$tab->name] = (strlen($tab->perms) == 0 ? 1 : $tab->perms);
@ -954,7 +954,7 @@ class ExtraFields
$this->attributes[$tab->elementtype]['computed'][$tab->name] = $tab->fieldcomputed; $this->attributes[$tab->elementtype]['computed'][$tab->name] = $tab->fieldcomputed;
$this->attributes[$tab->elementtype]['unique'][$tab->name] = $tab->fieldunique; $this->attributes[$tab->elementtype]['unique'][$tab->name] = $tab->fieldunique;
$this->attributes[$tab->elementtype]['required'][$tab->name] = $tab->fieldrequired; $this->attributes[$tab->elementtype]['required'][$tab->name] = $tab->fieldrequired;
$this->attributes[$tab->elementtype]['param'][$tab->name] = ($tab->param ? unserialize($tab->param) : ''); $this->attributes[$tab->elementtype]['param'][$tab->name] = ($tab->param ? jsonOrUnserialize($tab->param) : '');
$this->attributes[$tab->elementtype]['pos'][$tab->name] = $tab->pos; $this->attributes[$tab->elementtype]['pos'][$tab->name] = $tab->pos;
$this->attributes[$tab->elementtype]['alwayseditable'][$tab->name] = $tab->alwayseditable; $this->attributes[$tab->elementtype]['alwayseditable'][$tab->name] = $tab->alwayseditable;
$this->attributes[$tab->elementtype]['perms'][$tab->name] = (strlen($tab->perms) == 0 ? 1 : $tab->perms); $this->attributes[$tab->elementtype]['perms'][$tab->name] = (strlen($tab->perms) == 0 ? 1 : $tab->perms);

View File

@ -37,7 +37,7 @@ if (class_exists($keyforclass)) {
/* /*
* case 'sellist': * case 'sellist':
* $tmp=''; * $tmp='';
* $tmpparam=unserialize($obj->param); // $tmp ay be array 'options' => array 'c_currencies:code_iso:code_iso' => null * $tmpparam=jsonOrUnserialize($obj->param); // $tmp ay be array 'options' => array 'c_currencies:code_iso:code_iso' => null
* if ($tmpparam['options'] && is_array($tmpparam['options'])) { * if ($tmpparam['options'] && is_array($tmpparam['options'])) {
* $tmpkeys=array_keys($tmpparam['options']); * $tmpkeys=array_keys($tmpparam['options']);
* $tmp=array_shift($tmpkeys); * $tmp=array_shift($tmpkeys);

View File

@ -39,7 +39,7 @@ if ($resql) { // This can fail when class is used on old database (during mig
case 'checkbox': case 'checkbox':
case 'select': case 'select':
if (!empty($conf->global->EXPORT_LABEL_FOR_SELECT)) { if (!empty($conf->global->EXPORT_LABEL_FOR_SELECT)) {
$tmpparam = unserialize($obj->param); // $tmpparam may be array with 'options' = array(key1=>val1, key2=>val2 ...) $tmpparam = jsonOrUnserialize($obj->param); // $tmpparam may be array with 'options' = array(key1=>val1, key2=>val2 ...)
if ($tmpparam['options'] && is_array($tmpparam['options'])) { if ($tmpparam['options'] && is_array($tmpparam['options'])) {
$typeFilter = "Select:".$obj->param; $typeFilter = "Select:".$obj->param;
} }
@ -47,7 +47,7 @@ if ($resql) { // This can fail when class is used on old database (during mig
break; break;
case 'sellist': case 'sellist':
$tmp = ''; $tmp = '';
$tmpparam = unserialize($obj->param); // $tmp ay be array 'options' => array 'c_currencies:code_iso:code_iso' => null $tmpparam = jsonOrUnserialize($obj->param); // $tmp may be array 'options' => array 'c_currencies:code_iso:code_iso' => null
if ($tmpparam['options'] && is_array($tmpparam['options'])) { if ($tmpparam['options'] && is_array($tmpparam['options'])) {
$tmpkeys = array_keys($tmpparam['options']); $tmpkeys = array_keys($tmpparam['options']);
$tmp = array_shift($tmpkeys); $tmp = array_shift($tmpkeys);

View File

@ -993,7 +993,7 @@ function dol_buildpath($path, $type = 0, $returnemptyifnotfound = 0)
function dol_clone($object, $native = 0) function dol_clone($object, $native = 0)
{ {
if (empty($native)) { if (empty($native)) {
$myclone = unserialize(serialize($object)); $myclone = unserialize(serialize($object)); // serialize then unserialize is hack to be sure to have a new object for all fields
} else { } else {
$myclone = clone $object; // PHP clone is a shallow copy only, not a real clone, so properties of references will keep the reference (refering to the same target/variable) $myclone = clone $object; // PHP clone is a shallow copy only, not a real clone, so properties of references will keep the reference (refering to the same target/variable)
} }
@ -10301,9 +10301,10 @@ function readfileLowMemory($fullpath_original_file_osencoded, $method = -1)
*/ */
function showValueWithClipboardCPButton($valuetocopy, $showonlyonhover = 1, $texttoshow = '') function showValueWithClipboardCPButton($valuetocopy, $showonlyonhover = 1, $texttoshow = '')
{ {
/*
global $conf; global $conf;
/*if (!empty($conf->dol_no_mouse_hover)) { if (!empty($conf->dol_no_mouse_hover)) {
$showonlyonhover = 0; $showonlyonhover = 0;
}*/ }*/
@ -10315,3 +10316,20 @@ function showValueWithClipboardCPButton($valuetocopy, $showonlyonhover = 1, $tex
return $result; return $result;
} }
/**
* Decode an encode string. The string can be encoded in json format (recommended) or with serialize (avoid this)
*
* @param string $stringtodecode String to decode (json or serialize coded)
* @return mixed The decoded object.
*/
function jsonOrUnserialize($stringtodecode)
{
$result = json_decode($stringtodecode);
if ($result === null) {
$result = unserialize($stringtodecode);
}
return $result;
}

View File

@ -849,7 +849,7 @@ function projectLinesa(&$inc, $parent, &$lines, &$level, $var, $showproject, &$t
// Contacts of task // Contacts of task
if (count($arrayfields) > 0 && !empty($arrayfields['c.assigned']['checked'])) { if (count($arrayfields) > 0 && !empty($arrayfields['c.assigned']['checked'])) {
print '<td>'; print '<td class="center">';
foreach (array('internal', 'external') as $source) { foreach (array('internal', 'external') as $source) {
$tab = $lines[$i]->liste_contact(-1, $source); $tab = $lines[$i]->liste_contact(-1, $source);
$num = count($tab); $num = count($tab);

View File

@ -277,8 +277,8 @@ class ExportCsv extends ModeleExports
$newvalue = $this->csvClean($newvalue, $outputlangs->charset_output); $newvalue = $this->csvClean($newvalue, $outputlangs->charset_output);
if (preg_match('/^Select:/i', $typefield, $reg) && $typefield = substr($typefield, 7)) { if (preg_match('/^Select:/i', $typefield) && $typefield = substr($typefield, 7)) {
$array = unserialize($typefield); $array = json_decode($typefield, true);
$array = $array['options']; $array = $array['options'];
$newvalue = $array[$newvalue]; $newvalue = $array[$newvalue];
} }

View File

@ -315,8 +315,8 @@ class ExportExcel2007 extends ModeleExports
$newvalue = $this->excel_clean($newvalue); $newvalue = $this->excel_clean($newvalue);
$typefield = isset($array_types[$code]) ? $array_types[$code] : ''; $typefield = isset($array_types[$code]) ? $array_types[$code] : '';
if (preg_match('/^Select:/i', $typefield, $reg) && $typefield = substr($typefield, 7)) { if (preg_match('/^Select:/i', $typefield) && $typefield = substr($typefield, 7)) {
$array = unserialize($typefield); $array = json_decode($typefield, true);
$array = $array['options']; $array = $array['options'];
$newvalue = $array[$newvalue]; $newvalue = $array[$newvalue];
} }

View File

@ -252,8 +252,8 @@ class ExportTsv extends ModeleExports
$newvalue = $this->tsv_clean($newvalue, $outputlangs->charset_output); $newvalue = $this->tsv_clean($newvalue, $outputlangs->charset_output);
if (preg_match('/^Select:/i', $typefield, $reg) && $typefield = substr($typefield, 7)) { if (preg_match('/^Select:/i', $typefield) && $typefield = substr($typefield, 7)) {
$array = unserialize($typefield); $array = json_decode($typefield, true);
$array = $array['options']; $array = $array['options'];
$newvalue = $array[$newvalue]; $newvalue = $array[$newvalue];
} }

View File

@ -623,6 +623,12 @@ class ImportCsv extends ModeleImports
} }
} elseif ($objimport->array_import_convertvalue[0][$val]['rule'] == 'numeric') { } elseif ($objimport->array_import_convertvalue[0][$val]['rule'] == 'numeric') {
$newval = price2num($newval); $newval = price2num($newval);
} elseif ($objimport->array_import_convertvalue[0][$val]['rule'] == 'accountingaccount') {
if (empty($conf->global->ACCOUNTING_MANAGE_ZERO)) {
$newval = rtrim(trim($newval), "0");
} else {
$newval = trim($newval);
}
} }
//print 'Val to use as insert is '.$newval.'<br>'; //print 'Val to use as insert is '.$newval.'<br>';

View File

@ -664,6 +664,12 @@ class ImportXlsx extends ModeleImports
} }
} elseif ($objimport->array_import_convertvalue[0][$val]['rule'] == 'numeric') { } elseif ($objimport->array_import_convertvalue[0][$val]['rule'] == 'numeric') {
$newval = price2num($newval); $newval = price2num($newval);
} elseif ($objimport->array_import_convertvalue[0][$val]['rule'] == 'accountingaccount') {
if (empty($conf->global->ACCOUNTING_MANAGE_ZERO)) {
$newval = rtrim(trim($newval), "0");
} else {
$newval = trim($newval);
}
} }
//print 'Val to use as insert is '.$newval.'<br>'; //print 'Val to use as insert is '.$newval.'<br>';

View File

@ -297,6 +297,10 @@ class modAccounting extends DolibarrModules
); );
$this->import_fieldshidden_array[$r] = array('b.doc_type'=>'const-import_from_external', 'b.fk_doc'=>'const-0', 'b.fk_docdet'=>'const-0', 'b.fk_user_author'=>'user->id', 'b.date_creation'=>'const-'.dol_print_date(dol_now(), 'standard')); // aliastable.field => ('user->id' or 'lastrowid-'.tableparent) $this->import_fieldshidden_array[$r] = array('b.doc_type'=>'const-import_from_external', 'b.fk_doc'=>'const-0', 'b.fk_docdet'=>'const-0', 'b.fk_user_author'=>'user->id', 'b.date_creation'=>'const-'.dol_print_date(dol_now(), 'standard')); // aliastable.field => ('user->id' or 'lastrowid-'.tableparent)
$this->import_regex_array[$r] = array('b.doc_date'=>'^[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]$'); $this->import_regex_array[$r] = array('b.doc_date'=>'^[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]$');
$this->import_convertvalue_array[$r] = array(
'b.numero_compte' => array('rule' => 'accountingaccount'),
'b.subledger_account' => array('rule' => 'accountingaccount')
);
$this->import_examplevalues_array[$r] = array( $this->import_examplevalues_array[$r] = array(
'b.piece_num'=>'123 (!!! use next value not already used)', 'b.piece_num'=>'123 (!!! use next value not already used)',
'b.doc_date'=>dol_print_date(dol_now(), "%Y-%m-%d"), 'b.doc_date'=>dol_print_date(dol_now(), "%Y-%m-%d"),
@ -350,6 +354,8 @@ class modAccounting extends DolibarrModules
'b.sens'=>'rule-computeSens' 'b.sens'=>'rule-computeSens'
); // aliastable.field => ('user->id' or 'lastrowid-'.tableparent) ); // aliastable.field => ('user->id' or 'lastrowid-'.tableparent)
$this->import_convertvalue_array[$r]=array( $this->import_convertvalue_array[$r]=array(
'b.numero_compte'=>array('rule'=>'accountingaccount'),
'b.subledger_account'=>array('rule'=>'accountingaccount'),
'b.montant' => array('rule' => 'compute', 'classfile' => '/accountancy/class/accountancyimport.class.php', 'class' => 'AccountancyImport', 'method' => 'computeAmount', 'element' => 'Accountancy'), 'b.montant' => array('rule' => 'compute', 'classfile' => '/accountancy/class/accountancyimport.class.php', 'class' => 'AccountancyImport', 'method' => 'computeAmount', 'element' => 'Accountancy'),
'b.sens' => array('rule' => 'compute', 'classfile' => '/accountancy/class/accountancyimport.class.php', 'class' => 'AccountancyImport', 'method' => 'computeDirection', 'element' => 'Accountancy'), 'b.sens' => array('rule' => 'compute', 'classfile' => '/accountancy/class/accountancyimport.class.php', 'class' => 'AccountancyImport', 'method' => 'computeDirection', 'element' => 'Accountancy'),
); );
@ -395,6 +401,7 @@ class modAccounting extends DolibarrModules
$this->import_fields_array[$r] = array('aa.fk_pcg_version'=>"Chartofaccounts*", 'aa.account_number'=>"AccountAccounting*", 'aa.label'=>"Label*", 'aa.account_parent'=>"Accountparent", "aa.fk_accounting_category"=>"AccountingCategory", "aa.pcg_type"=>"Pcgtype*", 'aa.active'=>'Status*', 'aa.datec'=>"DateCreation"); $this->import_fields_array[$r] = array('aa.fk_pcg_version'=>"Chartofaccounts*", 'aa.account_number'=>"AccountAccounting*", 'aa.label'=>"Label*", 'aa.account_parent'=>"Accountparent", "aa.fk_accounting_category"=>"AccountingCategory", "aa.pcg_type"=>"Pcgtype*", 'aa.active'=>'Status*', 'aa.datec'=>"DateCreation");
$this->import_regex_array[$r] = array('aa.fk_pcg_version'=>'pcg_version@'.MAIN_DB_PREFIX.'accounting_system', 'aa.account_number'=>'^.{1,32}$', 'aa.label'=>'^.{1,255}$', 'aa.account_parent'=>'^.{0,32}$', 'aa.fk_accounting_category'=>'rowid@'.MAIN_DB_PREFIX.'c_accounting_category', 'aa.pcg_type'=>'^.{1,20}$', 'aa.active'=>'^0|1$', 'aa.datec'=>'^\d{4}-\d{2}-\d{2}$'); $this->import_regex_array[$r] = array('aa.fk_pcg_version'=>'pcg_version@'.MAIN_DB_PREFIX.'accounting_system', 'aa.account_number'=>'^.{1,32}$', 'aa.label'=>'^.{1,255}$', 'aa.account_parent'=>'^.{0,32}$', 'aa.fk_accounting_category'=>'rowid@'.MAIN_DB_PREFIX.'c_accounting_category', 'aa.pcg_type'=>'^.{1,20}$', 'aa.active'=>'^0|1$', 'aa.datec'=>'^\d{4}-\d{2}-\d{2}$');
$this->import_convertvalue_array[$r] = array( $this->import_convertvalue_array[$r] = array(
'aa.account_number'=>array('rule'=>'accountingaccount'),
'aa.account_parent'=>array('rule'=>'fetchidfromref', 'classfile'=>'/accountancy/class/accountingaccount.class.php', 'class'=>'AccountingAccount', 'method'=>'fetch', 'element'=>'AccountingAccount'), 'aa.account_parent'=>array('rule'=>'fetchidfromref', 'classfile'=>'/accountancy/class/accountingaccount.class.php', 'class'=>'AccountingAccount', 'method'=>'fetch', 'element'=>'AccountingAccount'),
'aa.fk_accounting_category'=>array('rule'=>'fetchidfromcodeorlabel', 'classfile'=>'/accountancy/class/accountancycategory.class.php', 'class'=>'AccountancyCategory', 'method'=>'fetch', 'dict'=>'DictionaryAccountancyCategory'), 'aa.fk_accounting_category'=>array('rule'=>'fetchidfromcodeorlabel', 'classfile'=>'/accountancy/class/accountancycategory.class.php', 'class'=>'AccountancyCategory', 'method'=>'fetch', 'dict'=>'DictionaryAccountancyCategory'),
); );

View File

@ -285,7 +285,7 @@ class modFournisseur extends DolibarrModules
$r++; $r++;
$this->export_code[$r] = $this->rights_class.'_'.$r; $this->export_code[$r] = $this->rights_class.'_'.$r;
$this->export_label[$r] = 'Vendor invoices and lines of invoices'; $this->export_label[$r] = 'Vendor invoices and lines of invoices';
$this->export_icon[$r] = 'bill'; $this->export_icon[$r] = 'invoice';
$this->export_permission[$r] = array(array("fournisseur", "facture", "export")); $this->export_permission[$r] = array(array("fournisseur", "facture", "export"));
$this->export_fields_array[$r] = array( $this->export_fields_array[$r] = array(
's.rowid'=>"IdCompany", 's.nom'=>'CompanyName', 'ps.nom'=>'ParentCompany', 's.address'=>'Address', 's.zip'=>'Zip', 's.town'=>'Town', 'c.code'=>'CountryCode', 's.phone'=>'Phone', 's.rowid'=>"IdCompany", 's.nom'=>'CompanyName', 'ps.nom'=>'ParentCompany', 's.address'=>'Address', 's.zip'=>'Zip', 's.town'=>'Town', 'c.code'=>'CountryCode', 's.phone'=>'Phone',
@ -328,81 +328,14 @@ class modFournisseur extends DolibarrModules
); );
$this->export_dependencies_array[$r] = array('invoice_line'=>'fd.rowid', 'product'=>'fd.rowid'); // To add unique key if we ask a field of a child to avoid the DISTINCT to discard them $this->export_dependencies_array[$r] = array('invoice_line'=>'fd.rowid', 'product'=>'fd.rowid'); // To add unique key if we ask a field of a child to avoid the DISTINCT to discard them
// Add extra fields object // Add extra fields object
$sql = "SELECT name, label, type, param FROM ".MAIN_DB_PREFIX."extrafields WHERE elementtype = 'facture_fourn' AND entity IN (0, ".$conf->entity.")"; $keyforselect = 'facture_fourn';
$resql = $this->db->query($sql); $keyforelement = 'invoice';
if ($resql) { // This can fail when class is used on old database (during migration for example) $keyforaliasextra = 'extra';
while ($obj = $this->db->fetch_object($resql)) { include DOL_DOCUMENT_ROOT.'/core/extrafieldsinexport.inc.php';
$fieldname = 'extra.'.$obj->name; $keyforselect = 'facture_fourn_det';
$fieldlabel = ucfirst($obj->label); $keyforelement = 'invoice_line';
$typeFilter = "Text"; $keyforaliasextra = 'extraline';
switch ($obj->type) { include DOL_DOCUMENT_ROOT.'/core/extrafieldsinexport.inc.php';
case 'int':
case 'double':
case 'price':
$typeFilter = "Numeric";
break;
case 'date':
case 'datetime':
$typeFilter = "Date";
break;
case 'boolean':
$typeFilter = "Boolean";
break;
case 'sellist':
$tmp = '';
$tmpparam = unserialize($obj->param); // $tmp ay be array 'options' => array 'c_currencies:code_iso:code_iso' => null
if ($tmpparam['options'] && is_array($tmpparam['options'])) {
$var = array_keys($tmpparam['options']);
$tmp = array_shift($var);
}
if (preg_match('/[a-z0-9_]+:[a-z0-9_]+:[a-z0-9_]+/', $tmp)) {
$typeFilter = "List:".$tmp;
}
break;
}
$this->export_fields_array[$r][$fieldname] = $fieldlabel;
$this->export_TypeFields_array[$r][$fieldname] = $typeFilter;
$this->export_entities_array[$r][$fieldname] = 'invoice';
}
}
// End add extra fields
// Add extra fields line
$sql = "SELECT name, label, type, param FROM ".MAIN_DB_PREFIX."extrafields WHERE elementtype = 'facture_fourn_det' AND entity IN (0, ".$conf->entity.")";
$resql = $this->db->query($sql);
if ($resql) { // This can fail when class is used on old database (during migration for example)
while ($obj = $this->db->fetch_object($resql)) {
$fieldname = 'extraline.'.$obj->name;
$fieldlabel = ucfirst($obj->label);
$typeFilter = "Text";
switch ($obj->type) {
case 'int':
case 'double':
case 'price':
$typeFilter = "Numeric";
break;
case 'date':
case 'datetime':
$typeFilter = "Date";
break;
case 'boolean':
$typeFilter = "Boolean";
break;
case 'sellist':
$tmp = '';
$tmpparam = unserialize($obj->param); // $tmp ay be array 'options' => array 'c_currencies:code_iso:code_iso' => null
if ($tmpparam['options'] && is_array($tmpparam['options'])) {
$tmp = array_shift(array_keys($tmpparam['options']));
}
if (preg_match('/[a-z0-9_]+:[a-z0-9_]+:[a-z0-9_]+/', $tmp)) {
$typeFilter = "List:".$tmp;
}
break;
}
$this->export_fields_array[$r][$fieldname] = $fieldlabel;
$this->export_TypeFields_array[$r][$fieldname] = $typeFilter;
$this->export_entities_array[$r][$fieldname] = 'invoice_line';
}
}
// End add extra fields line // End add extra fields line
$this->export_sql_start[$r] = 'SELECT DISTINCT '; $this->export_sql_start[$r] = 'SELECT DISTINCT ';
$this->export_sql_end[$r] = ' FROM '.MAIN_DB_PREFIX.'societe as s'; $this->export_sql_end[$r] = ' FROM '.MAIN_DB_PREFIX.'societe as s';
@ -426,7 +359,7 @@ class modFournisseur extends DolibarrModules
$r++; $r++;
$this->export_code[$r] = $this->rights_class.'_'.$r; $this->export_code[$r] = $this->rights_class.'_'.$r;
$this->export_label[$r] = 'Factures fournisseurs et reglements'; $this->export_label[$r] = 'Factures fournisseurs et reglements';
$this->export_icon[$r] = 'bill'; $this->export_icon[$r] = 'invoice';
$this->export_permission[$r] = array(array("fournisseur", "facture", "export")); $this->export_permission[$r] = array(array("fournisseur", "facture", "export"));
$this->export_fields_array[$r] = array( $this->export_fields_array[$r] = array(
's.rowid'=>"IdCompany", 's.nom'=>'CompanyName', 's.address'=>'Address', 's.zip'=>'Zip', 's.town'=>'Town', 'c.code'=>'CountryCode', 's.phone'=>'Phone', 's.rowid'=>"IdCompany", 's.nom'=>'CompanyName', 's.address'=>'Address', 's.zip'=>'Zip', 's.town'=>'Town', 'c.code'=>'CountryCode', 's.phone'=>'Phone',
@ -465,43 +398,10 @@ class modFournisseur extends DolibarrModules
'p.datep'=>'payment', 'p.num_paiement'=>'payment', 'p.fk_bank'=>'account', 'project.rowid'=>'project', 'project.ref'=>'project', 'project.title'=>'project'); 'p.datep'=>'payment', 'p.num_paiement'=>'payment', 'p.fk_bank'=>'account', 'project.rowid'=>'project', 'project.ref'=>'project', 'project.title'=>'project');
$this->export_dependencies_array[$r] = array('payment'=>'p.rowid'); // To add unique key if we ask a field of a child to avoid the DISTINCT to discard them $this->export_dependencies_array[$r] = array('payment'=>'p.rowid'); // To add unique key if we ask a field of a child to avoid the DISTINCT to discard them
// Add extra fields object // Add extra fields object
$sql = "SELECT name, label, type, param FROM ".MAIN_DB_PREFIX."extrafields WHERE elementtype = 'facture_fourn' AND entity IN (0, ".$conf->entity.")"; $keyforselect = 'facture_fourn';
$resql = $this->db->query($sql); $keyforelement = 'invoice';
if ($resql) { // This can fail when class is used on old database (during migration for example) $keyforaliasextra = 'extra';
while ($obj = $this->db->fetch_object($resql)) { include DOL_DOCUMENT_ROOT.'/core/extrafieldsinexport.inc.php';
$fieldname = 'extra.'.$obj->name;
$fieldlabel = ucfirst($obj->label);
$typeFilter = "Text";
switch ($obj->type) {
case 'int':
case 'double':
case 'price':
$typeFilter = "Numeric";
break;
case 'date':
case 'datetime':
$typeFilter = "Date";
break;
case 'boolean':
$typeFilter = "Boolean";
break;
case 'sellist':
$tmp = '';
$tmpparam = unserialize($obj->param); // $tmp ay be array 'options' => array 'c_currencies:code_iso:code_iso' => null
if ($tmpparam['options'] && is_array($tmpparam['options'])) {
$array_keys = array_keys($tmpparam['options']);
$tmp = array_shift($array_keys);
}
if (preg_match('/[a-z0-9_]+:[a-z0-9_]+:[a-z0-9_]+/', $tmp)) {
$typeFilter = "List:".$tmp;
}
break;
}
$this->export_fields_array[$r][$fieldname] = $fieldlabel;
$this->export_TypeFields_array[$r][$fieldname] = $typeFilter;
$this->export_entities_array[$r][$fieldname] = 'invoice';
}
}
// End add extra fields object // End add extra fields object
$this->export_sql_start[$r] = 'SELECT DISTINCT '; $this->export_sql_start[$r] = 'SELECT DISTINCT ';
$this->export_sql_end[$r] = ' FROM '.MAIN_DB_PREFIX.'societe as s'; $this->export_sql_end[$r] = ' FROM '.MAIN_DB_PREFIX.'societe as s';
@ -564,83 +464,16 @@ class modFournisseur extends DolibarrModules
); );
$this->export_dependencies_array[$r] = array('order_line'=>'fd.rowid', 'product'=>'fd.rowid'); // To add unique key if we ask a field of a child to avoid the DISTINCT to discard them $this->export_dependencies_array[$r] = array('order_line'=>'fd.rowid', 'product'=>'fd.rowid'); // To add unique key if we ask a field of a child to avoid the DISTINCT to discard them
// Add extra fields object // Add extra fields object
$sql = "SELECT name, label, type, param FROM ".MAIN_DB_PREFIX."extrafields WHERE elementtype = 'commande_fournisseur' AND entity IN (0, ".$conf->entity.")"; $keyforselect = 'commande_fournisseur';
$resql = $this->db->query($sql); $keyforelement = 'order';
if ($resql) { // This can fail when class is used on old database (during migration for example) $keyforaliasextra = 'extra';
while ($obj = $this->db->fetch_object($resql)) { include DOL_DOCUMENT_ROOT.'/core/extrafieldsinexport.inc.php';
$fieldname = 'extra.'.$obj->name;
$fieldlabel = ucfirst($obj->label);
$typeFilter = "Text";
switch ($obj->type) {
case 'int':
case 'double':
case 'price':
$typeFilter = "Numeric";
break;
case 'date':
case 'datetime':
$typeFilter = "Date";
break;
case 'boolean':
$typeFilter = "Boolean";
break;
case 'sellist':
$tmp = '';
$tmpparam = unserialize($obj->param); // $tmp ay be array 'options' => array 'c_currencies:code_iso:code_iso' => null
$tmpkey = array_keys($tmpparam['options']);
if ($tmpparam['options'] && is_array($tmpparam['options'])) {
$tmp = array_shift($tmpkey);
}
if (preg_match('/[a-z0-9_]+:[a-z0-9_]+:[a-z0-9_]+/', $tmp)) {
$typeFilter = "List:".$tmp;
}
break;
}
$this->export_fields_array[$r][$fieldname] = $fieldlabel;
$this->export_TypeFields_array[$r][$fieldname] = $typeFilter;
$this->export_entities_array[$r][$fieldname] = 'order';
}
}
// End add extra fields object // End add extra fields object
// Add extra fields line // Add extra fields line
$sql = "SELECT name, label, type, param FROM ".MAIN_DB_PREFIX."extrafields WHERE elementtype = 'commande_fournisseurdet' AND entity IN (0, ".$conf->entity.")"; $keyforselect = 'commande_fournisseurdet';
$resql = $this->db->query($sql); $keyforelement = 'order_line';
if ($resql) { // This can fail when class is used on old database (during migration for example) $keyforaliasextra = 'extraline';
while ($obj = $this->db->fetch_object($resql)) { include DOL_DOCUMENT_ROOT.'/core/extrafieldsinexport.inc.php';
$fieldname = 'extraline.'.$obj->name;
$fieldlabel = ucfirst($obj->label);
$typeFilter = "Text";
switch ($obj->type) {
case 'int':
case 'double':
case 'price':
$typeFilter = "Numeric";
break;
case 'date':
case 'datetime':
$typeFilter = "Date";
break;
case 'boolean':
$typeFilter = "Boolean";
break;
case 'sellist':
$tmp = '';
$tmpparam = unserialize($obj->param); // $tmp ay be array 'options' => array 'c_currencies:code_iso:code_iso' => null
if ($tmpparam['options'] && is_array($tmpparam['options'])) {
$tmpparam_param_key = array_keys($tmpparam['options']);
$tmp = array_shift($tmpparam_param_key);
}
if (preg_match('/[a-z0-9_]+:[a-z0-9_]+:[a-z0-9_]+/', $tmp)) {
$typeFilter = "List:".$tmp;
}
break;
}
$this->export_fields_array[$r][$fieldname] = $fieldlabel;
$this->export_TypeFields_array[$r][$fieldname] = $typeFilter;
$this->export_entities_array[$r][$fieldname] = 'order_line';
}
}
// End add extra fields line // End add extra fields line
$this->export_sql_start[$r] = 'SELECT DISTINCT '; $this->export_sql_start[$r] = 'SELECT DISTINCT ';
$this->export_sql_end[$r] = ' FROM '.MAIN_DB_PREFIX.'societe as s'; $this->export_sql_end[$r] = ' FROM '.MAIN_DB_PREFIX.'societe as s';

View File

@ -573,6 +573,12 @@ class modProduct extends DolibarrModules
'method' => 'fetch', 'method' => 'fetch',
'dict' => 'DictionaryProductNature' 'dict' => 'DictionaryProductNature'
), ),
'p.accountancy_code_sell'=>array('rule'=>'accountingaccount'),
'p.accountancy_code_sell_intra'=>array('rule'=>'accountingaccount'),
'p.accountancy_code_sell_export'=>array('rule'=>'accountingaccount'),
'p.accountancy_code_buy'=>array('rule'=>'accountingaccount'),
'p.accountancy_code_buy_intra'=>array('rule'=>'accountingaccount'),
'p.accountancy_code_buy_export'=>array('rule'=>'accountingaccount'),
); );
$this->import_regex_array[$r] = array( $this->import_regex_array[$r] = array(

View File

@ -130,8 +130,16 @@ $coldisplay++;
$reshook = $hookmanager->executeHooks('formEditProductOptions', $parameters, $this, $action); $reshook = $hookmanager->executeHooks('formEditProductOptions', $parameters, $this, $action);
} }
$situationinvoicelinewithparent = 0;
if ($line->fk_prev_id != null && in_array($object->element, array('facture', 'facturedet'))) {
if ($object->type == $object::TYPE_SITUATION) { // The constant TYPE_SITUATION exists only for object invoice
// Set constant to disallow editing during a situation cycle
$situationinvoicelinewithparent = 1;
}
}
// Do not allow editing during a situation cycle // Do not allow editing during a situation cycle
if ($line->fk_prev_id == null) { if (!$situationinvoicelinewithparent) {
// editor wysiwyg // editor wysiwyg
require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
$nbrows = ROWS_2; $nbrows = ROWS_2;
@ -181,7 +189,7 @@ $coldisplay++;
} }
$coldisplay++; $coldisplay++;
if ($line->fk_prev_id == null) { if (!$situationinvoicelinewithparent) {
print '<td class="right">'.$form->load_tva('tva_tx', $line->tva_tx.($line->vat_src_code ? (' ('.$line->vat_src_code.')') : ''), $seller, $buyer, 0, $line->info_bits, $line->product_type, false, 1).'</td>'; print '<td class="right">'.$form->load_tva('tva_tx', $line->tva_tx.($line->vat_src_code ? (' ('.$line->vat_src_code.')') : ''), $seller, $buyer, 0, $line->info_bits, $line->product_type, false, 1).'</td>';
} else { } else {
print '<td class="right"><input size="1" type="text" class="flat right" name="tva_tx" value="'.price($line->tva_tx).'" readonly />%</td>'; print '<td class="right"><input size="1" type="text" class="flat right" name="tva_tx" value="'.price($line->tva_tx).'" readonly />%</td>';
@ -189,7 +197,7 @@ $coldisplay++;
$coldisplay++; $coldisplay++;
print '<td class="right"><input type="text" class="flat right" size="5" id="price_ht" name="price_ht" value="'.(isset($line->pu_ht) ?price($line->pu_ht, 0, '', 0) : price($line->subprice, 0, '', 0)).'"'; print '<td class="right"><input type="text" class="flat right" size="5" id="price_ht" name="price_ht" value="'.(isset($line->pu_ht) ?price($line->pu_ht, 0, '', 0) : price($line->subprice, 0, '', 0)).'"';
if ($line->fk_prev_id != null) { if ($situationinvoicelinewithparent) {
print ' readonly'; print ' readonly';
} }
print '></td>'; print '></td>';
@ -211,12 +219,12 @@ $coldisplay++;
<td class="right"> <td class="right">
<?php $coldisplay++; <?php $coldisplay++;
if (($line->info_bits & 2) != 2) { if (($line->info_bits & 2) != 2) {
// I comment this because it shows info even when not required // I comment warning of stock because it shows the info even when it should not.
// for example always visible on invoice but must be visible only if stock module on and stock decrease option is on invoice validation and status is not validated // for example always visible on invoice but must be visible only if stock module on and stock decrease option is on invoice validation and status is not validated
// must also not be output for most entities (proposal, intervention, ...) // must also not be output for most entities (proposal, intervention, ...)
//if($line->qty > $line->stock) print img_picto($langs->trans("StockTooLow"),"warning", 'style="vertical-align: bottom;"')." "; //if($line->qty > $line->stock) print img_picto($langs->trans("StockTooLow"),"warning", 'style="vertical-align: bottom;"')." ";
print '<input size="3" type="text" class="flat right" name="qty" id="qty" value="'.$line->qty.'"'; print '<input size="3" type="text" class="flat right" name="qty" id="qty" value="'.$line->qty.'"';
if ($line->fk_prev_id != null) { if ($situationinvoicelinewithparent) { // Do not allow editing during a situation cycle
print ' readonly'; print ' readonly';
} }
print '>'; print '>';
@ -249,7 +257,7 @@ $coldisplay++;
<?php $coldisplay++; <?php $coldisplay++;
if (($line->info_bits & 2) != 2) { if (($line->info_bits & 2) != 2) {
print '<input size="1" type="text" class="flat right" name="remise_percent" id="remise_percent" value="'.$line->remise_percent.'"'; print '<input size="1" type="text" class="flat right" name="remise_percent" id="remise_percent" value="'.$line->remise_percent.'"';
if ($line->fk_prev_id != null) { if ($situationinvoicelinewithparent) {
print ' readonly'; print ' readonly';
} }
print '>%'; print '>%';

View File

@ -18,8 +18,8 @@
CREATE TABLE llx_oauth_token ( CREATE TABLE llx_oauth_token (
rowid integer AUTO_INCREMENT PRIMARY KEY, rowid integer AUTO_INCREMENT PRIMARY KEY,
service varchar(36), -- What king of key or token: 'Google', 'Stripe', 'auth-public-key', ... service varchar(36), -- What king of key or token: 'Google', 'Stripe', 'auth-public-key', ...
token text, -- token in serialize() format, of an object StdOAuth2Token of library phpoauth2 token text, -- token in serialize format, of an object StdOAuth2Token of library phpoauth2. Deprecated, use tokenstring instead.
tokenstring text, -- token in text or json format. Value depends on 'service'. For example for an OAUTH service: '{"access_token": "sk_test_cccc", "refresh_token": "rt_aaa", "token_type": "bearer", ..., "scope": "read_write"} tokenstring text, -- token in json or text format. Value depends on 'service'. For example for an OAUTH service: '{"access_token": "sk_test_cccc", "refresh_token": "rt_aaa", "token_type": "bearer", ..., "scope": "read_write"}
fk_soc integer, -- Id of thirdparty in llx_societe fk_soc integer, -- Id of thirdparty in llx_societe
fk_user integer, -- Id of user in llx_user fk_user integer, -- Id of user in llx_user
fk_adherent integer, -- Id of member in llx_adherent fk_adherent integer, -- Id of member in llx_adherent

View File

@ -902,7 +902,7 @@ if ($action == 'create' && $user->rights->projet->creer && (empty($object->third
} }
*/ */
if (!empty($arrayfields['c.assigned']['checked'])) { if (!empty($arrayfields['c.assigned']['checked'])) {
print_liste_field_titre($arrayfields['c.assigned']['label'], $_SERVER["PHP_SELF"], "", '', $param, '', $sortfield, $sortorder, 'right ', ''); print_liste_field_titre($arrayfields['c.assigned']['label'], $_SERVER["PHP_SELF"], "", '', $param, '', $sortfield, $sortorder, 'center ', '');
} }
// Extra fields // Extra fields
$disablesortlink = 1; $disablesortlink = 1;

View File

@ -1410,7 +1410,7 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0) {
// By User // By User
if (!empty($arrayfields['author']['checked'])) { if (!empty($arrayfields['author']['checked'])) {
print '<td class="nowrap">'; print '<td class="tdoverflowmax100">';
if ($action == 'editline' && $_GET['lineid'] == $task_time->rowid) { if ($action == 'editline' && $_GET['lineid'] == $task_time->rowid) {
if (empty($object->id)) { if (empty($object->id)) {
$object->fetch($id); $object->fetch($id);
@ -1441,7 +1441,7 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0) {
// Note // Note
if (!empty($arrayfields['t.note']['checked'])) { if (!empty($arrayfields['t.note']['checked'])) {
print '<td class="left">'; print '<td class="small">';
if ($action == 'editline' && $_GET['lineid'] == $task_time->rowid) { if ($action == 'editline' && $_GET['lineid'] == $task_time->rowid) {
print '<textarea name="timespent_note_line" width="95%" rows="'.ROWS_2.'">'.$task_time->note.'</textarea>'; print '<textarea name="timespent_note_line" width="95%" rows="'.ROWS_2.'">'.$task_time->note.'</textarea>';
} else { } else {
@ -1773,7 +1773,7 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0) {
// Note // Note
if (!empty($arrayfields['t.note']['checked'])) { if (!empty($arrayfields['t.note']['checked'])) {
print '<td class="left">'; print '<td class="small tdoverflowmax300"">';
if ($action == 'splitline' && $_GET['lineid'] == $task_time->rowid) { if ($action == 'splitline' && $_GET['lineid'] == $task_time->rowid) {
print '<textarea name="timespent_note_line_2" width="95%" rows="'.ROWS_2.'">'.$task_time->note.'</textarea>'; print '<textarea name="timespent_note_line_2" width="95%" rows="'.ROWS_2.'">'.$task_time->note.'</textarea>';
} else { } else {

View File

@ -161,6 +161,15 @@ class JsonLibTest extends PHPUnit\Framework\TestCase
$this->savlangs=$langs; $this->savlangs=$langs;
$this->savdb=$db; $this->savdb=$db;
// Try to decode a string encoded with serialize
$encoded = 'a:1:{s:7:"options";a:3:{s:3:"app";s:11:"Application";s:6:"system";s:6:"System";s:6:"option";s:6:"Option";}}';
$decoded=json_decode($encoded, true);
$this->assertEquals(null, $decoded, 'test to json_decode() a string that was encoded with serialize()');
$encoded = 'rubishstring!aa{bcd';
$decoded=json_decode($encoded, true);
$this->assertEquals(null, $decoded, 'test to json_decode() a string that was encoded with serialize()');
// Do a test with an array starting with 0 // Do a test with an array starting with 0
$arraytotest=array(0=>array('key'=>1,'value'=>'PRODREF','label'=>'Product ref with é and special chars \\ \' "')); $arraytotest=array(0=>array('key'=>1,'value'=>'PRODREF','label'=>'Product ref with é and special chars \\ \' "'));
$arrayencodedexpected='[{"key":1,"value":"PRODREF","label":"Product ref with \u00e9 and special chars \\\\ \' \""}]'; $arrayencodedexpected='[{"key":1,"value":"PRODREF","label":"Product ref with \u00e9 and special chars \\\\ \' \""}]';