diff --git a/htdocs/api/class/api_setup.class.php b/htdocs/api/class/api_setup.class.php index 1f59762c865..f5f301e9c16 100644 --- a/htdocs/api/class/api_setup.class.php +++ b/htdocs/api/class/api_setup.class.php @@ -1013,7 +1013,7 @@ class Setup extends DolibarrApi $list[$tab->elementtype][$tab->name]['computed'] = $tab->fieldcomputed; $list[$tab->elementtype][$tab->name]['unique'] = $tab->fieldunique; $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]['alwayseditable'] = $tab->alwayseditable; $list[$tab->elementtype][$tab->name]['perms'] = $tab->perms; diff --git a/htdocs/blockedlog/class/blockedlog.class.php b/htdocs/blockedlog/class/blockedlog.class.php index 366d7042d77..112456480e1 100644 --- a/htdocs/blockedlog/class/blockedlog.class.php +++ b/htdocs/blockedlog/class/blockedlog.class.php @@ -777,10 +777,8 @@ class BlockedLog public function dolDecodeBlockedData($data, $mode = 0) { try { - //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); } catch (Exception $e) { //print $e->getErrs); } diff --git a/htdocs/compta/bank/treso.php b/htdocs/compta/bank/treso.php index 6ccd953a68b..d9b54ad1c3d 100644 --- a/htdocs/compta/bank/treso.php +++ b/htdocs/compta/bank/treso.php @@ -163,8 +163,8 @@ if (GETPOST("account") || GETPOST("ref")) { $sqls[] = $sql; // 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 .= ", cs.fk_account"; + $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 .= " 0 as socid, 'noname' as name, 0 as fournisseur"; $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 .= " WHERE cs.entity = ".$conf->entity; @@ -188,7 +188,18 @@ if (GETPOST("account") || GETPOST("ref")) { $resql = $db->query($sql); if ($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); } $db->free($resql); @@ -201,15 +212,6 @@ if (GETPOST("account") || GETPOST("ref")) { if (!$error) { 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); $i = 0; diff --git a/htdocs/compta/facture/card.php b/htdocs/compta/facture/card.php index 1f6a03ca351..d2c6a9bd643 100644 --- a/htdocs/compta/facture/card.php +++ b/htdocs/compta/facture/card.php @@ -3296,11 +3296,11 @@ if ($action == 'create') { if (is_array($facids)) { foreach ($facids as $facparam) { $options .= ''; } } diff --git a/htdocs/compta/facture/class/facture.class.php b/htdocs/compta/facture/class/facture.class.php index fab10da3751..735f2877184 100644 --- a/htdocs/compta/facture/class/facture.class.php +++ b/htdocs/compta/facture/class/facture.class.php @@ -4090,8 +4090,8 @@ class Facture extends CommonInvoice * Invoices matching the following rules are returned: * (Status validated or abandonned for a reason 'other') + not payed + no payment at all + not already replaced * - * @param int $socid Id thirdparty - * @return array|int Array of invoices ('id'=>id, 'ref'=>ref, 'status'=>status, 'paymentornot'=>0/1) + * @param int $socid Id thirdparty + * @return array|int Array of invoices ('id'=>id, 'ref'=>ref, 'status'=>status, 'paymentornot'=>0/1) */ public function list_replacable_invoices($socid = 0) { @@ -4100,28 +4100,34 @@ class Facture extends CommonInvoice $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 .= ", SUM(pf.amount) as alreadypaid"; $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."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 .= " AND f.entity IN (".getEntity('invoice').")"; - $sql .= " AND f.paye = 0"; // Pas classee payee completement - $sql .= " AND pf.fk_paiement IS NULL"; // Aucun paiement deja fait - $sql .= " AND ff.fk_statut IS NULL"; // Renvoi vrai si pas facture de remplacement + $sql .= " AND f.paye = 0"; // Not paid completely + $sql .= " AND pf.fk_paiement IS NULL"; // No payment already done + $sql .= " AND ff.fk_statut IS NULL"; // Return true if it is not a replacement invoice if ($socid > 0) { $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"; dol_syslog(get_class($this)."::list_replacable_invoices", LOG_DEBUG); $resql = $this->db->query($sql); if ($resql) { while ($obj = $this->db->fetch_object($resql)) { - $return[$obj->rowid] = array('id' => $obj->rowid, - 'ref' => $obj->ref, - 'status' => $obj->fk_statut); + $return[$obj->rowid] = array( + 'id' => $obj->rowid, + 'ref' => $obj->ref, + 'status' => $obj->status, + 'paid' => $obj->paid, + 'alreadypaid' => 0 + ); } //print_r($return); return $return; diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index ec9449eba8f..5467490ea0e 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -8167,15 +8167,6 @@ abstract class CommonObject } else { $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)) { // $this->{$field} may be null, '', 0, '0', 123, '123' if ((isset($this->{$field}) && $this->{$field} != '') || !empty($info['notnull'])) { @@ -8236,16 +8227,6 @@ abstract class CommonObject } else { $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)) { if ($field == 'rowid') { $this->id = (int) $obj->{$field}; diff --git a/htdocs/core/class/extrafields.class.php b/htdocs/core/class/extrafields.class.php index b4d7f1a74df..54d812aeafb 100644 --- a/htdocs/core/class/extrafields.class.php +++ b/htdocs/core/class/extrafields.class.php @@ -936,7 +936,7 @@ class ExtraFields $this->attribute_computed[$tab->name] = $tab->fieldcomputed; $this->attribute_unique[$tab->name] = $tab->fieldunique; $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_alwayseditable[$tab->name] = $tab->alwayseditable; $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]['unique'][$tab->name] = $tab->fieldunique; $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]['alwayseditable'][$tab->name] = $tab->alwayseditable; $this->attributes[$tab->elementtype]['perms'][$tab->name] = (strlen($tab->perms) == 0 ? 1 : $tab->perms); diff --git a/htdocs/core/commonfieldsinexport.inc.php b/htdocs/core/commonfieldsinexport.inc.php index a02a21afdd6..3b201e4f10a 100644 --- a/htdocs/core/commonfieldsinexport.inc.php +++ b/htdocs/core/commonfieldsinexport.inc.php @@ -37,7 +37,7 @@ if (class_exists($keyforclass)) { /* * case 'sellist': * $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'])) { * $tmpkeys=array_keys($tmpparam['options']); * $tmp=array_shift($tmpkeys); diff --git a/htdocs/core/extrafieldsinexport.inc.php b/htdocs/core/extrafieldsinexport.inc.php index 861ef142c25..70dd0077e57 100644 --- a/htdocs/core/extrafieldsinexport.inc.php +++ b/htdocs/core/extrafieldsinexport.inc.php @@ -39,7 +39,7 @@ if ($resql) { // This can fail when class is used on old database (during mig case 'checkbox': case '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'])) { $typeFilter = "Select:".$obj->param; } @@ -47,7 +47,7 @@ if ($resql) { // This can fail when class is used on old database (during mig break; case 'sellist': $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'])) { $tmpkeys = array_keys($tmpparam['options']); $tmp = array_shift($tmpkeys); diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 87a4b966056..28c553d747c 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -993,7 +993,7 @@ function dol_buildpath($path, $type = 0, $returnemptyifnotfound = 0) function dol_clone($object, $native = 0) { 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 { $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 = '') { + /* global $conf; - /*if (!empty($conf->dol_no_mouse_hover)) { + if (!empty($conf->dol_no_mouse_hover)) { $showonlyonhover = 0; }*/ @@ -10315,3 +10316,20 @@ function showValueWithClipboardCPButton($valuetocopy, $showonlyonhover = 1, $tex 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; +} diff --git a/htdocs/core/lib/project.lib.php b/htdocs/core/lib/project.lib.php index 1ba9e0e3d1c..26d66ceae23 100644 --- a/htdocs/core/lib/project.lib.php +++ b/htdocs/core/lib/project.lib.php @@ -849,7 +849,7 @@ function projectLinesa(&$inc, $parent, &$lines, &$level, $var, $showproject, &$t // Contacts of task if (count($arrayfields) > 0 && !empty($arrayfields['c.assigned']['checked'])) { - print ''; + print ''; foreach (array('internal', 'external') as $source) { $tab = $lines[$i]->liste_contact(-1, $source); $num = count($tab); diff --git a/htdocs/core/modules/export/export_csv.modules.php b/htdocs/core/modules/export/export_csv.modules.php index 2d15f3999d0..88ae937bb6d 100644 --- a/htdocs/core/modules/export/export_csv.modules.php +++ b/htdocs/core/modules/export/export_csv.modules.php @@ -277,8 +277,8 @@ class ExportCsv extends ModeleExports $newvalue = $this->csvClean($newvalue, $outputlangs->charset_output); - if (preg_match('/^Select:/i', $typefield, $reg) && $typefield = substr($typefield, 7)) { - $array = unserialize($typefield); + if (preg_match('/^Select:/i', $typefield) && $typefield = substr($typefield, 7)) { + $array = json_decode($typefield, true); $array = $array['options']; $newvalue = $array[$newvalue]; } diff --git a/htdocs/core/modules/export/export_excel2007.modules.php b/htdocs/core/modules/export/export_excel2007.modules.php index 370fc49df7e..54842ff8278 100644 --- a/htdocs/core/modules/export/export_excel2007.modules.php +++ b/htdocs/core/modules/export/export_excel2007.modules.php @@ -315,8 +315,8 @@ class ExportExcel2007 extends ModeleExports $newvalue = $this->excel_clean($newvalue); $typefield = isset($array_types[$code]) ? $array_types[$code] : ''; - if (preg_match('/^Select:/i', $typefield, $reg) && $typefield = substr($typefield, 7)) { - $array = unserialize($typefield); + if (preg_match('/^Select:/i', $typefield) && $typefield = substr($typefield, 7)) { + $array = json_decode($typefield, true); $array = $array['options']; $newvalue = $array[$newvalue]; } diff --git a/htdocs/core/modules/export/export_tsv.modules.php b/htdocs/core/modules/export/export_tsv.modules.php index c93787a762c..7718dd3e350 100644 --- a/htdocs/core/modules/export/export_tsv.modules.php +++ b/htdocs/core/modules/export/export_tsv.modules.php @@ -252,8 +252,8 @@ class ExportTsv extends ModeleExports $newvalue = $this->tsv_clean($newvalue, $outputlangs->charset_output); - if (preg_match('/^Select:/i', $typefield, $reg) && $typefield = substr($typefield, 7)) { - $array = unserialize($typefield); + if (preg_match('/^Select:/i', $typefield) && $typefield = substr($typefield, 7)) { + $array = json_decode($typefield, true); $array = $array['options']; $newvalue = $array[$newvalue]; } diff --git a/htdocs/core/modules/import/import_csv.modules.php b/htdocs/core/modules/import/import_csv.modules.php index 1768029b97e..6bec94d6130 100644 --- a/htdocs/core/modules/import/import_csv.modules.php +++ b/htdocs/core/modules/import/import_csv.modules.php @@ -623,6 +623,12 @@ class ImportCsv extends ModeleImports } } elseif ($objimport->array_import_convertvalue[0][$val]['rule'] == 'numeric') { $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.'
'; diff --git a/htdocs/core/modules/import/import_xlsx.modules.php b/htdocs/core/modules/import/import_xlsx.modules.php index d90a52755e3..0378180475d 100644 --- a/htdocs/core/modules/import/import_xlsx.modules.php +++ b/htdocs/core/modules/import/import_xlsx.modules.php @@ -664,6 +664,12 @@ class ImportXlsx extends ModeleImports } } elseif ($objimport->array_import_convertvalue[0][$val]['rule'] == 'numeric') { $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.'
'; diff --git a/htdocs/core/modules/modAccounting.class.php b/htdocs/core/modules/modAccounting.class.php index 21618c56bc9..d6127f65b83 100644 --- a/htdocs/core/modules/modAccounting.class.php +++ b/htdocs/core/modules/modAccounting.class.php @@ -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_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( 'b.piece_num'=>'123 (!!! use next value not already used)', 'b.doc_date'=>dol_print_date(dol_now(), "%Y-%m-%d"), @@ -350,6 +354,8 @@ class modAccounting extends DolibarrModules 'b.sens'=>'rule-computeSens' ); // aliastable.field => ('user->id' or 'lastrowid-'.tableparent) $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.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_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( + '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.fk_accounting_category'=>array('rule'=>'fetchidfromcodeorlabel', 'classfile'=>'/accountancy/class/accountancycategory.class.php', 'class'=>'AccountancyCategory', 'method'=>'fetch', 'dict'=>'DictionaryAccountancyCategory'), ); diff --git a/htdocs/core/modules/modFournisseur.class.php b/htdocs/core/modules/modFournisseur.class.php index 41107d5c34a..5d71a5abdc8 100644 --- a/htdocs/core/modules/modFournisseur.class.php +++ b/htdocs/core/modules/modFournisseur.class.php @@ -285,7 +285,7 @@ class modFournisseur extends DolibarrModules $r++; $this->export_code[$r] = $this->rights_class.'_'.$r; $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_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', @@ -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 // 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.")"; - $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 = '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'])) { - $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'; - } - } + $keyforselect = 'facture_fourn'; + $keyforelement = 'invoice'; + $keyforaliasextra = 'extra'; + include DOL_DOCUMENT_ROOT.'/core/extrafieldsinexport.inc.php'; + $keyforselect = 'facture_fourn_det'; + $keyforelement = 'invoice_line'; + $keyforaliasextra = 'extraline'; + include DOL_DOCUMENT_ROOT.'/core/extrafieldsinexport.inc.php'; // End add extra fields line $this->export_sql_start[$r] = 'SELECT DISTINCT '; $this->export_sql_end[$r] = ' FROM '.MAIN_DB_PREFIX.'societe as s'; @@ -426,7 +359,7 @@ class modFournisseur extends DolibarrModules $r++; $this->export_code[$r] = $this->rights_class.'_'.$r; $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_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', @@ -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'); $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 - $sql = "SELECT name, label, type, param FROM ".MAIN_DB_PREFIX."extrafields WHERE elementtype = 'facture_fourn' 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 = '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'; - } - } + $keyforselect = 'facture_fourn'; + $keyforelement = 'invoice'; + $keyforaliasextra = 'extra'; + include DOL_DOCUMENT_ROOT.'/core/extrafieldsinexport.inc.php'; // End add extra fields object $this->export_sql_start[$r] = 'SELECT DISTINCT '; $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 // 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.")"; - $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 = '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'; - } - } + $keyforselect = 'commande_fournisseur'; + $keyforelement = 'order'; + $keyforaliasextra = 'extra'; + include DOL_DOCUMENT_ROOT.'/core/extrafieldsinexport.inc.php'; // End add extra fields object // 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.")"; - $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'])) { - $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'; - } - } + $keyforselect = 'commande_fournisseurdet'; + $keyforelement = 'order_line'; + $keyforaliasextra = 'extraline'; + include DOL_DOCUMENT_ROOT.'/core/extrafieldsinexport.inc.php'; // End add extra fields line $this->export_sql_start[$r] = 'SELECT DISTINCT '; $this->export_sql_end[$r] = ' FROM '.MAIN_DB_PREFIX.'societe as s'; diff --git a/htdocs/core/modules/modProduct.class.php b/htdocs/core/modules/modProduct.class.php index 3459973a699..37cda4b7b30 100644 --- a/htdocs/core/modules/modProduct.class.php +++ b/htdocs/core/modules/modProduct.class.php @@ -572,7 +572,13 @@ class modProduct extends DolibarrModules 'class' => 'CProductNature', 'method' => 'fetch', '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( diff --git a/htdocs/core/tpl/objectline_edit.tpl.php b/htdocs/core/tpl/objectline_edit.tpl.php index 6138bcecc1a..9094daaa2d1 100644 --- a/htdocs/core/tpl/objectline_edit.tpl.php +++ b/htdocs/core/tpl/objectline_edit.tpl.php @@ -130,8 +130,16 @@ $coldisplay++; $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 - if ($line->fk_prev_id == null) { + if (!$situationinvoicelinewithparent) { // editor wysiwyg require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php'; $nbrows = ROWS_2; @@ -181,7 +189,7 @@ $coldisplay++; } $coldisplay++; - if ($line->fk_prev_id == null) { + if (!$situationinvoicelinewithparent) { print ''.$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).''; } else { print '%'; @@ -189,7 +197,7 @@ $coldisplay++; $coldisplay++; print 'fk_prev_id != null) { + if ($situationinvoicelinewithparent) { print ' readonly'; } print '>'; @@ -211,12 +219,12 @@ $coldisplay++; 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 // 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;"')." "; print 'fk_prev_id != null) { + if ($situationinvoicelinewithparent) { // Do not allow editing during a situation cycle print ' readonly'; } print '>'; @@ -249,7 +257,7 @@ $coldisplay++; info_bits & 2) != 2) { print 'fk_prev_id != null) { + if ($situationinvoicelinewithparent) { print ' readonly'; } print '>%'; diff --git a/htdocs/install/mysql/tables/llx_oauth_token.sql b/htdocs/install/mysql/tables/llx_oauth_token.sql index 7674f7f3455..62542d13401 100644 --- a/htdocs/install/mysql/tables/llx_oauth_token.sql +++ b/htdocs/install/mysql/tables/llx_oauth_token.sql @@ -18,8 +18,8 @@ CREATE TABLE llx_oauth_token ( rowid integer AUTO_INCREMENT PRIMARY 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 - 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"} + token text, -- token in serialize format, of an object StdOAuth2Token of library phpoauth2. Deprecated, use tokenstring instead. + 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_user integer, -- Id of user in llx_user fk_adherent integer, -- Id of member in llx_adherent diff --git a/htdocs/projet/tasks.php b/htdocs/projet/tasks.php index 9de05d67e29..d4b5bf89bbf 100644 --- a/htdocs/projet/tasks.php +++ b/htdocs/projet/tasks.php @@ -902,7 +902,7 @@ if ($action == 'create' && $user->rights->projet->creer && (empty($object->third } */ 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 $disablesortlink = 1; diff --git a/htdocs/projet/tasks/time.php b/htdocs/projet/tasks/time.php index a9316bcedcd..bbe9671faf3 100644 --- a/htdocs/projet/tasks/time.php +++ b/htdocs/projet/tasks/time.php @@ -1410,7 +1410,7 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0) { // By User if (!empty($arrayfields['author']['checked'])) { - print ''; + print ''; if ($action == 'editline' && $_GET['lineid'] == $task_time->rowid) { if (empty($object->id)) { $object->fetch($id); @@ -1441,7 +1441,7 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0) { // Note if (!empty($arrayfields['t.note']['checked'])) { - print ''; + print ''; if ($action == 'editline' && $_GET['lineid'] == $task_time->rowid) { print ''; } else { @@ -1773,7 +1773,7 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0) { // Note if (!empty($arrayfields['t.note']['checked'])) { - print ''; + print ''; if ($action == 'splitline' && $_GET['lineid'] == $task_time->rowid) { print ''; } else { diff --git a/test/phpunit/JsonLibTest.php b/test/phpunit/JsonLibTest.php index ddb62a90204..a8619ae08c5 100644 --- a/test/phpunit/JsonLibTest.php +++ b/test/phpunit/JsonLibTest.php @@ -161,6 +161,15 @@ class JsonLibTest extends PHPUnit\Framework\TestCase $this->savlangs=$langs; $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 $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 \\\\ \' \""}]';