Módulo vTiger para crear nuevas Entidades
La gran mayoria de las empresas hoy en día, con la evolución de la tecnología y por el aumento de los datos que se manejan dentro de ellas, necesitan de una plataforma CRM, siglas que significan Gestion de Relación con Clientes, como su nombre lo indica, es un software que se utiliza para la administracion de las relaciones entre las empresas y sus clientes o potenciales, por ejemplo, cada vez que una empresa se pone en contacto con un cliente o potencial se tiene la opción de introducir esos datos en el CRM de manera que siempre están disponibles y compartidos entre todas las areas de la empresa por ejemplo; contabilidad puede añadir una factura asignada a un cliente; se pueden tener las cotizaciones realizadas a los clientes o vincular a un prospecto o cliente potencial con sus productos o servicios de interés.
Podemos decir que en el contexto de plataformas open source y de caracter CRM vTiger ocupa un lugar muy privilegiado.
Una de las peticiones que se hacen a los desarrolladores a menudo para CRM, es la introducción de nuevas entidades: una entidad puede ser definida como un objeto que interactúa con otros componentes del software y cuenta con campos característicos; podemos considerar como entidad u objeto todo lo que nos rodea, como animales, vehículos, plantas o las personas mismas.
En el caso de un CRM, las entidades son simplemente contactos, empresas, productos, o cualquier cosa que pueda relacionarse con un contacto o un cliente.
A modo de ejemplo podemos querer crear una nueva entidad, llamada Curso, a través de un módulo de VTiger que se creará dentro de nuestra instalación.
Para entender mejor el uso de esta nueva entidad, supongamos que deseamos administrar una universidad. Cada contacto es un estudiante y nuestra secretaria quiere registrar sus datos y relacionarlo con los cursos a los que asisten a fin de conocer, para cada estudiante, cuáles son los cursos a los que todo el mundo asiste.
Un curso se define por:
- Código del curso: el código del curso de acuerdo con un identificador único
- Nombre: el nombre del curso para el que quiera participar
- Año academico: el curso académico durante el cual el curso está disponible
- Descripción: una descripción del curso y los temas tratados
- Creditos: un número de créditos universitarios
- Profesor: el profesor que da el curso
Nuestra entidad se llamará Cursos, con muy poca imaginación.
Empezamos a continuación, después de esta larga introducción, con el desarrollo.
VTiger proporciona un lenguaje llamado VTLib para la creación de módulos y extensiones.
Creamos en el directorio raíz de la instalación de un archivo llamado VTiger Cursos.php.
$Vtiger_Utils_Log = true;
include_once('vtlib/Vtiger/Menu.php');
include_once('vtlib/Vtiger/Module.php');
// Crea modulo
$module = new Vtiger_Module();
$module->name = 'Cursos';
$module->parent = "Tools";
$module->version = 1.0;
$module->save();
$module->initWebservice();
$module->initTables();
$block1 = new Vtiger_Block();
$block1->label = 'LBL_CURSOS_INFORMATION';
$module->addBlock($block1);
//Creación de campos
// Código del curso
$field1 = new Vtiger_Field();
$field1->name = 'curso_code';
$field1->label = 'Codigo del Curso';
$field1->table = $module->basetable;
$field1->column = 'curso_code';
$field1->columntype = 'VARCHAR(255)';
$field1->uitype = 2;
$field1->typeofdata = 'V~M';
$block1->addField($field1);
$module->setEntityIdentifier($field1);
// Titulo del curso
$field2 = new Vtiger_Field();
$field2->name = 'curso_title';
$field2->label = 'Nombre del Curso';
$field2->table = $module->basetable;
$field2->column = 'curso_title';
$field2->columntype = 'VARCHAR(512)';
$field2->uitype = 2;
$field2->typeofdata = 'V~M';
$block1->addField($field2);
// Docente
$field3 = new Vtiger_Field();
$field3->name = 'teacher';
$field3->label= 'Teacher';
$field3->table = $module->basetable;
$field3->column = 'contact';
$field3->columntype = 'VARCHAR(255)';
$field3->uitype = 10;
$field3->typeofdata = 'V~M';
$field3->helpinfo = 'Relate to a contact';
$block1->addField($field3);
$field3->setRelatedModules(Array('Contacts'));
// Año Academico
$field4 = new Vtiger_Field();
$field4->name = 'accademic_year';
$field4->label = 'Año academico';
$field4->table = $module->basetable;
$field4->column = 'accademic_year';
$field4->columntype = 'VARCHAR(255)';
$field4->uitype = 15;
$field4->setPicklistValues( array("2012/2013","2013/2014","2014/2015","2015/2016","2016/2017","2017/2018") );
$field4->typeofdata = 'V~O';
$block1->addField($field4);
// Creditos Formativos
$field5 = new Vtiger_Field();
$field5->name = 'creditos';
$field5->label= 'Creditos';
$field5->table = $module->basetable;
$field5->column = 'creditos';
$field5->columntype = 'DECIMAL(25,2)';
$field5->uitype = 7;
$field5->typeofdata = 'N~O';
$block1->addField($field5);
// Descripcion
$field6 = new Vtiger_Field();
$field6->name = 'description';
$field6->label= 'Description';
$field6->table = $module->basetable;
$field6->column = 'description';
$field6->columntype = 'TEXT';
$field6->uitype = 19;
$field6->typeofdata = 'V~O';
$block1->addField($field6);
// Fecha de inicio
$field7 = new Vtiger_Field();
$field7->name = 'start_date';
$field7->label= 'Fecha de inicio';
$field7->table = $module->basetable;
$field7->column = 'start_date';
$field7->columntype = 'DATE';
$field7->uitype = 5;
$field7->typeofdata = 'D~O';
$block1->addField($field7);
//Usuario Asignado
$field8 = new Vtiger_Field();
$field8->name = 'assigned_user_id';
$field8->label = 'Assigned To';
$field8->table = $module->basetable;
$field8->column = 'assigned_user_id';
$field8->table = 'vtiger_crmentity';
$field8->column = 'smownerid';
$field8->uitype = 53;
$field8->typeofdata = 'V~M';
$block1->addField($field8);
// Fecha de Creacion
$field9 = new Vtiger_Field();
$field9->name = 'createdtime';
$field9->label= 'Created Time';
$field9->table = 'vtiger_crmentity';
$field9->column = 'createdtime';
$field9->uitype = 70;
$field9->typeofdata = 'T~O';
$field9->displaytype= 2;
$block1->addField($field9);
// Fecha de Modificacion
$field10 = new Vtiger_Field();
$field10->name = 'modifiedtime';
$field10->label= 'Modified Time';
$field10->table = 'vtiger_crmentity';
$field10->column = 'modifiedtime';
$field10->uitype = 70;
$field10->typeofdata = 'T~O';
$field10->displaytype= 2;
$block1->addField($field10);
//Búsqueda genérica de creación de filtros
$filter1 = new Vtiger_Filter();
$filter1->name = 'All';
$filter1->isdefault = true;
$module->addFilter($filter1);
$filter1->addField($field1)
->addField($field2)
->addField($field3)
->addField($field4)
->addField($field5)
->addField($field6)
->addField($field7)
->addField($field8)
->addField($field9)
->addField($field10);
// Adición de contactos como una lista de RELACIONADOS
$contacts = Vtiger_Module::getInstance('Contacts');
$contacts->setRelatedList(Vtiger_Module::getInstance('Cursos'), 'Cursos', Array('ADD'),'get_dependents_list');
$module->setDefaultSharing('Private');
$module->enableTools(Array('Import', 'Export'));
$module->disableTools('Merge');
$moduleInstance = Vtiger_Module::getInstance('Cursos');
$moduleInstance->initWebservice();
// Adición de forma para la creación de los comentarios sobre el alcance del modulo
$commentsModule = Vtiger_Module::getInstance('ModComments');
$fieldInstance = Vtiger_Field::getInstance('related_to', $commentsModule);
$fieldInstance->setRelatedModules(array("Cursos"));
$detailviewblock = ModComments::addWidgetTo('Cursos');
echo 'addEntityMethod complete!';
Para ejecutar el script, vamos con el navegador a:
[url nostro sito]/Cursos.php
El resultado se muestra en la imagen y demuestra que VTiger se ha hecho cargo y ejecutar nuestro script.
En este punto es necesario crear una carpeta para crear los archivos de módulo.
Acceder a la carpetas módulos disponibles en la ubicación principal de nuestra instalación de VTiger y creamos la carpeta de nuestro módulo, la carpeta se llamará Cursos.
En el interior se crea un archivo llamado Cursos.php cuyo contenido se detalla a continuación.
require_once('data/Tracker.php');
require_once 'include/Webservices/Create.php';
require_once 'include/Webservices/Update.php';
require_once 'include/Webservices/Delete.php';
require_once 'include/Webservices/Revise.php';
require_once 'include/Webservices/Retrieve.php';
require_once 'include/Webservices/DataTransform.php';
require_once 'vtlib/Vtiger/Utils.php';
require_once 'data/CRMEntity.php';
require_once 'include/QueryGenerator/QueryGenerator.php';
require_once 'vtlib/Vtiger/Mailer.php';
class Cursos extends CRMEntity {
var $db, $log; // Used in class functions of CRMEntity
var $table_name = 'vtiger_cursos';
var $table_index= 'cursosid';
var $column_fields = Array();
/** Indicator if this is a custom module or standard module */
var $IsCustomModule = true;
/**
* Mandatory table for supporting custom fields.
*/
var $customFieldTable = Array('vtiger_corsoscf', 'cursosid');
/**
* Mandatory for Saving, Include tables related to this module.
*/
var $tab_name = Array('vtiger_crmentity','vtiger_cursos','vtiger_cursoscf');
/**
* Mandatory for Saving, Include tablename and tablekey columnname here.
*/
var $tab_name_index = Array(
'vtiger_crmentity'=>'crmid',
'vtiger_cursos'=>'cursosid',
'vtiger_cursoscf'=>'cursosid');
/**
* Mandatory for Listing (Related listview)
*/
var $list_fields = Array(
/* Format: Field Label => Array(tablename, columnname) */
// tablename should not have prefix 'vtiger_'
'Curso code' => Array('cursos' => 'curso_code'),
'Title' => Array('cursos' => 'curso_title'),
'Teacher' => Array('cursos' => 'teacher'),
'Accademic Year' => Array('cursos' => 'accademic_year'),
'Creditos' => Array('cursos' => 'creditos'),
'Description' => Array('cursos' => 'description'),
'Start date' => Array('cursos' => 'start_date'),
'End Date' => Array('cursos' => 'end_date'),
'Assigned to' => Array('cursos' => 'assigned_user_id'),
);
var $list_fields_name = Array(
/* Format: Field Label => fieldname */
'Curso code' => 'curso_code',
'Title' => 'curso_title',
'Teacher' => 'teacher',
'Accademic Year' => 'accademic_year',
'Creditos' => 'creditos',
'Description' => 'description',
'Start date' => 'start_date',
'End Date' => 'end_date',
'Assigned to' => 'assigned_user_id',
);
// Make the field link to detail view
var $list_link_field= 'name';
// For Popup listview and UI type support
var $search_fields = Array(
/* Format: Field Label => Array(tablename, columnname) */
// tablename should not have prefix 'vtiger_'
'Curso code' => Array('cursos' => 'curso_code'),
'Title' => Array('cursos' => 'curso_title'),
'Teacher' => Array('cursos' => 'teacher'),
'Accademic Year' => Array('cursos' => 'accademic_year'),
'Credito' => Array('cursos' => 'creditos'),
'Description' => Array('cursos' => 'description'),
'Start date' => Array('cursos' => 'start_date'),
'End Date' => Array('cursos' => 'end_date'),
'Assigned to' => Array('cursos' => 'assigned_user_id'),
);
var $search_fields_name = Array(
/* Format: Field Label => fieldname */
'Curso code' => 'curso_code',
'Title' => 'curso_title',
'Teacher' => 'teacher',
'Accademic Year' => 'accademic_year',
'Creditos' => 'creditos',
'Description' => 'description',
'Start date' => 'start_date',
'End Date' => 'end_date',
'Assigned to' => 'assigned_user_id',
);
// For Popup window record selection
var $popup_fields = Array ('curso_code','curso_title');
// Placeholder for sort fields - All the fields will be initialized for Sorting through initSortFields
var $sortby_fields = Array();
// For Alphabetical search
var $def_basicsearch_col = 'curso_title';
// Required Information for enabling Import feature
var $required_fields = Array('curso_code' => 1,'curso_title' => 2);
// Used when enabling/disabling the mandatory fields for the module.
// Refers to vtiger_field.fieldname values.
var $mandatory_fields = Array('curso_code','curso_title');
// Callback function list during Importing
var $special_functions = Array('set_import_assigned_user');
var $default_order_by = 'curso_code';
var $default_sort_order='ASC';
var $unit_price;
function __construct() {
global $log;
$this->column_fields = getColumnFields(get_class($this));
$this->db = PearDatabase::getInstance();
$this->log = $log;
}
function save_module($module){
//module specific save
}
}
Podemos encontrar un ejemplo de cómo implementar esta clase directamente en la carpeta VTiger
vtlib/ModuleDir/6.0.0
donde un ejemplo de la carpeta módulo está disponible.
Ahora nuestra aplicación estará disponible en la interfaz principal. Al igual que hemos solicitado, seleccionaremos cursos dentro del menú Herramientas. Al seleccionar este tema, la pantalla que aparecerá será el siguiente.
No es esto lo que esperábamos o esperábamos encontrar, pero sigue siendo un buen resultado.
Como podemos ver faltan algunas traducciones como "SINGLE_Cursos" Para resolver este problema se acaba de crear una carpeta en el idioma deseado, y crear un archivo con el nombre del módulo, por lo que en nuestro caso, que quieren entrar en la traducción para el idioma Inglés, vamos a crear el archivo.
languages/en_us/Cursos.php
que contendrá las traducciones de la no traducida, por lo que, por ejemplo:
<?php
$languageStrings = array(
"SINGLE_Courses" => "Course",
"LBL_COURSES_INFORMATION" => "Course Details"
);
La segunda cadena de traducción nos servirá en la forma de la nueva creación entidad.
Podemos crear archivos de idioma para cada uno de los idiomas disponibles, será suficiente para crear un archivo de este tipo en la carpeta correspondiente a su idioma preferido.
Ahora vamos a tratar de crear una nueva entidad. Recordemos que dicho módulo para tener un campo llamado "Maestro" que está conectado a los contactos por lo que tendrá que crear en primer lugar un tipo de contacto entidades.
Ahora podemos seleccionar "Agregar" para crear una nueva entidad, conseguir este formulario para introducir datos.
Como podemos ver todos los campos disponibles definidos en nuestro script de creación.
Basta con introducir los valores en los campos y hacer que la entidad de rescate.
Será posible asociar un contacto de un curso al detallar el contacto y la selección de la columna de la izquierda el nombre de nuestro módulo. Esta es una manera muy fácil de definir un tipo de inscripción y pista.
Todavía hay muchas sutilezas que se pueden definir, pero por ahora podemos decir que han alcanzado el objetivo deseado, por lo que gran trabajo!