Feature: Synchro user depuis fiche adherent
Qual: Deplacement fonction trigger dans core.
This commit is contained in:
parent
ba5c56f6db
commit
1331b29a29
@ -370,7 +370,7 @@ class Adherent
|
|||||||
$this->id=$id;
|
$this->id=$id;
|
||||||
|
|
||||||
// Mise a jour
|
// Mise a jour
|
||||||
$result=$this->update($user,1);
|
$result=$this->update($user,1,1);
|
||||||
if ($result < 0)
|
if ($result < 0)
|
||||||
{
|
{
|
||||||
$this->db->rollback();
|
$this->db->rollback();
|
||||||
@ -445,13 +445,15 @@ class Adherent
|
|||||||
\brief Fonction qui met à jour l'adhérent
|
\brief Fonction qui met à jour l'adhérent
|
||||||
\param user Utilisateur qui réalise la mise a jour
|
\param user Utilisateur qui réalise la mise a jour
|
||||||
\param notrigger 1=désactive le trigger UPDATE (quand appelé par creation)
|
\param notrigger 1=désactive le trigger UPDATE (quand appelé par creation)
|
||||||
|
\param nosyncuser Do not synchronize linked user
|
||||||
\return int <0 si KO, >0 si OK
|
\return int <0 si KO, >0 si OK
|
||||||
*/
|
*/
|
||||||
function update($user,$notrigger=0)
|
function update($user,$notrigger=0,$nosyncuser=0)
|
||||||
{
|
{
|
||||||
global $conf,$langs;
|
global $conf,$langs;
|
||||||
|
$error=0;
|
||||||
|
|
||||||
dolibarr_syslog("Adherent::update user->id=".$user->id.", notrigger=".$notrigger);
|
dolibarr_syslog("Adherent::update notrigger=".$notrigger.", nosyncuser=".$nosyncuser);
|
||||||
|
|
||||||
// Verification parametres
|
// Verification parametres
|
||||||
if ($conf->global->ADHERENT_MAIL_REQUIRED && ! ValidEMail($this->email))
|
if ($conf->global->ADHERENT_MAIL_REQUIRED && ! ValidEMail($this->email))
|
||||||
@ -493,6 +495,7 @@ class Adherent
|
|||||||
if (! $result)
|
if (! $result)
|
||||||
{
|
{
|
||||||
$this->error=$this->db->error();
|
$this->error=$this->db->error();
|
||||||
|
dolibarr_syslog("Adherent::update ".$this->error,LOG_ERROR);
|
||||||
$this->db->rollback();
|
$this->db->rollback();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -500,6 +503,7 @@ class Adherent
|
|||||||
if (sizeof($this->array_options) > 0)
|
if (sizeof($this->array_options) > 0)
|
||||||
{
|
{
|
||||||
$sql_del = "DELETE FROM ".MAIN_DB_PREFIX."adherent_options WHERE adhid = ".$this->id;
|
$sql_del = "DELETE FROM ".MAIN_DB_PREFIX."adherent_options WHERE adhid = ".$this->id;
|
||||||
|
dolibarr_syslog("Adherent::update sql=".$sql_del);
|
||||||
$this->db->query($sql_del);
|
$this->db->query($sql_del);
|
||||||
|
|
||||||
$sql = "INSERT INTO ".MAIN_DB_PREFIX."adherent_options (adhid";
|
$sql = "INSERT INTO ".MAIN_DB_PREFIX."adherent_options (adhid";
|
||||||
@ -516,19 +520,59 @@ class Adherent
|
|||||||
}
|
}
|
||||||
$sql.=")";
|
$sql.=")";
|
||||||
|
|
||||||
|
dolibarr_syslog("Adherent::update sql=".$sql);
|
||||||
$result = $this->db->query($sql);
|
$result = $this->db->query($sql);
|
||||||
if (! $result)
|
if (! $result)
|
||||||
{
|
{
|
||||||
$this->error=$this->db->error();
|
$this->error=$this->db->error();
|
||||||
dolibarr_syslog("Adherent::update ".$this->error);
|
dolibarr_syslog("Adherent::update ".$this->error,LOG_ERROR);
|
||||||
$this->db->rollback();
|
$this->db->rollback();
|
||||||
return -2;
|
return -2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($this->user_id && ! $nosyncuser)
|
||||||
|
{
|
||||||
|
// This member is linked with a user, so we also update users informations
|
||||||
|
// if this is an update.
|
||||||
|
$luser=new User($this->db);
|
||||||
|
$luser->id=$this->user_id;
|
||||||
|
$result=$luser->fetch();
|
||||||
|
|
||||||
|
if ($result >= 0)
|
||||||
|
{
|
||||||
|
$luser->prenom=$this->prenom;
|
||||||
|
$luser->nom=$this->nom;
|
||||||
|
$luser->login=$this->user_login;
|
||||||
|
$luser->pass=$this->pass;
|
||||||
|
$luser->societe_id=$this->societe;
|
||||||
|
|
||||||
|
$luser->email=$this->email;
|
||||||
|
$luser->office_phone=$this->phone;
|
||||||
|
$luser->user_mobile=$this->phone_mobile;
|
||||||
|
|
||||||
|
$luser->note=$this->commentaire;
|
||||||
|
|
||||||
|
$luser->fk_member=$this->id;
|
||||||
|
|
||||||
|
$result=$luser->update($user,0,1);
|
||||||
|
if ($result < 0)
|
||||||
|
{
|
||||||
|
$this->error=$luser->error;
|
||||||
|
dolibarr_syslog("Adherent::update ".$this->error,LOG_ERROR);
|
||||||
|
$error++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$this->error=$luser->error;
|
||||||
|
$error++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$this->fullname=trim($this->nom.' '.$this->prenom);
|
$this->fullname=trim($this->nom.' '.$this->prenom);
|
||||||
|
|
||||||
if (! $notrigger)
|
if (! $error && ! $notrigger)
|
||||||
{
|
{
|
||||||
$this->use_webcal=($conf->global->PHPWEBCALENDAR_MEMBERSTATUS=='always'?1:0);
|
$this->use_webcal=($conf->global->PHPWEBCALENDAR_MEMBERSTATUS=='always'?1:0);
|
||||||
|
|
||||||
@ -540,7 +584,14 @@ class Adherent
|
|||||||
// Fin appel triggers
|
// Fin appel triggers
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (! $error)
|
||||||
|
{
|
||||||
$this->db->commit();
|
$this->db->commit();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$this->db->rollback();
|
||||||
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -506,7 +506,7 @@ class Fichinter extends CommonObject
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dolibarr_syslog("Suppression de la fiche intervention $this->id par $user->fullname ($user->id)");
|
dolibarr_syslog("Suppression de la fiche intervention $this->id par $user->id");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
@ -1,122 +0,0 @@
|
|||||||
<?php
|
|
||||||
/* Copyright (C) 2006 Rodolphe Quiedeville <rodolphe@quiedeville.org>
|
|
||||||
*
|
|
||||||
* 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
|
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
||||||
*
|
|
||||||
* $Id$
|
|
||||||
* $Source$
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
\file htdocs/includes/triggers/interface_user.class.php
|
|
||||||
\ingroup stock
|
|
||||||
\brief Fichier des actions du workflow de stock utilisateurs
|
|
||||||
\remarks Son propre fichier d'actions peut etre créé par recopie de celui-ci:
|
|
||||||
- Le nom du fichier doit etre interface_xxx.class.php
|
|
||||||
- Le fichier doit rester stocké dans includes/triggers
|
|
||||||
- Le nom de la classe doit etre InterfaceXxx
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
\class InterfaceUser
|
|
||||||
\brief Classe des fonctions triggers des actions personalisées du workflow
|
|
||||||
*/
|
|
||||||
|
|
||||||
class InterfaceUser
|
|
||||||
{
|
|
||||||
var $db;
|
|
||||||
var $error;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Constructeur.
|
|
||||||
* \param DB Handler d'accès base
|
|
||||||
*/
|
|
||||||
function InterfaceUser($DB)
|
|
||||||
{
|
|
||||||
$this->db = $DB ;
|
|
||||||
|
|
||||||
$this->name = "User";
|
|
||||||
$this->family = "user";
|
|
||||||
$this->description = "Les triggers de ce composant s'appliquent sur les utilisateurs gérant des stocks.";
|
|
||||||
$this->revision = explode(' ','$Revision$');
|
|
||||||
$this->version = $this->revision[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Renvoi nom du lot de triggers
|
|
||||||
* \return string Nom du lot de triggers
|
|
||||||
*/
|
|
||||||
function getName()
|
|
||||||
{
|
|
||||||
return $this->name;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Renvoi descriptif du lot de triggers
|
|
||||||
* \return string Descriptif du lot de triggers
|
|
||||||
*/
|
|
||||||
function getDesc()
|
|
||||||
{
|
|
||||||
return $this->description;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Renvoi version du lot de triggers
|
|
||||||
* \return string Version du lot de triggers
|
|
||||||
*/
|
|
||||||
function getVersion()
|
|
||||||
{
|
|
||||||
global $langs;
|
|
||||||
$langs->load("admin");
|
|
||||||
|
|
||||||
if ($this->version == 'experimental') return $langs->trans("Experimental");
|
|
||||||
elseif ($this->version == 'dolibarr') return DOL_VERSION;
|
|
||||||
elseif ($this->version) return $this->version;
|
|
||||||
else return $langs->trans("Unknown");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Fonction appelée lors du déclenchement d'un évènement Dolibarr.
|
|
||||||
* D'autres fonctions run_trigger peuvent etre présentes dans includes/triggers
|
|
||||||
* \param action Code de l'evenement
|
|
||||||
* \param object Objet concern
|
|
||||||
* \param user Objet user
|
|
||||||
* \param lang Objet lang
|
|
||||||
* \param conf Objet conf
|
|
||||||
* \return int <0 si ko, 0 si aucune action faite, >0 si ok
|
|
||||||
*/
|
|
||||||
function run_trigger($action,$object,$user,$langs,$conf)
|
|
||||||
{
|
|
||||||
// Users
|
|
||||||
if ($action == 'USER_CREATE')
|
|
||||||
{
|
|
||||||
dolibarr_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id);
|
|
||||||
|
|
||||||
if ($conf->global->STOCK_USERSTOCK == 1 && $conf->global->STOCK_USERSTOCK_AUTOCREATE == 1)
|
|
||||||
{
|
|
||||||
require_once(DOL_DOCUMENT_ROOT."/product/stock/entrepot.class.php");
|
|
||||||
$entrepot = new Entrepot($this->db);
|
|
||||||
$entrepot->libelle = 'Stock Personnel '.$object->nom;
|
|
||||||
$entrepot->description = 'Cet entrepot représente le stock personnel de '.$object->prenom.' '.$object->nom;
|
|
||||||
$entrepot->statut = 1;
|
|
||||||
$entrepot->create($user);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
?>
|
|
||||||
@ -388,7 +388,7 @@ if (! session_id() || ! isset($_SESSION["dol_login"]))
|
|||||||
if ($user->login != $ldap->login && $ldap->login)
|
if ($user->login != $ldap->login && $ldap->login)
|
||||||
{
|
{
|
||||||
$user->login = $ldap->login;
|
$user->login = $ldap->login;
|
||||||
$user->update();
|
$user->update($user);
|
||||||
}
|
}
|
||||||
//$resultUpdate = $user->update_ldap2dolibarr();
|
//$resultUpdate = $user->update_ldap2dolibarr();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1562,7 +1562,7 @@ class Propal extends CommonObject
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dolibarr_syslog("Suppression de la proposition $this->id par $user->fullname ($user->id)");
|
dolibarr_syslog("Suppression de la proposition $this->id par $user->id");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
@ -700,13 +700,23 @@ class User
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Update minor fields
|
// Update minor fields
|
||||||
if ($this->update(1) < 0)
|
if ($this->update($user,1,1) < 0)
|
||||||
{
|
{
|
||||||
$this->error=$this->db->error();
|
$this->error=$this->db->error();
|
||||||
$this->db->rollback();
|
$this->db->rollback();
|
||||||
return -4;
|
return -4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($conf->global->STOCK_USERSTOCK == 1 && $conf->global->STOCK_USERSTOCK_AUTOCREATE == 1)
|
||||||
|
{
|
||||||
|
require_once(DOL_DOCUMENT_ROOT."/product/stock/entrepot.class.php");
|
||||||
|
$entrepot = new Entrepot($this->db);
|
||||||
|
$entrepot->libelle = 'Stock Personnel '.$this->nom;
|
||||||
|
$entrepot->description = 'Cet entrepot représente le stock personnel de '.$this->prenom.' '.$this->nom;
|
||||||
|
$entrepot->statut = 1;
|
||||||
|
$entrepot->create($user);
|
||||||
|
}
|
||||||
|
|
||||||
if (! $notrigger)
|
if (! $notrigger)
|
||||||
{
|
{
|
||||||
// Appel des triggers
|
// Appel des triggers
|
||||||
@ -896,12 +906,17 @@ class User
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Mise à jour en base d'un utilisateur
|
* \brief Mise à jour en base d'un utilisateur
|
||||||
|
* \param user User qui fait la mise a jour
|
||||||
* \param notrigger 1 ne declenche pas les triggers, 0 sinon
|
* \param notrigger 1 ne declenche pas les triggers, 0 sinon
|
||||||
|
* \param nosyncmember Do not synchronize linked member
|
||||||
* \return int <0 si KO, >=0 si OK
|
* \return int <0 si KO, >=0 si OK
|
||||||
*/
|
*/
|
||||||
function update($notrigger=0)
|
function update($user,$notrigger=0,$nosyncmember=0)
|
||||||
{
|
{
|
||||||
global $conf,$langs,$user;
|
global $conf,$langs,$user;
|
||||||
|
$error=0;
|
||||||
|
|
||||||
|
dolibarr_syslog("User::update notrigger=".$notrigger.", nosyncmember=".$nosyncmember);
|
||||||
|
|
||||||
// Nettoyage parametres
|
// Nettoyage parametres
|
||||||
$this->nom=trim($this->nom);
|
$this->nom=trim($this->nom);
|
||||||
@ -913,22 +928,8 @@ class User
|
|||||||
$this->note=trim($this->note);
|
$this->note=trim($this->note);
|
||||||
$this->admin=$this->admin?$this->admin:0;
|
$this->admin=$this->admin?$this->admin:0;
|
||||||
|
|
||||||
dolibarr_syslog("User::update notrigger=".$notrigger." nom=".$this->nom.", prenom=".$this->prenom);
|
|
||||||
$error=0;
|
|
||||||
|
|
||||||
$this->db->begin();
|
$this->db->begin();
|
||||||
|
|
||||||
// Mise a jour mot de passe
|
|
||||||
if ($this->pass)
|
|
||||||
{
|
|
||||||
if ($this->pass != $this->pass_indatabase &&
|
|
||||||
$this->pass != $this->pass_indatabase_crypted)
|
|
||||||
{
|
|
||||||
// Si mot de passe saisi et différent de celui en base
|
|
||||||
$this->password($user,$this->pass,$conf->password_encrypted);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mise a jour autres infos
|
// Mise a jour autres infos
|
||||||
$sql = "UPDATE ".MAIN_DB_PREFIX."user SET";
|
$sql = "UPDATE ".MAIN_DB_PREFIX."user SET";
|
||||||
$sql.= " name = '".addslashes($this->nom)."'";
|
$sql.= " name = '".addslashes($this->nom)."'";
|
||||||
@ -949,15 +950,30 @@ class User
|
|||||||
{
|
{
|
||||||
$nbrowsaffected=$this->db->affected_rows($resql);
|
$nbrowsaffected=$this->db->affected_rows($resql);
|
||||||
|
|
||||||
|
// Mise a jour mot de passe
|
||||||
|
if ($this->pass)
|
||||||
|
{
|
||||||
|
if ($this->pass != $this->pass_indatabase &&
|
||||||
|
$this->pass != $this->pass_indatabase_crypted)
|
||||||
|
{
|
||||||
|
// Si mot de passe saisi et différent de celui en base
|
||||||
|
$this->password($user,$this->pass,$conf->password_encrypted);
|
||||||
|
|
||||||
|
if (! $nbrowsaffected) $nbrowsaffected++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ($nbrowsaffected)
|
if ($nbrowsaffected)
|
||||||
{
|
{
|
||||||
if ($this->fk_member && ! $notrigger)
|
if ($this->fk_member && ! $nosyncmember)
|
||||||
{
|
{
|
||||||
// This user is linked with a member, so we also update members informations
|
// This user is linked with a member, so we also update members informations
|
||||||
// if this is an update (notrigger = 0).
|
// if this is an update.
|
||||||
$adh=new Adherent($this->db);
|
$adh=new Adherent($this->db);
|
||||||
$result=$adh->fetch($this->fk_member);
|
$result=$adh->fetch($this->fk_member);
|
||||||
|
|
||||||
|
if ($result >= 0)
|
||||||
|
{
|
||||||
$adh->prenom=$this->prenom;
|
$adh->prenom=$this->prenom;
|
||||||
$adh->nom=$this->nom;
|
$adh->nom=$this->nom;
|
||||||
$adh->login=$this->login;
|
$adh->login=$this->login;
|
||||||
@ -966,21 +982,26 @@ class User
|
|||||||
|
|
||||||
$adh->email=$this->email;
|
$adh->email=$this->email;
|
||||||
$adh->phone=$this->office_phone;
|
$adh->phone=$this->office_phone;
|
||||||
$adh->phone_perso=$this->office_fax;
|
|
||||||
$adh->phone_mobile=$this->user_mobile;
|
$adh->phone_mobile=$this->user_mobile;
|
||||||
|
|
||||||
$adh->commentaire=$user->note;
|
$adh->commentaire=$this->note;
|
||||||
|
|
||||||
$adh->user_id=$this->id;
|
$adh->user_id=$this->id;
|
||||||
$adh->user_login=$this->login;
|
$adh->user_login=$this->login;
|
||||||
|
|
||||||
$result=$adh->update($user,0);
|
$result=$adh->update($user,0,1);
|
||||||
if ($result < 0)
|
if ($result < 0)
|
||||||
{
|
{
|
||||||
$this->error=$adh->error;
|
$this->error=$adh->error;
|
||||||
$error++;
|
$error++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$this->error=$adh->error;
|
||||||
|
$error++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (! $error && ! $notrigger)
|
if (! $error && ! $notrigger)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -78,7 +78,7 @@ if ($_GET["id"])
|
|||||||
*/
|
*/
|
||||||
$head = user_prepare_head($fuser);
|
$head = user_prepare_head($fuser);
|
||||||
|
|
||||||
dolibarr_fiche_head($head, 'bookmark4u', $langs->trans("User").": ".$fuser->fullname);
|
dolibarr_fiche_head($head, 'bookmark4u', $langs->trans("User"));
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@ -70,7 +70,7 @@ if ($_GET["id"])
|
|||||||
*/
|
*/
|
||||||
$head = user_prepare_head($fuser);
|
$head = user_prepare_head($fuser);
|
||||||
|
|
||||||
dolibarr_fiche_head($head, 'clicktodial', $langs->trans("User").": ".$fuser->fullname);
|
dolibarr_fiche_head($head, 'clicktodial', $langs->trans("User"));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Fiche en mode visu
|
* Fiche en mode visu
|
||||||
|
|||||||
@ -243,7 +243,7 @@ if ($_POST["action"] == 'update' && ! $_POST["cancel"] && $caneditfield)
|
|||||||
$edituser->email = trim($_POST["email"]);
|
$edituser->email = trim($_POST["email"]);
|
||||||
$edituser->webcal_login = trim($_POST["webcal_login"]);
|
$edituser->webcal_login = trim($_POST["webcal_login"]);
|
||||||
|
|
||||||
$ret=$edituser->update();
|
$ret=$edituser->update($user);
|
||||||
if ($ret < 0)
|
if ($ret < 0)
|
||||||
{
|
{
|
||||||
if ($db->errno() == 'DB_ERROR_RECORD_ALREADY_EXISTS')
|
if ($db->errno() == 'DB_ERROR_RECORD_ALREADY_EXISTS')
|
||||||
|
|||||||
@ -566,6 +566,7 @@ ALTER TABLE `llx_socpeople` CHANGE `fk_user_create` `fk_user_creat` INT(11) NULL
|
|||||||
-- V4 ALTER TABLE llx_socpeople ADD CONSTRAINT fk_socpeople_user_creat_user_rowid FOREIGN KEY (fk_user_creat) REFERENCES llx_user (rowid);
|
-- V4 ALTER TABLE llx_socpeople ADD CONSTRAINT fk_socpeople_user_creat_user_rowid FOREIGN KEY (fk_user_creat) REFERENCES llx_user (rowid);
|
||||||
|
|
||||||
ALTER TABLE llx_user add pass_temp VARCHAR(32) NULL after pass_crypted;
|
ALTER TABLE llx_user add pass_temp VARCHAR(32) NULL after pass_crypted;
|
||||||
|
update llx_user set pass = null where pass = pass_crypted and length(pass) = 32;
|
||||||
|
|
||||||
drop table if exists llx_soc_events;
|
drop table if exists llx_soc_events;
|
||||||
drop table if exists llx_todocomm;
|
drop table if exists llx_todocomm;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user