diff --git a/htdocs/bom/class/bom.class.php b/htdocs/bom/class/bom.class.php index 524fd5c0f93..be4e9eed510 100644 --- a/htdocs/bom/class/bom.class.php +++ b/htdocs/bom/class/bom.class.php @@ -95,7 +95,7 @@ class BOM extends CommonObject 'fk_product' => array('type'=>'integer:Product:product/class/product.class.php:1:(finished IS NULL or finished <> 0)', 'label'=>'Product', 'enabled'=>1, 'visible'=>1, 'position'=>35, 'notnull'=>1, 'index'=>1, 'help'=>'ProductBOMHelp'), 'qty' => array('type'=>'real', 'label'=>'Quantity', 'enabled'=>1, 'visible'=>1, 'default'=>1, 'position'=>55, 'notnull'=>1, 'isameasure'=>'1', 'css'=>'maxwidth75imp'), 'efficiency' => array('type'=>'real', 'label'=>'ManufacturingEfficiency', 'enabled'=>1, 'visible'=>-1, 'default'=>1, 'position'=>100, 'notnull'=>0, 'css'=>'maxwidth50imp', 'help'=>'ValueOfMeansLoss'), - 'duration' => array('type'=>'real', 'label'=>'EstimatedDuration', 'enabled'=>1, 'visible'=>-1, 'position'=>101, 'notnull'=>-1, 'css'=>'maxwidth50imp', 'help'=>'EstimatedDurationDesc'), + 'duration' => array('type'=>'duration', 'label'=>'EstimatedDuration', 'enabled'=>1, 'visible'=>-1, 'position'=>101, 'notnull'=>-1, 'css'=>'maxwidth50imp', 'help'=>'EstimatedDurationDesc'), 'fk_warehouse' => array('type'=>'integer:Entrepot:product/stock/class/entrepot.class.php:0', 'label'=>'WarehouseForProduction', 'enabled'=>1, 'visible'=>-1, 'position'=>102), 'note_public' => array('type'=>'html', 'label'=>'NotePublic', 'enabled'=>1, 'visible'=>-2, 'position'=>161, 'notnull'=>-1,), 'note_private' => array('type'=>'html', 'label'=>'NotePrivate', 'enabled'=>1, 'visible'=>-2, 'position'=>162, 'notnull'=>-1,), diff --git a/htdocs/core/actions_addupdatedelete.inc.php b/htdocs/core/actions_addupdatedelete.inc.php index 45fe792c81a..a24274b81af 100644 --- a/htdocs/core/actions_addupdatedelete.inc.php +++ b/htdocs/core/actions_addupdatedelete.inc.php @@ -1,5 +1,5 @@ +/* Copyright (C) 2017-2019 Laurent Destailleur * * 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 @@ -49,15 +49,24 @@ if ($action == 'add' && ! empty($permissiontoadd)) { foreach ($object->fields as $key => $val) { - if (in_array($key, array('rowid', 'entity', 'date_creation', 'tms', 'fk_user_creat', 'fk_user_modif', 'import_key'))) continue; // Ignore special fields + if ($object->fields[$key]['type'] == 'duration') { + if (GETPOST($key.'hour') == '' && GETPOST($key.'min') == '') continue; // The field was not submited to be edited + } + else { + if (!GETPOSTISSET($key)) continue; // The field was not submited to be edited + } + // Ignore special fields + if (in_array($key, array('rowid', 'entity', 'date_creation', 'tms', 'fk_user_creat', 'fk_user_modif', 'import_key'))) continue; // Set value to insert if (in_array($object->fields[$key]['type'], array('text', 'html'))) { $value = GETPOST($key, 'none'); - } elseif ($object->fields[$key]['type']=='date') { + } elseif ($object->fields[$key]['type'] == 'date') { $value = dol_mktime(12, 0, 0, GETPOST($key.'month', 'int'), GETPOST($key.'day', 'int'), GETPOST($key.'year', 'int')); - } elseif ($object->fields[$key]['type']=='datetime') { + } elseif ($object->fields[$key]['type'] == 'datetime') { $value = dol_mktime(GETPOST($key.'hour', 'int'), GETPOST($key.'min', 'int'), 0, GETPOST($key.'month', 'int'), GETPOST($key.'day', 'int'), GETPOST($key.'year', 'int')); + } elseif ($object->fields[$key]['type'] == 'duration') { + $value = 60*60*GETPOST($key.'hour', 'int') + 60*GETPOST($key.'min', 'int'); } elseif (preg_match('/^(integer|price|real|double)/', $object->fields[$key]['type'])) { $value = price2num(GETPOST($key, 'none')); // To fix decimal separator according to lang setup } else { @@ -108,8 +117,16 @@ if ($action == 'update' && !empty($permissiontoadd)) { foreach ($object->fields as $key => $val) { - if (!GETPOSTISSET($key)) continue; // The field was not submited to be edited - if (in_array($key, array('rowid', 'entity', 'date_creation', 'tms', 'fk_user_creat', 'fk_user_modif', 'import_key'))) continue; // Ignore special fields + // Check if field was submited to be edited + if ($object->fields[$key]['type'] == 'duration') { + if (!GETPOSTISSET($key.'hour') || !GETPOSTISSET($key.'min')) continue; // The field was not submited to be edited + } + else { + if (!GETPOSTISSET($key)) continue; // The field was not submited to be edited + } + // Ignore special fields + if (in_array($key, array('rowid', 'entity', 'date_creation', 'tms', 'fk_user_creat', 'fk_user_modif', 'import_key'))) continue; + // Set value to update if (in_array($object->fields[$key]['type'], array('text', 'html'))) { $value = GETPOST($key, 'none'); @@ -117,6 +134,12 @@ if ($action == 'update' && !empty($permissiontoadd)) $value = dol_mktime(12, 0, 0, GETPOST($key.'month'), GETPOST($key.'day'), GETPOST($key.'year')); } elseif ($object->fields[$key]['type'] == 'datetime') { $value = dol_mktime(GETPOST($key.'hour'), GETPOST($key.'min'), 0, GETPOST($key.'month'), GETPOST($key.'day'), GETPOST($key.'year')); + } elseif ($object->fields[$key]['type'] == 'duration') { + if (GETPOST($key.'hour', 'int') != '' || GETPOST($key.'min', 'int') != '') { + $value = 60*60*GETPOST($key.'hour', 'int') + 60*GETPOST($key.'min', 'int'); + } else { + $value = ''; + } } elseif (in_array($object->fields[$key]['type'], array('price', 'real'))) { $value = price2num(GETPOST($key)); } else { diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index a70cf20503a..1ce1eca120f 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -5626,14 +5626,12 @@ abstract class CommonObject $objectid = $this->id; - if ($computed) { if (!preg_match('/^search_/', $keyprefix)) return ''.$langs->trans("AutomaticallyCalculated").''; else return ''; } - // Set value of $morecss. For this, we use in priority showsize from parameters, then $val['css'] then autodefine if (empty($morecss) && !empty($val['css'])) { @@ -5689,6 +5687,10 @@ abstract class CommonObject // TODO Must also support $moreparam $out = $form->selectDate($value, $keyprefix.$key.$keysuffix, $showtime, $showtime, $required, '', 1, (($keyprefix != 'search_' && $keyprefix != 'search_options_') ? 1 : 0), 0, 1); } + elseif (in_array($type, array('duration'))) + { + $out=$form->select_duration($keyprefix.$key.$keysuffix, $value, 0, 'text', 0, 1); + } elseif (in_array($type, array('int', 'integer'))) { $tmp = explode(',', $size); @@ -6239,7 +6241,6 @@ abstract class CommonObject $type = 'sellist'; } - $langfile = $val['langfile']; $list = $val['list']; $help = $val['help']; @@ -6313,9 +6314,16 @@ abstract class CommonObject $value = ''; } } + elseif ($type == 'duration') + { + include_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php'; + if (! is_null($value) && $value !== '') { + $value = convertSecondToTime($value, 'allhourmin'); + } + } elseif ($type == 'double' || $type == 'real') { - if (!empty($value)) { + if (! is_null($value) && $value !== '') { $value = price($value); } } @@ -6341,7 +6349,9 @@ abstract class CommonObject } elseif ($type == 'price') { - $value = price($value, 0, $langs, 0, 0, -1, $conf->currency); + if (! is_null($value) && $value !== '') { + $value = price($value, 0, $langs, 0, 0, -1, $conf->currency); + } } elseif ($type == 'select') { @@ -6733,7 +6743,7 @@ abstract class CommonObject $out .= ''; $html_id = !empty($this->id) ? $this->element.'_extras_'.$key.'_'.$this->id : ''; - + $out .= ''; switch ($mode) { @@ -7181,6 +7191,22 @@ abstract class CommonObject return false; } + /** + * Function test if type is duration + * + * @param array $info content informations of field + * @return bool true if field of type duration + */ + public function isDuration($info) + { + if (is_array($info)) + { + if (isset($info['type']) && ($info['type'] == 'duration')) return true; + else return false; + } + else return false; + } + /** * Function test if type is integer * @@ -7315,27 +7341,32 @@ abstract class CommonObject $queryarray[$field] = null; } } - elseif ($this->isInt($info)) + elseif ($this->isDuration($info)) + { + // $this->{$field} may be null, '', 0, '0', 123, '123' + if ($this->{$field} != '' || !empty($info['notnull'])) $queryarray[$field] = (int) $this->{$field}; // If '0', it may be set to null later if $info['notnull'] == -1 + else $queryarray[$field] = null; + } + elseif ($this->isInt($info) || $this->isFloat($info)) { if ($field == 'entity' && is_null($this->{$field})) $queryarray[$field] = $conf->entity; else { - $queryarray[$field] = (int) $this->{$field}; - if (empty($queryarray[$field])) $queryarray[$field] = 0; // May be reset to null later if property 'notnull' is -1 for this field. + // $this->{$field} may be null, '', 0, '0', 123, '123' + if ($this->{$field} != '' || !empty($info['notnull'])) { + if ($this->isInt($info)) $queryarray[$field] = (int) $this->{$field}; // If '0', it may be set to null later if $info['notnull'] == -1 + if ($this->isFloat($info)) $queryarray[$field] = (double) $this->{$field}; // If '0', it may be set to null later if $info['notnull'] == -1 + } + else $queryarray[$field] = null; } } - elseif ($this->isFloat($info)) - { - $queryarray[$field] = (double) $this->{$field}; - if (empty($queryarray[$field])) $queryarray[$field] = 0; - } else { $queryarray[$field] = $this->{$field}; } if ($info['type'] == 'timestamp' && empty($queryarray[$field])) unset($queryarray[$field]); - if (!empty($info['notnull']) && $info['notnull'] == -1 && empty($queryarray[$field])) $queryarray[$field] = null; + if (!empty($info['notnull']) && $info['notnull'] == -1 && empty($queryarray[$field])) $queryarray[$field] = null; // May force 0 to null } return $queryarray; @@ -7378,7 +7409,11 @@ abstract class CommonObject } else { - $this->{$field} = (int) $obj->{$field}; + if (! is_null($obj->{$field}) || (isset($info['notnull']) && $info['notnull'] == 1)) { + $this->{$field} = (int) $obj->{$field}; + } else { + $this->{$field} = null; + } } } } @@ -7391,7 +7426,11 @@ abstract class CommonObject } else { - $this->{$field} = (double) $obj->{$field}; + if (! is_null($obj->{$field}) || (isset($info['notnull']) && $info['notnull'] == 1)) { + $this->{$field} = (double) $obj->{$field}; + } else { + $this->{$field} = null; + } } } else @@ -7425,7 +7464,7 @@ abstract class CommonObject protected function quote($value, $fieldsentry) { if (is_null($value)) return 'NULL'; - elseif (preg_match('/^(int|double|real)/i', $fieldsentry['type'])) return $this->db->escape("$value"); + elseif (preg_match('/^(int|double|real|price)/i', $fieldsentry['type'])) return $this->db->escape("$value"); else return "'".$this->db->escape($value)."'"; } @@ -7446,6 +7485,7 @@ abstract class CommonObject $now = dol_now(); $fieldvalues = $this->setSaveQuery(); + if (array_key_exists('date_creation', $fieldvalues) && empty($fieldvalues['date_creation'])) $fieldvalues['date_creation'] = $this->db->idate($now); if (array_key_exists('fk_user_creat', $fieldvalues) && !($fieldvalues['fk_user_creat'] > 0)) $fieldvalues['fk_user_creat'] = $user->id; unset($fieldvalues['rowid']); // The field 'rowid' is reserved field name for autoincrement field so we don't need it into insert. @@ -7467,7 +7507,7 @@ abstract class CommonObject if (!empty($this->fields[$key]['foreignkey']) && $values[$key] == '-1') $values[$key] = ''; //var_dump($key.'-'.$values[$key].'-'.($this->fields[$key]['notnull'] == 1)); - if (isset($this->fields[$key]['notnull']) && $this->fields[$key]['notnull'] == 1 && !isset($values[$key]) && is_null($val['default'])) + if (isset($this->fields[$key]['notnull']) && $this->fields[$key]['notnull'] == 1 && !isset($values[$key]) && is_null($this->fields[$key]['default'])) { $error++; $this->errors[] = $langs->trans("ErrorFieldRequired", $this->fields[$key]['label']); @@ -7678,6 +7718,7 @@ abstract class CommonObject $now = dol_now(); $fieldvalues = $this->setSaveQuery(); + if (array_key_exists('date_modification', $fieldvalues) && empty($fieldvalues['date_modification'])) $fieldvalues['date_modification'] = $this->db->idate($now); if (array_key_exists('fk_user_modif', $fieldvalues) && !($fieldvalues['fk_user_modif'] > 0)) $fieldvalues['fk_user_modif'] = $user->id; unset($fieldvalues['rowid']); // The field 'rowid' is reserved field name for autoincrement field so we don't need it into update. diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index b85ed6c5a3b..cac859c53b5 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -5749,14 +5749,14 @@ class Form /** * Function to show a form to select a duration on a page * - * @param string $prefix Prefix for input fields - * @param int $iSecond Default preselected duration (number of seconds or '') - * @param int $disabled Disable the combo box - * @param string $typehour If 'select' then input hour and input min is a combo, - * if 'text' input hour is in text and input min is a text, - * if 'textselect' input hour is in text and input min is a combo - * @param integer $minunderhours If 1, show minutes selection under the hours - * @param int $nooutput Do not output html string but return it + * @param string $prefix Prefix for input fields + * @param int $iSecond Default preselected duration (number of seconds or '') + * @param int $disabled Disable the combo box + * @param string $typehour If 'select' then input hour and input min is a combo, + * If 'text' input hour is in text and input min is a text, + * If 'textselect' input hour is in text and input min is a combo + * @param integer $minunderhours If 1, show minutes selection under the hours + * @param int $nooutput Do not output html string but return it * @return string|void */ public function select_duration($prefix, $iSecond = '', $disabled = 0, $typehour = 'select', $minunderhours = 0, $nooutput = 0) diff --git a/htdocs/core/lib/modulebuilder.lib.php b/htdocs/core/lib/modulebuilder.lib.php index 4e5cbb92c02..02a9932d474 100644 --- a/htdocs/core/lib/modulebuilder.lib.php +++ b/htdocs/core/lib/modulebuilder.lib.php @@ -63,8 +63,8 @@ function rebuildObjectClass($destdir, $module, $objectname, $newmask, $readdir = setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv("Label")), null, 'errors'); return -2; } - if (! preg_match('/^(integer|price|sellist|date|varchar|double|text|html)/', $addfieldentry['type']) - && ! preg_match('/^(boolean|real|timestamp)$/', $addfieldentry['type'])) + if (! preg_match('/^(integer|price|sellist|varchar|double|text|html|duration)/', $addfieldentry['type']) + && ! preg_match('/^(boolean|real|date|datetime|timestamp)$/', $addfieldentry['type'])) { setEventMessages($langs->trans('BadValueForType', $objectname), null, 'errors'); return -2; @@ -164,7 +164,7 @@ function rebuildObjectClass($destdir, $module, $objectname, $newmask, $readdir = if (count($object->fields)) { - $typetotypephp=array('integer'=>'integer', 'varchar'=>'string'); + //$typetotypephp=array('integer'=>'integer', 'duration'=>'integer', 'varchar'=>'string'); foreach($object->fields as $key => $val) { @@ -266,7 +266,7 @@ function rebuildObjectSql($destdir, $module, $objectname, $newmask, $readdir = ' if ($type == 'html') $type = 'text'; // html modulebuilder type is a text type in database elseif ($type == 'price') $type = 'double'; // html modulebuilder type is a text type in database - elseif ($type == 'link' || $type == 'sellist') $type = 'integer'; + elseif (in_array($type, array('link', 'sellist', 'duration'))) $type = 'integer'; $texttoinsert.= "\t".$key." ".$type; if ($key == 'rowid') $texttoinsert.= ' AUTO_INCREMENT PRIMARY KEY'; if ($key == 'entity') $texttoinsert.= ' DEFAULT 1'; diff --git a/htdocs/modulebuilder/index.php b/htdocs/modulebuilder/index.php index 68eec5513a9..a3a503e702b 100644 --- a/htdocs/modulebuilder/index.php +++ b/htdocs/modulebuilder/index.php @@ -2480,7 +2480,7 @@ elseif (! empty($module)) print '
'; print ''; print ''; - print ''; print '
'.$langs->trans("Property"); + print ''.$langs->trans("Property"); print ' ('.$langs->trans("SeeExamples").')'; print ''; diff --git a/htdocs/modulebuilder/template/class/myobject.class.php b/htdocs/modulebuilder/template/class/myobject.class.php index efb3013bd6d..bb9f8eda4e0 100644 --- a/htdocs/modulebuilder/template/class/myobject.class.php +++ b/htdocs/modulebuilder/template/class/myobject.class.php @@ -64,7 +64,7 @@ class MyObject extends CommonObject /** - * 'type' if the field format ('integer', 'integer:ObjectClass:PathToClass[:AddCreateButtonOrNot[:Filter]]', 'varchar(x)', 'double(24,8)', 'text', 'html', 'datetime', 'timestamp', 'float') + * 'type' if the field format ('integer', 'integer:ObjectClass:PathToClass[:AddCreateButtonOrNot[:Filter]]', 'varchar(x)', 'double(24,8)', 'real', 'price', 'text', 'html', 'date', 'datetime', 'timestamp', 'duration', 'mail', 'phone', 'url', 'password') * Note: Filter can be a string like "(t.ref:like:'SO-%') or (t.date_creation:<:'20160101') or (t.nature:is:NULL)" * 'label' the translation key. * 'enabled' is a condition when the field must be managed. @@ -94,7 +94,7 @@ class MyObject extends CommonObject 'ref' =>array('type'=>'varchar(128)', 'label'=>'Ref', 'enabled'=>1, 'visible'=>1, 'noteditable'=>0, 'default'=>'', 'notnull'=> 1, 'showoncombobox'=>1, 'index'=>1, 'position'=>10, 'searchall'=>1, 'comment'=>'Reference of object'), 'entity' =>array('type'=>'integer', 'label'=>'Entity', 'enabled'=>1, 'visible'=>0, 'notnull'=> 1, 'default'=>1, 'index'=>1, 'position'=>20), 'label' =>array('type'=>'varchar(255)', 'label'=>'Label', 'enabled'=>1, 'visible'=>1, 'position'=>30, 'searchall'=>1, 'css'=>'minwidth200', 'help'=>'Help text', 'showoncombobox'=>1), - 'amount' =>array('type'=>'double(24,8)', 'label'=>'Amount', 'enabled'=>1, 'visible'=>1, 'default'=>'null', 'position'=>40, 'searchall'=>0, 'isameasure'=>1, 'help'=>'Help text for amount'), + 'amount' =>array('type'=>'price', 'label'=>'Amount', 'enabled'=>1, 'visible'=>1, 'default'=>'null', 'position'=>40, 'searchall'=>0, 'isameasure'=>1, 'help'=>'Help text for amount'), 'qty' =>array('type'=>'real', 'label'=>'Qty', 'enabled'=>1, 'visible'=>1, 'default'=>'0', 'position'=>45, 'searchall'=>0, 'isameasure'=>1, 'help'=>'Help text for quantity', 'css'=>'maxwidth75imp'), 'fk_soc' =>array('type'=>'integer:Societe:societe/class/societe.class.php:1:status=1 AND entity IN (__SHARED_ENTITIES__)', 'label'=>'ThirdParty', 'visible'=> 1, 'enabled'=>1, 'position'=>50, 'notnull'=>-1, 'index'=>1, 'help'=>'LinkToThirparty'), 'fk_project' =>array('type'=>'integer:Project:projet/class/project.class.php:1', 'label'=>'Project', 'enabled'=>1, 'visible'=>-1, 'position'=>52, 'notnull'=>-1, 'index'=>1),