viernes, 3 de agosto de 2018

Cómo crear un plugins en glpi

Vamos a crear un plugin básico que solo diga hola mundo, pero que dará las primeras luces en cómo crear un plugin en glpi


La estructura del directorio:
Depende de tu plugin, se pueden crear infinitas carpetas, pero el estándar es

-Miplugin(*)/
   -front(*)/
   -inc(*)/
   -locales(**)/
   -tools/
   -README.md
   -LICENSE
   -setup.php(*)
   -hook.php(*)
   -miplugin.xml
   -miplugin.png

(*)   Obligatorio que existan.
(**) Para mi debería ser obligatorio porque hace internacional tu aplicación
  • en front, están los archivos de php que se mostraran al usuario (la vista)
  • en inc, están las clases
  • el setup.php, es automáticamente cargado por el core de glpi, chequea prerequisitos, etc 
  • el hook.php, se usa para realizar acciones por ejemplo al instalar o desinstalar el plugin

Pasos para crear el plugin

1.-la carpeta raíz se debe llamar igual que el plugin y debe estar en minúscula y sin espacios. Ejemplo: holamundo

2.-Recrear las carpetas y archivos obligatorios necesarios para el plugins, como lo son front/ inc/ locales/ setup.php y hook.php Ejemplo:

holamundo/
    front/
    inc/
    locales/
    setup.php
    hook.php

3.-Editar el archivo setup.php ejemplo:

<?php

/*
 *
  -------------------------------------------------------------------------
  Plugin GLPI hola mundo
 */

function plugin_init_holamundo() {
    global $PLUGIN_HOOKS;

    $PLUGIN_HOOKS['csrf_compliant']['holamundo'] = true;
    $PLUGIN_HOOKS['change_profile']['holamundo'] = array('PluginHolamundoProfile', 'changeProfile');

//aquí esta registrando la clase profile que es la que desencadena todo en este ejemplo
    Plugin::registerClass('PluginHolamundoProfile', array('addtabon' => 'Profile'));
 
    $plugin = new Plugin();

    if (isset($_SESSION['glpiID']) && $plugin->isInstalled('holamundo') && $plugin->isActivated('holamundo')) {
        if (Session::haveRight('plugin_holamundo', READ)) {

//aquí se agrega al menú complementos   
$PLUGIN_HOOKS['menu_toadd']['holamundo'] = array(
               'plugins' => 'PluginHolamundoIndex'); //en la clase form.class.php hace referencia esto

        }
    }
}

function plugin_version_holamundo() {
    global $LANG;

    return array(
        'name' => $LANG['plugin_holamundo']['title'],
        'version' => '1.1.0',
        'author' => "Alexander Chale",
        'license' => "GPLv2+",
        'homepage' => 'https://glpiconchale.blogspot.com',
        'minGlpiVersion' => '9.2' //aqui le digo que mi plugin va a trabajar con la versión minima de glpi
    );
}

function plugin_holamundo_check_prerequisites() {
    if (GLPI_VERSION >= 9.2) { //aqui le digo que el prerequisito es la versión 9.2 de glpi
        return true;
    } else {  //aquí le mando un mensaje si no tiene instalada la versión de glpi que yo deseo, y no lo deja instalar el plugin
        echo "La versión de GLPI no es compatible. Requiere GLPI 9.2";
        return false;
    }
}

function plugin_holamundo_check_config() {
    return true;
}


4.-  Editar el archivo hook.php ejemplo:

<?php
// plugin_"nombredelpluginenminúscula"_install() Nombre de la carpeta del plugin en el directorio plugins
function plugin_holamundo_install() {
  global $DB;

//PluginHolamundoProfile el Plugin"Nombredelpluginprimeraletramayúscula"Profile
//donde Profile es un archivo ubicado en plugins/holamundo/inc/profile.class.php
 PluginHolamundoProfile::createFirstAccess($_SESSION['glpiactiveprofile']['id']);

// aquí podrías crear tablas en la base de datos que luego tu aplicación necesite
    return true;
}

function plugin_holamundo_uninstall() {
 global $DB;

PluginHolamundoProfile::uninstallProfile();

// aquí podrás eliminar las tablas que creaste en la base de datos
    
      return true;
}

?>


5.- deberíamos empezar con las clases que declaramos en el archivo setup.php

las clases declaradas fueron Profile y hacemos un llamado en el menú de Index

5.1.- Creamos y editamos el archivo profile.class.php en inc/

<?php

/*
 *
  -------------------------------------------------------------------------
 
  Copyright (C) 2017 by Walid H.
 */

if (!defined('GLPI_ROOT')) {
    die("Sorry. You can't access directly to this file");
}

class PluginHolamundoProfile extends Profile {

    static $rightname = 'profile';

    public static function getAllRights() {
        global $LANG;

        return array(
            array(
                'itemtype' => 'PluginHolamundoProfile',
                'label' => $LANG['plugin_holamundo']['manage_alerts'],
                'field' => 'plugin_holamundo'
            ),
        );
    }

    public static function addDefaultProfileInfos($profiles_id, $rights) {
        $profileRight = new ProfileRight();
        foreach ($rights as $right => $value) {
            if (!countElementsInTable('glpi_profilerights', "`profiles_id`='$profiles_id' AND `name`='$right'")) {
                $myright['profiles_id'] = $profiles_id;
                $myright['name'] = $right;
                $myright['rights'] = $value;
                $profileRight->add($myright);

                //Add right to the current session
                $_SESSION['glpiactiveprofile'][$right] = $value;
            }
        }
    }

    /**
     * @param $ID  integer
     */
    public static function createFirstAccess($profiles_id) {
        $profile = new self();
        foreach ($profile->getAllRights() as $right) {
            self::addDefaultProfileInfos($profiles_id, array($right['field'] => ALLSTANDARDRIGHT));
        }
    }

    public static function changeProfile() {
        $profile = new self();

        if ($profile->getFromDBByProfile($_SESSION['glpiactiveprofile']['id'])) {
            $_SESSION['glpiactiveprofile']['holamundo_alert'] = $profile->getField('alert');
        } else {
            unset($_SESSION['glpiactiveprofile']['holamundo_alert']);
        }
    }

    public function getTabNameForItem(CommonGLPI $item, $withtemplate = 0) {
        global $LANG;
        return $LANG['plugin_holamundo']['title'];
    }

    public function getFromDBByProfile($profiles_id) {
        global $DB;

        $query = "SELECT *
                FROM `" . $this->getTable() . "`
                WHERE `profiles_id` = '" . (int) $profiles_id . "' ";

        if ($result = $DB->query($query)) {
            if ($DB->numrows($result)) {
                $this->fields = $DB->fetch_assoc($result);
                if (is_array($this->fields) && count($this->fields)) {
                    return true;
                }
            }
        }

        return false;
    }

    public static function displayTabContentForItem(CommonGLPI $item, $tabnum = 1, $withtemplate = 0) {
        $profile = new self();

        if (!$profile->getFromDBByProfile($item->getID())) {
            self::createFirstAccess($item->getID());
            $profile->getFromDBByProfile($item->getID());
        }
        $profile->showForm($item->getField('id'));
    }

    public function showForm($profiles_id, $options = array()) {
        global $LANG;

        $profile = new Profile();
        $profile->getFromDB($profiles_id);

        if ($canedit = Session::haveRightsOr(self::$rightname, array(CREATE, UPDATE, PURGE))) {
            echo "<form action='" . $profile->getFormURL() . "' method='post'>";
        }

        $profile = new Profile();
        $profile->getFromDB($profiles_id);

        $rights = $this->getAllRights();
        $profile->displayRightsChoiceMatrix($rights, array(
            'canedit' => $canedit,
            'default_class' => 'tab_bg_2',
            'title' => $LANG['plugin_holamundo']['title'],
        ));

        if ($canedit) {
            echo "<div class='center'>";
            echo Html::hidden('id', array('value' => $profiles_id));
            echo Html::submit(_sx('button', 'Save'), array('name' => 'update'));
            echo "</div>\n";
            Html::closeForm();
        }
        HTML::closeForm();
    }

    public static function uninstallProfile() {
        $pfProfile = new self();
        $a_rights = $pfProfile->getAllRights();
        foreach ($a_rights as $data) {
            ProfileRight::deleteProfileRights(array($data['field']));
        }
    }

}

5.2.- Creamos y editamos el archivo index.class.php en inc/


<?php

/*
 *
  -------------------------------------------------------------------------
  Plugin GLPI Example
  Copyright (C) 2017 by Walid H.
 */

if (!defined('GLPI_ROOT')) {
    die("Sorry. You can't access directly to this file");
}

class PluginHolamundoIndex extends CommonDBTM {

    static $rightname = 'plugin_holamundo';

    /**
     *
     * @return type
     */
    public static function getTypeName() {
      
    return $GLOBALS['LANG']['plugin_holamundo']['title'];
    }

      /**
     * Show the form (menu->plugin->holamundo)
     */
    public function formIndex() {
        echo "<form action='' method='post'>";
        echo '<div class="tab_cadre_fixe" style="box-shadow: 0 1px 8px #aaa;text-align:center;padding:1em;">';
        echo "<h1>Ver holamundo</h1>";
        echo "<p>...</p>";
        echo "</div>";
        html::closeForm();
    }


 /**
    * @see CommonGLPI::getAdditionalMenuLinks()
   **/
   static function getAdditionalMenuLinks() {
      global $CFG_GLPI;
      $links = array();

   //   $links['config'] = '/plugins/holamundo/front/link_cualquiera.php';
    //  $links["<img  src='".$CFG_GLPI["root_doc"]."/pics/menu_showall.png' title='".__s('Show all')."' alt='".__s('Show all')."'>"] = '/plugins/holamundo/front/link_cualquiera.php';
      $links[__s('Ver Link', 'holamundo')] = '/plugins/holamundo/front/link_cualquiera.php';

      return $links;
   }

}


6.- aqui agrego una clase que no esta declarada en ninguna lugar pero que yo denomino mis funciones, en este ejemplo solo tiene funciones de saludo, pero esto muestra la potencia de los plugins

creamos y editamos misfunciones.php en inc/

<?php

if (!defined('GLPI_ROOT')) {
   die("Sorry. You can't access directly to this file");
}


function printHolamundo () {//agregado


   global $DB, $CFG_GLPI, $LANG;

   $itemtype            = 0;
   $items_id            = "";
   $content             = "";
   $title               = "";
   $ticketcategories_id = 0;
   $urgency             = 3;
   $type                = 0;

   echo "Hola mundo...de aqui puedo llamar a cualquier cosa";

}

function printHolamundo2 () {//agregado


   global $DB, $CFG_GLPI, $LANG;

   $itemtype            = 0;
   $items_id            = "";
   $content             = "";
   $title               = "";
   $ticketcategories_id = 0;
   $urgency             = 3;
   $type                = 0;

   echo "aqui podría estar otro código que tenga relación con la creación";

}

?>

7.- en algunos de estos archivos hemos utilizado los locales por eso creamos el archivo es_VE.php que es mi idioma predeterminado

creamos y editamos el archivo es_VE.php en locales/

<?php

$LANG['plugin_holamundo']['title'] = "Titulo del plugin";
$LANG['plugin_holamundo']['manage_alerts'] = "Plugin de ejemplo para GLPI";


8.- creamos el archivo index.php en front/ que sera lo ṕrimero que veamos al invocar el plugin desde el menú



<?php
/*
 *
 -------------------------------------------------------------------------
 Plugin GLPI Example
 */

include ("../../../inc/includes.php");
include ('../inc/misfunciones.php'); //aqui esta parte de la lógica

Session::checkLoginUser();
session_start();



$plugin = new Plugin();
if (!$plugin->isInstalled("holamundo") || !$plugin->isActivated("holamundo")) {
   Html::displayNotFoundError();
}

Session::checkRight('plugin_holamundo', READ);

$app = new PluginHolamundoIndex();

Html::header(
   $LANG['plugin_holamundo']['title'],
   $_SERVER["PHP_SELF"],
   'plugins',
   "PluginHolamundoIndex"
);


//podriamos llamar a las funciones desde cualquier lado con include

//printHolamundo();


ó  utilizamos la herencia de la clase index


$app->formIndex();

if (Session::getCurrentInterface() == "helpdesk") {
   Html::helpFooter();
} else {
   Html::footer();
}


9.- con esto ya tienes un plugin en glpi que no hace nada, para que en el boton de busqueda de + haga algo (en nuestro caso mostrar otro mensaje) vamos a crear el archivo  index.form.php en front/



<?php
/*
 *
 -------------------------------------------------------------------------
 Plugin GLPI Example
 Copyright (C) 2017 by Walid H.
*/

include ("../../../inc/includes.php");
include ('../inc/misfunciones.php'); //aqui esta parte de la lógica

Session::checkLoginUser();
session_start();



$plugin = new Plugin();
if (!$plugin->isInstalled("holamundo") || !$plugin->isActivated("holamundo")) {
   Html::displayNotFoundError();
}

Session::checkRight('plugin_holamundo', READ);

$app = new PluginHolamundoIndex();

Html::header(
   $LANG['plugin_holamundo']['title'],
   $_SERVER["PHP_SELF"],
   'plugins',
   "PluginHolamundoIndex"
);



printHolamundo2();



if (Session::getCurrentInterface() == "helpdesk") {
   Html::helpFooter();
} else {
   Html::footer();
}

y por último en el paso 5.2 especificamente en la función  "static function getAdditionalMenuLinks()" estamos llamando a un archivo link_cualquiera.php

ese archivo hay que crearlo  en front/

<?php



include ("../../../inc/includes.php");


Session::checkLoginUser();
session_start();



$plugin = new Plugin();
if (!$plugin->isInstalled("holamundo") || !$plugin->isActivated("holamundo")) {
   Html::displayNotFoundError();
}

Session::checkRight('plugin_holamundo', READ);

$app = new PluginHolamundoIndex();

Html::header(
   $LANG['plugin_holamundo']['title'],
   $_SERVER["PHP_SELF"],
   'plugins',
   "PluginHolamundoIndex"
);

//aqui va lo que ve el usuario

echo ("me llamaron desde otro lugar");


//$app->formIndex();

if (Session::getCurrentInterface() == "helpdesk") {
   Html::helpFooter();
} else {
   Html::footer();
}

Eso es todo.






miércoles, 1 de agosto de 2018

Cómo descargar un vídeo de youtube en formato mp3 con youtube-dl



youtube-dl --extract-audio --audio-format mp3 URL //POR DEFAULT A 32Kbps


youtube-dl --extract-audio --audio-format mp3 --audio-quality 128K URL

lunes, 30 de julio de 2018

Cómo insertar una marca de agua a un pdf en debian 9

A veces es necesario insertar una marca de agua a un documento, en esta ocasión nos vamos a abocar en insertar una marca de agua a cualquier documento en formato pdf.

Posibles usos:
  • Tengo un documento editable, como word o writer o lo que sea.
  • Tengo un pdf al que quiero agregarle una marca de agua.
  • La persona propietaria del documento utiliza un software especial y no sabe como agregar una marca de agua.
Sean de windows o linux todos tienen la forma de exportar a pdf, por esta razón la forma más fácil de agregarle una marca de agua a un archivo es convirtiendolo a pdf y luego agregarle la marca de agua.

Previamente:
Se debe instalar pdftk

aptitude install  pdftk

y tener un archivo en pdf en blanco solo con la marca de agua.

Nota: Para realizar el archivo de marca de agua, lo más sencillo es realizarlo en writer y luego exportarlo a pdf

desde writer -->Formato-->Marca de agua...


y al darle "aceptar" aparecerá la marca de agua


Solo basta con exportarlo a pdf y ya tenemos nuestro archivo en blanco con el texto que queramos de marca de agua, en este caso Borrador.


y en consola


pdftk nombre_archivo_original.pdf stamp nombre_archivo_pdf_que_tiene_la_marca_de_agua.pdf output archivo_original_con_marca_de_agua.pdf

Por ahí encontré un script que lo hace de forma gráfica:


 #!/bin/sh
 # Desarrollado por Gustavo Báez Moreno

        FILE=`zenity --file-selection  --title="Selecciona el archivo pdf a insertar la marca de agua"`

        case $? in
                 0)
                        echo "\"$FILE\" seleccionado.";;
                 1)
                        echo "No ha seleccionado ningún archivo.";;
                -1)
                        echo "No ha seleccionado ningún archivo.";;
        esac
zenity --info \
          --text="Cuando acepte este cuadro se abrirá un diálogo para seleccionar el archivo que hará de marca de agua. El archivo que va a seleccionar como marca de agua debe ser pdf, no vale un jpg."

    FILE2=`zenity --file-selection --title="Selecciona el archivo pdf  que servirá de marca de agua"`

        case $? in
                 0)
                        echo "\"$FILE2\" seleccionado.";;
                 1)
                        echo "No ha seleccionado ningún archivo.";;
                -1)
                        echo "No ha seleccionado ningún archivo.";;
        esac


    salida=$(zenity --file-selection --save --confirm-overwrite);echo $salida
   
    pdftk "$FILE" stamp "$FILE2" output "$salida"


Para descargar el script y algunas marcas de aguas clic aqui Script y marcas de aguas en pdf





jueves, 26 de julio de 2018

Integrar ocs inventory con glpi


Descargar desde la siguiente dirección http://plugins.glpi-project.org/
el plugin OCS Inventory NG la versión correspondiente a su glpi

Luego lo descomprimen y colocan la carpeta en el directorio plugins de glpi y vía web lo instalan y lo activan.

Luego de eso lo configuran de la siguiente manera

Inicio-->Herramientas-->OCS Inventory NG


Luego se realiza el test de conexión, si todo esta bien sale que se pudo conectar correctamente.

En el caso que no se pueda conectar verifiquen que el mysql pueda ser accedido desde otra computadora






Aquí el mysql no puede ser accedido desde otra máquina, para solventar eso nos vamos a la maquina donde tenemos el mysql del ocsinventory instalado y editamos el siguiente archivo:

vi /etc/mysql/mariadb.conf.d/50-server.cnf

y en bind-address modificamos el 127.0.0.1 por 0.0.0.0 (para que todos tengan acceso desde cualquier lado ó colocamos la ip donde esta el glpi, para que esa sola máquina sea la que se conecte al mysql)

Luego reinician el mysql

service mysql restart

debería conectarse, pero si al hacer el test desde el glpi le sale esto:

Invalid OCSNG configuration (TRACE_DELETED must be active)

esto es porque en el servidor web ocsinventory  no esta habilitado

para habilitarlo clicn en configurar --> servidor



 y colocar en on




Luego volver a realizar el test desde el plugin de glpi y debería decir lo siguiente:





Para proceder a importar los computadores


 click en Importación de nuevas computadoras



Seleccionamos y damos clic a importar


Nota: el error no se aún porque se dió o que significa

Luego verificamos la correcta importación





y listo.



Integrar ocs inventory con glpi


Descargar desde la siguiente dirección http://plugins.glpi-project.org/
el plugin OCS Inventory NG la versión correspondiente a su glpi

Luego lo descomprimen y colocan la carpeta en el directorio plugins de glpi y vía web lo instalan y lo activan.

Luego de eso lo configuran de la siguiente manera

Inicio-->Herramientas-->OCS Inventory NG


Luego se realiza el test de conexión, si todo esta bien sale que se pudo conectar correctamente.

En el caso que no se pueda conectar verifiquen que el mysql pueda ser accedido desde otra computadora






Aquí el mysql no puede ser accedido desde otra máquina, para solventar eso nos vamos a la maquina donde tenemos el mysql del ocsinventory instalado y editamos el siguiente archivo:

vi /etc/mysql/mariadb.conf.d/50-server.cnf

y en bind-address modificamos el 127.0.0.1 por 0.0.0.0 (para que todos tengan acceso desde cualquier lado ó colocamos la ip donde esta el glpi, para que esa sola máquina sea la que se conecte al mysql)

Luego reinician el mysql

service mysql restart

debería conectarse, pero si al hacer el test desde el glpi le sale esto:

Invalid OCSNG configuration (TRACE_DELETED must be active)

esto es porque en el servidor web ocsinventory  no esta habilitado

para habilitarlo clicn en configurar --> servidor



 y colocar en on




Luego volver a realizar el test desde el plugin de glpi y debería decir lo siguiente:





Para proceder a importar los computadores


 click en Importación de nuevas computadoras



Seleccionamos y damos clic a importar


Nota: el error no se aún porque se dió o que significa

Luego verificamos la correcta importación





y listo.






miércoles, 25 de julio de 2018

Cómo asignar un tecnico o grupos de tecnicos a una categoría en glpi (Reglas en glpi) cuando el usuario crea el incidente


A manera educativa creamos una regla que asigne un técnico a una categoría en glpi

Administración-->Reglas

Seleccione "Reglas de negocio para servicios" y cree una nueva regla con el signo "+"






Nombre: Un nombre identificativo para la regla
Descripción: Una descripción de lo que hace la regla
Operador lógico: "y" o "o", dependiendo para que quiere la regla en este caso es "y".
Activo: Sí, si esta en no simplemente la regla no se ejecuta.
Usar regla para: "Agregar", "Actualizar" o "Agregar Actualizar", dependiendo para que quiere la regla en este caso es "agregar"

Luego en la pestaña "Criterios" click en "agregar un nuevo criterio":



Luego en la pestaña "Acciones" click en "agregar una acción":




Para probarla nos devolvemos a la pestaña "regla"


y le damos probar









En nuestro caso todo salio bien.


Quitar de la pnatalla de login el texto "¿Olvidó su contraseña? de glpi


Cuando los usuarios son autenticados con ldap, el método ¿Olvidó su Contraseña? no tiene sentido porque el usuario no puede cambiar su clave, debido a utilizar este método de autenticación.

Para quitarlo solo basta comentar dentro de la carpeta glpi el archivo index.php





No es necesario reiniciar el apache.



Transferir usuarios de una entidad a otra entidad en glpi


Administración --> Usuarios







Clic en el usuario para cambiarlo de entidad


En este punto podemos observar que aunque estamos en la entidad raiz y existiendo entidades previamente creadas, no se nos permite asignarle otra entidad a este usuario. Esto es debido a los permisos dinámicos que el usuario tiene cuando un usuario tiene (R=Recursivo y D=Dinámico).

Recursivo es que tiene toda la configuración en su entidad y las entidades hijas y Dinámico es que la configuración en su entidad es dada por reglas previamente establecidas.

Por defecto cuando se realiza una conexión ldap, se aplica la regla que todo usuario se crea en la entidad raiz o root. Por esta razón no podemos cambiar de entidad.

Para cambiarlo podríamos modificar la regla y decirle que una acción a tomar sea la de asignarle recursividad, pero aqui lo vamos hacer de otra forma.

clic en la pestaña autorizaciones



Aquí seleccionamos la entidad a la que queremos que vaya, seleccionamos el perfil root (pero podríamos seleccionar el que queramos, a nivel explicativo lo dejamos aquí) seleccionamos self-service y el recursivo seleccionamos Sí

Y luego podemos verificar que ya se le puede asignar otra entidad por defecto.







Luego de esto ya podríamos transferir el usuario o varios usuarios a cualquier otra entidad de la siguiente manera:





y se vera que el usuario cambio de entidad:







lunes, 23 de julio de 2018

Cómo ver los log de glpi



En el directorio _log del glpi

cd  /var/www/glpi/files/_log/
 
Allí se encuentran los siguientes archivos de registros de eventos:
 
*cron.log
*event.log
*mail.log
*notification.log
*php-errors.log
*remove.txt
*sql-errors.log
Entre otros.

Transferir elementos del inventario de una entidad a otra entidad en glpi



En nuestro ejemplo vamos a transferir dos (02) computadores de la entidad root a la entidad contabilidad, previamente creada:






Seleccionamos las (dos (02) computadoras y le damos click en Acciones y seleccionamos la opción "Agregar a lista de transferencia":



y le damos publicar.

Seleccionamos en "modo de transferencia" la opción complete:

Luego de eso se desplegara las siguientes opciones:


Aqui elegimos la entidad donde la queremos pasar (en nuestro caso contabilidad) y le damos ejecutar.

Luego comprobamos que efectivamente se haya realizado la transacción















Ocultar el campo "Avisarme sobre las acciones tomadas" en la interfaz simplificada en GLPI


Para ocultar este campo de la interfaz simplificada se debe comentar "NotificationTargetTicket::isAuthorMailingActivatedForHelpdesk())"

Si no sabemos donde esta, buscamos la aparición de esta cadena en todo el código de glpi:


Esto nos indica que en el archivo inc/ticket.class.php se encuetra esta cadena, la editamos y comentamos de la siguiente manera:


luego reiniciar el servidor web  y listo.

Campos únicos en glpi



Si se quiere que un campo como por ejemplo el serial de un computador no sea repetido se utiliza la funcionalidad de "campos únicos" de glpi:


Configuraciones-->Verificaciones

Damos click en el signo +


Nombre: Un nombre representativo.

Activo: Sí, para activar la regla

Tipo: Selecciona el tipo de inventario en el cual se encuentra el campo que desea que sea único, en mi caso "Computadora".

Campos únicos: Seleccione el campo que se desea que sea único, en mi caso "Número de Serie", aunque se pueden colocar más de un campo.

Registro en la base de datos denegado: Si se elige "Sí", el registro no podrá ser procesado.



Si se elige "No", el registro se hace pero muestra una advertencia diciendo que esta duplicado.



Enviar notificación: Sí se desea que glpi envié una notificación

Nota: Los campos únicos funcionan en la entidad que lo hayamos creado, si queremos que los campos sean únicos también en otra entidad, se debe tildar la opción "Subentidades" en Sí.

De esta forma si mueves equipos de entidad seguirá aplicando esta restricción.





jueves, 12 de julio de 2018

Modificar las plantillas de notificación vía email

 Inicio > Configuración > Notificaciones



Clic en "Plantillas de notificación"





Buscar la plantilla a modificar en este caso "Tickets" y  click en:

La pestaña "Plantilla de Notificación":






La pestaña "Traducciones de plantilla"






Se vera la traducción por defecto, he aquí la forma de trabajar de glpi.
Las traducciones son la forma de modificar las plantillas sin dañar la "traducción por defecto".

En nuestro caso de la Plantilla Tickets la traducción por defecto es 

 ##IFticket.storestatus=5##
 ##lang.ticket.url## : ##ticket.urlapprove##
 ##lang.ticket.autoclosewarning##
 ##lang.ticket.solvedate## : ##ticket.solvedate##
 ##lang.ticket.solution.type## : ##ticket.solution.type##
 ##lang.ticket.solution.description## : ##ticket.solution.description## ##ENDIFticket.storestatus##
 ##ELSEticket.storestatus## ##lang.ticket.url## : ##ticket.url## ##ENDELSEticket.storestatus##

 ##lang.ticket.description##

 ##lang.ticket.title## : ##ticket.title##
 ##lang.ticket.authors## : ##IFticket.authors## ##ticket.authors## ##ENDIFticket.authors## ##ELSEticket.authors##--##ENDELSEticket.authors##
 ##lang.ticket.creationdate## : ##ticket.creationdate##
 ##lang.ticket.closedate## : ##ticket.closedate##
 ##lang.ticket.requesttype## : ##ticket.requesttype##
##lang.ticket.item.name## :

##FOREACHitems##

 ##IFticket.itemtype##
  ##ticket.itemtype## - ##ticket.item.name##
  ##IFticket.item.model## ##lang.ticket.item.model## : ##ticket.item.model## ##ENDIFticket.item.model##
  ##IFticket.item.serial## ##lang.ticket.item.serial## : ##ticket.item.serial## ##ENDIFticket.item.serial##
  ##IFticket.item.otherserial## ##lang.ticket.item.otherserial## : ##ticket.item.otherserial## ##ENDIFticket.item.otherserial##
 ##ENDIFticket.itemtype##

##ENDFOREACHitems##
##IFticket.assigntousers## ##lang.ticket.assigntousers## : ##ticket.assigntousers## ##ENDIFticket.assigntousers##
 ##lang.ticket.status## : ##ticket.status##
##IFticket.assigntogroups## ##lang.ticket.assigntogroups## : ##ticket.assigntogroups## ##ENDIFticket.assigntogroups##
 ##lang.ticket.urgency## : ##ticket.urgency##
 ##lang.ticket.impact## : ##ticket.impact##
 ##lang.ticket.priority## : ##ticket.priority##
##IFticket.user.email## ##lang.ticket.user.email## : ##ticket.user.email ##ENDIFticket.user.email##
##IFticket.category## ##lang.ticket.category## : ##ticket.category## ##ENDIFticket.category## ##ELSEticket.category## ##lang.ticket.nocategoryassigned## ##ENDELSEticket.category##
 ##lang.ticket.content## : ##ticket.content##
 ##IFticket.storestatus=6##

 ##lang.ticket.solvedate## : ##ticket.solvedate##
 ##lang.ticket.solution.type## : ##ticket.solution.type##
 ##lang.ticket.solution.description## : ##ticket.solution.description##
 ##ENDIFticket.storestatus##
 ##lang.ticket.numberoffollowups## : ##ticket.numberoffollowups##

##FOREACHfollowups##

 [##followup.date##] ##lang.followup.isprivate## : ##followup.isprivate##
 ##lang.followup.author## ##followup.author##
 ##lang.followup.description## ##followup.description##
 ##lang.followup.date## ##followup.date##
 ##lang.followup.requesttype## ##followup.requesttype##

##ENDFOREACHfollowups##
 ##lang.ticket.numberoftasks## : ##ticket.numberoftasks##

##FOREACHtasks##

 [##task.date##] ##lang.task.isprivate## : ##task.isprivate##
 ##lang.task.author## ##task.author##
 ##lang.task.description## ##task.description##
 ##lang.task.time## ##task.time##
 ##lang.task.category## ##task.category##

##ENDFOREACHtasks##




 El correo que llega es el siguiente:



Al agregar una nueva traducción a la Plantilla Tickets
Nota: hay que seleccionar el idioma predeterminado de nuestro glpi, en el campo idioma.



##IFticket.storestatus=5##
 ##lang.ticket.url## : ##ticket.urlapprove##
 ##lang.ticket.autoclosewarning##
 ##lang.ticket.solvedate## : ##ticket.solvedate##
 ##lang.ticket.solution.type## : ##ticket.solution.type##
 ##lang.ticket.solution.description## : ##ticket.solution.description## ##ENDIFticket.storestatus##
 ##ELSEticket.storestatus## ##lang.ticket.url## : ##ticket.url## ##ENDELSEticket.storestatus##

 ##lang.ticket.description##

 ##lang.ticket.title## : ##ticket.title##
 ##lang.ticket.authors## : ##IFticket.authors## ##ticket.authors## ##ENDIFticket.authors## ##ELSEticket.authors##--##ENDELSEticket.authors##
 ##lang.ticket.creationdate## : ##ticket.creationdate##
 ##lang.ticket.closedate## : ##ticket.closedate##


##IFticket.assigntousers## ##lang.ticket.assigntousers## : ##ticket.assigntousers## ##ENDIFticket.assigntousers##
 ##lang.ticket.status## : ##ticket.status##
##IFticket.assigntogroups## ##lang.ticket.assigntogroups## : ##ticket.assigntogroups## ##ENDIFticket.assigntogroups##
##IFticket.user.email## ##lang.ticket.user.email## : ##ticket.user.email ##ENDIFticket.user.email##
##IFticket.category## ##lang.ticket.category## : ##ticket.category## ##ENDIFticket.category## ##ELSEticket.category## ##lang.ticket.nocategoryassigned## ##ENDELSEticket.category##
 ##lang.ticket.content## : ##ticket.content##
 ##IFticket.storestatus=6##

 ##lang.ticket.solvedate## : ##ticket.solvedate##
 ##lang.ticket.solution.type## : ##ticket.solution.type##
 ##lang.ticket.solution.description## : ##ticket.solution.description##
 ##ENDIFticket.storestatus##
 ##lang.ticket.numberoffollowups## : ##ticket.numberoffollowups##

##FOREACHfollowups##

 [##followup.date##] ##lang.followup.isprivate## : ##followup.isprivate##
 ##lang.followup.author## ##followup.author##
 ##lang.followup.description## ##followup.description##
 ##lang.followup.date## ##followup.date##
 ##lang.followup.requesttype## ##followup.requesttype##

##ENDFOREACHfollowups##
 ##lang.ticket.numberoftasks## : ##ticket.numberoftasks##

##FOREACHtasks##

 [##task.date##] ##lang.task.isprivate## : ##task.isprivate##
 ##lang.task.author## ##task.author##
 ##lang.task.description## ##task.description##
 ##lang.task.time## ##task.time##
 ##lang.task.category## ##task.category##

##ENDFOREACHtasks##



 El correo que llega es el siguiente:



Como saber el nombre de las etiquetas a cambiar





Click en "Mostrar lista de etiquetas disponibles" ya lo demás es configurarlo a nuestro gusto.