diff --git a/htdocs/user/class/user.class.php b/htdocs/user/class/user.class.php index 578e5e25d8a..5fa0a6a90ae 100644 --- a/htdocs/user/class/user.class.php +++ b/htdocs/user/class/user.class.php @@ -550,9 +550,10 @@ class User extends CommonObject $sql .= " u.admin, u.login, u.note_private, u.note_public,"; $sql .= " u.pass, u.pass_crypted, u.pass_temp, u.api_key,"; $sql .= " u.fk_soc, u.fk_socpeople, u.fk_member, u.fk_user, u.ldap_sid, u.fk_user_expense_validator, u.fk_user_holiday_validator,"; + $sql .= " fk_user_creat as user_creation_id, fk_user_modif as user_modification_id,"; $sql .= " u.statut as status, u.lang, u.entity,"; $sql .= " u.datec as datec,"; - $sql .= " u.tms as datem,"; + $sql .= " GREATEST(u.tms, uef.tms) as datem,"; $sql .= " u.datelastlogin as datel,"; $sql .= " u.datepreviouslogin as datep,"; $sql .= " u.flagdelsessionsbefore,"; @@ -581,6 +582,7 @@ class User extends CommonObject $sql .= " d.code_departement as state_code, d.nom as state,"; $sql .= " s.label as label_establishment, u.fk_establishment"; $sql .= " FROM ".$this->db->prefix()."user as u"; + $sql .= " LEFT JOIN ".$this->db->prefix()."user_extrafields as uef ON uef.fk_object = u.rowid"; $sql .= " LEFT JOIN ".$this->db->prefix()."c_country as c ON u.fk_country = c.rowid"; $sql .= " LEFT JOIN ".$this->db->prefix()."c_departements as d ON u.fk_state = d.rowid"; $sql .= " LEFT JOIN ".$this->db->prefix()."establishment as s ON u.fk_establishment = s.rowid"; @@ -658,55 +660,57 @@ class User extends CommonObject $this->employee = $obj->employee; $this->login = $obj->login; - $this->gender = $obj->gender; - $this->birth = $this->db->jdate($obj->birth); + $this->gender = $obj->gender; + $this->birth = $this->db->jdate($obj->birth); $this->pass_indatabase = $obj->pass; $this->pass_indatabase_crypted = $obj->pass_crypted; $this->pass = $obj->pass; - $this->pass_temp = $obj->pass_temp; + $this->pass_temp = $obj->pass_temp; $this->datelastpassvalidation = $obj->datelastpassvalidation; $this->api_key = dolDecrypt($obj->api_key); - $this->address = $obj->address; - $this->zip = $obj->zip; - $this->town = $obj->town; + $this->address = $obj->address; + $this->zip = $obj->zip; + $this->town = $obj->town; $this->country_id = $obj->country_id; $this->country_code = $obj->country_id ? $obj->country_code : ''; //$this->country = $obj->country_id?($langs->trans('Country'.$obj->country_code)!='Country'.$obj->country_code?$langs->transnoentities('Country'.$obj->country_code):$obj->country):''; - $this->state_id = $obj->state_id; - $this->state_code = $obj->state_code; - $this->state = ($obj->state != '-' ? $obj->state : ''); + $this->state_id = $obj->state_id; + $this->state_code = $obj->state_code; + $this->state = ($obj->state != '-' ? $obj->state : ''); - $this->office_phone = $obj->office_phone; - $this->office_fax = $obj->office_fax; - $this->user_mobile = $obj->user_mobile; + $this->office_phone = $obj->office_phone; + $this->office_fax = $obj->office_fax; + $this->user_mobile = $obj->user_mobile; $this->personal_mobile = $obj->personal_mobile; $this->email = $obj->email; $this->email_oauth2 = $obj->email_oauth2; $this->personal_email = $obj->personal_email; $this->socialnetworks = ($obj->socialnetworks ? (array) json_decode($obj->socialnetworks, true) : array()); + $this->user_creation_id = $obj->user_creation_id; + $this->user_modification_id = $obj->user_modification_id; $this->job = $obj->job; $this->signature = $obj->signature; - $this->admin = $obj->admin; + $this->admin = $obj->admin; $this->note_public = $obj->note_public; $this->note_private = $obj->note_private; - $this->statut = $obj->status; // deprecated - $this->status = $obj->status; + $this->statut = $obj->status; // deprecated + $this->status = $obj->status; - $this->photo = $obj->photo; - $this->openid = $obj->openid; - $this->lang = $obj->lang; - $this->entity = $obj->entity; + $this->photo = $obj->photo; + $this->openid = $obj->openid; + $this->lang = $obj->lang; + $this->entity = $obj->entity; $this->accountancy_code_user_general = $obj->accountancy_code_user_general; $this->accountancy_code = $obj->accountancy_code; - $this->thm = $obj->thm; - $this->tjm = $obj->tjm; + $this->thm = $obj->thm; + $this->tjm = $obj->tjm; $this->salary = $obj->salary; $this->salaryextra = $obj->salaryextra; $this->weeklyhours = $obj->weeklyhours; @@ -714,8 +718,8 @@ class User extends CommonObject $this->dateemployment = $this->db->jdate($obj->dateemployment); $this->dateemploymentend = $this->db->jdate($obj->dateemploymentend); - $this->datec = $this->db->jdate($obj->datec); - $this->datem = $this->db->jdate($obj->datem); + $this->datec = $this->db->jdate($obj->datec); + $this->datem = $this->db->jdate($obj->datem); $this->datelastlogin = $this->db->jdate($obj->datel); $this->datepreviouslogin = $this->db->jdate($obj->datep); $this->flagdelsessionsbefore = $this->db->jdate($obj->flagdelsessionsbefore, 'gmt'); @@ -724,9 +728,9 @@ class User extends CommonObject $this->datestartvalidity = $this->db->jdate($obj->datestartvalidity); $this->dateendvalidity = $this->db->jdate($obj->dateendvalidity); - $this->socid = $obj->fk_soc; - $this->contact_id = $obj->fk_socpeople; - $this->fk_member = $obj->fk_member; + $this->socid = $obj->fk_soc; + $this->contact_id = $obj->fk_socpeople; + $this->fk_member = $obj->fk_member; $this->fk_user = $obj->fk_user; $this->fk_user_expense_validator = $obj->fk_user_expense_validator; $this->fk_user_holiday_validator = $obj->fk_user_holiday_validator; @@ -1749,6 +1753,7 @@ class User extends CommonObject $this->civility_code = trim((string) $this->civility_code); $this->login = trim((string) $this->login); + $this->user_creation_id = (int) $user->id; if (!isset($this->entity)) { $this->entity = $conf->entity; // If not defined, we use default value } @@ -1810,8 +1815,8 @@ class User extends CommonObject } // Insert into database - $sql = "INSERT INTO ".$this->db->prefix()."user (datec, login, ldap_sid, entity)"; - $sql .= " VALUES('".$this->db->idate($this->datec)."', '".$this->db->escape($this->login)."', '".$this->db->escape($this->ldap_sid)."', ".((int) $this->entity).")"; + $sql = "INSERT INTO ".$this->db->prefix()."user (datec, login, ldap_sid, fk_user_creat, entity)"; + $sql .= " VALUES('".$this->db->idate($this->datec)."', '".$this->db->escape($this->login)."', '".$this->db->escape($this->ldap_sid)."', ".(int) $this->user_creation_id.", ".((int) $this->entity).")"; $result = $this->db->query($sql); dol_syslog(get_class($this)."::create", LOG_DEBUG); @@ -2122,7 +2127,7 @@ class User extends CommonObject $this->lastname = trim((string) $this->lastname); $this->firstname = trim((string) $this->firstname); $this->ref_employee = trim((string) $this->ref_employee); - $this->national_registration_number = trim((string) $this->national_registration_number); + $this->national_registration_number = trim((string) $this->national_registration_number); $this->employee = ($this->employee > 0 ? $this->employee : 0); $this->login = trim((string) $this->login); $this->gender = trim((string) $this->gender); @@ -2151,8 +2156,9 @@ class User extends CommonObject $this->note_private = trim((string) $this->note_private); $this->openid = trim((string) $this->openid); $this->admin = ($this->admin > 0 ? $this->admin : 0); + $this->user_modification_id = $user->id; - $this->accountancy_code_user_general = trim((string) $this->accountancy_code_user_general); + $this->accountancy_code_user_general = trim((string) $this->accountancy_code_user_general); $this->accountancy_code = trim((string) $this->accountancy_code); $this->color = trim((string) $this->color); $this->dateemployment = empty($this->dateemployment) ? '' : $this->dateemployment; @@ -2255,6 +2261,7 @@ class User extends CommonObject $sql .= ", photo = ".($this->photo ? "'".$this->db->escape($this->photo)."'" : "null"); $sql .= ", openid = ".($this->openid ? "'".$this->db->escape($this->openid)."'" : "null"); $sql .= ", fk_user = ".($this->fk_user > 0 ? "'".((int) $this->fk_user)."'" : "null"); + $sql .= ", fk_user_modif = ".($this->user_modification_id > 0 ? "'".((int) $this->user_modification_id)."'" : "null"); $sql .= ", fk_user_expense_validator = ".($this->fk_user_expense_validator > 0 ? "'".((int) $this->fk_user_expense_validator)."'" : "null"); $sql .= ", fk_user_holiday_validator = ".($this->fk_user_holiday_validator > 0 ? "'".((int) $this->fk_user_holiday_validator)."'" : "null"); if (isset($this->thm) || $this->thm != '') { @@ -3608,6 +3615,7 @@ class User extends CommonObject $this->id = 0; $this->ref = 'SPECIMEN'; $this->specimen = 1; + $this->user_creation_id = $user->id; $this->lastname = 'DOLIBARR'; $this->firstname = 'SPECIMEN'; @@ -3638,7 +3646,6 @@ class User extends CommonObject $this->iplastlogin = '127.0.0.1'; $this->datepreviouslogin = $now; $this->ippreviouslogin = '127.0.0.1'; - $this->statut = 1; // deprecated $this->status = 1; $this->entity = 1; @@ -3654,9 +3661,10 @@ class User extends CommonObject */ public function info($id) { - $sql = "SELECT u.rowid, u.login as ref, u.datec,"; - $sql .= " u.tms as date_modification, u.entity"; + $sql = "SELECT u.rowid, u.login as ref, u.datec, fk_user_creat as user_creation_id, fk_user_modif as user_modification_id,"; + $sql .= " GREATEST(u.tms, uef.tms) as date_modification, u.entity"; $sql .= " FROM ".$this->db->prefix()."user as u"; + $sql .= " LEFT JOIN ".$this->db->prefix()."user_extrafields as uef ON uef.fk_object = u.rowid"; $sql .= " WHERE u.rowid = ".((int) $id); $result = $this->db->query($sql); @@ -3666,6 +3674,9 @@ class User extends CommonObject $this->id = $obj->rowid; + $this->user_creation_id = $obj->user_creation_id; + $this->user_modification_id = $obj->user_modification_id; + $this->ref = (!$obj->ref) ? $obj->rowid : $obj->ref; $this->date_creation = $this->db->jdate($obj->datec); $this->date_modification = $this->db->jdate($obj->date_modification); diff --git a/htdocs/user/home.php b/htdocs/user/home.php index 7af5fccb0ba..a1fff09b084 100644 --- a/htdocs/user/home.php +++ b/htdocs/user/home.php @@ -1,8 +1,8 @@ - * Copyright (C) 2005-2024 Regis Houssin - * Copyright (C) 2019 Nicolas ZABOURI - * Copyright (C) 2024 Frédéric France +/* Copyright (C) 2005-2018 Laurent Destailleur + * Copyright (C) 2005-2024 Regis Houssin + * Copyright (C) 2019 Nicolas ZABOURI + * Copyright (C) 2024-2025 Frédéric France * * 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 diff --git a/htdocs/user/list.php b/htdocs/user/list.php index 446ce7ca539..19392030558 100644 --- a/htdocs/user/list.php +++ b/htdocs/user/list.php @@ -7,7 +7,7 @@ * Copyright (C) 2024-2025 MDW * Copyright (C) 2024 Benjamin Falière * Copyright (C) 2024 William Mead - * Copyright (C) 2024 Frédéric France + * Copyright (C) 2024-2025 Frédéric France * * 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 @@ -154,7 +154,7 @@ $arrayfields = array( 'u.job' => array('label' => "PostOrFunction", 'checked' => '-1', 'position' => 60), 'u.salary' => array('label' => "Salary", 'checked' => '-1', 'position' => 80, 'enabled' => (string) (int) (isModEnabled('salaries') && $user->hasRight("salaries", "readall")), 'isameasure' => 1), 'u.datec' => array('label' => "DateCreation", 'checked' => '0', 'position' => 500), - 'u.tms' => array('label' => "DateModificationShort", 'checked' => '0', 'position' => 500), + 'date_modification' => array('label' => "DateModificationShort", 'checked' => '0', 'position' => 500), 'u.statut' => array('label' => "Status", 'checked' => '1', 'position' => 1000), ); @@ -392,7 +392,7 @@ $sql .= " u.fk_user,"; $sql .= " u.ref_employee, u.national_registration_number, u.job, u.salary, u.datelastlogin, u.datepreviouslogin,"; $sql .= " u.datestartvalidity, u.dateendvalidity,"; $sql .= " u.ldap_sid, u.statut as status, u.entity,"; -$sql .= " u.tms as date_modification, u.datec as date_creation,"; +$sql .= " GREATEST(u.tms, ef.tms) as date_modification, u.datec as date_creation,"; $sql .= " u2.rowid as id2, u2.login as login2, u2.firstname as firstname2, u2.lastname as lastname2, u2.admin as admin2, u2.fk_soc as fk_soc2, u2.office_phone as ofice_phone2, u2.user_mobile as user_mobile2, u2.email as email2, u2.gender as gender2, u2.photo as photo2, u2.entity as entity2, u2.statut as status2,"; $sql .= " s.nom as name, s.canvas,"; $sql .= " co.code as country_code, co.label as country_label"; @@ -411,9 +411,7 @@ $sql = preg_replace('/,\s*$/', '', $sql); $sqlfields = $sql; // $sql fields to remove for count total $sql .= " FROM ".MAIN_DB_PREFIX.$object->table_element." as u"; -if (isset($extrafields->attributes[$object->table_element]['label']) && is_array($extrafields->attributes[$object->table_element]['label']) && count($extrafields->attributes[$object->table_element]['label'])) { - $sql .= " LEFT JOIN ".MAIN_DB_PREFIX.$object->table_element."_extrafields as ef on (u.rowid = ef.fk_object)"; -} +$sql .= " LEFT JOIN ".MAIN_DB_PREFIX.$object->table_element."_extrafields as ef on (u.rowid = ef.fk_object)"; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s ON u.fk_soc = s.rowid"; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."user as u2 ON u.fk_user = u2.rowid"; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_country as co ON u.fk_country = co.rowid"; @@ -863,7 +861,7 @@ if (!empty($arrayfields['u.datec']['checked'])) { print ''; print ''; } -if (!empty($arrayfields['u.tms']['checked'])) { +if (!empty($arrayfields['date_modification']['checked'])) { // Date modification print ''; print ''; @@ -988,8 +986,8 @@ if (!empty($arrayfields['u.datec']['checked'])) { print_liste_field_titre("DateCreationShort", $_SERVER["PHP_SELF"], "u.datec", "", $param, '', $sortfield, $sortorder, 'center nowrap '); $totalarray['nbfield']++; } -if (!empty($arrayfields['u.tms']['checked'])) { - print_liste_field_titre("DateModificationShort", $_SERVER["PHP_SELF"], "u.tms", "", $param, '', $sortfield, $sortorder, 'center nowrap '); +if (!empty($arrayfields['date_modification']['checked'])) { + print_liste_field_titre("DateModificationShort", $_SERVER["PHP_SELF"], "date_modification", "", $param, '', $sortfield, $sortorder, 'center nowrap '); $totalarray['nbfield']++; } if (!empty($arrayfields['u.statut']['checked'])) { @@ -1376,7 +1374,7 @@ while ($i < $imaxinloop) { } } // Date modification - if (!empty($arrayfields['u.tms']['checked'])) { + if (!empty($arrayfields['date_modification']['checked'])) { print ''; print dol_print_date($db->jdate($obj->date_modification), 'dayhour', 'tzuser'); print ''; diff --git a/test/phpunit/UserTest.php b/test/phpunit/UserTest.php index ef426c838b4..e2b76cc0111 100644 --- a/test/phpunit/UserTest.php +++ b/test/phpunit/UserTest.php @@ -1,8 +1,8 @@ - * Copyright (C) 2023 Alexandre Janniaux - * Copyright (C) 2024 MDW - * Copyright (C) 2024 Frédéric France +/* Copyright (C) 2010-2015 Laurent Destailleur + * Copyright (C) 2023 Alexandre Janniaux + * Copyright (C) 2024 MDW + * Copyright (C) 2024-2025 Frédéric France * * 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 @@ -144,7 +144,38 @@ class UserTest extends CommonClassTest $newlocalobject->initAsSpecimen(); $this->changeProperties($newlocalobject); // Change some properties int $newlocalobject - $this->assertEquals($this->objCompare($localobject, $newlocalobject, true, array('array_options','id','socid','societe_id','specimen','note','ref','pass','pass_indatabase','pass_indatabase_crypted','pass_temp','datec','datem','datelastlogin','datepreviouslogin','datelastpassvalidation','flagdelsessionsbefore','iplastlogin','ippreviouslogin','trackid')), array()); // Actual, Expected + $this->assertEquals( + $this->objCompare( // Actual, Expected + $localobject, + $newlocalobject, + true, + array( + 'array_options', + 'id', + 'socid', + 'societe_id', + 'specimen', + 'statut', + 'user_modification_id', + 'note', + 'ref', + 'pass', + 'pass_indatabase', + 'pass_indatabase_crypted', + 'pass_temp', + 'datec', + 'datem', + 'datelastlogin', + 'datepreviouslogin', + 'datelastpassvalidation', + 'flagdelsessionsbefore', + 'iplastlogin', + 'ippreviouslogin', + 'trackid' + ) + ), + array() + ); return $localobject; }