From dcb79e66cc9478af383ea5473c3fbb8643979893 Mon Sep 17 00:00:00 2001
From: Laurent Destailleur <eldy@destailleur.fr>
Date: Mon, 24 Jul 2017 13:55:12 +0200
Subject: [PATCH] Debug modulebuilder

---
 htdocs/core/class/commonobject.class.php      | 89 +++++++++++--------
 htdocs/langs/en_US/main.lang                  |  1 +
 htdocs/langs/en_US/modulebuilder.lang         |  3 +-
 htdocs/modulebuilder/index.php                | 36 ++++++--
 .../template/class/myobject.class.php         | 25 ++++--
 .../modulebuilder/template/myobject_card.php  |  5 +-
 .../modulebuilder/template/myobject_list.php  | 52 +++++++----
 .../template/sql/llx_myobject.sql             |  6 +-
 8 files changed, 140 insertions(+), 77 deletions(-)

diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php
index f1ec086cd03..b1b6de3eb03 100644
--- a/htdocs/core/class/commonobject.class.php
+++ b/htdocs/core/class/commonobject.class.php
@@ -4807,7 +4807,7 @@ abstract class CommonObject
 	{
 		if(is_array($info))
 		{
-			if(isset($info['type']) && $info['type']=='float') return true;
+			if (isset($info['type']) && (preg_match('/^(double|real)/i', $info['type']))) return true;
 			else return false;
 		}
 		else return false;
@@ -4846,49 +4846,58 @@ abstract class CommonObject
 	}
 
 	/**
-	 * Function to prepare the values to insert
+	 * Function to prepare the values to insert.
+	 * Note $this->${field} are set by the page that make the createCommon or the updateCommon.
 	 *
 	 * @return array
 	 */
 	private function set_save_query()
 	{
-		$query=array();
-		foreach ($this->fields as $field=>$info)
+		global $conf;
+
+		$queryarray=array();
+		foreach ($this->fields as $field=>$info)	// Loop on definition of fields
 		{
+			// Depending on field type ('datetime', ...)
 			if($this->isDate($info))
 			{
 				if(empty($this->{$field}))
 				{
-					$query[$field] = NULL;
+					$queryarray[$field] = NULL;
 				}
 				else
 				{
-					$query[$field] = $this->db->idate($this->{$field});
+					$queryarray[$field] = $this->db->idate($this->{$field});
 				}
 			}
 			else if($this->isArray($info))
 			{
-				$query[$field] = serialize($this->{$field});
+				$queryarray[$field] = serialize($this->{$field});
 			}
 			else if($this->isInt($info))
 			{
-				$query[$field] = (int) price2num($this->{$field});
+				if ($field == 'entity' && is_null($this->{$field})) $queryarray[$field]=$conf->entity;
+				else
+				{
+					$queryarray[$field] = (int) price2num($this->{$field});
+					if (empty($queryarray[$field])) $queryarray[$field]=0;		// May be rest to null later if property 'nullifempty' is on for this field.
+				}
 			}
 			else if($this->isFloat($info))
 			{
-				$query[$field] = (double) price2num($this->{$field});
-			}
-			elseif($this->isNull($info))
-			{
-				$query[$field] = (is_null($this->{$field}) || (empty($this->{$field}) && $this->{$field}!==0 && $this->{$field}!=='0') ? null : $this->{$field});
+				$queryarray[$field] = (double) price2num($this->{$field});
+				if (empty($queryarray[$field])) $queryarray[$field]=0;
 			}
 			else
 			{
-				$query[$field] = $this->{$field};
+				$queryarray[$field] = $this->{$field};
 			}
+
+			if ($info['type'] == 'timestamp' && empty($queryarray[$field])) unset($queryarray[$field]);
+			if (! empty($info['nullifempty']) && empty($queryarray[$field])) $queryarray[$field] = null;
 		}
 
-		return $query;
+		return $queryarray;
 	}
 
 	/**
@@ -4947,15 +4956,14 @@ abstract class CommonObject
 	/**
 	 * Add quote to field value if necessary
 	 *
-	 * @param string|int	$value	value to protect
-	 * @return string|int
+	 * @param 	string|int	$value			Value to protect
+	 * @param	array		$fieldsentry	Properties of field
+	 * @return 	string
 	 */
-	protected function quote($value) {
-
-	    if(is_null($value)) return 'NULL';
-	    else if(is_numeric($value)) return $value;
-	    else return "'".$this->db->escape( $value )."'";
-
+	protected function quote($value, $fieldsentry) {
+	    if (is_null($value)) return 'NULL';
+	    else if (preg_match('/^(int|double|real)/i', $fieldsentry['type'])) return $this->db->escape("$value");
+	    else return "'".$this->db->escape($value)."'";
 	}
 
 
@@ -4970,23 +4978,27 @@ abstract class CommonObject
 	{
         $error = 0;
 
-	    $fields = array_merge(array('datec'=>$this->db->idate(dol_now())), $this->set_save_query());
+        $now=dol_now();
+
+	    $fieldvalues = $this->set_save_query();
+		if (array_key_exists('date_creation', $fieldvalues) && empty($fieldvalues['date_creation'])) $fieldvalues['date_creation']=$this->db->idate($now);
 
 	    $keys=array();
 	    $values = array();
-	    foreach ($fields as $k => $v) {
+	    foreach ($fieldvalues as $k => $v) {
 	    	$keys[] = $k;
-	    	$values[] = $this->quote($v);
+	    	$values[] = $this->quote($v, $this->fields[$k]);
 	    }
 
 	    $this->db->begin();
 
 	    if (! $error)
 	    {
-    	    $sql = 'INSERT INTO '.MAIN_DB_PREFIX.$this->table_element.'
-    					( '.implode( ",", $keys ).' )
-    					VALUES ( '.implode( ",", $values ).' ) ';
-    	    $res = $this->db->query( $sql );
+    	    $sql = 'INSERT INTO '.MAIN_DB_PREFIX.$this->table_element;
+    		$sql.= ' ('.implode( ", ", $keys ).')';
+    		$sql.= ' VALUES ('.implode( ", ", $values ).')';
+
+			$res = $this->db->query( $sql );
     	    if ($res===false) {
     	        $error++;
     	        $this->errors[] = $this->db->lasterror();
@@ -5075,11 +5087,11 @@ abstract class CommonObject
 	{
 		if (empty($id) && empty($ref)) return false;
 
-		$sql = 'SELECT '.$this->get_field_list().', datec, tms';
+		$sql = 'SELECT '.$this->get_field_list().', date_creation, tms';
 		$sql.= ' FROM '.MAIN_DB_PREFIX.$this->table_element;
 
 		if(!empty($id)) $sql.= ' WHERE rowid = '.$id;
-		else  $sql.= ' WHERE ref = \''.$this->quote($ref).'\'';
+		else $sql.= " WHERE ref = ".$this->quote($ref, $this->fields['ref']);
 
 		$res = $this->db->query($sql);
 		if ($res)
@@ -5091,7 +5103,7 @@ abstract class CommonObject
         			$this->id = $id;
         			$this->set_vars_by_db($obj);
 
-        			$this->datec = $this->db->idate($obj->datec);
+        			$this->date_creation = $this->db->idate($obj->date_creation);
         			$this->tms = $this->db->idate($obj->tms);
 
         			return $this->id;
@@ -5127,27 +5139,26 @@ abstract class CommonObject
 	{
 	    $error = 0;
 
-		$fields = $this->set_save_query();
+		$fieldvalues = $this->set_save_query();
 
-		foreach ($fields as $k => $v) {
+		foreach ($fieldvalues as $k => $v) {
 			if (is_array($key)){
 				$i=array_search($k, $key);
 				if ( $i !== false) {
-					$where[] = $key[$i].'=' . $this->quote( $v ) ;
+					$where[] = $key[$i].'=' . $this->quote($v, $this->fields[$k]);
 					continue;
 				}
 			} else {
 				if ( $k == $key) {
-					$where[] = $k.'=' .$this->quote( $v ) ;
+					$where[] = $k.'=' .$this->quote($v, $this->fields[$k]);
 					continue;
 				}
 			}
-			$tmp[] = $k.'='.$this->quote($v);
+			$tmp[] = $k.'='.$this->quote($v, $this->fields[$k]);
 		}
 		$sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element.' SET '.implode( ',', $tmp ).' WHERE rowid='.$this->id ;
 
 		$this->db->begin();
-
 		if (! $error)
 		{
     		$res = $this->db->query($sql);
diff --git a/htdocs/langs/en_US/main.lang b/htdocs/langs/en_US/main.lang
index f3f9a4a1902..333943c02cc 100644
--- a/htdocs/langs/en_US/main.lang
+++ b/htdocs/langs/en_US/main.lang
@@ -792,6 +792,7 @@ HRAndBank=HR and Bank
 AutomaticallyCalculated=Automatically calculated
 TitleSetToDraft=Go back to draft
 ConfirmSetToDraft=Are you sure you want to go back to Draft status ?
+ImportId=Import id
 # Week day
 Monday=Monday
 Tuesday=Tuesday
diff --git a/htdocs/langs/en_US/modulebuilder.lang b/htdocs/langs/en_US/modulebuilder.lang
index 063e1c8d332..457b6fd3fcd 100644
--- a/htdocs/langs/en_US/modulebuilder.lang
+++ b/htdocs/langs/en_US/modulebuilder.lang
@@ -54,4 +54,5 @@ SqlFile=Sql file
 SqlFileExtraFields=Sql file for complementary attributes
 SqlFileKey=Sql file for keys
 AnObjectAlreadyExistWithThisNameAndDiffCase=An object already exists with this name and a different case
-UseAsciiDocFormat=You can use Markdown format, but it is recommanded to use Asciidoc format (Comparison between .md and .asciidoc: http://asciidoctor.org/docs/user-manual/#compared-to-markdown)
\ No newline at end of file
+UseAsciiDocFormat=You can use Markdown format, but it is recommanded to use Asciidoc format (Comparison between .md and .asciidoc: http://asciidoctor.org/docs/user-manual/#compared-to-markdown)
+IsAMeasure=Is a measure
\ No newline at end of file
diff --git a/htdocs/modulebuilder/index.php b/htdocs/modulebuilder/index.php
index 0b5c1da7039..969ed3d05ed 100644
--- a/htdocs/modulebuilder/index.php
+++ b/htdocs/modulebuilder/index.php
@@ -360,7 +360,7 @@ if ($dirins && $action == 'confirm_delete')
 
 if ($dirins && $action == 'confirm_deleteobject' && $objectname)
 {
-    if (preg_match('/\s/', $objectname))
+    if (preg_match('/[^a-z0-9]/i', $objectname))
     {
         $error++;
         setEventMessages($langs->trans("SpaceOrSpecialCharAreNotAllowed"), null, 'errors');
@@ -604,7 +604,11 @@ if ($action == 'savefile' && empty($cancel))
 // Enable module
 if ($action == 'set' && $user->admin)
 {
-	$param='module='.$module;
+	$param='';
+	if ($module) $param.='&module='.$module;
+	if ($tab)    $param.='&tab='.$tab;
+	if ($tabobj) $param.='&tabobj='.$tabobj;
+
 	$value = GETPOST('value','alpha');
 	$resarray = activateModule($value);
 	if (! empty($resarray['errors'])) setEventMessages('', $resarray['errors'], 'errors');
@@ -635,7 +639,11 @@ if ($action == 'set' && $user->admin)
 // Disable module
 if ($action == 'reset' && $user->admin)
 {
-	$param='module='.$module;
+	$param='';
+	if ($module) $param.='&module='.$module;
+	if ($tab)    $param.='&tab='.$tab;
+	if ($tabobj) $param.='&tabobj='.$tabobj;
+
 	$value = GETPOST('value','alpha');
 	$result=unActivateModule($value);
 	if ($result) setEventMessages($result, null, 'errors');
@@ -839,7 +847,11 @@ elseif (! empty($module))
         $modulelowercase=strtolower($module);
         $const_name = 'MAIN_MODULE_'.strtoupper($module);
 
-        $param='&tab='.$tab.'&module='.$module;
+        $param='';
+        if ($tab) $param.= '&tab='.$tab;
+        if ($module) $param.='&module='.$module;
+        if ($tabobj) $param.='&tabobj='.$tabobj;
+
         $urltomodulesetup='<a href="'.DOL_URL_ROOT.'/admin/modules.php?search_keyword='.urlencode($module).'">'.$langs->trans('Home').'-'.$langs->trans("Setup").'-'.$langs->trans("Modules").'</a>';
         $linktoenabledisable='';
         if (! empty($conf->global->$const_name))	// If module is already activated
@@ -1240,9 +1252,10 @@ elseif (! empty($module))
                         print '<td class="center">'.$langs->trans("NotNull").'</td>';
                         //print '<td>'.$langs->trans("DefaultValue").'</td>';
                         print '<td class="center">'.$langs->trans("DatabaseIndex").'</td>';
+                        print '<td class="right">'.$langs->trans("Position").'</td>';
                         print '<td class="right">'.$langs->trans("Enabled").'</td>';
                         print '<td class="right">'.$langs->trans("Visible").'</td>';
-                        print '<td class="right">'.$langs->trans("Position").'</td>';
+                        print '<td class="right">'.$langs->trans("IsAMeasure").'</td>';
                         print '<td class="center">'.$langs->trans("SearchAll").'</td>';
                         print '<td>'.$langs->trans("Comment").'</td>';
                         print '<td></td>';
@@ -1254,9 +1267,10 @@ elseif (! empty($module))
                         print '<td class="center"><input class="text" size="2" name="propnotnull" value=""></td>';
                         //print '<td><input class="text" name="propdefault" value=""></td>';
                         print '<td class="center"><input class="text" size="2" name="propindex" value=""></td>';
+                        print '<td class="right"><input class="text right" size="2" name="propposition" value=""></td>';
                         print '<td class="center"><input class="text" size="2" name="propenabled" value=""></td>';
                         print '<td class="center"><input class="text" size="2" name="propvisible" value=""></td>';
-                        print '<td class="right"><input class="text right" size="2" name="propposition" value=""></td>';
+                        print '<td class="center"><input class="text" size="2" name="propisameasure" value=""></td>';
                         print '<td class="center"><input class="text" size="2" name="propsearchall" value=""></td>';
                         print '<td><input class="text" name="propcomment" value=""></td>';
                         print '<td align="center">';
@@ -1284,13 +1298,14 @@ elseif (! empty($module))
                             $propname=$propkey;
                             $proplabel=$propval['label'];
                             $proptype=$propval['type'];
-                            $propposition=$propval['position'];
                             $propnotnull=$propval['notnull'];
                             $propsearchall=$propval['searchall'];
                             //$propdefault=$propval['default'];
                             $propindex=$propval['index'];
+                            $propposition=$propval['position'];
                             $propenabled=$propval['enabled'];
                             $propvisible=$propval['visible'];
+                            $propisameasure=$propval['isameasure'];
                             $propcomment=$propval['comment'];
 
                             print '<tr class="oddeven">';
@@ -1313,14 +1328,17 @@ elseif (! empty($module))
                             print '<td class="center">';
                             print $propindex?'X':'';
                             print '</td>';
+                            print '<td align="right">';
+                            print $propposition;
+                            print '</td>';
                             print '<td class="center">';
                             print $propenabled?$propenabled:'';
                             print '</td>';
                             print '<td class="center">';
                             print $propvisible?$propvisible:'';
                             print '</td>';
-                            print '<td align="right">';
-                            print $propposition;
+                            print '<td class="center">';
+                            print $propisameasure?$propisameasure:'';
                             print '</td>';
                             print '<td class="center">';
                             print $propsearchall?'X':'';
diff --git a/htdocs/modulebuilder/template/class/myobject.class.php b/htdocs/modulebuilder/template/class/myobject.class.php
index a371d5fad8a..75540df892e 100644
--- a/htdocs/modulebuilder/template/class/myobject.class.php
+++ b/htdocs/modulebuilder/template/class/myobject.class.php
@@ -58,17 +58,30 @@ class MyObject extends CommonObject
 	public $picto = 'myobject';
 
 
+	/*
+	 *             'type' if the field format, 'label' the translation key, 'enabled' is a condition when the filed must be managed,
+	 *             'visible' says if field is visible in list (-1 means not shown by default but can be aded into list to be viewed)
+	 *             'notnull' if not null in database
+	 *             'index' if we want an index in database
+	 *             'position' is the sort order of field
+	 *             'searchall' is 1 if we want to search in this field when making a search from the quick search button
+	 *             'isameasure' must be set to 1 if you want to have a total on list for this field. Field type must be summable like integer or double(24,8).
+	 *             'comment' is not used. You can store here any text of your choice.
+	 */
+
 	// BEGIN MODULEBUILDER PROPERTIES
 	/**
      * @var array  Array with all fields and their property
      */
 	public $fields=array(
-	    'ref'   =>array('type'=>'varchar(64)',  'label'=>'Ref',              'enabled'=>1, 'visible'=>1,  'notnull'=>true, 'index'=>true, 'visible'=>1, 'position'=>10, 'searchall'=>1, 'comment'=>'Reference of object'),
-	    'entity'=>array('type'=>'integer',      'label'=>'Entity',           'enabled'=>1, 'visible'=>0,  'notnull'=>true, 'index'=>true, 'visible'=>0, 'position'=>20),
-	    'label' =>array('type'=>'varchar(255)', 'label'=>'Label',            'enabled'=>1, 'visible'=>1,  'position'=>30,  'visible'=>1, 'searchall'=>1),
-	    'datec' =>array('type'=>'datetime',     'label'=>'DateCreation',     'enabled'=>1, 'visible'=>-1, 'notnull'=>true, 'visible'=>-1, 'position'=>500),
-	    'tms'   =>array('type'=>'timestamp',    'label'=>'DateModification', 'enabled'=>1, 'visible'=>-1, 'notnull'=>true, 'visible'=>-1, 'position'=>500),
-	    'status'=>array('type'=>'integer',      'label'=>'Status',           'enabled'=>1, 'visible'=>1,  'index'=>true,   'visible'=>1, 'position'=>1000),
+	    'ref'           =>array('type'=>'varchar(64)',  'label'=>'Ref',              'enabled'=>1, 'visible'=>1,  'notnull'=>true, 'index'=>true, 'position'=>10, 'searchall'=>1, 'comment'=>'Reference of object'),
+	    'entity'        =>array('type'=>'integer',      'label'=>'Entity',           'enabled'=>1, 'visible'=>0,  'notnull'=>true, 'index'=>true, 'position'=>20),
+	    'label'         =>array('type'=>'varchar(255)', 'label'=>'Label',            'enabled'=>1, 'visible'=>1,  'position'=>30,  'searchall'=>1),
+	    'qty'           =>array('type'=>'double(24,8)', 'label'=>'Qty',              'enabled'=>1, 'visible'=>1,  'position'=>40,  'searchall'=>0, 'isameasure'=>1),
+	    'status'        =>array('type'=>'integer',      'label'=>'Status',           'enabled'=>1, 'visible'=>1,  'index'=>true,   'position'=>1000),
+		'date_creation' =>array('type'=>'datetime',     'label'=>'DateCreation',     'enabled'=>1, 'visible'=>-1, 'notnull'=>true, 'position'=>500),
+	    'tms'           =>array('type'=>'timestamp',    'label'=>'DateModification', 'enabled'=>1, 'visible'=>-1, 'notnull'=>true, 'position'=>500),
+		'import_key'    =>array('type'=>'varchar(14)',  'label'=>'ImportId',         'enabled'=>1, 'visible'=>-1,  'index'=>true,  'position'=>1000, 'nullifempty'=>1),
 	);
 	// END MODULEBUILDER PROPERTIES
 
diff --git a/htdocs/modulebuilder/template/myobject_card.php b/htdocs/modulebuilder/template/myobject_card.php
index 994aca35c88..c2927885e35 100644
--- a/htdocs/modulebuilder/template/myobject_card.php
+++ b/htdocs/modulebuilder/template/myobject_card.php
@@ -136,8 +136,9 @@ if (empty($reshook))
 
         foreach ($object->fields as $key => $val)
         {
+            if (in_array($key, array('entity', 'date_creation', 'tms', 'import_key'))) continue;	// Ignore special fields
+
             $object->$key=GETPOST($key,'alpha');
-            if (in_array($key, array('entity', 'datec', 'tms'))) continue;
             if ($val['notnull'] && $object->$key == '')
             {
                 $error++;
@@ -267,7 +268,7 @@ if ($action == 'create')
 	print '<table class="border centpercent">'."\n";
 	foreach($object->fields as $key => $val)
 	{
-	    if (in_array($key, array('rowid', 'entity', 'datec', 'tms'))) continue;
+	    if (in_array($key, array('rowid', 'entity', 'date_creation', 'tms', 'import_key'))) continue;
     	print '<tr><td';
     	print ' class="titlefieldcreate';
     	if ($val['notnull']) print ' fieldrequired';
diff --git a/htdocs/modulebuilder/template/myobject_list.php b/htdocs/modulebuilder/template/myobject_list.php
index 6430944bec7..8d2a5edce34 100644
--- a/htdocs/modulebuilder/template/myobject_list.php
+++ b/htdocs/modulebuilder/template/myobject_list.php
@@ -227,7 +227,7 @@ foreach ($search_array_options as $key => $val)
     $tmpkey=preg_replace('/search_options_/','',$key);
     $typ=$extrafields->attribute_type[$tmpkey];
     $mode=0;
-    if (in_array($typ, array('int','double'))) $mode=1;    // Search on a numeric
+    if (in_array($typ, array('int','double','real'))) $mode=1;    // Search on a numeric
     if ($val && ( ($crit != '' && ! in_array($typ, array('select'))) || ! empty($crit)))
     {
         $sql .= natural_search('ef.'.$tmpkey, $crit, $mode);
@@ -363,7 +363,7 @@ print '<table class="tagtable liste'.($moreforfilter?" listwithfilterbefore":"")
 print '<tr class="liste_titre">';
 foreach($object->fields as $key => $val)
 {
-    if (in_array($key, array('datec','tms','status'))) continue;
+    if (in_array($key, array('date_creation', 'tms', 'import_key', 'status'))) continue;
     $align='';
     if (in_array($val['type'], array('date','datetime','timestamp'))) $align='center';
     if (in_array($val['type'], array('timestamp'))) $align.=' nowrap';
@@ -399,7 +399,7 @@ print $hookmanager->resPrint;
 // Rest of fields search
 foreach($object->fields as $key => $val)
 {
-    if (! in_array($key, array('datec','tms','status'))) continue;
+    if (! in_array($key, array('date_creation', 'tms', 'import_key', 'status'))) continue;
     $align='';
     if (in_array($val['type'], array('date','datetime','timestamp'))) $align='center';
     if (in_array($val['type'], array('timestamp'))) $align.=' nowrap';
@@ -418,7 +418,7 @@ print '</tr>'."\n";
 print '<tr class="liste_titre">';
 foreach($object->fields as $key => $val)
 {
-    if (in_array($key, array('datec','tms','status'))) continue;
+    if (in_array($key, array('date_creation', 'tms', 'import_key', 'status'))) continue;
     $align='';
     if (in_array($val['type'], array('date','datetime','timestamp'))) $align='center';
     if (in_array($val['type'], array('timestamp'))) $align.='nowrap';
@@ -445,7 +445,7 @@ print $hookmanager->resPrint;
 // Rest of fields title
 foreach($object->fields as $key => $val)
 {
-    if (! in_array($key, array('datec','tms','status'))) continue;
+    if (! in_array($key, array('date_creation', 'tms', 'import_key', 'status'))) continue;
     $align='';
     if (in_array($val['type'], array('date','datetime','timestamp'))) $align='center';
     if (in_array($val['type'], array('timestamp'))) $align.=' nowrap';
@@ -476,7 +476,7 @@ while ($i < min($num, $limit))
         print '<tr class="oddeven">';
         foreach($object->fields as $key => $val)
         {
-            if (in_array($key, array('datec','tms','status'))) continue;
+            if (in_array($key, array('date_creation', 'tms', 'import_key', 'status'))) continue;
             $align='';
             if (in_array($val['type'], array('date','datetime','timestamp'))) $align='center';
             if (in_array($val['type'], array('timestamp'))) $align.='nowrap';
@@ -488,6 +488,11 @@ while ($i < min($num, $limit))
                 else print $obj->$key;
                 print '</td>';
                 if (! $i) $totalarray['nbfield']++;
+                if (! empty($val['isameasure']))
+                {
+                	if (! $i) $totalarray['pos'][$totalarray['nbfield']]='t.'.$key;
+                	$totalarray['val']['t.'.$key] += $obj->$key;
+                }
             }
         }
     	// Extra fields
@@ -505,6 +510,11 @@ while ($i < min($num, $limit))
 					print $extrafields->showOutputField($key, $obj->$tmpkey, '', 1);
 					print '</td>';
 		            if (! $i) $totalarray['nbfield']++;
+	                if (! empty($val['isameasure']))
+	                {
+			            if (! $i) $totalarray['pos'][$totalarray['nbfield']]='ef.'.$tmpkey;
+	                	$totalarray['val']['ef.'.$tmpkey] += $obj->$tmpkey;
+	                }
 				}
 		   }
 		}
@@ -515,18 +525,23 @@ while ($i < min($num, $limit))
         // Rest of fields
         foreach($object->fields as $key => $val)
         {
-            if (! in_array($key, array('datec','tms','status'))) continue;
+            if (! in_array($key, array('date_creation', 'tms', 'import_key', 'status'))) continue;
             $align='';
-            if (in_array($val['type'], array('date','datetime','timestamp'))) $align='center';
-            if (in_array($val['type'], array('timestamp'))) $align.='nowrap';
+            if (in_array($val['type'], array('date','datetime','timestamp'))) $align.=($align?' ':'').'center';
+            if (in_array($val['type'], array('timestamp'))) $align.=($align?' ':'').'nowrap';
             if (! empty($arrayfields['t.'.$key]['checked']))
             {
                 print '<td'.($align?' class="'.$align.'"':'').'>';
                 if (in_array($val['type'], array('date','datetime','timestamp'))) print dol_print_date($db->jdate($obj->$key), 'dayhour');
-                elseif ($key == 'status') print '<td align="center">'.$object->getLibStatut(3).'</td>';
+                elseif ($key == 'status') print $object->getLibStatut(3);
                 else print $obj->$key;
                 print '</td>';
                 if (! $i) $totalarray['nbfield']++;
+                if (! empty($val['isameasure']))
+                {
+	                if (! $i) $totalarray['pos'][$totalarray['nbfield']]='t.'.$key;
+	               	$totalarray['val']['t.'.$key] += $obj->$key;
+                }
             }
         }
         // Action column
@@ -546,22 +561,23 @@ while ($i < min($num, $limit))
 }
 
 // Show total line
-if (isset($totalarray['totalhtfield']))
+if (isset($totalarray['pos']))
 {
     print '<tr class="liste_total">';
     $i=0;
     while ($i < $totalarray['nbfield'])
     {
         $i++;
-        if ($i == 1)
+        if (! empty($totalarray['pos'][$i]))  print '<td align="right">'.price($totalarray['val'][$totalarray['pos'][$i]]).'</td>';
+        else
         {
-            if ($num < $limit) print '<td align="left">'.$langs->trans("Total").'</td>';
-            else print '<td align="left">'.$langs->trans("Totalforthispage").'</td>';
+            if ($i == 1)
+	        {
+	            if ($num < $limit) print '<td align="left">'.$langs->trans("Total").'</td>';
+	            else print '<td align="left">'.$langs->trans("Totalforthispage").'</td>';
+	        }
+        	print '<td></td>';
         }
-        elseif ($totalarray['totalhtfield'] == $i)  print '<td align="right">'.price($totalarray['totalht']).'</td>';
-        elseif ($totalarray['totalvatfield'] == $i) print '<td align="right">'.price($totalarray['totalvat']).'</td>';
-        elseif ($totalarray['totalttcfield'] == $i) print '<td align="right">'.price($totalarray['totalttc']).'</td>';
-        else print '<td></td>';
     }
     print '</tr>';
 }
diff --git a/htdocs/modulebuilder/template/sql/llx_myobject.sql b/htdocs/modulebuilder/template/sql/llx_myobject.sql
index b5810f0f227..1c47004f4e7 100644
--- a/htdocs/modulebuilder/template/sql/llx_myobject.sql
+++ b/htdocs/modulebuilder/template/sql/llx_myobject.sql
@@ -19,8 +19,10 @@ CREATE TABLE llx_myobject(
 	-- BEGIN MODULEBUILDER FIELDS
 	entity INTEGER DEFAULT 1 NOT NULL,
 	label VARCHAR(255),
-	datec DATETIME NOT NULL,
+	qty INTEGER,
+	status INTEGER,
+	date_creation DATETIME NOT NULL,
 	tms TIMESTAMP NOT NULL,
-	status INTEGER
+	import_key VARCHAR(14)
 	-- END MODULEBUILDER FIELDS
 ) ENGINE=innodb;
\ No newline at end of file
-- 
GitLab