MANUAL PROGRAMACIÓN EXPERTIS
Transcripción
MANUAL PROGRAMACIÓN EXPERTIS
MANUAL PROGRAMACIÓN EXPERTIS Versión Expertis 5 R2 Solmicro Organización y Software S.L. Versión 1.4 / Mayo 2014 Manual Programación Expertis ÍNDICE 1. INTRODUCCIÓN A EXPERTIS Información de Expertis ............................................................................................................................................5 Estructura de Expertis ...............................................................................................................................................5 2. CONFIGURACIÓN PUESTO DESARROLLO Herramientas y Componentes...................................................................................................................................6 Esquema de Directorio ..............................................................................................................................................6 Diseñador de Expertis ...............................................................................................................................................7 GAC de Windows ......................................................................................................................................................9 Templates y Snippets de Expertis .............................................................................................................................10 3. DISTRIBUCIÓN DE CAPAS 3.1. CAPA DE DATOS Introducción Capa de Datos...............................................................................................................................16 Tipificación de Campos......................................................................................................................................16 Base de Datos de Sistema y de Usuario ............................................................................................................17 Actualización de Metadatos ...............................................................................................................................17 Campos de Auditoría Automáticos .....................................................................................................................19 Tablas Satélites .................................................................................................................................................19 Consideraciones Generales ...............................................................................................................................21 3.2. CAPA DE NEGOCIO Introducción Capa de Negocio ...........................................................................................................................22 Entidad 1. Metodo AddNew ..................................................................................................................................23 2. Método AddNewForm ..........................................................................................................................23 3. Método Delete......................................................................................................................................23 4. Método Validate ...................................................................................................................................23 5. Método Update ....................................................................................................................................23 6. Método Filter ........................................................................................................................................24 7. Método SelOnPrimaryKey ...................................................................................................................24 8. Método GetItemRow ............................................................................................................................24 9. Método ApplyBusinessRules ...............................................................................................................24 Tarea .................................................................................................................................................................25 Documento 1. Concepto .............................................................................................................................................26 2. Creación y Manejo ...............................................................................................................................26 Proceso 1. Concepto .............................................................................................................................................27 2. Bucles y Condicionales ........................................................................................................................28 3. Control de Excepciones .......................................................................................................................29 4. Llamadas a Procesos ..........................................................................................................................30 1/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis 5. Ejemplo Creación Proceso ..................................................................................................................30 Programación General en la Capa de Negocio 1. Creación/Configuración de Proyectos de Negocio ...............................................................................36 2. Creación de Entidades en Negocio......................................................................................................41 3. Creación de Tareas .............................................................................................................................43 4. Llamada a Tareas en Capa Negocio ...................................................................................................44 5. Procesos de Entidades 1. Proceso RegisterValidateTasks ....................................................................................................46 2. Proceso RegisterUpdateTasks .....................................................................................................47 3. Proceso RegisterAddNewTasks ...................................................................................................50 4. Proceso RegisterDeleteTasks.......................................................................................................51 5. Proceso GetBusinessRules ..........................................................................................................52 Componentes de Motor en Capa Negocio 1. AdminData ....................................................................................................................................54 2. BusinessHelper ............................................................................................................................56 3. ApplicationService ........................................................................................................................57 4. IPropertyAccessor ........................................................................................................................57 5. UpdatePackage ............................................................................................................................58 6. ServiceProvider ............................................................................................................................58 7. ContextBoundObject ....................................................................................................................59 Configuración del Manager para procesar Capa Negocio .................................................................................60 Extensibilidad de Procesos y Tareas 1. Sobreescritura de Clases .............................................................................................................62 2. Sobreescritura de Documentos ....................................................................................................63 3. Ejemplos.......................................................................................................................................66 3.3. CAPA DE PRESENTACIÓN Introducción Capa de Presentación ...................................................................................................................76 Creación / Configuración de Proyectos de Presentación ...................................................................................77 Llamada a Tareas de Negocio desde Presentación...........................................................................................83 Tipos de Formularios Expertis 1. Formas de Creación de Formularios ............................................................................................83 2. Formulario Tipo Tabla ..................................................................................................................88 3. Formulario Tipo Ficha ...................................................................................................................90 4. Formulario Tipo Mantenimiento Simple ........................................................................................93 5. Formulario Tipo Consulta Interactiva ............................................................................................97 6. Formulario Tipo Consulta Interactiva Padre .................................................................................101 Controles de Expertis en Presentación 1. Agregar Controles de Expertis a Barra de Herramientas ..............................................................102 2. AdvSearch ....................................................................................................................................104 3. CounterTextBox............................................................................................................................107 4. ComboBox ....................................................................................................................................108 5. CalendarBox .................................................................................................................................114 6. NumericTextBox ...........................................................................................................................115 7. TextBox ........................................................................................................................................116 8. Grid ...............................................................................................................................................117 2/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis 9. UnderLineLabel ............................................................................................................................125 10. Label.............................................................................................................................................125 11. RadioButton ..................................................................................................................................126 12. CheckBox .....................................................................................................................................127 13. Otros Controles a. Panel ..............................................................................................................................128 b. Frame .............................................................................................................................128 c. Tab .................................................................................................................................128 Acciones Locales ...............................................................................................................................................130 Acciones Globales .............................................................................................................................................131 Parametros Formularios .....................................................................................................................................134 Componentes de Motor en Presentación 1. BE.DataEngine ....................................................................................................................................135 2. ExpertisApp .........................................................................................................................................135 Configuración del Manager de Datos de la Capa de Presentación ....................................................................136 4. PROGRAMACIÓN GENERAL Enumerados ..............................................................................................................................................................138 Filter ..........................................................................................................................................................................140 Contadores ...............................................................................................................................................................142 Parámetros ...............................................................................................................................................................145 Agrupaciones ............................................................................................................................................................146 ProviderNeededData.................................................................................................................................................148 Login en Expertis para Ejecutables Externos ............................................................................................................149 Cambio de Base de Datos en MultiEmpresa .............................................................................................................150 Transacciones ...........................................................................................................................................................150 Filtrado Horizontal .....................................................................................................................................................151 Extensibilidad en Mensajería y Alertas de Expertis ...................................................................................................154 5. PROYECTOS EXPERTIS Proyectos Presentación ............................................................................................................................................154 Proyectos Negocio ....................................................................................................................................................163 Proyectos Motor ........................................................................................................................................................165 6. VARIOS Objeto Datatable .......................................................................................................................................................167 Modificadores de Métodos ........................................................................................................................................167 Atributo Shared .........................................................................................................................................................168 Genéricos ..................................................................................................................................................................168 ? Atributo Nulo en Variables......................................................................................................................................168 Componente BackgroundWorker ..............................................................................................................................168 LINQ To SQL ............................................................................................................................................................171 7. REMOTING 3/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Consideraciones .......................................................................................................................................................172 Errores Comunes ......................................................................................................................................................172 Configuración Remoting Puesto Cliente y Servidor ..................................................................................................173 8. INFORMES Introducción a Informes en Expertis ..........................................................................................................................175 Tipos de Informes Registro Actual...................................................................................................................................................175 Criterio Selección ...............................................................................................................................................177 Tabla Auxiliar .....................................................................................................................................................178 RecordSet ..........................................................................................................................................................179 Sin Filtro .............................................................................................................................................................179 Personalizado ....................................................................................................................................................179 Configuración del Manager de Datos de Informes ....................................................................................................179 Servicio de Informes .................................................................................................................................................180 Tipos de Conexión ....................................................................................................................................................181 Eventos Informes ......................................................................................................................................................183 9. HERRAMIENTAS DE EXPERTIS Consola de Administración .......................................................................................................................................185 DataBase Comparer .................................................................................................................................................195 Expertis.Tools.Translator ..........................................................................................................................................198 Expertis.Tools.CRConnectionUpdater ......................................................................................................................199 Federated Search & SmartTags ................................................................................................................................ 202 Doble Expertis Host en Servidor ...............................................................................................................................204 4/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis 1. INTRODUCCIÓN A EXPERTIS Información de Expertis Expertis es una aplicación desarrollada en plataforma Windows. Se basa en el componente de Microsoft de .NetFrameWork 3.5. La aplicación está estructurada en varias capas aprovechando esta tecnología de Microsoft. Para la comunicación entre capas se usa la tecnología de remoting. La parte de base de datos nos apoyamos en versiones de SQL Server 2000 o posteriores. Para los informes presentados en la aplicación usamos Crystal Reports en su versión 11 Release 2 para la versión 5.0 de Expertis. Nos servimos también para la parte de presentación de eXpertis de controles de Windows de Janus. Es importante entender cómo está estructurado eXpertis en las diferentes capas, qué función tiene cada capa y qué debemos programar en qué una de ellas. Volver al Índice Estructura de Expertis Expertis es una aplicación distribuida a 3 capas: Datos -> Negocio -> Presentación. En las cuales está presente en todas ellas el motor de eXpertis para su manejo. Para las partes de negocio y presentación nos apoyamos en el .NetFrameWork de Microsoft. Iremos viendo a lo largo de este manual esta distribución a 3 capas de eXpertis y qué funcionalidades tendremos en cada capa. Tenemos que tener claro que para el manejo en cualquiera de los niveles / capas tendremos presente el motor de eXpertis en todo momento para darnos la funcionalidad necesaria. Esto nos ayudará tanto en fiabilidad de la ejecución de la funcionalidad, como rapidez, tanto en ejecución, como en el desarrollo funcional. Volver al Índice 5/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis 2. CONFIGURACIÓN PUESTO DESARROLLO Herramientas y Componentes Para la configuración de un puesto de desarrollo se deben instalar las siguientes aplicaciones y componentes: 1. SQL Server 2008 - 2012: Las base de datos de Expertis 5 son suministradas en SQL2008, pudiendo funcionar en superiores. 2. Microsoft Visual Studio .Net 2008 Development Edition: La instalación de Microsoft Visual Studio .Net 2008 instala Microsoft Framework 3.5. 3. Microsoft Visual Studio .NET 2008 Service Pack 1: Este service pack se puede encontrar en la web de actualizaciones de Microsoft. 4. Net Framework 3.5 SP1: Este service pack se puede descargar a través de Windows Update de Microsoft 5. Janus Winforms Controls Suite v3.0 for .NET: Se recomienda, aunque no es obligatorio, agregar los ensamblados de Janus a la GAC. Ver agregar ensamblados a la cache global. Esto lo suele hacer de manera automática el propio instalador de Janus pero asegurarse de que lo hace así efectivamente. 6. Janus Controls v3 Patch 35109: JanusWinFormsV35Patch.msi instala la versión 3.5.1.09 de los ensamblados de Janus. 7. Crystal Reports XI Release 2 / Msi Crystal Reports XIII 8. Diseñador de Expertis R2: En el paquete de distribución de Expertis se incluye el paquete de instalación del diseñador (ExpertisDesignerSetup.msi). Ver el apartado Diseñador de Expertis. 9. Snippets y Templates de Expertis: instalable con fragmentos de código y plantillas de objetos de expertis para la programación. 10. Windows Update: Ejecutar y revisar los Windows Update del Sistema Operativo. 11. DataBase Comparer: programa de solmicro para poder llevar a cabo comparaciones de estructura de datos entre bases de datos, para poder extraer scripts de actualizaciones. Se dispone tanto de una versión 2000 como de 2008. 12. Expertis Tools Translator R2: herramienta de expertis para poder procesar del código fuente de origen todos los textos y mensajes para llevar a cabo la traducción, 13. Expertis Tools CRConnectionUpdater: herramienta de reconexión de informes de cristal reports. Se usa generalmente para reconectar los informes contra la BD final del cliente final para una mayor velocidad de procesamiento. Volver al Índice Esquema de Directorios La ubicación de las fuentes de desarrollo y los ensamblados compilados es importante, sobre todo si en el proceso de desarrollo interviene más de un desarrollador y además se utiliza un sistema de control de código fuente. El hecho de que todos los componentes de un grupo de desarrollo compartan un mismo esquema de directorios agiliza las pruebas que tiene que realizar cada programador, y facilita la posterior compilación y distribución de los ensamblados, además evita posibles confusiones entre las diferentes versiones que se pueden manejar para un mismo proyecto. NOTA: Como ejemplo se propone la estructura de carpetas que se utiliza en los proyectos de Solmicro. El esquema de directorios de trabajo se compone de los siguientes directorios: C:\ExpertisNet50\Main\Source\Application C:\ExpertisNet50\Main\Source\Business C:\ExpertisNet50\Main\Reports C:\ExpertisNet50\Bin C:\ExpertisNet50\Bin\Informes C:\ExpertisNet50\Bin\Recursos\Imagenes El directorio Bin contiene todos los archivos necesarios para ejecutar la aplicación en desarrollo: Ensamblados del Engine de Expertis (Expertis.Engine.*). 6/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Ensamblados de Presentación de Expertis (Expertis.Application.ERP.*). Ensamblados de Negocio de Expertis (Expertis.Business.*) Archivo de Configuración de Sistema (System.Config) Archivo de Configuración de Carcasa de Expertis (Expertis.Engine.UI.Shell.exe.config) Ensamblados de Janus WinControls (Janus.Windows.*.v3.dll) Ensamblados de Infragistics Controls (Infragistics3.*) Fichero de Licencia de Expertis (Expertis.Lic) Ensamblado de Plataforma GAIA (CegaiaDll.dll) Ensamblado de Diseñador para equipos de desarrollo ( Expertis.Engine.UI.Design.dll) Ensamblados de Firma Electrónica de XML Facturae (BouncyCastle.Crypto.dll y Xades.dll) Ensamblado de Firma Electrónica PDF (PDFSignDll.dll) Ensamblado de Microsoft Point of Service para TPV (Microsoft.PointOfService.dll) Directorio de informes (Reports) Directorio de recursos (Recursos de Imágenes y Iconos) Volver al Índice Diseñador de Expertis El diseñador de eXpertis es un Add-in que se integra en el entorno de desarrollo de Visual Studio. Se ha creado con el objeto de facilitar ciertas tareas en tiempo de diseño como, por ejemplo, la creación de controles consumidores de datos o la carga de columnas de los controles grid. En el paquete de distribución de eXpertis se proporciona el paquete de instalación ExpertisDesignerSetup.msi. Una vez instalado el complemento se abre desde el menú Herramientas -> Diseñador de Expertis. La primera vez que arranquemos el diseñador de eXpertis tendremos un aspecto parecido a este: Como primer paso pulsaremos el botón de Sistema para establecer la conexión con una base de datos de Sistema. 7/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Esta configuración se guarda en el fichero Expertis.Designer.config en programa\Solmicro\Expertis Designer Tool\VS2008 (Ruta por defecto del Instalador). la ruta C:\Archivos de A continuación tendremos disponible en el despegable de Aplicación todas las bases de datos dadas de alta en el sistema que nos hemos conectado. Seleccionamos la base de datos con la que queremos trabajar. Para refrescar los datos obtenidos por el diseñador de la base de datos dispondremos del botón de Actualizar. Como último botón tendremos la Opción de MetaDatos que nos permite regenerar la información de tablas, vistas, campos, etc.. de la base de datos de usuario que estamos en la base de datos de sistema a la que estamos conectados. La ventana tendría este aspecto y bastaría con pulsar el botón de Actualizar tablas de campos y relaciones. Esta utilidad sería la misma que utilizar el procedimiento almacenado de sistema de xCargarSistema disponible en las bases de datos de Sistema. 8/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis NOTA: si tenemos fallos o problemas con el diseñador de eXpertis puede ser necesario introducir las Dlls del Engine en la GAC de Windows quedando de la siguiente manera: NOTA: tener en cuenta que si actualizamos las dll’s de motor de eXpertis en nuestro bin, tendríamos que reactualizar estas dll’s metidas en la GAC de Windows. NOTA: para el correcto funcionamiento y diseño de proyectos de de presentación, debemos tener en nuestro Bin de eXpertis la dll de Expertis.Engine.UI.Design.dll. Esto es muy importante, ya que si no la tenemos presente, puede que nos haga cambios no deseados en proyectos de presentación. Volver al Índice GAC de Windows Para poder usar correctamente el Diseñador de eXpertis y sin errores, es necesario y obligatorio el llevar a la GAC de Windows las dlls del motor de eXpertis del Bin que trabajemos. Con esto tenemos que tener en cuenta que si actualizamos el motor de eXpertis a una nueva versión, éstas dlls hay que actualizarlas también en la GAC. Para ello basta con que arastremos las dlls del motor de expertis de nuestro bien a la carpeta: C:\Windows\Assembly. Conviene tener abiertas dos ventanas del explorador de Windows, la primera ventana con el directorio donde están los ensamblados que se quieren agregar a la GAC, y la segunda ventana con el directorio C:\Windows\assembly, que es la ubicación del sistema que utiliza el framework de .NET para la cache de ensamblados. Una vez seleccionadas las DLL que se quieren agregar, arrastrarlas a la ventana del explorador de la carpeta C:\Windows\Assembly y soltar los archivos en ella. 9/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis En la siguiente imagen se puede ver que se han agregado los ensamblados de Janus a la GAC. Se puede comprobar también que la versión de dichos ensamblados es la 3.5.109. 10/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Volver al Índice Snippets y Templates Los Snippets serían fragmentos de código para poder escribir de una manera más rápida y segura ciertos procesos y funciones de Expertis. El listado de fragmentos de código disponibles serían: 1. t -> Escribe código de Tipo: <Task()> Friend Shared Sub.... 2. ft -> Escribe Código de Tipo <Task()> Friend Shared Function.... 3. et -> Escribe código en Presentación de Tipo: ExpertisApp.ExecuteTask.... 4. pt -> Escribe código en Negocio de Tipo: ProcessServer.ExecuteTask.... 5. rvt -> Escribe código en Negocio de Tipo: ValidateProcess.AddTask.... 6. rut -> Escribe código en Negocio de Tipo: UpdateProcess.AddTask.... 7. rdt -> Escribe código en Negocio de Tipo: DeleteProcess.AddTask.... 8. adt -> escribe código en Negocio de Tipo: AddNewProcess.AddTask..... 9. AS -> escribe código en Negocio de Tipo: ApplicationService.GenerateError..... 10. AL -> escribe código en Presentación de Tipo: Acción Local de Expertis..... 11. EAP -> escribe código en Presentación de Tipo: ExpertisApp.GenerateMessage..... 12. EAPIF -> escribe código en Presentación de Tipo: Mensaje con Condición..... 13. FIL -> escribe código de Tipo: Filter de Expertis..... 14. EAPOF -> escribe código en Presentación de Tipo: ExpertisApp.OpenForm..... 15. EAPOR -> escribe código en Presentación de Tipo: ExpertisApp.OpenReport….. 16. FILCOM -> escribe código de Tipo: Filtro Complejo de AND + OR + AND…. 17. ADGET -> escribe código en Negocio de Tipo: AdminData.GetAutonumeric.... 18. BEFIL -> escribe código de Tipo: BE.DataEngine.Filter…. 19. ASL -> escribe código para crear una conexión de Login con Expertis… 20. BRT -> escribe código para crear una Tarea para reglas de Negocio… 21. RDTD -> escribe código para escribir las Tareas necesarias para mandar borrar un registro en un RegisterDeleteTasks… 22. RUTUD -> escribe código para escribir las Tareas necesarias para mandar grabar un documento de Expertis en un RegisterUpdateTask con Document… 23. RUTUR -> escribe código para escribir las Tareas necesarias para mandar grabar un datarow en un RegisterUpdateTask con Datarow... 24. RUTUT -> escribe código para escribir las Tareas necesarias para mandar grabar un datatable en un RegisterUpdateTask con Datatable… Estos pueden ser escritos directamente en el Código de pantalla escribiendo las letras descritas anteriormente seguida de una “?” y luego pulsando dos veces la tabulación. 11/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Otra manera de acceder a estos fragmentos de código, es posicionarnos con el cursor donde queremos insertar el código. Pulsar con el botón derecho del ratón y darn en la opción de Insertar fragmento de código: Seguidamente seleccionaremos Mis Fragmentos de Código: 12/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Seguidamente tendremos disponibles los fragmentos de código fuente personalizados para eXpertis disponibles hasta este momento. Seleccionaremos el que queramos y pasaremos a completar la información para el fragmento de código fuente seleccionada. Item Templates Los Templates serían las plantillas personalizadas para poder agregar de manera fácil los diferentes tipos de formularios de eXpertis, de Clase de Negocio. El listado de plantillas personalizadas de objetos / formularios disponibles serían: - ClassExpertis: Clase de negocio genérica. - SimpleMntoExpertis: Formulario de tipo Mantenimiento Simple. - CIMntoExpertis: Formulario de tipo Consulta Interactiva. - CIMntoBaseExpertis: Formulario de tipo Consulta Interactiva Padre. - GridMntoExpertis: Formulario de tipo Mantenimiento en Grid. - FormBaseExpertis: Formulario de tipo Base de eXpertis. - DocumentExpertis: Clase de negocio de Documento de Expertis para Procesos. - ProfileExpertis: Clase de Profile de Expertis para Filtrado Horizontal. - GlobalActionExpertis: Clase de Acción Global de Expertis. Para agregar elementos de los templates de Expertis iremos en un proyecto ya existente al menú: Proyecto -> Agregar Nuevo Elemento. 13/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis En la nueva pantalla que se nos abre, nos posicionaremos en Elementos Comunes dentro de Categorías, y en la sección de Expertis veremos las diferentes plantillas de elementos disponibles dependiendo de la capa en la que necesitemos dicho elemento. Project Templates El listado de proyectos personalizados disponibles serían: - ProjectBusinessExpertis: Proyecto con Clase de negocio genérica. - ProjectSimpleMntoExpertis: Proyecto con Formulario de tipo Mantenimiento Simple. - ProjectCIMntoExpertis: Proyecto con Formulario de tipo Consulta Interactiva. 14/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis - ProjectCIMntoBaseExpertis: Proyecto con Formulario de tipo Consulta Interactiva Padre. - ProjectGridMntoExpertis: Proyecto con Formulario de tipo Mantenimiento en Grid. - ProjectProcessOverrideTasks: Proyecto con Clase de negocio para sobrescribir un Proceso de otra entidad de Expertis. - ProjectExecutableLogin: Proyecto con Formulario con código para hacer login y logout en expertis. En primer lugar accedemos en el entorno de visual studio a crear un nuevo proyecto. Para ello Accederemos a través de Archivo -> Nuevo -> Proyecto. Una vez que nos salga la ventana de Nuevo Proyecto, elegiremos en el menú -> Visual Basic y luego ya tendremos disponibles en la sección de Expertis las diferentes plantillas disponibles según en la capa que necesitemos 15/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Volver al Índice 16/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis 3. DISTRIBUCIÓN DE CAPAS 3.1. CAPA DE DATOS Introducción Capa de Datos El nivel de capa de datos es el nivel más bajo y básico de eXpertis, siendo el nivel final donde almacenaremos todos los datos de eXpertis. En Expertis 5 se almacenan en sistema de SQL Server, de versión 2008 en adelante. La versión más común con la que trabajamos es sobre todo versión 2008. Interacción con esta capa a través de los objetos de motor. Dispondremos de un serie de dlls del motor de eXpertis para interaccionar con la base de datos. Será la encargada de velar por la correcta gestión de transacciones y evitar posibles errores de concurrencia. Por eso es conveniente que actualicemos los datos pasando siempre por los objetos de motor para garantizar la fiabilidad de todo el proceso. Veremos en los siguientes apartados cómo para el sistema expertis funcionaremos obligatoriamente con 2 bases de datos como mínimo. Siendo una de sistema que registrará toda la información del sistema de eXpertis y otra con los datos finales de una empresa/cliente/usuario_final. Volver al Índice Tipificación de Campos NVarchar Se utiliza para almacenar valores alfanuméricos no Unicode/Unicode. Si admiten nulos o no depende del significado funcional que tiene el campo. Se definen sin valor predeterminado. Numeric Se utiliza para almacenar valores numéricos con decimales (cantidades fraccionarias, precios, importes, etc.). Se definen con una precisión de 23 y una escala de 8, con un valor predeterminado, que generalmente es 0, y no admiten nulos. Int Se utiliza para almacenar valores enteros. Puede aparecer como tipo de dato para un campo que actúa como clave extranjera (de un campo que generalmente es auto numérico en la tabla principal). También se utilizan para almacenar valores que están relacionados con enumerados de la aplicación. Se suelen definir con un valor predeterminado, excepto cuando actúan como clave extranjera. El valor predeterminado generalmente es 0, aunque dependiendo del significado funcional puede convenir otro valor por defecto. No suelen admitir nulos si el campo representa valores enteros en general, o enumerados. Si el campo es una clave extranjera, el que admita nulos o no, dependerá de la relación funcional que define el propio campo entre las dos tablas. Bit Se utiliza para almacenar valores de tipo booleano. No admiten nulos y se definen con valor predeterminado, 0 ó 1. Datetime Se utiliza para almacenar valores de tipo fecha-hora. En general admiten nulos y sin valor predeterminado. Cuando es necesario un valor por defecto, en algunas bases de datos, se utiliza dbo.Fecha que realiza una llamada a la función de GETDATE() de SQL para obtener la fecha-hora actual. Autonumerico (int) Se utiliza como tipo de dato para la clave principal de algunas tablas. El tipo de dato autonumeric propio de SQL Server no se utiliza en eXpertis. En su lugar, se utiliza este tipo “auto numérico”, que básicamente, es un alias del tipo int, propio de SQL. En eXpertis los valores auto numéricos no se mantienen a nivel de tabla, si no que se mantienen a nivel de base de datos. Se puede decir que todas las tablas que poseen un campo de este tipo, comparten un mismo origen para sus valores auto numérico. Dado que SQL Server no asigna los valores a estos campos, el mantenimiento de estos campos auto numéricos se hace por código, unas veces de forma automatizada por el engine de eXpertis, y otras veces por medio de código que es responsabilidad del propio programador. 17/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Ntext Se suelen utilizar para almacenar datos no Unicode/Unicode de gran tamaño. Image Se utilizan para almacenar datos de gran tamaño en formato binario, como por ejemplo campos que contienen fotos o ficheros. Uniqueidentifier Se utilizan para almacenar valores de tipo GUID. Se utiliza como tipo de dato para la clave principal de algunas tablas. Para asignar un valor predeterminado se utiliza la función NEWID () de SQL. Volver al Índice Base de Datos de Sistema y de Usuario Habitualmente, el desarrollo debe contar con: - Una base de datos de sistema (sxExpertisXXXX). Al menos una base de datos de usuario (xExpertisXXXX). La base de datos de sistema almacena los metadatos de la aplicación, esto es, información referente a usuarios, menús, bases de datos, programas, entidades de negocio, informes, campos de las tablas funcionales, etc. La base de datos de usuario contiene la estructura y toda la información funcional que utiliza la aplicación. Tanto la base de datos de sistema como la de aplicación se proporcionan en el CD de distribución de eXpertis. A efectos de desarrollo, no es necesario realizar modificaciones en el esquema o la estructura de la base de datos de sistema, aunque habitualmente, si es necesario modificar cierto contenido de la misma. Para realizar modificaciones en las tablas de la base de datos de sistema se utiliza la Consola Administración de Expertis. NOTA: Para abrir la consola de administración de Expertis ejecutar Expertis.Engine.UI.Manager.exe, que se encuentra en el directorio de desarrollo. El desarrollo funcional afecta única y exclusivamente a la base de datos de usuario. Por lo tanto el primer trabajo consiste en analizar la estructura de tablas, datos y objetos de la base de datos que se van a utilizar. Volver al Índice Actualización de MetaDatos Cuando se crean tablas nuevas, la información de su esquema (campos, tipo de los campos, relaciones entre tablas, etc.) debe incluirse en el conjunto de metadatos de la base de datos de sistema. Para realizar esta acción se cuenta con un procedimiento almacenado, xCargarSistema, en la base de datos de sistema. Este procedimiento almacenado recibe dos parámetros: el primero es obligatorio y es el nombre de la base de datos de usuario de la que se quieren extraer los metadatos; el segundo parámetro es opcional y puede ser 0 o 1. Si es 0, el proceso de carga solo tiene en cuenta campos y relaciones nuevas. Si es 1, el proceso tiene en cuenta todos los campos de la base de datos pudiendo actualizar aquellos que han cambiado. El valor por defecto es 1. El procedimiento habitual consiste en abrir un analizador de consultas de SQL, y desde la base de datos de sistema, ejecutar el procedimiento almacenado Otra alternativa a este método manual de actualización de los metadatos tendremos la posibilidad de hacerlo a través del diseñador de eXpertis. 18/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Volver al Índice Campos de Auditoría Automáticos En Expertis tenemos un sistema automático de auditoría de registros a nivel de SQL-Server. Este sistema consiste en crear 3 campos en una tabla para que el Engine de Expertis se encargue de manera automática de rellenarlos y con ello poseer una pequeña información de qué es lo que ha pasado un registro en la base de datos. Para ello bastaría con crear los siguientes 3 campos, con los nombres exactos descritos y con los tipos de datos descritos: FechaCreacionAudi: Campo fecha que rellenará automáticame el motor solo cuando se crea el nuevo registro, quedando para siempre esta fecha y no modificándose nunca mas. FechaModificacionAudi: Campo fecha que rellenará automáticamente el motor solo cuando se modifique el registro, actualizándose cada vez que se modifique alguna información de dicho registro. UsuarioAudi: Nombre de Usuario de Expertis que ha llevado a cabo la ultima operación sobre el registro. Bien sea si la última operación ha sido de añadir un nuevo registro o bien sea por una modificación. Cada vez que ocurra una modificación se actualiza esta información de manera automática. Volver al Índice Tablas Satélites Descripción de Tablas Satélites La definición de Tablas Satélites en eXpertis nos permite desarrollar los cambios que necesitamos a nivel de bases de datos sobre tablas ya existentes, de manera que no tengamos que modificar las tablas en sí sino crear nuevas con los campos que necesitamos. Creación de la Tabla y Relaciones Creamos la tabla con los campos que necesitemos y con el nombre de tabla que queramos. El requisito fundamental de la configuración de la tabla sería que tuviera un campo clave principal llamado igual que el campo clave de la tabla principal de la que vamos a hacer una tabla satélite. En este caso sería el campo IDArtículo porque vamos a hacer una satélite de la tabla tbMaestroArtículo, creándonos una tabla nueva llamada tbExtra. 19/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Una vez creada la tabla configuramos las relaciones de la tabla. Para ello damos de alta una nueva y relacionamos la tabla tbMaestroArticulo con tbExtra a través del campo IDArtículo. Con esta relación tenemos que ver y entender que se establece una relación de 1 a 1. Tendríamos que llevar a cabo una vez realizado esto, el que se carguen en la tabla satélite todos los registros que contenga la tabla principal. Esto es necesario para que tengamos los registros equivalentes en la tabla satélite con los existentes ya en nuestra base de datos. Sobre todo estar presentes las claves primarias de relación, en el caso del ejemplo, sería tener todos los IDArtículo presentes en la tabla satélite. Esto si no hacemos notaremos que cuando modificamos un dato de la tabla satélite no se grabará por expertis, ya que no existe la relación. Si damos de alta nuevos registros no tendríamos ningún problema. Después de todo esto configurado y grabado, ejecutamos el procedimiento de xCargarSistema en nuestra BD de sistema con BD de datos que hayamos configurado esto. Alta y Configuración en Manager de Tablas Satélites Una vez hecho todos los pasos y cambios a nivel de Base de datos, acudimos al manager de eXpertis y hemos de buscar en la sección de Objetos -> Entidades, la entidad principal padre de la que hemos desarrollado una tabla satélite, en nuestro caso la entidad de Artículo de la tabla tbMaestroArtículo. 20/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Teniendo esta entidad seleccionada, acudimos a la pestaña de Tablas Satélite. En ella damos al botón de añadir de la barra de herramientas de arriba. Nos aparecerá una ventana con muchos nombres de tablas, lo que hacemos es buscar nuestra tabla satélite tbExtra. Una vez hecho esto ya veremos entonces que para nuestra entidad de Artículo tiene una tabla satélite que se llama tbExtra. Grabamos los cambios. 21/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Como último paso importante sería editar la parte del campo de Sentencia de Selección de la entidad principal, en este caso Artículo. Debemos rellenar este campo una sentencia SQL en la que se seleccionen todos los registros de la tabla principal y asimismo todos los de la tabla satélite. Esto es para que por defecto cuando obtengamos datos de la entidad Artículo nos vengan sus datos y de sus tablas satélites. Es importante en este punto que si tenemos los campos de Auditoría en la tabla satélite, estos si que no se seleccionen ya que tendríamos problemas. Los campos de Auditoría que pueden estar presentes son de la tabla principal. Es recomendable revisar la sentencia de búsqueda de la búsqueda avanzada, si vamos a necesitar que estos campos nuevos estén disponibles en las búsquedas de artículos. Para ello en la entidad correspondiente, en nuestro caso Artículo damos a configurar la sentencia de búsqueda y añadiríamos nuestra tabla satélite con los campos que queramos visualizar. 22/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Desarrollo e implementación de funcionalidad de campos de la Tabla Satélite Después de haber llevado cabo toda la configuración de las tablas satélites, lo más seguro es que necesitemos dar más funcionalidad a nuestros nuevos campos de la tabla, bien sea validaciones nuevas antes de grabados, o reglas nuevas para antes del grabado en la base de datos, etc… Para ello simplemente nos serviremos de la extensibilidad de eXpertis. Programando tareas antes o después de otras, sobre-escribiendo tareas, etc.. Para ello ver manuales y referencias de Extensibilidad de eXpertis de Solmicro. Volver al Índice Consideraciones Generales A la hora de crear tablas nuevas en la base de datos de desarrollo se siguen una serie de convenios en la definición de campos nuevos. Los convenios se refieren al tipo de dato y a ciertas propiedades como los valores por defecto, si admite nulos, etc. Se han de crear todas las tablas siempre con una clave primaria, sea simple o compuesta pero siempre presente una en cada tabla. Recomendamos indexar los campos más habituales de búsqueda, para una mayor rapidez en los accesos a la información, teniendo siempre en mente buscar el equilibrio, ya que abusar de estos índices podría provocar el efecto contrario y que la tabla fuera lenta en las búsquedas. Para los tipos de datos autonuméricos recordemos poner este tipo de dato el de eXpertis y no el autonumeric de sql. Este tipo de datos nos daría problemas a la larga en nuestra ejecución con eXpertis. Recordemos que a partir de la versión de SQL2005 los ORDER By de las vistas no se hacen caso cuando se ejecutan externamente. Con lo cual no contemos con estos ordenamientos que dejemos hecho en diseño. No construyamos vistas con SELECT * de alguna tabla ya que esto también puede perjudicarnos en la ejecución con eXpertis. También tenemos que tener en consideración que cuando creemos tablas nuevas, aunque sean temporales o de paso de datos, éstas tengan siempre una clave primaria en tabla, bien sea sencilla o compuesta. Esto es que si usamos la versión de expertis en Azure, es un requisito por parte de Microsoft en su SQL en Azure que dispongan las tablas de clave primaria siempre. NOTA: Habitualmente el siguiente paso a la creación de nuevas tablas, o a la modificación del diseño de las mismas, es actualizar los metadatos de la base de datos de sistema con estas nuevas modificaciones. Ver Actualización de los metadatos asociados a la estructura de la base de datos de usuario. Volver al Índice 23/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis 3.2. CAPA DE NEGOCIO Introducción Capa de Negocio La capa de Negocio de eXpertis es la capa en la que estableceremos una relación de tablas con clases de .Net. De manera que el manejo de una tabla (inserciones, modificaciones, borrados,…) sea a través de estas clases que están relacionadas con tablas. Igualmente las clases de Negocio nos sirven para definir funciones o procesos auxiliares que podamos necesitar en relación con la Clase – Tabla relacionada. De esta manera establecemos un orden en el código. Asimismo en el entorno remoting, la capa de negocio sirve para que se ejecute puramente en el parte servidor, de manera que procesos pesados, ya sea de acceso a datos como de procesamiento en sí, lo lleve a cabo un equipo servidor y no la parte cliente del mismo. Volver al Índice Entidad El concepto de Entidad de eXpertis hay que entenderla como un manejador de una tabla de sql server. De manera que una entidad de eXpertis representa realmente a una tabla de nuestra base de datos. De esta manera la idea es que las tablas de usuario las manejemos a través de este concepto de entidad que iremos viendo a lo largo de esta manual. Con ello la comunicación de la tabla, bien sea para obtener datos o bien sea para actualizaciones lo realizaríamos a través de la entidad de eXpertis asociada. Lo que nos permitirá esta entidad de eXpertis es establecer reglas de validación y ejecución de procesos en las inserciones , modificaciones y borrados de registros contra esta tabla. Asimismo se gestiona el concepto de reglas de negocio de eXpertis, el cual nos permitirá definir una serie de validaciones y actualizaciones cada vez que modifiquemos un campo relacionado con una tabla/entidad de expertis. También con este concepto de entidad lo que intentamos es tener aglutinado todo el código fuente relacionado con la entidad/tabla de expertis y toda la programación en esta capa de negocio. Public Class ClassExpertis1 #Region "Constructor" Inherits Solmicro.Expertis.Engine.BE.BusinessHelper Public Sub New() MyBase.New(cnEntidad) End Sub Private Const cnEntidad As String = "NOMBRE_TABLA" #End Region End Class Las entidades, una vez que las tenemos creadas, aportan una serie de métodos paor defecto. Para ello bastaría con instanciarse un objeto de tipo la entidad que buscamos y acceder a sus métodos. 24/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis A continuación marcamos los métodos más habiltuales en una entidad de eXpertis. 1. Método AddNew El Método AddNew devuelve la estructura de campos y tipos que conforman la tabla que maneja dicha entidad. Para ello el motor solicita a la base de datos la configuración de campos, tipos y valores por defecto que hayamos configurado en dicha tabla en base de datos. Esto nos permite obtener un DataTable con la estructura de datos que compone dicha tabla pero sin ningún registro. Dim ClsArticulo As New Solmicro.Expertis.Business.Negocio.Articulo Dim DtNewArt As DataTable = ClsArticulo.AddNew Volver al Índice 2. Método AddNewForm El Método AddNewForm lo usaremos para obtener un nuevo registro de la entidad que estamos con una serie de datos mínimos. Esto nos permite invocar a las tareas asociadas al proceso de RegisterAddNewTasks que tenga la entidad a la que hacemos referencia. Si de todos modos no tuviéramos tareas en dicho proceso lo que hace el motor es conforman un DataTable con un registro que contiene todos los valores por defecto y restricciones configuradas a nivel de tabla de la base de datos. También en el proceso de RegisterAddNewTasks la información que se va manejando en las tareas es este DataTable con un registro. Por ello siempre recibiriremos de este método un DataTable con un registro conformado con la información de la base de datos y si lo hubiera con lo programado en las tareas del RegisterAddNewTasks. Dim ClsArticulo As New Solmicro.Expertis.Business.Negocio.Articulo Dim DtNewArt As DataTable = ClsArticulo.AddNewForm DtNewArt.Rows(0)("IDArticulo") = "ART001" Volver al Índice 3. Método Delete El Método Delete lo usaremos para borrar uno o varios registros de la entidad que estamos. Esto nos permite invocar last areas asociadas al proceso de RegisterDeleteTasks que tenga la entidad a la que hacemos referencia. Si no tuviera tareas sobreescritas se llevaría a cabo el borrado contra la base de datos del/los registro/s mandados. Para ello usaremos este método pasándole un datatable con los registros que deseamos eliminar y cuyos registros estén en estado de Saved. No pueden ir en estado Deleted los registros que enviamos en este datatable. Dim ClsArticulo As New Solmicro.Expertis.Business.Negocio.Articulo Dim DtNewArt As DataTable = ClsArticulo.SelOnPrimaryKey("ART001") ClsArticulo.Delete(DtNewArt) Volver al Índice 4. Método Validate El Método Validate lo usaremos para llevar a cabo la validación de un datatable contra las tareas programadas en el proceso de RegisterValidateTasks. Se trata de ejecutar una serie de validaciones previas con el objetivo de que los datos vayan correctos a la actualización. Dim ClsArticulo As New Solmicro.Expertis.Business.Negocio.Articulo Dim DtNewArt As DataTable = ClsArticulo.SelOnPrimaryKey("ART001") DtNewArt.Rows(0)(“PrecioA”) = 100.5 ClsArticulo.Validate(DtNewArt) Volver al Índice 5. Método Update El Método UpdateValidate lo usaremos para llevar a cabo actualizaciones de datos contra la tabla de la entidad que usemos. Bien sea para registros nuevos o registros modificados. Invocando este método haremos que se ejecuten las tareas asociadas al proceso de RegisterUpdateTasks o bien si no hubiera se 25/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis llevaría a cabo el grabado de datos directo contra la base de datos. Para ello entonces tendremos que enviar a este método un DataTable con registros con estado Added o algunos de los de tipo Modified. Dim ClsArticulo As New Solmicro.Expertis.Business.Negocio.Articulo Dim DtNewArt As DataTable = ClsArticulo.SelOnPrimaryKey("ART001") DtNewArt.Rows(0)(“PrecioA”) = 100.5 ClsArticulo.Update(DtNewArt) Volver al Índice 6. Método Filter El Método Filter es uno de los métodos de una entidad que nos permite obtener datos de la entidad asociada. Éste método debería de utilizarse con el objeto Filter de eXpertis para conformar un filtro contra la tabla. Como resultado nos devolverá un objeto DataTable con todos los datos que concuerden con el filtro que hayamos pasado. Dim ClsArticulo As New Solmicro.Expertis.Business.Negocio.Articulo Dim FilArt As New Filter FilArt.Add("PrecioA", FilterOperator.GreaterThanOrEqual, 100.5) FilArt.Add("IDTipo", FilterOperator.Equal, "FAB") Dim DtNewArt As DataTable = ClsArticulo.Filter(FilArt) Nota: Para más información del objeto Filter de eXpertis ver el apartado del manual de Objeto Filter de eXpertis. Volver al Índice 7. Método SelOnPrimaryKey El Método SelOnPrimaryKey nos permite obtener datos de una entidad pero a diferencia del método Filter, sólo tendremos que pasar el valor o valores que conformen la clave primaria de dicha entidad / tabla. Es un método más directo y rápido para obtener datos cuando se quieren filtrar por dicho/s campo/s de la clave Primaria. Como resultado devolverá un datatable con el registro solicitado. Dim ClsArticulo As New Solmicro.Expertis.Business.Negocio.Articulo Dim DtNewArt As DataTable = ClsArticulo.SelOnPrimaryKey("Art001") Volver al Índice 8. Método GetItemRow El Método GetItemRow nos permite al igual que el SelOnPrimaryKey obtener datos de la entidad especificando solo los valores del/os campo/s que conforman la clave primaria, pero el objeto devuelto será un DataRow. Sería para usar porque buscamos un valor muy concreto del registro buscado de la entidad. Dim ClsArticulo As New Solmicro.Expertis.Business.Negocio.Articulo Dim DtArt As DataRow = ClsArticulo.GetItemRow("Art001") Nota: éste método se debe de usar solamente a nivel de la capa de negocio de eXpertis y entre negocios de eXpertis, puesto que el objeto DataRow no es un objeto serializable y no está preparado para viajar por remoting entra la capa de presentación y de negocio de eXpertis. Volver al Índice 9. Método ApplyBusinessRule El Método ApplyBusinessRules nos permite invocar a las reglas de negocio asociadas de una entidad, con ello invocamos a las tareas asociadas a los campos programados en el proceso GetBusinessRules de la entidad. Es por ello que si no existieran tareas programadas en el GetBusinessRules no se ejecutaría nada y tampoco daría ningún error. Dim ClsArticulo As New Articulo Dim DtArticuloNew As New DataTable Dim DrNew As DataRow = DtArticuloNew.NewRow DrNew("IDArticulo") = "00" Dim StData As New BusinessData(DrNew) 26/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis StData = ClsArticulo.ApplyBusinessRule("IDArticulo", "00", StData) For Each Dc As DataColumn In DtArticuloNew.Columns DrNew(Dc.ColumnName) = StData(Dc.ColumnName) Next Volver al Índice Tarea Son métodos que cumplen ciertas características. Se identifican por la etiqueta <Task> y tienen siempre 2 parámetros, el primero con los datos de entrada y el segundo un parámetro de tipo ServiceProvider. También tienen la peculiaridad que deben ser shared. <Task()> Public Shared Function GetContadorPredeterminadoCGestionUsuario(ByVal data As CentroGestion.ContadorEntidad, ByVal services As ServiceProvider) As String Dim CentroEnt As CentroEntidad CentroEnt.CentroGestion = New UsuarioCentroGestion().CentroGestionUsuario() CentroEnt.ContadorEntidad = data Return ProcessServer.ExecuteTask(Of CentroEntidad, String)(AddressOf GetContadorPredeterminado, CentroEnt, services) End Function Dentro de una misma clase no puede haber más de una tarea con el mismo nombre. Por ejemplo, MantenimientoValoresAyB. Antes teníamos bastantes métodos con distintas firmas dependiendo del tipo de entrada,.. Ahora estas se reducen a 2: <Task()> Public Shared Function MantenimientoValoresAyB(ByVal dataAB As ValoresAyB, ByVal services As ServiceProvider) As IpropertyAccessor Para los casos en los que tenemos un Datarow o un BusinessData (debemos reducir los tipos de datos a unos de estos 2) y para los casos en los que tenemos un Double: <Task()> Public Shared Function MantenimientoValoresImporteAyB(ByVal dataAB As ValoresAyB, ByVal services As ServiceProvider) As fImporte Como vemos ambas funciones tienen distinto nombre, aunque el tipo de datos de entrada es el mismo, (ya que además de indicar el importe o el registro, debemos indicarle la moneda, los cambios,….) Nos encontraremos bastante con esta situación, de tener varios parámetros de entrada y sólo podemos tener 2, y que debemos introducir “todo” lo que necesitemos dentro del primer parámetro, mediante una clase. Se utilizan de manera un tanto especial, y dependiendo desde donde se haga la llamada a la tarea se hace de una manera u otra. Por ejemplo, desde negocio: Dim IDContador As String = ProcessServer.ExecuteTask(Of ContadorEntidad, String)(AddressOf CentroGestion.GetContadorPredeterminadoCGestionUsuario, ContadorEntidad.FacturaCompra, services) (la tarea CentroGestion.GetContadorPredetermindadoCGestionUsuario se ejecuta con ProcessServer.ExecuteTask, indicando el tipo del parámetro de entrada, en este caso ContadorEntidad, seguido del tipo del elemento de salida (sólo en el caso de funciones), se le pasa el parámetro de entrada y un objeto del tipo ServiceProvider) Desde presentación: Dim IDContador As String = ExpertisApp.ExecuteTask(Of ContadorEntidad, String)(AddressOf CentroGestion.GetContadorPredeterminadoCGestionUsuario, CentroGestion.ContadorEntidad.FacturaCompra) (la tarea CentroGestion.GetContadorPredetermindadoCGestionUsuario se ejecuta con ExpertisApp.ExecuteTask, indicando el tipo del parámetro de entrada, en este caso ContadorEntidad, seguido del tipo del elemento de salida (sólo en el caso de funciones), se le pasa el parámetro de entrada y NO se le pasa el objeto del tipo ServiceProvider) Volver al Índice Documento 27/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis 1. Concepto Ante los problemas derivados por el hecho de que unas entidades precisen de modificaciones en otras, como pueden ser problemas de concurrencia, o bien, hacer el Update en 2 partes (Update+Updated) para hacer cálculos (p.ej: recalculo de cabeceras de facturas, por cambios en la líneas), ha surgido un nuevo tipo de datos Document (en Expertis.Business.General), que nos servirá para agrupar varias entidades como si fueran una única entidad, y procesarlas de manera conjunta. 2. Creación y Manejo Vamos a ver a través de un ejemplo, cómo hacer un Documento, para ellos nos fijaremos en las Facturas. Document: Clase genérica para crear Documentos Sobre ella iremos añadiendo (mediante herencia) elementos que nos permitirán adaptarla a nuestras necesidades. DocumentCabLin: En todos los elementos del circuito logístico tenemos, una cabecera, unas líneas y existe la posibilidad de tener Analítica, esto es lo que se contempla en DocumentCabLin, así como la información de las Monedas (la del cliente/proveedor, la MonedaA y la MonedaB) Además, contiene también información del origen del que partimos para crear el Documento. (P.Ej: en el caso de las facturas generadas desde albaranes, contiene la información de los albaranes) – campo Cabecera. Esta información se incluye dentro del documento, porque a lo largo del proceso el parámetro de entrada de las tareas va a ser el documento, y en alguna de ellas se necesita la información del albarán. (El equivalente en 4.1 son las cabeceras y lineas que nos devolvían las agrupaciones) DocumentoComercial, DocumentoCompra: Tanto en Compras como en Ventas hay elementos comunes al Pedido, Albarán y Factura, por lo que se han creado otros 2 documentos que tienen la información específica de cada circuito, como puede ser la información del Cliente, del Proveedor o los representantes. DocumentoPedidoVenta, DocumentoPedidoCompra,….: En estos documentos hay información específica de cada uno, así como cierta configuración que se necesita especificar (indicar cuál es la primarykey de las entidades de cabecera, líneas,…..) Constructores de los documentos Importante especificar en cada uno de los distintos documentos los constructores de cada uno. P. Ej. Los de albarán compra serían los siguientes: Public Sub New(ByVal Cabecera As AlbCabCompra, ByVal services As ServiceProvider) MyBase.New(Cabecera, services) End Sub Public Sub New(ByVal UpdtCtx As Engine.BE.UpdatePackage) MyBase.New(UpdtCtx) End Sub Public Sub New(ByVal ParamArray PrimaryKey() As Object) MyBase.New(PrimaryKey) End Sub Se necesitan 3 constructores para crear los documentos desde distintos sitios: - El primero se utiliza desde el proceso de recepción de pedidos (por ejemplo), y se le pasa un objeto del tipo AlbCabCompra, que tiene la información necesaria para crear un Albaran de Compra desde pedidos (por ejemplo). Con ésta información es suficiente para montar un Documento con la información mínima y a lo largo del proceso éste documento se irá completando a medida que pasa por las distintas tareas. - El segundo es el que utiliza el motor, para hacernos llegar a Negocio la información modificada en presentación documento cuando se han hecho cambios desde presentación. La primera tarea de un 28/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis RegisterUpdateTask que recibe un UpdatePackage, será un CrearDocumento, en el cual mezclaremos los registros modificados que vienen en el UpdatePackage, con lo que tenemos en la BBDD (método MergeData de la clase Document). Una vez hecho esto tendremos en el documento todo lo referente al Pedido (por ejemplo) y podremos operar sobre el documento - En ocasiones necesitamos obtener un documento a través de la clave primaria de la entidad de cabecera, esto es para lo que se utiliza el tercer constructor. Métodos sobre-escribibles Es posible que tengamos que sobrescribir los métodos LoadEntityHeader, LoadEntitiesChilds y LoadEntitiesGrandChilds para poder cargar la información de cabecera y de las entidades hijas o nietas de la cabecera. P.EJ. En el DocumentoFacturaCompra cargamos los Vencimientos y las Bases Imponibles como hijas. También tendremos que sobrescribir métodos como EntidadCabecera, EntidadLineas,… para indicar el nombre de la entidad que estamos tratando. Otros métodos Otros métodos que podemos tener en estas clases, son métodos para proporcionar transparencia a la hora de hacer algunas modificaciones sobre elementos de la entidad. Por.Ej: en el caso de los Albaranes al Facturarlos, se debe indicar en el Albarán la Qfacturada y las líneas del albarán cambiarán de estado en función de esa cantidad. De manera que desde la facturación se indica la cantidad facturada en ese momento y el método en cuestión se encarga de sumarla en las líneas del albarán y de actualizar el estado de la líneas.(método SetQFacturada (en DocumentoAlbaranCompra/DocumentoAlbaranVenta)) Uso Estos documentos los utilizamos en procesos creados por nosotros (p.ej: PrcCrearFacturaCompra) , en los procesos RegisterUpdateTask,…. Al registro de cabecera haremos referencia a través de la propiedad HeaderRow, y las entidades hijas y nietas se accederán mediante datatables. En las entidades hijas/nietas que estén bajo un Documento, no hay que programar sus RegisterUpdateTask, ya que se van a tratar siempre ligadas a la cabecera,… se guardarán en el Documento que las agrupa. Por ejemplo, el RegisterUpdateTask de FacturaCompraLinea no está programado, porque ya está incluida en el de FacturaCompraCabecera, ya que este último lo trata como un Documento. Volver al Índice Proceso 1. Concepto Los procesos son una lista de tareas que dado un objeto de entrada lo transforma en otro objeto a la salida. Pudiendo ser el mismo objeto de entrada con más cosas añadidas, o bien, otro objeto completamente diferente. En esa lista de tareas el objeto de salida de una tarea es la entrada para la siguiente tarea. Algunos de estos procesos, son propios del motor, como son RegisterDeleteTask, RegisterValidateTask, RegisterUpdateTask, GetBusinessRules y RegisterAddNewTasks. En la definición de estos procesos, construimos la lista de tareas, pero dichas tareas no se ejecutarán en ese momento. Los procesos RegisterDeleteTask y RegisterUpdateTask tienen, además, otra peculiaridad (DeleteProcessContext y UpdateProcessContext, respectivamente). Volver al Índice 2. Bucles y Condicionales Además de estos procesos básicos, podremos crear nuestros propios procesos. Que podrán formarse mediante una serie de tareas y/o procesos, pudiendo incluirlos de manera iterativa(AddForEachTask), condicional (AddIfThenTask) y/o simple(AddTask). Se asume que la entrada de una tarea es la salida de la anterior. Los procesos deberán heredar de la clase Process y le podremos indicar cuales son los tipos de entrada y salida del proceso. 29/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Ejemplo 1: (proceso Facturación de Compra) Este proceso tiene como entrada un objeto del tipo DataPrcFacturacionCompra y devuelve un objeto de tipo ResultFacturacion. Está formado por varias tareas. También se incluye mediante una iteración, la llamada a otro proceso. Que se ejecutará tantas veces como elementos tenga el array que devuelve la tarea anterior. Es decir, que el proceso PrcCrearFraCompra tendrá como entrada un elemento de tipo FraCabCompra, ya que le llegarán los elementos de uno en uno. Public Class PrcFacturacionCompra Inherits Process(Of DataPrcFacturacionCompra, ResultFacturacion) 'Lista de tareas a ejecutar Public Overrides Sub RegisterTasks() Me.AddTask(Of DataPrcFacturacionCompra)(AddressOf DatosIniciales) Me.AddTask(Of DataPrcFacturacionCompra, FraCabCompra())(AddressOf ProcesoFacturacionCompra.AgruparAlbaranesCompra) Me.AddTask(Of FraCabCompra())(AddressOf ProcesoFacturacionCompra.Ordenar) 'Bucle para recorrer todos los documentos a factura a generar Me.AddForEachTask(Of PrcCrearFraCompra)(OnExceptionBehaviour.NextLoop) Me.AddTask(Of Object, ResultFacturacion)(AddressOf ProcesoFacturacionCompra.Resultado) End Sub 'Registar en el services la información que vamos a compartir durante el proceso, para evitar accesos innecesarios <Task()> Public Shared Sub DatosIniciales(ByVal data As DataPrcFacturacionCompra, ByVal services As ServiceProvider) Dim TipoLineaDef As String = New TipoLinea().TipoLineaPorDefecto services.RegisterService(New ProcessInfoFra(data.IDContador, TipoLineaDef, data.SuFactura)) Dim Facturas As DataTable = New FacturaCompraCabecera().AddNew services.RegisterService(New ResultFacturacion(Facturas)) End Sub End Class Ejemplo 2: (Proceso de Contabilización de Remesa) Este proceso tiene como entrada un objeto del tipo DataPrcContabilizacionRemesa y devuelve un objeto de tipo ResultContabilizacion. Está formado por varias tareas. También se incluye mediante una condición la llamada a otro proceso. Si la tarea RemesaAlCobro devuelve el valor True (esta tarea se introduce mediante un delegado), se ejecuta el proceso PrcContabilizacionRemesaAlCobro Public Class PrcContabilizacionRemesa Inherits Process(Of DataPrcContabilizacionRemesa, ResultContabilizacion) 'Lista de tareas a ejecutar Public Overrides Sub RegisterTasks() Me.AddTask(Of DataPrcContabilizacionRemesa)(AddressOf ProcesoContabilizacion.DatosIniciales) Me.AddIfThenTask(Of PrcContabilizacionRemesaAlCobro, DataPrcContabilizacionRemesa)(New BooleanTaskDelegate(Of DataPrcContabilizacionRemesa)(AddressOf RemesaAlCobro)) Me.AddIfThenTask(Of PrcContabilizacionRemesaAlDescuento, DataPrcContabilizacionRemesa)(New BooleanTaskDelegate(Of DataPrcContabilizacionRemesa)(AddressOf RemesaAlDescuento)) Me.AddTask(Of Object, ResultContabilizacion)(AddressOf ProcesoContabilizacion.GetResultado) End Sub <Task()> Public Shared Function RemesaAlCobro(ByVal data As DataPrcContabilizacionRemesa, ByVal services As ServiceProvider) As Boolean Return data.TipoRemesa = enumTipoRemesa.RemesaAlCobro End Function <Task()> Public Shared Function RemesaAlDescuento(ByVal data As DataPrcContabilizacionRemesa, ByVal services As ServiceProvider) As Boolean Return data.TipoRemesa = enumTipoRemesa.RemesaAlDescuento End Function 30/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis End Class Volver al Índice 3. Control de Excepciones Cuando se produce una excepción en un proceso, salta el evento OnException que capturaremos si queremos realizar un tratamiento de la excepción. Este retornará un valor que indicará como debe comportarse el proceso tras finalizar la tarea que ha producido la excepción. Los valores posibles a retornar, son : OnExceptionBehaviour.ThrowException (valor predeterminado) Propaga la excepción OnExceptionBehaviour.NextTask Ejecuta la siguiente tarea OnExceptionBehaviour.NextLoop Ejecuta la siguiente iteración OnExceptionBehaviour.Exit Sale de la iteración, proceso, … Protected Overrides Function OnException(ByVal exceptionArgs As Engine.BE.BusinessProcesses.ProcessExceptionArgs) As Engine.BE.BusinessProcesses.OnExceptionBehaviour Dim Datafvr As DataPrcActualizarFactura = exceptionArgs.Services.GetService(Of DataPrcActualizarFactura)() Dim fvr As ResultFacturacion = Datafvr.RstFacturacion Dim log As LogProcess = fvr.Log ReDim Preserve log.Errors(log.Errors.Length) Dim fra As FraCab = CType(exceptionArgs.TaskData, DocumentoFacturaVenta).Cabecera If TypeOf fra Is FraCabAlbaran Then Dim FraAlb As FraCabAlbaran = CType(fra, FraCabAlbaran) Select Case FraAlb.Agrupacion Case enummcAgrupFactura.mcAlbaran log.Errors(log.Errors.Length - 1) = New ClassErrors(" Albarán: " & FraAlb.NAlbaran, exceptionArgs.Exception.Message) Case enummcAgrupFactura.mcCliente log.Errors(log.Errors.Length - 1) = New ClassErrors(" Cliente: " & FraAlb.IDCliente, exceptionArgs.Exception.Message) End Select ElseIf TypeOf fra Is FraCabObra Then Dim FraObra As FraCabObra = CType(fra, FraCabObra) Select Case FraObra.AgrupacionObra Case enummcAgrupFacturaObra.mcCliente log.Errors(log.Errors.Length - 1) = New ClassErrors(" Cliente: " & FraObra.IDCliente, exceptionArgs.Exception.Message) Case enummcAgrupFacturaObra.mcObra log.Errors(log.Errors.Length - 1) = New ClassErrors(" Obra: " & FraObra.NObra, exceptionArgs.Exception.Message) Case enummcAgrupFacturaObra.mcObraPedidoClte log.Errors(log.Errors.Length - 1) = New ClassErrors(" Obra/PedidoCliente: " & FraObra.NObra & "/" & FraObra.NumeroPedido, exceptionArgs.Exception.Message) Case enummcAgrupFacturaObra.mcObraTrabajo log.Errors(log.Errors.Length - 1) = New ClassErrors(" Obra/Trabajo: " & FraObra.NObra & "/" & FraObra.IDTrabajo, exceptionArgs.Exception.Message) End Select End If Return MyBase.OnException(exceptionArgs) End Function 4. Llamada a Procesos Para hacer la llamada a un proceso fuera de una lista de tareas, lo haremos de la siguiente manera. Desde Negocio: Dim dataAddAptes As New Financiero.DataPrcAddApuntes(DtAsientoReg, Nothing) Dim ResultAddApuntes As DataResultadoAddApuntes = ProcessServer.RunProcess(GetType(PrcAddApuntes), dataAddAptes) Desde Presentación: 31/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Dim dataAddAptes As New Financiero.DataPrcAddApuntes(Me.Asientos, Me.Analitica) ResultAddApuntes = New BE.DataEngine().RunProcess(GetType(PrcAddApuntes), dataAddAptes) Volver al Índice 5. Ejemplo Creación Proceso COMO CREAR UN ALBARAN DE VENTA Queremos generar un Albarán de Venta partiendo de una información mínima como puede ser, por ejemplo, un cliente, un artículo, una cantidad y un precio. Sabemos que el Albarán ahora se almacena en el sistema a través de un ‘DocumentoAlbaranVenta’, por lo que nos surgirán algunas dudas. ¿Tenemos que construir un objeto del tipo ‘DocumentoAlbaranVenta’? ¿cómo? ¿tendremos que crear un proceso específico para crear un Albarán? La primera tarea del RegisterUpdateTask es un UpdatePackage ¿cómo lo construimos? ¿Qué información debe llevar este objeto? Vamos a intentar solventar estas dudas a través de unos ejemplos. Detalles a tener en cuenta: - El objeto UpdatePackage NO es SERIALIZABLE - Vínculos entre tablas (la información del Albarán se guarda en el origen desde el que se genera el albarán, o bien, la información del origen se guarda en el Albarán) Visión de un solo cliente o adaptación de nuestro procesos a otros posibles clientes. (procesos) - Utilizaremos la clase DataCrearAlbaranVenta para pasar la información suficiente a Negocio. <Serializable()> _ Public Class DataCrearAlbaranVenta Public IDCliente As String Public IDArticulo As String Public Cantidad As Double Public Precio As Double Public Sub New(ByVal IDCliente As String, ByVal IDArticulo As String, ByVal Cantidad As Double, ByVal Precio As Double) Me.IDCliente = IDCliente Me.IDArticulo = IDArticulo Me.Cantidad = Cantidad Me.Precio = Precio End Sub End Class Opción 1 La primera opción y más sencilla, nos permite generar un albarán tal cual. Pero tiene el inconveniente que no podemos saber qué albarán se ha generado, aunque podemos asegurarnos que se graba a través del Update, con lo que las tareas que estén inventariadas en el RegisterUpdateTask de AlbaranVentaCabecera las ejecutará. Sin vínculos con la tabla de la provienen los datos del Albarán, o bien, con un vínculo a dicha tabla, guardando el identificador del registro origen en alguna tabla del albarán, ya sea la cabecera, líneas,… En Negocio tendremos una tarea: '// Opción 1 <Task()> Public Shared Sub CrearAlbaranVenta(ByVal data As DataCrearAlbaranVenta, ByVal services As ServiceProvider) '//Rellenamos un registro de Cabecera Dim AVC As New AlbaranVentaCabecera Dim dtCab As DataTable = AVC.AddNewForm AVC.ApplyBusinessRule("IdCliente", data.IDCliente, dtCab.Rows(0)) AVC.ApplyBusinessRule("FechaAlbaran", Today, dtCab.Rows(0)) '//Rellenamos un registro de Lineas Dim context As New BusinessData(dtCab.Rows(0)) 32/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Dim AVL As New AlbaranVentaLinea Dim dtLin As DataTable = AVL.AddNewForm AVL.ApplyBusinessRule("IdArticulo", data.IDArticulo, dtLin.Rows(0), context) AVL.ApplyBusinessRule("QServida", data.Cantidad, dtLin.Rows(0), context) dtLin.Rows(0)("Regalo") = 0 Dim upg As New UpdatePackage upg.Add(dtCab) upg.Add(dtLin) AVC.Update(upg) End Sub En presentación la utilizaremos de la siguiente manera: Private Sub btnOpcion1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnOpcion1.Click Dim data As New DataCrearAlbaranVenta data.IDCliente = Me.advCliente.Value data.IDArticulo = Me.advArticulo.Value data.Cantidad = Me.nbxCantidad.Value data.Precio = Me.nbxPrecio.Value ExpertisApp.ExecuteTask(Of DataCrearAlbaranVenta)(AddressOf GenerarAlbaranVenta.CrearAlbaranVenta, data) ExpertisApp.GenerateMessage("Albarán generado.") End Sub Opción 2 Si varios clientes nos piden una funcionalidad similar, que no está en eXpertis, con pequeñas peculiaridades para cada cliente, podemos desarrollarla de manera que, utilizando la sobreescritura de procesos, podamos adaptar la funcionalidad a las necesidades del cliente. En este caso utilizaremos un proceso para generar el Albarán. Por otro lado, según las necesidades del proceso, el tratamiento que el proceso RegisterUpdateTask da a los datos, puede no ser exactamente igual que lo requerido en el proceso de generación del albarán. Por ejemplo, puede que tengamos que generar un albarán que a través del proceso no tenga que calcular cierta información, por ejemplo, los representantes, por lo que no sería necesario utilizar la tarea que calcule los representantes. Para el ejemplo, vamos a partir de una tabla de estas características. (la llamaremos tbMaestroEjemplo) En la que tenemos unos datos de origen a través de los cuales generaremos un albarán con una línea, la cual vincularemos a la tabla origen e indicaremos al usuario qué albarán se ha generado. Suponemos los siguientes datos: La Razón Social ha sido modificada por el usuario y le asignaremos un precio fijo de 15€. 33/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Entonces, para hacer ese ejemplo, necesitaremos crear 2 tipos AlbCabVentaEjemplo y AlbLinVentaEjemplo. Estos tipos serán los que contengan la información mínima a rellenar para crear el Albarán, heredarán de los tipos base para crear el albarán (AlbCabVenta y AlbLinVenta). Por el hecho de heredar de AlbCabVenta y AlbLinVenta se rellenará cierta información en estas clases nuevas. Public Class AlbCabVentaEjemplo Inherits AlbCabVenta Public RazonSocial As String Public Overrides Function FieldNOrigen() As String Return String.Empty '''Indicamos el campo cual es el campo NOrigen, en caso de que exista (en este ejemplo no existe) End Function Public Overrides Function PrimaryKeyCabOrigen() As String Return New String("IDOrigen") '''Indicamos cual es el campo IDOrigen de la cabecera (en este ejemplo, será el mismo que ls líneas) End Function Public Sub New(ByVal row As DataRow) MyBase.New(row) MyBase.Origen = -1 'enumOrigenAlbaranVenta.Ejemplo '''El campo Razón social del origen tenemos que trasladarlo al campo PedidoCliente de la cabecera del albarán Me.RazonSocial = row("RazonSocial") & String.Empty End Sub End Class Public Class AlbLinVentaEjemplo Inherits AlbLinVenta Public Overrides Function PrimaryKeyLinOrigen() As String Return New String("IDOrigen") '''Indicamos cual es el campo IDOrigen de las lineas (en este ejemplo, será el mismo que de la cabecera) End Function Public Sub New(ByVal oRow As DataRow) MyBase.New(oRow) '//Aquí se rellena el IDLineaOrigen de AlbLinVenta Me.QaServir = Nz(oRow("Cantidad"), 0) '''Como no vamos a modificar la cantidad del registro, la podemos asignar en este punto. End Sub End Class AlbCabVentaEjemplo contendrá la información mínima para crear una cabecera y, lo mismo ocurre con AlbLinVentaEjemplo para las líneas. (En la versión 4.1 de eXpertis, estas clases equivalen a los DataTables de cabeceras y líneas que surgían de hacer las agrupaciones ). Y nos quedará crear una clase que será un proceso con algunas tareas específicas para realizar la funcionalidad del nuevo proceso (Se creará un albarán en el que se trasladan los campos de la tabla tbMaestroEjemplo; IDCliente, IDArticulo, Cantidad tal cual se esperan y el campo RazonSocial se lleva al campo PedidoCliente de la cabecera del albarán, así como el precio será fijo 15€. Una vez generado el albarán, se llevará el IDLineaAlbaran a la tabla tbMaestroEjemplo y se mostrará en presentación cuál es el albarán generado) En este ejemplo, le pasamos el IDOrigen del registro a partir del cual vamos a generar el albarán. Tendremos que crearnos una tarea (DatosIniciales) para convertir dicha información al tipo AlbCabVenta, que necesitamos para crear un documento, luego tendremos utilizar las tareas de Expertis para crear el DocumentoAlbaranVenta y otras para ir completando el documento con la información necesaria para crear el Albarán según la funcionalidad requerida. Dado que tenemos que asignar la Razón Social al campo PedidoCliente crearemos una tarea (AsignarFuncionalidadEjemplo) para ello. La tarea para crear las líneas también tendremos que personalizarla (CrearLineasDesdeEjemplo), para montar las líneas con nuestra funcionalidad, y más tarde incluiremos una tarea para actualizar el Origen y retornar los datos del albarán creado (tarea ActualizarOrigen). (Los accesos a la tabla tbMaestroEjemplo están hechos de manera que no haya que crear una entidad para ello, aunque lo programado en la tarea ActualizarOrigen también requiera crear la entidad) Public Class PrcAlbaranarEjemplo 34/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Inherits Process(Of Integer, CreateElement) 'Lista de tareas a ejecutar Public Overrides Sub RegisterTasks() Me.AddTask(Of Integer, AlbCabVenta)(AddressOf DatosIniciales) 'EJEMPLO Me.AddTask(Of AlbCabVenta, DocumentoAlbaranVenta)(AddressOf ProcesoAlbaranVenta.CrearDocumentoAlbaranVenta) Me.AddTask(Of DocumentoAlbaranVenta)(AddressOf ProcesoAlbaranVenta.AsignarValoresPredeterminadosGenerales) Me.AddTask(Of DocumentoAlbaranVenta)(AddressOf ProcesoAlbaranVenta.AsignarDatosCliente) Me.AddTask(Of DocumentoAlbaranVenta)(AddressOf AsignarFuncionalidadEjemplo) 'EJEMPLO Me.AddTask(Of DocumentoAlbaranVenta)(AddressOf ProcesoAlbaranVenta.AsignarDireccion) Me.AddTask(Of DocumentoAlbaranVenta)(AddressOf ProcesoAlbaranVenta.AsignarBanco) Me.AddTask(Of DocumentoAlbaranVenta)(AddressOf ProcesoComercial.AsignarObservacionesComercial) Me.AddTask(Of DocumentoAlbaranVenta)(AddressOf ProcesoComunes.AsignarCentroGestion) Me.AddTask(Of DocumentoAlbaranVenta)(AddressOf ProcesoComunes.AsignarAlmacen) Me.AddTask(Of DocumentoAlbaranVenta)(AddressOf ProcesoAlbaranVenta.AsignarContador) Me.AddTask(Of DocumentoAlbaranVenta)(AddressOf ProcesoComunes.AsignarNumeroAlbaran) Me.AddTask(Of DocumentoAlbaranVenta)(AddressOf ProcesoComercial.AsignarEjercicio) Me.AddTask(Of DocumentoAlbaranVenta)(AddressOf ProcesoComunes.AsignarCambiosMoneda) Me.AddTask(Of DocumentoAlbaranVenta)(AddressOf CrearLineasDesdeEjemplo) 'EJEMPLO Me.AddTask(Of DocumentoAlbaranVenta)(AddressOf ProcesoAlbaranVenta.GestionArticulosKit) 'Sin Kits Me.AddTask(Of DocumentoAlbaranVenta)(AddressOf ProcesoAlbaranVenta.AsignarDireccionFacturaEnLineas) Me.AddTask(Of DocumentoAlbaranVenta)(AddressOf ProcesoAlbaranVenta.AsignarClienteBancoEnLineas) Me.AddTask(Of DocumentoAlbaranVenta)(AddressOf ProcesoAlbaranVenta.AsignarEstadoFacturaEnLineas) Me.AddTask(Of DocumentoAlbaranVenta)(AddressOf ProcesoAlbaranVenta.AsignarCondicionesEnLineas) Me.AddTask(Of DocumentoAlbaranVenta)(AddressOf ProcesoComunes.CalcularImporteLineasAlbaran) Me.AddTask(Of DocumentoAlbaranVenta)(AddressOf ProcesoAlbaranVentaPedidos.CalcularAnalitica) Me.AddTask(Of DocumentoAlbaranVenta)(AddressOf ProcesoAlbaranVenta.CalcularBasesImponibles) Me.AddTask(Of DocumentoAlbaranVenta)(AddressOf ProcesoComunes.TotalDocumento) Me.AddTask(Of DocumentoAlbaranVenta)(AddressOf ProcesoAlbaranVenta.TotalPesos) Me.AddTask(Of DocumentoAlbaranVenta)(AddressOf ProcesoAlbaranVenta.ActualizarEstadoAlbaran) Me.AddTask(Of DocumentoAlbaranVenta)(AddressOf ProcesoAlbaranVenta.GrabarDocumento) Me.AddTask(Of DocumentoAlbaranVenta)(AddressOf ProcesoAlbaranVenta.AñadirAResultado) Me.AddTask(Of DocumentoAlbaranVenta)(AddressOf ProcesoAlbaranVenta.ActualizacionAutomaticaStock) Me.AddTask(Of DocumentoAlbaranVenta, CreateElement)(AddressOf ActualizarOrigen) 'EJEMPLO End Sub <Task()> Public Shared Function DatosIniciales(ByVal IDOrigen As Integer, ByVal services As ServiceProvider) As AlbCabVenta Dim AppParamsGeneral As ParametroTesoreria = services.GetService(Of ParametroTesoreria)() Dim ProcInfo As New ProcessInfoAV(Nothing, AppParamsGeneral.TipoAlbaranPorDefecto, Today, -1) services.RegisterService(ProcInfo) '//Para no dar de alta la entidad de ejemplo en el sistema, accedemos a la tabla a través del Admindata. Dim dtOrigen As DataTable = AdminData.GetData("tbMaestroEjemplo", New NumberFilterItem("IDOrigen", IDOrigen)) If dtOrigen.Rows.Count > 0 Then 35/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Dim AVC As New AlbCabVentaEjemplo(dtOrigen.Rows(0)) Dim AVL As New AlbLinVentaEjemplo(dtOrigen.Rows(0)) ReDim Preserve AVC.LineasOrigen(AVC.LineasOrigen.Length) AVC.LineasOrigen(AVC.LineasOrigen.Length - 1) = AVL Return AVC End If End Function <Task()> Public Shared Sub AsignarFuncionalidadEjemplo(ByVal data As DocumentoAlbaranVenta, ByVal services As ServiceProvider) data.HeaderRow("PedidoCliente") = CType(data.Cabecera, AlbCabVentaEjemplo).RazonSocial End Sub <Task()> Public Shared Sub CrearLineasDesdeEjemplo(ByVal data As DocumentoAlbaranVenta, ByVal services As ServiceProvider) Dim AVL As New AlbaranVentaLinea For Each alblin As AlbLinVentaEjemplo In data.Cabecera.LineasOrigen Dim dtDatosOrigen As DataTable = AdminData.GetData("tbMaestroEjemplo", New NumberFilterItem("IDOrigen", alblin.IDLineaOrigen)) If dtDatosOrigen.Rows.Count > 0 Then Dim context As New BusinessData(data.HeaderRow) Dim linea As DataRow = data.dtLineas.NewRow linea("IDAlbaran") = data.HeaderRow("IDAlbaran") ProcessServer.ExecuteTask(Of DataRow)(AddressOf ProcesoAlbaranVenta.AsignarValoresPredeterminadosLinea, linea, services) linea = AVL.ApplyBusinessRule("IDArticulo", dtDatosOrigen.Rows(0)("IdArticulo"), linea, context) linea = AVL.ApplyBusinessRule("Cantidad", dtDatosOrigen.Rows(0)("Cantidad"), linea, context) linea("IDFormaPago") = data.HeaderRow("IDFormaPago") linea = AVL.ApplyBusinessRule("IDCondicionPago ", data.HeaderRow("IDCondicionPago"), linea, context) linea = AVL.ApplyBusinessRule("Precio", 15, linea, context) data.dtLineas.Rows.Add(linea.ItemArray) End If Next End Sub <Task()> Public Shared Function ActualizarOrigen(ByVal data As DocumentoAlbaranVenta, ByVal services As ServiceProvider) As CreateElement '//Código de ejemplo, por no tener una Entidad Asociada a la tabla tbMaestroEjemplo Dim dtOrigen As DataTable = AdminData.GetData("tbMaestroEjemplo", New NumberFilterItem("IDOrigen", data.Cabecera.IDOrigen)) dtOrigen.TableName = "Ejemplo" If dtOrigen.Rows.Count > 0 AndAlso data.dtLineas.Rows.Count > 0 Then dtOrigen.Rows(0)("IDLineaAlbaran") = data.dtLineas.Rows(0)("IDLineaAlbaran") End If AdminData.SetData(dtOrigen) Dim e As New CreateElement e.IDElement = data.HeaderRow("IDAlbaran") e.NElement = data.HeaderRow("NAlbaran") Return e End Function Desde presentación: Private Sub btnOpcion2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnOpcion2.Click Dim ID As Integer = 11111 Dim info As CreateElement = ExpertisApp.RunProcess(Of PrcAlbaranarEjemplo)(ID) If Not info Is Nothing Then ExpertisApp.GenerateMessage("Se la creado el Albarán {0}.", Windows.Forms.MessageBoxButtons.OK, Windows.Forms.MessageBoxIcon.Information, info.NElement) End If End Sub Opción 3 36/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Usando extensibilidad, podemos hacer un proceso utilizando el Update para crear el Albarán (similar al caso 1) y poder recuperar cuál es el Albarán creado. Public Class DataAlbaran Public IDAlbaran As Integer Public NAlbaran As String Public Sub New(ByVal IDAlbaran As Integer, ByVal NAlbaran As String) Me.IDAlbaran = IDAlbaran Me.NAlbaran = NAlbaran End Sub End Class Public Class AlbaranesCreados Public Albaranes As Hashtable Public Sub New() Albaranes = New Hashtable End Sub End Class '// Opción 3 <Task()> Public Shared Function CrearAlbaranVentaConAlbaran(ByVal data As DataCrearAlbaranVenta, ByVal services As ServiceProvider) As CreateElement() '//Rellenamos un registro de Cabecera Dim AVC As New AlbaranVentaCabecera Dim dtCab As DataTable = AVC.AddNewForm AVC.ApplyBusinessRule("IdCliente", data.IDCliente, dtCab.Rows(0)) AVC.ApplyBusinessRule("FechaAlbaran", Today, dtCab.Rows(0)) '//Rellenamos un registro de Lineas Dim context As New BusinessData(dtCab.Rows(0)) Dim AVL As New AlbaranVentaLinea Dim dtLin As DataTable = AVL.AddNewForm AVL.ApplyBusinessRule("IdArticulo", data.IDArticulo, dtLin.Rows(0), context) AVL.ApplyBusinessRule("QServida", data.Cantidad, dtLin.Rows(0), context) dtLin.Rows(0)("Regalo") = 0 Dim upg As New UpdatePackage upg.Add(dtCab) upg.Add(dtLin) AVC.Update(upg, services) Return ProcessServer.ExecuteTask(Of Object, CreateElement())(AddressOf RecuperarElementoCreado, Nothing, services) End Function '//Tarea que intercalaremos en el RegisterUpdateTask del Albaran de Venta, tras el MarcarComoActualizado, por ejemplo. <Task()> Public Shared Sub CachearElementoCreado(ByVal data As DocumentoAlbaranVenta, ByVal services As ServiceProvider) If data.HeaderRow.RowState = DataRowState.Added Then Dim alb As New DataAlbaran(data.HeaderRow("IDAlbaran"), data.HeaderRow("NAlbaran")) Dim htAlb As AlbaranesCreados = services.GetService(Of AlbaranesCreados)() htAlb.Albaranes(data.HeaderRow("IDAlbaran")) = alb End If End Sub <Task()> Public Shared Function RecuperarElementoCreado(ByVal data As Object, ByVal services As ServiceProvider) As CreateElement() Dim Elems(-1) As CreateElement Dim htAlb As AlbaranesCreados = services.GetService(Of AlbaranesCreados)() For Each item As DataAlbaran In htAlb.Albaranes.Values Dim e As New CreateElement e.IDElement = item.IDAlbaran e.NElement = item.NAlbaran ReDim Preserve Elems(Elems.Length) Elems(Elems.Length - 1) = e Next Return Elems End Function 37/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Y desde presentación: Private Sub btnOpcion3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnOpcion3.Click Dim data As New DataCrearAlbaranVenta(Me.advCliente.Value, Me.advArticulo.Value, Me.nbxCantidad.Value, Me.nbxPrecio.Value) Dim elem As CreateElement() = ExpertisApp.ExecuteTask(Of DataCrearAlbaranVenta, CreateElement())(AddressOf GenerarAlbaranVenta.CrearAlbaranVentaConAlbaran, data) If Not elem Is Nothing AndAlso elem.Length > 0 Then ExpertisApp.GenerateMessage("Se ha creado el Albarán {0}.", Windows.Forms.MessageBoxButtons.OK, Windows.Forms.MessageBoxIcon.Information, elem(0).NElement) End If End Sub Volver al Índice Programación General Capa Negocio 1. Creación / Configuración de Proyectos de Negocio Método Manual Creación Proyecto Para crear un componente de la capa de negocio, crear un nuevo proyecto de Windows -> Visual Basic, del tipo Biblioteca de clases en VS2008. Establecer el nombre y la ubicación del proyecto como en la imagen. Así mismo asegurarnos de elegir la Opción de Arriba que esté en .NetFrameWork 3.5. En la página de propiedades del proyecto se puede comprobar cómo el nombre del proyecto define por defecto un espacio de nombres. El framework de .NET utiliza los espacios de nombres para definir ámbitos de objetos relacionados. Estos ámbitos permiten organizar el código y proporciona una forma de crear tipos globalmente únicos. Para diferenciar el componente de negocio nuevo del resto de componentes de negocio estándares, podemos cambiar el espacio de nombres de la raíz como aparece en la imagen 38/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis NOTA: El espacio de nombres de la raíz de los proyectos de negocio estándar de Expertis tiene la forma Solmicro.Expertis.Business.nombre_negocio Opciones de Compilación y Depuración del Proyecto Para la compilación de un proyecto de negocio hay que tener en cuenta la ubicación final de los ensamblados. Existen varias opciones pero lo más habitual es: A. Compilar directamente en el directorio de desarrollo (en este caso C:\ExpertisNet50t\Bin) Para ello, desde la página de propiedades del proyecto, en la sección Compilar se establece la Ruta de acceso de los resultados B. La segunda opción es compilar en el directorio bin del proyecto (el que está establecido por defecto), y después copiar “a mano” los ensamblados actualizados al directorio de desarrollo. NOTA: Existe un inconveniente en esta opción que consiste en que mientras se compila el proyecto no es posible tener abierto ningún otro proyecto que lo tenga referenciado. Durante la compilación se muestra un error que nos avisa de que el archivo está siendo utilizado por otro proceso. Esto es debido a que el directorio de compilación y al que apuntan las referencias del resto de proyectos es, habitualmente, el mismo. No tiene por qué suceder esto en el 100% de los casos. A veces el visual studio 2008 es inteligente y se entera de los cambios que ha habido, pero no es la mayoría de los casos. Si queremos compilar correctamente debemos cerrar todos los proyectos que tengan referenciado el proyecto que se quiere compilar. Referencias del Proyecto 39/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis En la mayoría de los casos las clases de negocio tienen que utilizar los servicios que les proporcionan los componentes de negocio y de datos del framework de eXpertis. Para utilizar dichos servicios es necesario referenciar los siguientes componentes del Engine de eXpertis Expertis.Engine.BE.BusinessEngine Expertis.Engine.DAL Expertis.Engine.Global Para agregar una referencia al proyecto, accedemos a las propiedades del proyecto y vamos a la pestaña de Referencias. O bien desde el menú Proyecto -> Agregar referencia 40/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Una vez agregadas las referencias tenemos que asegurarnos en las propiedades de cada una de las dlls del motor que tienen las propiedades de Copia Local y Copia Específica a False. Hay que recordar que estas dos propiedades en todas las dlls que tenga nuestro proyecto siempre estén a falso. Tanto dlls del Engine de Expertis, como dlls de capa de negocio, de capa de presentación, de las de janus en presentación, etc.… todas las referencias sin excepción. El componente Expertis.Engine.BE.BusinessEngine permite establecer un vínculo entre la capa de presentación y la capa de negocio. La clase BusinessHelper que se encuentra en esta librería se utiliza como clase base para la gran mayoría de los componentes funcionales de la capa de negocio. La clase base BusinessHelper hereda de la clase ContextBoundObject propia del framework de .NET, y tiene asociado el atributo TransactionalAttribute (también propia de .NET), todo ello permite que todas las clases que heredan de BusinessHelper se puedan integrar en un contexto transaccional, y en particular, en el contexto transaccional de eXpertis. Además, BusinessHelper, define una interfaz común que permite la comunicación entre los componentes del Engine de la capa de presentación y los componentes de negocio. A menudo el desarrollo funcional se basa en sobrescribir los métodos que proporciona la clase BusinessHelper. El componente Expertis.Engine.DAL proporciona una interfaz de programación que permite acceder a la base de datos, utilizando la capa de datos desde la capa de negocio. NOTA: La clase más utilizada de este componente es la clase AdminData. Casi todos los métodos de esta clase son Shared, con lo que en la gran mayoría de los casos utilizaremos directamente el nombre AdminData para utilizar sus métodos, y no será necesario crear una instancia de la clase. En muchos casos será suficiente con utilizar los componentes de negocio del Engine de eXpertis Expertis.Engine.BE.BusinessEngine, pero en ciertos desarrollos es necesario invocar los métodos de la clase AdminData para actualizar datos, realizar consultas, gestionar transacciones, gestionar la conexión con diferentes bases de datos de usuario, etc. El ensamblado Expertis.Engine.Global es una componente de uso general, tanto en la parte cliente, como en la parte de negocio, y dispone de un conjunto de clases publicas útiles en desarrollo. También es muy común encontrar en los proyectos de negocio una referencia a Expertis.Business.BusinessEnum. Este es un componente de negocio que contiene exclusivamente la definición de los enumerados que se utilizan en la aplicación. De esta manera la definición de los enumerados queda englobada en el mismo ámbito y se pueden utilizar en el resto de los componentes de la capa de negocio. En principio, no es obligatorio agregar una referencia a otros componentes externos de negocio. Solo agregar la referencia cuando sea necesario. De esta manera, en la medida de lo posible, se evita la dependencia entre los distintos componentes de negocio, hecho que facilita la compilación y posterior distribución de ensamblados. 41/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis NOTAS: A parte de los componentes del Engine, los componentes de negocio funcionales pueden referenciar a otros componentes de negocio. Por ejemplo, en el estándar de eXpertis el ensamblado Expertis.Business.Negocio.dll contiene la mayoría de las clases funcionales centrales de la aplicación (Artículo, Cliente, Proveedor, Moneda, etc.), el resto de componentes de negocio necesitan utilizar en mayor o menor medida dichas clases, y por ello poseen una referencia a dicha DLL. Método Template Creación Proyecto Otro método para la creación de un proyecto de eXpertis de tipo Negocio. Tendremos la posibilidad de seleccionar un template / plantilla personalizado de expertis para este fin (sistema de templates anteriormente descrito). Para ello bastará con que abramos el visual studio. Damos a la opción de Archivo -> Nuevo -> Proyecto. En el nuevo menú nos aseguraremos de dar a la opción de .NetFrameWork 3.5. y elegiremos en la opción de la izquierda VisualBasic, para que efectivamente ya en plantillas nos cargue las plantillas para aplicaciones en VisualBasic. Como últimos nos fijamos que en la sección Mis Plantillas tendremos una personalizada de Solmicro llamada: ProjectBusinessExpertis. Una vez realizado esto bastará con que demos un nombre personalizado al proyecto y aceptemos. Con este paso ya tendríamos creado un proyecto de negocio de eXpertis y con una clase minima ya existente que podremos cambiar su nombre y editarla para darle forma a una entidad de expertis 42/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Si pasásemos a ver las propiedades del proyecto y sus referencias tendremos las ya comentadas y necesarias en el proceso manual de creación de un proyecto de negocio de eXpertis. Volver al Índice 2. Creación de Entidades de Negocio Método Manual Creación Entidad Agregar una clase nueva al proyecto desde la acción Agregar nuevo elemento del menú contextual del proyecto: El código básico para crear una clase de negocio tiene esta forma Public Class CursoArticulo Inherits Solmicro.Expertis.Engine.BE.BusinessHelper Private Const cnEntidad As String = "tbCursoMaestroArticulo" 43/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Public Sub New() MyBase.New(cnEntidad) End Sub End Class En este ejemplo se crea la clase de negocio CursoArticulo que está asociada a la tabla tbCursoMaestroArticulo. Esta clase deberá contener la lógica de negocio que se corresponde con la funcionalidad que se le da a la información con la cual se asocia la clase, en este caso, los datos de la tabla. A partir de este código de ejemplo, crear las clases (entre paréntesis se define la constante cnEntidad): CursoFacturaVentaAnalitica (tbCursoFacturaVentaAnalitica) CursoFacturaVentaCabecera (tbCursoFacturaVentaCabecera) CursoFacturaVentaLinea (tbCursoFacturaVentaLinea) CursoArticulo (tbCursoMaestroArticulo) CursoCliente (tbCursoMaestroCliente) CursoMoneda (tbCursoMaestroMoneda) CursoTipoIva (tbCursoMaestroTipoIva) Cuando se crea el componente de negocio, el siguiente paso es actualizar la base de datos de sistema, para que las nuevas clases se incluyan en el conjunto de metadatos de dicha base de datos. Método Template Creación Entidad Para agregar una entidad de expertis usando template iremos a: Proyecto -> Agregar Nuevo elemento Después de este menú accederemos en el siguiente en la sección de la izquierda a Elementos Comunes y después en el centro abajo del todo buscamos en la sección de mis plantillas una personalizado de solmicro de ClassExpertis. 44/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Con esto nos agregará un fichero de clase tipo Entidad de eXpertis. Lo que tendríamos que hacer ahora es editar el contenido de esta clase para reflejar lo que necesitemos e ir mirando las anotaciones de ayuda de lo que tenemos que tener en cuenta. Volver al Índice 3. Creación de Tareas Una Tarea en eXpertis sería una función o proceso definido en una clase de Negocio de eXpertis, que posea el atributo de Task(). Al especificar este atributo dicha función o proceso debe poseer la siguiente forma: <Task()> Private Shared Sub ProcesoTask(ByVal data As Object, ByVal services As ServiceProvider) End Sub La tarea de eXpertis además de este atributo ha de recibir siempre 2 parámetros. Uno el del tipo que necesitemos y el segundo parámetro siempre un ServiceProvider y llamándolo si se puede como Services. Asimismo es obligatorio que las funciones o procesos, ya sean privados o públicos o del tipo que necesitemos, que se definan del tipo Shared. Siempre y obligatoriamente tendremos que definirlas como Shared. Para concretar la creación de Tareas en la Capa de negocio dividiríamos en tres tipos las tareas dependiendo de las necesidades. A. Tareas que reciban sólo un parámetro de entrada: <Task()> Private Shared Sub ProcesoTask(ByVal data As String, ByVal services As ServiceProvider) End Sub B. Tareas que reciban más de un parámetro de entrada: <Serializable()> _ Public Class Datos Public Valor1 As Double Public Valor2 As String Public Valor3 As Integer Public Sub New() End Sub End Class <Task()> Private Shared Sub ProcesoTask(ByVal Data As Datos, ByVal services As ServiceProvider) End Sub C. Tareas que no reciban parámetros de entrada (si no se recibe parámetro de entrada se deja de tipo object por defecto): <Task()> Private Shared Sub ProcesoTask(ByVal data As Object, ByVal services As ServiceProvider) 45/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis End Sub 4. Llamada a Tareas en Capa Negocio Para llamar a otras Tareas de Negocio desde Negocio lo haremos con el objeto ProcessServer, perteneciente al dll de Expertis.Engine.BE, y en el espacio de nombres de Expertis.Business.BE.BusinessProcessess. Es de tipo Shared con lo cual haciendo una importación a este espacio de nombres nos permitirá usarlo sin necesidad de instanciarlo. Este objeto ProcessServer posee el método de ExecuteTask con el que podremos llamar y configurar la tarea que deseamos llamar. Especificando los parámetros de entrada, salida y dirección de la función. Vemos en el siguiente ejemplo la llamada a una tarea con un parámetro de entrada y llamándolo desde otra función de Negocio. <Task()> Public Shared Sub LlamarSuma(ByVal Data As Object, ByVal Services As ServiceProvider) Dim StData As DatosSuma StData.Valor1 = 1 : StData.Valor2 = 2 Dim DblResultado As Double = ProcessServer.ExecuteTask(Of DatosSuma, Double)(AddressOf CalcularSuma, StData, Services) End Sub Private Class DatosSuma Public Valor1 As Double Public Valor2 As Double Public Sub New() End Sub End Class <Task()> Private Shared Function CalcularSuma(ByVal data As DatosSuma, ByVal services As ServiceProvider) As Double Dim DblResultado As Double DblResultado = data.Valor1 + data.Valor2 Return DblResultado End Function NOTA: siempre se ha de pasar el parámetro de Services del tipo ServiceProvider al llamar a tareas de negocio desde negocios. Volver al Índice 5. Procesos Entidades 46/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Los procesos son una lista de tareas que dado un objeto de entrada lo transforma en otro objeto a la salida. Pudiendo ser el mismo objeto de entrada con más cosas añadidas, o bien, otro objeto completamente diferente. En esa lista de tareas el objeto de salida de una tarea es la entrada para la siguiente tarea, y esto se asume si no especificamos el tipo de salida. Algunos de estos procesos, son propios del motor, como son RegisterDeleteTask, RegisterValidateTask, RegisterUpdateTask, GetBusinessRules y RegisterAddNewTasks. En la definición de estos procesos, construimos la lista de tareas, pero dichas tareas no se ejecutarán en ese momento. Los procesos RegisterDeleteTask y RegisterUpdateTask tienen, además, otra peculiaridad (DeleteProcessContext y UpdateProcessContext, respectivamente). El orden de ejecución de los procesos de una entidad cuando enviamos en algún caso la demanda de varios estados: insertados, actualizados y borrados, sería: DELETE (RegisterDeleteTasks) VALIDATE (RegisterValidateTasks) UPDATE (RegisterUpdateTasks) Como se puede apreciar siempre se ejecutarían primero la demanda de los registros borrados y a continuación se ejecutaría la validación de los registros nuevos y modificaciones y por último la inserción y modificación de dichos registros. a. Proceso RegisterValidateTasks [Validaciones Generales] El proceso RegisterValidateTasks sería el evento de una clase de negocio que usaríamos para concretar una lista de tareas a ejecutar, cuya labor sea efectivamente realizar validaciones de los datos antes de grabarlos en la base de datos, y antes de llamar al evento RegisterUpdateTasks. Ejecutaría este método automáticamente el motor de eXpertis cuando hagamos actualizaciones de una clase, ya sea inserciones o modificaciones. En el Proceso RegisterValidateTasks sólo se admite como parámetro de entrada de tipo Datarow. Si se usase otro tipo no funcionaría correctamente este evento. Este proceso lo llama automáticamente el motor en caso de ser llamada de actualización de datos desde formularios u objetos de presentación enlazados a formularios. En caso de invocar manualmente a un update de una entidad se llamaría unicamente al RegisterUpdateTasks omitiendo el RegisterValidateTasks. Para ello debemos llamar manualmente al RegisterValidateTasks a través de método Validate de una entidad Dim DtArticuloNew As New DataTable Dim ClsArticulo As New Articulo ClsArticulo.Validate(DtArticuloNew) El aspecto general que tendría el Proceso RegisterValidateTasks sería la siguiente: Protected Overrides Sub RegisterValidateTasks(ByVal validateProcess As Engine.BE.BusinessProcesses.Process) MyBase.RegisterValidateTasks(validateProcess) validateProcess.AddTask(Of DataRow)(AddressOf ValidarDatosObligatorios) End Sub La primera línea de mybase es siempre así y obligatoria para el correcto funcionamiento. Las siguientes lineas usaríamos el objeto de ValidateProcess en el cual añadiríamos las tareas correspondientes. 47/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis En el Proceso RegisterValidateTasks sólo se admite como parámetro de entrada de tipo Datarow. Si se usase otro tipo no funcionaría correctamente este evento. A. Campos No Nulos Validación de campos que no admiten valores nulos. Para evitar que se muestre el error de SQL se suelen validar en el método RegisterValidateTasks de las clases de negocio. El código de la validación dependerá del tipo de dato. Por ejemplo, para un tipo de dato cadena una forma habitual seria Protected Overrides Sub RegisterValidateTasks(ByVal validateProcess As Engine.BE.BusinessProcesses.Process) MyBase.RegisterValidateTasks(validateProcess) validateProcess.AddTask(Of DataRow)(AddressOf ValidarCampoNulo) End Sub <Task()> Friend Shared Sub ValidarCampoNulo(ByVal data As DataRow, ByVal services As ServiceProvider) If Length(data("IDArticulo")) = 0 Then ApplicationService.GenerateError("El campo IDArticulo es obligatorio.") End Sub Donde Data es un objeto DataRow del DataTable que se quiere actualizar. Usamos el objeto Length que es propio del FrameWork de Expertis. Este método nos comprueba cualquier tipo de dato (sea tipo texto, numérico, ….) y nos devuelve la longitud de lo comprobado. Siendo 0 en caso de que lo comprobado sea con valor Nulo. Otros métodos que tenemos disponibles del framework de .NET: IsDBNull para campos de todo tipo en general; la función IsNumeric para campos de tipo numérico; la función IsDate para campos de tipo fecha. Además, dado que la mayoría de las veces la validación se hace sobre un objeto DataRow, también es frecuente el uso de la función IsNull del objeto DataRow, como en el ejemplo. NOTA: Todos los mensajes de error se ejecutan utilizando el método GenerateError de la clase ApplicationService, que está en el componente Solmicro.Expertis.Engine.BE. No es válido utilizar Windows.Forms para mostrar mensajes desde la capa de negocio. B. Claves Primarias Repetidas La validación de claves repetidas también se programa en el método RegisterValidateTasks de la clase, y se suele hacer utilizando el método SelOnPrimaryKey de la propia clase. Por ejemplo Protected Overrides Sub RegisterValidateTasks(ByVal validateProcess As Engine.BE.BusinessProcesses.Process) MyBase.RegisterValidateTasks(validateProcess) validateProcess.AddTask(Of DataRow)(AddressOf ValidarClavePrimaria) End Sub <Task()> Friend Shared Sub ValidarClavePrimaria(ByVal data As DataRow, ByVal services As ServiceProvider) Dim Dt As DataTable = New Articulo().SelOnPrimaryKey(data("IDArticulo")) If Dt.Rows.Count > 0 Then ApplicationService.GenerateError("El artículo introducido ya existe.") End If End Sub C. Existencia y Comprobación de Claves Extranjeras Esta validación también se programa en el método RegisterValidateTasks de la clase, y se suele hacer utilizando el método SelOnPrimaryKey de la clase correspondiente a la clave extranjera, o bien con el método GetItemRow, también de la misma clase. Hay dos diferencias entre ambas: la primera es que el método GetItemRow devuelve un DataRow en lugar de un DataTable, y la segunda es que GetItemRow lanza directamente una excepción si el registro correspondiente a la clave no existe. Por ejemplo Protected Overrides Sub RegisterValidateTasks(ByVal validateProcess As Engine.BE.BusinessProcesses.Process) MyBase.RegisterValidateTasks(validateProcess) validateProcess.AddTask(Of DataRow)(AddressOf ValidarClavePrimaria) End Sub <Task()> Friend Shared Sub ValidarClavePrimaria(ByVal data As DataRow, ByVal services As ServiceProvider) Dim Dt As DataTable = New CursoTipoIVA().SelOnPrimaryKey(data("IDTipoIVA")) If Dt.Rows.Count > 0 Then ApplicationService.GenerateError("El tipo iva | no existe.”, data("IDTipoIVA")) 48/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis End If End Sub Alternativamente Dim ti As New CursoTipoIva ti.GetItemRow(dr("IDTipoIva")) NOTA: es recomendable el uso de la primera opción, ya que permite mostrar un mensaje personalizado. Es preferible utilizar GetItemRow en otros procesos. Volver al Índice b. Proceso RegisterUpdateTasks [Reglas de Actualización] El proceso RegisterUpdateTasks sería el evento de una clase de negocio que usaríamos para concretar una lista de tareas a ejecutar, cuya labor sea comprobaciones y actualizaciones previas al grabado en base de datos. Este evento se llamaría de manera automática por parte del motor después de haber pasado previamente por el RegisterValidateTasks. El aspecto general que tendría el proceso RegisterUpdateTasks sería la siguiente: Protected Overrides Sub RegisterUpdateTasks(ByVal updateProcess As Engine.BE.BusinessProcesses.Process) MyBase.RegisterUpdateTasks(updateProcess) updateProcess.AddTask(Of DataRow)(AddressOf AsignarClavePrimaria) End Sub La primera línea de mybase es siempre así y obligatoria para el correcto funcionamiento. Las siguientes líneas usaríamos el objeto de UpdateProcess en el cual añadiríamos las tareas correspondientes. En el Proceso RegisterUpdateTasks se admiten como parámetros de entrada de tipo Datarow, DataTable, UpdatePackage y Document. Si se usase otro tipo no funcionaría correctamente este evento. El evento update de la entidad NO devuelve un datatable con los datos cambiados (esto era en versión 4.1 no ahora en 5.0) i. Generar Claves Autonuméricas Para asegurar un comportamiento correcto de los campos auto numérico que se manejan en eXpertis, estos campos precisan de un mantenimiento especial. NOTA: El campo auto numérico incremental de SQL no se utiliza en eXpertis, los campos declarados como auto numéricos comparten contador de manera que no se pueden repetir en distintas tablas. En primer lugar, se establece el valor por defecto del campo en el método AddNewForm de la clase correspondiente con el método GetAutoNumeric de AdminData. En segundo lugar, es necesario validar en el método RegisterUpdateTasks que el auto numérico es válido, y si no lo es, se le proporciona un valor valido con el método GetAutoNumeric de AdminData. El código ejemplo de los dos casos se muestra a continuación, en los que se da valor al campo auto numérico de la tabla tbCursoFacturaVentaLinea. Protected Overrides Sub RegisterAddnewTasks(ByVal addnewProcess As Solmicro.Expertis.Engine.BE.BusinessProcesses.Process) MyBase.RegisterAddnewTasks(addnewProcess) addnewProcess.AddTask(Of DataRow)(AddressOf FillDefaultValues) End Sub <Task()> Friend Shared Sub FillClavePrimaria(ByVal data As DataRow, ByVal services As ServiceProvider) data("IDLineaFactura") = AdminData.GetAutoNumeric End Sub Protected Overrides Sub RegisterUpdateTasks(ByVal updateProcess As Engine.BE.BusinessProcesses.Process) MyBase.RegisterUpdateTasks(updateProcess) updateProcess.AddTask(Of DataRow)(AddressOf AsignarClavePrimaria) End Sub 49/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis <Task()> Friend Shared Sub AsignarClavePrimaria(ByVal data As DataRow, ByVal services As ServiceProvider) If data.RowState = DataRowState.Added Then If Length(data("IDLineaFactura")) = 0 Then data("IDLineaFactura") = AdminData.GetAutoNumeric() End If End Sub ii. Generar Valores de Campos con Contador: Como en el caso de los campos auto numéricos, los campos cuyos valores provienen de un contador precisan de un programación adicional. Para ello, se utiliza la clase Contador, que está en el componente Solmicro.Expertis.Business.Negocio (será necesario añadir una referencia a dicho componente, si no la tiene). NOTA: En las tablas donde se utilice un campo cuyo valor proviene de un contador es obligatorio que exista un campo con el nombre IDContador, de tipo varchar, de longitud 10, y que admita nulos. Primero, en el método AddNewForm de la clase correspondiente hay que comprobar si la entidad tiene un contador predeterminado. Si lo tiene, se asignan los valores a los campos IDContador, con el identificador del contador y el campo que contendrá el valor provisional del contador. En segundo lugar, en el método RegisterUpdateTasks de la clase, se comprueba si el registro necesita un valor de contador (se comprueba si el campo IDContador no es nulo), y si es así, se le asigna un valor definitivo. El código ejemplo se muestra a continuación, en los que se da valor al campo NFactura de la tabla tbCursoFacturaVentaCabecera. Protected Overrides Sub RegisterUpdateTasks(ByVal updateProcess As Engine.BE.BusinessProcesses.Process) MyBase.RegisterUpdateTasks(updateProcess) updateProcess.AddTask(Of DataRow)(AddressOf AsignarContador) End Sub <Task()> Friend Shared Sub AsignarContador(ByVal data As DataRow, ByVal services As ServiceProvider) If data.RowState = DataRowState.Added Then If Length(data("IDContador")) > 0 Then Dim StData As New Contador.DatosCounterValue(data("IDContador"), New OrdenFabricacion, "NFactura", "", "") data("NFactura") = ProcessServer.ExecuteTask(Of Contador.DatosCounterValue, String)(AddressOf Contador.CounterValue, StData, services) End If End If End Sub NOTA: Es obligatorio llamar al método CounterValue de la clase Contador en el momento de actualizar el registro, ya que es el método que se encarga de actualizar e incrementar los valores de los contadores en la tabla maestra de contadores. En el Proceso RegisterUpdateTasks admite como parámetro de entrada de tipo Datarow ,DataTable y Document. Pudiendo definir para todo el proceso si se desea con datatable, con datarow o con document, no se pueden mezclar tareas con diferentes tipos. UpdateEntity y MarcarComoActualizado En el desarrollo de tareas del proceso de RegisterUpdateTasks, es posible que un desarrollador vea necesario el poder ejecutar una serie de procesos después de que se grabase un registro de la entidad. Para ello se han desarrollado dos tareas para llevar a cabo el guardado de datos y marcarlos como actualizados para el motor mientras podemos seguir ejecutando tareas después. Para llevar a cabo esto comentando tendremos en el proyecto de: Expertis.Business.General.Comunes todas estas tareas que vamos a comentar. Para ello y dependiendo del tipo de entrada de objeto que estemos usando en las tareas del proceso tendremos: - UpdateEntityRow UpdateEntityDataTable UpdateEntityDocument Después de ejecutar cualquiera de estas tareas, hay que ejecutar la tarea de marcarlos como actualizados (MarcarComoActualizado) para que el motor al terminar el listado de tareas del RegisterUpdateTasks no trate de nuevo de crearnos / actualizarnos los mismos registros: Protected Overrides Sub RegisterUpdateTasks(ByVal updateProcess As Solmicro.Expertis.Engine.BE.BusinessProcesses.Process) 50/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis MyBase.RegisterUpdateTasks(updateProcess) updateProcess.AddTask(Of DataRow)(AddressOf updateProcess.AddTask(Of DataRow)(AddressOf updateProcess.AddTask(Of DataRow)(AddressOf updateProcess.AddTask(Of DataRow)(AddressOf AsignarClavePrimaria) Comunes.UpdateEntityRow) Comunes.MarcarComoActualizado) ProcesoPostUpdate) End Sub Protected Overrides Sub RegisterUpdateTasks(ByVal updateProcess As Solmicro.Expertis.Engine.BE.BusinessProcesses.Process) MyBase.RegisterUpdateTasks(updateProcess) updateProcess.AddTask(Of DataTable)(AddressOf AsignarClavePrimaria) updateProcess.AddTask(Of DataTable)(AddressOf Comunes.UpdateEntityDataTable) updateProcess.AddTask(Of DataTable)(AddressOf Comunes.MarcarComoActualizado) updateProcess.AddTask(Of DataTable)(AddressOf ProcesoPostUpdate) End Sub Protected Overrides Sub RegisterUpdateTasks(ByVal updateProcess As Solmicro.Expertis.Engine.BE.BusinessProcesses.Process) MyBase.RegisterUpdateTasks(updateProcess) updateProcess.AddTask(Of Document)(AddressOf AsignarClavePrimaria) updateProcess.AddTask(Of Document)(AddressOf Comunes.UpdateDocument) updateProcess.AddTask(Of Document)(AddressOf Comunes.MarcarComoActualizado) updateProcess.AddTask(Of Document)(AddressOf ProcesoPostUpdate) End Sub Estas tareas especiales su uso más común es usarlas dentro de este proceso RegisterUpdateTasks pero pueden usarse en cualquier ámbito. UpdateDelegatedOn Cuando tenemos que manejar datos de una entidad en un formulario, cuya entidad se maneja en negocio a través de un Documento de Expertis, pero el formulario tiene como entidad principal una tabla que no está relacionada para nada con el documento, tenemos la propiedad UpdateDelegatedOn. Esta propiedad nos permite especificar para una entidad hija dentro de un documento cuál es su padre y guiar así al motor de eXpertis para cuando demandemos actualización de datos de la entidad, sepa a qué entidad cabecera tiene que ir para llevar a cabo el grabado con el documento configurado. Public Class ObraVariosControl Inherits Solmicro.Expertis.Engine.BE.BusinessHelper Public Sub New() MyBase.New(cnEntidad) End Sub Private Const cnEntidad As String = "tbObraVariosControl" Public Overrides ReadOnly Property UpdateDelegatedOn() As Engine.BE.BusinessHelper Get Return BusinessHelper.CreateBusinessObject("ObraCabecera") End Get End Property ………….. End Class A un Update también se le pueden enviar registros eliminados. Para ello tendrían que ir los registros del DataTable que enviamos en estado Deleted. En este tipo estado de los rows el motor se encarga de borrarlos. Volver al Índice c. Proceso RegisterAddNewTasks [Valores por Defecto Nuevo Registro] Los valores por defecto se programan en el Proceso RegisterAddNewTasks. Sería el evento que el motor llamaría automáticamente al añadir un nuevo registro en los formularios de tipo SimpleMnto. En este ejemplo se establecen por defecto los campos FechaAlta, PrecioEstandarA y PrecioEstandarB Protected Overrides Sub RegisterAddnewTasks(ByVal addnewProcess As Solmicro.Expertis.Engine.BE.BusinessProcesses.Process) MyBase.RegisterAddnewTasks(addnewProcess) addnewProcess.AddTask(Of DataRow)(AddressOf FillDefaultValues) End Sub 51/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis <Task()> Friend Shared Sub FillDefaultValues(ByVal data As DataRow, ByVal services As ServiceProvider) data("FechaAlta") = Date.Today data("PrecioEstandarA") = 0 data("PrecioEstandarB") = 0 End Sub En muchos casos los valores por defecto de ciertos campos están parametrizados a nivel general en la aplicación. La tabla que contiene estos parámetros es la tabla tbParametro, y la clase de la capa de negocio que se utiliza para el mantenimiento de esta información es la clase Parámetro, que está en el componente Solmicro.Expetis.Business.Negocio. Dicha clase posee métodos específicos para la obtención de los valores correspondientes a cada parámetro. En este ejemplo los valores de los campos IDFormaEnvio e IDFormaPago se obtienen de los parámetros de la aplicación Protected Overrides Sub RegisterAddnewTasks(ByVal addnewProcess As Solmicro.Expertis.Engine.BE.BusinessProcesses.Process) MyBase.RegisterAddnewTasks(addnewProcess) addnewProcess.AddTask(Of DataRow)(AddressOf FillDefaultValues) End Sub <Task()> Friend Shared Sub FillDefaultValues(ByVal data As DataRow, ByVal services As ServiceProvider) data("FechaAlta") = Date.Today data("PrecioEstandarA") = 0 data("PrecioEstandarB") = 0 Dim IDHoraPredeterminada As String = New Parametro().HoraPred If Len(IDHoraPredeterminada) = 0 Then ApplicationService.GenerateError("El parámetro 'PR_T_HORA' no existe o no está correctamente configurado.") Else : data("IdHora") = IDHoraPredeterminada End If End Sub En el Proceso RegisterAddNewTasks se admite sólo como parámetro de entrada de tipo Datarow. Si se usase otro tipo no funcionaría correctamente este evento. La llamada a este RegisterAddNewTasks se hace automáticamente en el motor a través de la entidad configurada en un formulario de tipo SimpleMnto y pulsando en el botón de Nuevo Registro. Para una llamada manual al proceso de RegisterAddNewTasks llamaríamos al método AddNewForm de la entidad. Dim DtArticuloNew As New DataTable Dim ClsArticulo As New Articulo DtArticuloNew = ClsArticulo.AddNewForm Volver al Índice d. Proceso RegisterDeleteTasks [Reglas de Borrado] El Proceso RegisterDeleteTasks sería el evento de una clase que nos serviría para hacer validaciones previas o llamadas a otras funciones o procesos antes que el motor lleve a cabo el borrado de datos en la base de datos. El aspecto general que tendría el Proceso RegisterDeleteTasks sería la siguiente: Protected Overrides Sub RegisterDeleteTasks(ByVal deleteProcess As Engine.BE.BusinessProcesses.Process) MyBase.RegisterDeleteTasks(deleteProcess) deleteProcess.AddTask(Of DataRow)(AddressOf ComprobarEstado) End Sub <Task()> Friend Shared Sub ComprobarEstado(ByVal data As DataRow, ByVal services As ServiceProvider) If data("Estado") <> enumofEstado.ofePlanificada Then ApplicationService.GenerateError("Sólo se permiten eliminar órdenes de fabricación en estado 'Planificado'") End If End Sub La primera línea de mybase es siempre así y obligatoria para el correcto funcionamiento. Las siguientes lineas usaríamos el objeto de DeleteProcess en el cual añadiríamos las tareas correspondientes. 52/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis En el Proceso RegisterDeleteTasks se admite sólo como parámetro de entrada de tipo Datarow. Si se usase otro tipo no funcionaría correctamente este evento. DeleteEntityRow y MarcarComoEliminado En el desarrollo de tareas del proceso de RegisterDeleteTasks, es posible que un desarrollador vea necesario el poder ejecutar una serie de procesos después de que se borre un registro de la entidad. Para ello se han desarrollado dos tareas para llevar a cabo el borrado de datos y marcarlos como borrados para el motor y podemos seguir ejecutando tareas después. Tendremos en el proyecto de: Expertis.Business.General.Comunes todas estas tareas que vamos a comentar. DeleteEntityRow. Después de ejecutar cualquier de estas tareas hay que ejecutar la tarea de marcarlos como eliminados (MarcarComoEliminado) para que el motor al terminar el listado de tareas del RegisterDeleteTasks no trate de nuevo de borrar los mismos registros: Protected Overrides Sub RegisterDeleteTasks(ByVal deleteProcess As Solmicro.Expertis.Engine.BE.BusinessProcesses.Process) MyBase.RegisterDeleteTasks(deleteProcess) deleteProcess.AddTask(Of DataRow)(AddressOf BorrarRelacionados) deleteProcess.AddTask(Of DataRow)(AddressOf Comunes.DeleteEntityRow) deleteProcess.AddTask(Of DataRow)(AddressOf Comunes.MarcarComoEliminado) deleteProcess.AddTask(Of DataRow)(AddressOf ProcesoPostDelete) End Sub Estas tareas especiales su uso más común es usarlas dentro de este proceso RegisterDeleteTasks pero pueden usarse en cualquier otro ámbito. DeleteRowCascade Cuando queremos borrar registros relacionados en una entidad dentro de las tareas de borrado de una entidad, no podemos usar simplemente la llamada Delete de la entidad para esos registros, puesto que no hay garantía de que el motor nos llame en cascada al resto de RegisterDeleteTasks de las entidades relacionadas. Para ello disponemos del método DeleteRowCascade para garantizar que el registro que queremos borrar recursivamente y se llamen a sus entidades relacionadas y se tenga en cuenta la configuración de borrados en cascada programados en el manager. <Task()> Public Shared Sub EliminarComponentes(ByVal Linea As System.Data.DataRow, ByVal services As ServiceProvider) 'KITS Y SUBCONTR. que no vienen de producción If Linea(_ACL.EstadoStock) = enumaclEstadoStock.aclSinGestion And _ ((Linea(_ACL.TipoLineaAlbaran) = enumaclTipoLineaAlbaran.aclSubcontratacion And IsDBNull(Linea(_ACL.IDOrdenRuta))) _ Or Linea(_ACL.TipoLineaAlbaran) = enumaclTipoLineaAlbaran.aclKit) Then Dim ACL As New AlbaranCompraLinea Dim componentes As DataTable = ACL.Filter(New NumberFilterItem("IDLineaPadre", Linea("IDLineaAlbaran"))) For Each drv As DataRow In componentes.Rows ACL.DeleteRowCascade(drv, services) Dim listaEliminados As LineasAlbaranCompraEliminadas = services.GetService(Of LineasAlbaranCompraEliminadas)() listaEliminados.IDLineas.Add(drv("IDLineaAlbaran"), drv("IDLineaAlbaran")) Next 'BusinessHelper.UpdateTable(componentes) Else ProcessServer.ExecuteTask(Of DataRow)(AddressOf DeleteComponentes, Linea, services) End If End Sub Volver al Índice e. Proceso GetBusinessRules [Reglas de Negocio] El proceso GetBusinessRules se utiliza para la codificación de parte de la lógica de negocio. Este método pertenece a la clase BusinessHelper y está disponible en todas las clases de negocio que heredan de dicha clase. El objetivo de este método es el de centralizar ciertas operaciones que den sentido funcional a los datos manejados, independientemente de cuál sea el entorno donde se estén utilizando dichos 53/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis datos (presentación o negocio), es decir, lo que se intenta con esto, es que parte de la lógica de negocio esté localizada en un solo método y que sea reutilizable, esto facilita el mantenimiento del código. Las clases de presentación llaman automáticamente a este método (siempre que la clase de presentación tenga conocimiento de la clase de negocio que puede utilizar), y de la misma forma, el Proceso GetBusinessRule podría utilizarse desde cualquier otro componente de negocio. La forma habitual del método es la siguiente Public Overrides Function GetBusinessRules() As Engine.BE.BusinessRules Dim OBrl As New BusinessRules OBrl.Add("Nombre_Columna1", AddressOf TareaColumna1) OBrl.Add("Nombre_Columna2", AddressOf TareaColumna2) OBrl.Add("...", AddressOf ...) Return OBrl End Function <Task()> Friend Shared Sub TareaColumna1(ByVal data As BusinessRuleData, ByVal services As ServiceProvider) If data.ColumnName = "Nombre_Columna1" Then If data.Context("Columna_Especial") = True Then data.Current("Columna") = data.Value End If End If End Sub De la tarea a la que llamamos desde el listado de tareas del proceso GetBusinessRules, recibe un parámetro de tipo BusinessRuleData. Éste se compone de los siguientes campos: ColumnName: Nombre de la columna sobre la cual se está aplicando la regla de negocio. Value: Valor actual. Current: Objeto BusinessData que contiene todos los valores del registro actual, incluido el de la columna que es objeto de la regla de negocio. Context: Objeto BusinessData que establece el contexto donde se aplica la regla de negocio. La clase BusinessData pertenece al Engine de eXpertis y deriva de la clase Hashtable del framework de .NET. Esta clase permite el paso de información entre las capas de presentación y negocio. Las clases de presentación disponen de dos eventos, BusinessCalling y BusinessCalled, que permiten programar las llamadas automáticas que realiza el motor de eXpertis. En el método GetBusinessRule no debe programarse código que actualice en la base de datos, la codificación debe centrarse exclusivamente en la aportación de información funcional y devolución de dicha información. El proceso GetBusinessRules se utiliza para la codificación de parte de la lógica de negocio. Este método pertenece a la clase BusinessHelper y está disponible en todas las clases de negocio que heredan de dicha clase. El objetivo de este método es el de centralizar ciertas operaciones que den sentido funcional a los datos manejados, independientemente de cuál sea el entorno donde se estén utilizando dichos datos (presentación o negocio), es decir, lo que se intenta con esto, es que parte de la lógica de negocio este localizada en un solo método y que sea reutilizable, esto facilita el mantenimiento del código. Las clases de presentación llaman automáticamente a este método (siempre que la clase de presentación tenga conocimiento de la clase de negocio que puede utilizar), y de la misma forma, el Proceso GetBusinessRule podría utilizarse desde cualquier otro componente de negocio. 54/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis La clase BusinessData pertenece al Engine de eXpertis y deriva de la clase Hashtable del framework de .NET. Esta clase permite el paso de información entre las capas de presentación y negocio. Las clases de presentación disponen de dos eventos, BusinessCalling y BusinessCalled, que permiten programar las llamadas automáticas que realiza el motor de eXpertis. En el método GetBusinessRule no debe programarse código que actualice en la base de datos, la codificación debe centrarse exclusivamente en la aportación de información funcional y devolución de dicha información. Las reglas de negocio de una entidad las llamará de manera automática el motor de eXpertis cuando sea desde las entidades configuradas en los formularios de presentación u objetos de datos como el DataGrid. Para llamar manualmente nosotros a las reglas de negocio de una entidad desde donde queramos lo podremos hacer de la siguiente manera y dependiendo de la capa en la que estemos y del tipo de objeto para invocar / actualizar estos datos: - Para llamar manualmente a las reglas de negocio de una entidad entre capas de negocio y teniendo como origen de datos un DataTable con su respectivo DataRow, lo haríamos de la siguiente manera: Dim ClsArticulo As New Articulo Dim DtArticuloNew As New DataTable Dim DrNew As DataRow = DtArticuloNew.NewRow DrNew("IDArticulo") = "00" DrNew = ClsArticulo.ApplyBusinessRule("IDArticulo", "00", DtArticuloNew.Rows(0)) O también alternativamente se puede realizar de esta manera: Dim ClsArticulo As New Articulo Dim DtArticuloNew As New DataTable Dim DrNew As DataRow = DtArticuloNew.NewRow DrNew("IDArticulo") = "00" Dim StData As New DataRowPropertyAccessor(DrNew) StData = ClsArticulo.ApplyBusinessRule("IDArticulo", "00", StData) For Each Dc As DataColumn In DtArticuloNew.Columns DrNew(Dc.ColumnName) = StData(Dc.ColumnName) Next - Para llamar manualmente a las reglas de negocio de una entidad entre la capa de presentación y negocio teniendo como origen de datos un DataTable con su respectivo DataRow, lo haríamos de la siguiente manera: Dim ClsArticulo As New Articulo Dim DtArticuloNew As New DataTable Dim DrNew As DataRow = DtArticuloNew.NewRow DrNew("IDArticulo") = "00" Dim StData As New BusinessData(DrNew) StData = ClsArticulo.ApplyBusinessRule("IDArticulo", "00", StData) For Each Dc As DataColumn In DtArticuloNew.Columns DrNew(Dc.ColumnName) = StData(Dc.ColumnName) Next - Para llamar a las reglas de negocio de una entidad de un DataGrid por cambios llevados a cabo en los campos de un Grid, lo haríamos de la siguiente manera: Grid1.EntityName = "Articulo" Grid1.InvokeBusinessRules("IDArticulo", "00", Grid1.GetValue("IDArticulo")) Grid1.SetValue("IDArticulo", "00") Éste último caso es necesario cuando nosotros introducimos y modificamos valores en un DataGrid a través de código fuente, puesto que en este caso el motor no tiene control y no es capaz de llamar él a las reglas de negocio, mientras que en la introducción manual por parte del usuario final si llama de manera automática a las reglas de negocio de la entidad del DataGrid. 55/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis SynonymousBusinessRules Cuando queramos desarrollar reglas de negocio compartidas entre diferentes entidades de eXpertis, tenemos la utilidad de SynonymousBusinessRules. Esta utilidad nos permite el establecer la relación de campos que queramos para llevar a cabo unas reglas de negocio genéricas. De esta manera podemos establecer que en nuestra entidad manejamos el campo FechaAlbaran y que se traducirá en campo Fecha cuando llamemos a las reglas de negocio compartida. Public Overrides Function GetBusinessRules() As Engine.BE.BusinessRules Dim services As New ServiceProvider Dim oBRL As New SynonymousBusinessRules oBRL.AddSynonymous("FechaAlbaran", "Fecha") oBRL = ProcessServer.ExecuteTask(Of BusinessRules, BusinessRules)(AddressOf ProcesoCompra.DetailBusinessRulesCab, oBRL, services) oBRL("IDProveedor") = AddressOf CambioProveedor oBRL.Add("Fecha", AddressOf ProcesoComunes.CambioFechaAlbaran) oBRL.Add("IDAlmacen", AddressOf ProcesoComunes.CambioAlmacen) oBRL.Add("IDTipoCompra", AddressOf CambioTipoCompra) oBRL.Add("IDCentroGestion", AddressOf ProcesoComunes.CambioCentroGestion) Return oBRL End Function Volver al Índice Componentes de Motor en Capa Negocio 1. AdminData AdminData objeto de Motor de la capa de Negocio y sólo disponible en la capa de Negocio. Nos brinda de diversos métodos y propiedades para administrar eXpertis. Los más importante y usados serían los siguientes. AdminData.ComposeFilter: Método que nos traduce las condiciones configuradas en un objeto Filter a una cadena de texto. Esta conversión se haría con nomenclatura de SQL. Dim FilSelec As New Filter FilSelec.Add("IDArticulo", FilterOperator.Equal, "Tuerca") Dim StrFiltro As String = AdminData.ComposeFilter(FilSelec) AdminData.GetAutoNumeric. Método que nos dato numérico único para establecer así valores numéricos de campos de clave primaria de tablas. Es un dato numérico que siempre genera un nuevo número el Engine de eXpertis y permitiéndonos tener números inequívocos para este tipo de campos de tablas. Dim Dr As DataRow Dr("IDArticulo") = AdminData.GetAutoNumeric AdminData.GetData Método que nos permite obtener datos de una tabla o vista, con una serie de parámetros para poder especificar la sentencia select, where, si queremos obtener datos de la base de datos de sistema, etc.…. Dim DtArt As DataTable = AdminData.GetData() AdminData.Filter Método para obtener datos de bases de datos ya sea una tabla o una vista y con una serie de parámetros de entrada para configurar la sentencia select, where, etc… Dim DtArt As DataTable = AdminData.Filter() AdminData.Execute Método que nos permite ejecutar scripts de SQL contra bases de datos. Este comando nos permite ejecutar una sentencia tal cual de SQL o bien mandar un comando de ejecución de un procedimiento almacenado, 56/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis etc... Este comando nos permite como parámetros de entrada o bien una instrucción en texto o bien un objeto DbCommand. Dim StrSQL As String = "SELECT IDArticulo FROM CursoArticulo WHERE DescArticulo" Dim DtArt As DataTable = AdminData.Execute(StrSQL) Además este método sería el principal para llevar a cabo la ejecución de Procedimientos almacenados en eXpertis. Para ello se aconsejo 2 maneras de realizarlo: La primera manera que tendríamos sería de una manera directa invocando al nombre del procedimiento almacenado, pasándole los parámetros de entrada de dicho procedimiento en orden: AdminData.Execute("sp_PROCEDURE", False, PARAMETRO1, PARAMETRO2) La segunda manera que tendríamos sería configurar un objeto de tipo DBCommand en el que configuremos todo los necesario para la llamada del procedimiento y pasándole los parámetros necesarios. Sería de la siguiente manera: Dim cmmComando As Common.DbCommand = AdminData.GetCommand cmmComando.CommandText = "sp_PROCEDURE" cmmComando.CommandType = CommandType.StoredProcedure Dim cmmParam As Common.DbParameter = cmmComando.CreateParameter cmmComando.Parameters.Add(cmmParam) cmmParam.ParameterName = "@Param1" cmmParam.Value = VALUEPARAM1 Dim prmEjercicio As Common.DbParameter = cmmComando.CreateParameter cmmComando.Parameters.Add(prmEjercicio) prmEjercicio.ParameterName = "@ParamEjercicio" prmEjercicio.Direction = ParameterDirection.Output AdminData.Execute(cmmComando) AdminData.ExecuteNonQuery Método que nos permite ejecutar scripts de SQL contra bases de datos. Este comando nos permite ejecutar una sentencia tal cual de SQL sin esperar ningún tipo de respuesta por parte de la Base de Datos. Es similar al comando de AdminData.Execute pero con esta salvedad de que no esperamos ninguna resputa, bien sea de conjunto de datos o de un total. AdminData.ExecuteNonQuery("sp_PROCEDURE",False, PARAMETRO1, PARAMETRO2) AdminData.SetSessionConnection Método que usaremos cuando queremos establecer la conexión de expertis actual con otra base de datos de Expertis para llevar a cabo diversos procesos. AdminData.SetSessionConnection("Nombre_Base_Datos_Destino") Para ver mas información consulta apartado de Programación General -> Cambio de Base de datos en MultiEmpresa. AdminData.BeginTx Método para comenzar una transacción en el punto que creamos oportuno de Expertis. AdminData.BeginTx() AdminData.CommitTx Método para llevar a cabo un Commit de la transacción abierta que tengamos de Expertis. AdminData.CommitTx() AdminData.RollBackTx Método para llevar a cabo un RollBack de la transacción abierta que tengamos de expertis. AdminData.RollBackTx() NOTA: además de estos métodos descritos existen más propiedades y métodos para otras gestiones de información que necesitemos. Los descritos serían los más habituales en el uso de eXpertis. Volver al Índice 57/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis 2. BusinessHelper El componente de BusinessHelper del Engine de eXpertis nos permite tener un objeto de tipo entidad de una tabla o entidad correspondiente. Lo que nos brinda es de los métodos básicos y estándar que posee una entidad de eXpertis. Esto lo usaríamos para casos en los que no deseamos o no podemos referenciar una Dll que contenga dicha entidad que queramos manejar. Bien sea por temas de diseño o bien por provocar referencias cíclicas. Sus formas de uso tendríamos, el instanciar el objeto pasando un nombre de tabla: Y la otra sería pasando un nombre de entidad ya existente. Atención que este método sólo nos daría los métodos básicos de la entidad y no nos permite acceder a las funciones o procesos públicos de dicha entidad: Además de esta utilidad nos permite actualizar en base de datos el contenido de un datatable o de un updatepackage en base de datos. Éste método es obligatorio utilizar cuando no usemos el método Update de actualización de datos de una entidad y queramos grabar datos de tablas pero no pasando por las reglas del valídate y del Update de dicha entidad. Para ello tendremos el método de UpdateTable (con varias sobrecargas) o bien UpdatePackage. Volver al Índice 3. ApplicationService 58/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis El ApplicationService sobre todo lo usamos por el método de ApplicationService.GenerateError para mostrar mensajes de error en expertis provocados en el parte de Negocio. If IsNothing(dt) OrElse dt.Rows.Count = 0 Then ApplicationService.GenerateError("No se han encontrado Datos de |.", "Articulos") Else Return True End If Volver al Índice 4. IPropertyAccesor En ocasiones nos surge la necesidad de tener una misma tarea para tratar un objeto de tipo DataRow y otras un objeto de tipo BusinessData. Por ello y con la restricción que tenemos (dentro de una misma clase no podemos tener 2 tareas con el mismo nombre), así como para facilitar el mantenimiento del código, podemos identificar ese tipo de datos de entrada como IPropertyAccesor. Esto, tanto para identificar el tipo de entrada y/o salida de una tarea, como para utilizar los 2 tipos mencionados en cualquier otra parte del código (variables, propiedades,…). Si utilizamos este objeto para contener un DataRow, deberemos utilizar una clase que lo convertirá en este nuevo tipo: (DataRowPropertyAccesor). Destacar, que este tipo no se podrá utilizar desde presentación, ya que no es serializable, en tal caso utilizaremos el BusinessData. <Task()> Friend Shared Sub CalcularImporteLineasAlbaran(ByVal doc As DocumentCabLin, ByVal services As ServiceProvider) For Each linea As DataRow In doc.dtLineas.Rows Dim ILinea As New DataRowPropertyAccessor(linea) ILinea("Cantidad") = linea("QServida") ProcessServer.ExecuteTask(Of IPropertyAccessor)(AddressOf General.CalcularPrecioImporte, ILinea, services) Dim lineaIProperty As New ValoresAyB(ILinea, doc.IDMoneda, doc.CambioA, doc.CambioB) ProcessServer.ExecuteTask(Of ValoresAyB)(AddressOf General.MantenimientoValoresAyB, lineaIProperty, services) Next End Sub Volver al Índice 5. UpdatePackage En los RegisterUpdateTask en los que viaja un Documento, en todos ellos la primera tarea recibe como parámetro un objeto del tipo UpdatePackage. Este tipo es una lista de DataTables de distintas entidades con los registros modificados. Es un tipo no serializable. Volver al Índice 6. ServiceProvider Objeto que nos servirá para cachear la infomación a lo largo de un proceso. Con él reduciremos accesos a la BBDD. Se accede al mismo a través de los tipos de datos, por lo que tendremos que prestar especial atención a los objetos que introducimos en él. Cuando queremos recuperar un objeto del mismo y hacemos referencia al objeto en cuestión, el ServiceProvider nos dará el elemento si lo tiene almacenado. Si no lo tiene almacenado, creará una instancia del tipo y la retornará. El uso de este elemento, normalmente, está relacionado con las clases EntityInfoCache, ClassEntityInfo, que funcionan de manera similar al ServiceProvider. Y lo hacen porque las clases X que nos retornará el objeto de tipo EntityInfoCache, heredan de la clase ClassEntityInfo, que nos rellena de forma “automática” las variables de la clase X, que tengan el mismo nombre que en la vista o en la tabla que será origen de datos de estas clases. Lo vemos con un ejemplo. NOTA: El ServiceProvider accede a la “cache” por tipo de datos y el EntityInfoCache lo hace por el valor de la PrimaryKey. Si hay herencia de clases. Se registrarán en el services las instancias de todas las clases en la jerarquía de la herencia. Además, tenemos también el objeto DocumentInfoCache, que funciona de manera similar al EntityInfoCache, pero con Documentos (instancias del objeto Document, que veremos más adelante). Ejemplo 1: Esta tarea puede ser llamada en un proceso varias veces con un mismo cliente, por ejemplo, en la Recepción de Pedidos. Le pedimos al services que nos de un objeto de tipo EntityInfoCache, que a su vez, contenga objetos del tipo ClienteInfo (que hereda de ClassEntityInfo). Si no lo tiene, lo creará en el services antes de retornarlo, con lo cual siempre nos devolverá un objeto de ese tipo. Este objeto retornado, actuará de forma similar al darnos un objeto de tipo ClienteInfo a través del data(“IDCliente”), si no tiene la información registrada, accede a la BBDD para obtenerla. 59/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis <Task()> Public Shared Sub ValidarClienteBloqueado(ByVal data As DataRow, ByVal services As ServiceProvider) Dim Clientes As EntityInfoCache(Of ClienteInfo) = services.GetService(Of EntityInfoCache(Of ClienteInfo))() Dim ClteInfo As ClienteInfo = Clientes.GetEntity(data("IDCliente")) If ClteInfo.Bloqueado Then ApplicationService.GenerateError("El Cliente está Bloqueado.") End Sub Ejemplo 2: En ocasiones necesitamos cachear información que el usuario nos ha proporcionado al lanzar un proceso, para tener acceso desde cualquiera de las tareas, pero no podemos identificarla bajo un tipo de datos. En este caso, nos creamos una clase (tipo de datos), que nos permita cachear esa información. Y deberemos registrarla en el services. En la Recepción de Pedidos, el usuario puede indicar un contador o una fecha de albarán, esto lo introduciremos en una clase ProcessInfoAlbCompra que registraremos en el services y luego accederemos a ella desde otro punto del proceso. <Task()> Public Shared Sub PrepararInformacionProceso(ByVal data As DataInfoProceso, ByVal services As ServiceProvider) If Length(data.IDTipoCompra) = 0 Then Dim ParamsAC As ParametroAlbaranCompra = services.GetService(Of ParametroAlbaranCompra)() data.IDTipoCompra = ParamsAC.TipoCompraNormal End If If data.FechaAlbaran Is Nothing OrElse data.FechaAlbaran = cnMinDate Then data.FechaAlbaran = Today services.RegisterService(New ProcessInfoAlbCompra(data.IDContador, data.IDTipoCompra, data.FechaAlbaran)) End Sub <Task()> Friend Shared Sub AsignarValoresPredeterminadosGenerales(ByVal alb As DocumentoAlbaranCompra, ByVal services As ServiceProvider) ProcessServer.ExecuteTask(Of DataRow)(AddressOf ProcesoComunes.AsignarIdentificadorAlbaran, alb.HeaderRow, services) Dim InfoProc As ProcessInfoAlbCompra = services.GetService(Of ProcessInfoAlbCompra)() If alb.HeaderRow.IsNull("FechaAlbaran") Or alb.HeaderRow("FechaAlbaran") = cnMinDate Then If InfoProc.FechaAlbaran <> cnMinDate Then alb.HeaderRow("FechaAlbaran") = InfoProc.FechaAlbaran Else ProcessServer.ExecuteTask(Of DataRow)(AddressOf ProcesoComunes.AsignarFechaAlbaran, alb.HeaderRow, services) End If Dim data As New DataEjercicio(New DataRowPropertyAccessor(alb.HeaderRow), alb.HeaderRow("FechaAlbaran")) ProcessServer.ExecuteTask(Of DataEjercicio)(AddressOf General.AsignarEjercicioContable, data, services) End If If alb.HeaderRow.IsNull("Estado") Then alb.HeaderRow("Estado") = enumaccEstado.accNoFacturado If alb.HeaderRow.IsNull("Automatico") Then alb.HeaderRow("Automatico") = False If alb.HeaderRow.IsNull("IDTipoCompra") Then alb.HeaderRow("IDTipoCompra") = InfoProc.IDTipoCompra End Sub Ejemplo 3 En ocasiones necesitamos cachear un Documento completo, para en sucesivas iteraciones actualizar el mismo Documento, la idea es la misma que con el EntityInfoCache. Le pedimos al services que nos dé un objeto de tipo DocumentInfoCache, que a su vez, contenga objetos del tipo DocumentoAlbaranCompra (que hereda de Document). Si no lo tiene, lo creará en el services antes de retornarlo, con lo cual siempre nos devolverá un objeto de ese tipo. Este objeto retornado, actuará de forma similar al darnos un objeto de tipo DocumentoAlbaranCompra a través del lineaAlbaran(“IDAlbaran”), si no tiene la información registrada, accede a la BBDD para obtenerla. <Task()> Friend Shared Sub ActualizarQServidaLineaPedido(ByVal lineaAlbaran As DataRow, ByVal services As ServiceProvider) If Length(lineaAlbaran("IDLineaPadre")) = 0 AndAlso Nz(lineaAlbaran("TipoLineaAlbaran"), enumaclTipoLineaAlbaran.aclNormal) <> enumaclTipoLineaAlbaran.aclComponente Then If lineaAlbaran.RowState <> DataRowState.Modified OrElse lineaAlbaran("QServida") <> lineaAlbaran("QServida", DataRowVersion.Original) Then 60/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Dim Albaranes As DocumentInfoCache(Of DocumentoAlbaranCompra) = services.GetService(Of DocumentInfoCache(Of DocumentoAlbaranCompra))() Dim DocAlb As DocumentoAlbaranCompra = Albaranes.GetDocument(lineaAlbaran("IDAlbaran")) If Length(lineaAlbaran("IDLineaPadre")) = 0 AndAlso Nz(lineaAlbaran("TipoLineaAlbaran"), enumaclTipoLineaAlbaran.aclNormal) <> enumaclTipoLineaAlbaran.aclComponente Then Dim Pedidos As DocumentInfoCache(Of DocumentoPedidoCompra) = services.GetService(Of DocumentInfoCache(Of DocumentoPedidoCompra))() Dim DocPed As DocumentoPedidoCompra = Pedidos.GetDocument(lineaAlbaran("IDPedido")) Dim OriginalQServida As Double Dim ProposedQServida As Double = Nz(lineaAlbaran("QServida"), 0) If lineaAlbaran.RowState = DataRowState.Modified Then OriginalQServida = lineaAlbaran("QServida", DataRowVersion.Original) End If DocPed.SetQServida(lineaAlbaran("IDLineaPedido"), ProposedQServida OriginalQServida, services) End If End If End If End Sub Volver al Índice 7. ContextBoundObject Al usar el sistema de tareas de Expertis no hace falta si tenemos una Clase de Negocio que no es entidad y que alberga tareas públicas el definirla con la Herencia con ContextBoundObject. Esto solo haría falta si tuviésemos una clase de Negocio de Expertis con Procesos o Funciones públicas pero sin ser tareas. Para ello necesitaríamos de establecer la herencia con ContextBoundObject y con el atributo Transactional. Public Class ClassTasks <Task()> Public Shared Function GiveAutonumeric(ByVal data As Object, ByVal services As ServiceProvider) As Integer Return AdminData.GetAutoNumeric End Function <Task()> Public Shared Sub EjecutarProceso(ByVal data As Integer, ByVal services As ServiceProvider) 'Proceso de ejecución End Sub End Class <Transactional()> _ Public Class ClassFunctions Inherits ContextBoundObject Public Function GiveAutonumeric() As Integer Return AdminData.GetAutoNumeric End Function Public Sub EjecutarProceso(ByVal data As Integer) 'Procesos de Ejecución End Sub End Class Volver al Índice Configuración del Manager para procesar Capa Negocio Debemos recordar en todo momento que después de generar nuestras nuevas entidades de negocio de Expertis, debemos de registrarlas en el manager de expertis para que consten inventariadas en su sistema, para un correcto funcionamiento de la aplicación y disponibilidad de uso de las entidades en cualquier punto de expertis. Para ello acudiremos al manager de expertis e iremos a la sección: Objetos -> Entidades. En el menú superior de Procesos tendremos un proceso automático de agregado de entidades indicándole en qué dll tenemos alojada la/s clase/s que queremos pasar. Si no siempre tendremos la opción manual de inserción de una nueva entidad. 61/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Para mayor información sobre las propiedades de una entidad acudir al manual de la Consola de Administración de Expertis 5.0. Por último si hemos editado la dll de Negocio de Enumerados, bien sea por actualización o creación de nuevos, acudiremos al manager de expertis para incluir en el sistema estos cambios. Para ello acudiremos al manager de expertis e iremos a la sección: Objetos -> Enumerados. En el menú superior de Procesos tendremos un proceso automático de agregado de enumerados indicándole la dll de enumerados de Expertis. Si no siempre tendremos la opción manual de inserción de un nuevo enumerado. Volver al Índice 62/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Extensibilidad de Procesos y Tareas Sobreescritura de Clases A veces para llevar a cabo la extensibilidad de Expertis sobre tareas, vemos que las tareas que vamos a llevar este a cabo reciben un tipo de objeto de clase (anteriormente estructura) y que a dicha clase también necesitamos tocar porque vamos a enviar más datos de los que originalmente recibe el objeto de Solmicro. Por ello vamos a explicar los pasos de cómo llevar a cabo esto descrito Con esto disponemos entonces de una tarea de origen que tiene configurado un objeto clase con una serie de variables y constructores iniciales como los descritos a continuación: <Serializable()> _ Public Class DataClass Public IDBase As Integer Public DescBase As String Public Sub New() End Sub Public Sub New(ByVal IDBase As Integer, ByVal DescBase As String) Me.IDBase = IDBase Me.DescBase = DescBase End Sub End Class <Task()> Public Shared Sub ClassTest(ByVal data As DataClass, ByVal services As ServiceProvider) If Length(data.IDBase) = 0 Then ApplicationService.GenerateError("No se puede dejar a nulo el: |", data.DescBase) End If End Sub Ahora lo que necesitamos es que esta clase ClassTest la vamos a sobreescribir por una nuestra propia pero necesitamos tocar el objeto de entrada de la tarea de tipo DataClass para insertarle mas variables. Para ello lo que tendriamos que hacer es escribir en nuestro proyecto propio dicha tarea que vamos a sobrescribir creandonos un objeto clae nuevo de la tarea base que recibe y haciendo que este objeto clase nuevo nuestro herede de la clase base de solmicro. Entonces creamos el objeto clase nuevo haciendo un Inherits con la clase base: <Serializable()> _ Public Class DataClassNew Inherits ProjectBase.PrBase.DataClass Public Estado As Boolean Public NewDesc As String Public Sub New() End Sub Public Sub New(ByVal IDBase As Integer, ByVal DescBase As String, ByVal Estado As Boolean, ByVal NewDesc As String) Me.IDBase = IDBase Me.DescBase = DescBase Me.Estado = Estado Me.NewDesc = NewDesc End Sub End Class Como se puede observar se hereda del objeto y añadimos las variables que necesitemos y otros constructores new que queramos sin problemas Con este objeto heredado creado creamos nuestra tarea que va a sobreescribir la tarea de solmicro. Para ello haremos que la firma de la tarea tiene que tener la misma que la de origen. Poniendo en este caso DataClass de la clase Prbase del proyecto ProjectBase. A continuación lo que hacemos y como medida de control de errores es que comprobamos que el objeto data que se recibe de entrada sea de nuestro tipo nuevo creado. A pesar de que en la tarea especificamos que es un DataClass nosotros vamos a enviar realmente nuestro nuevo DataClassNew y para ello comprobamos a ver si el data de entrada es de este tipo. Siendo asi podemos acceder a nuestras variables reconvirtiendo el objeto Data de tipo DataClass a nuestro DataClassNew. <Task()> Public Shared Sub ClassTestNew(ByVal data As ProjectBase.PrBase.DataClass, ByVal services As ServiceProvider) 63/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis If data.GetType Is GetType(DataClassNew) Then If Length(data.IDBase) = 0 Then If CType(data, DataClassNew).Estado = 1 Then ApplicationService.GenerateError("No se puede dejar nulo el: |", CType(data, DataClassNew).NewDesc) End If End If End If End Sub Para terminar de ver cómo sería esto, habría que localizar dónde se realizar la llamada a la tarea de origen para convertir el tipo de objeto clase antiguo al nuestro y metiendo los valores nuevos. Luego la llamada a la tarea sería igual y marcando como tipo de entrada de la tarea el tipo de objeto Clase de origen pero enviando nuestro objeto clase nuevo. Dim StDataNew As New PrNew.DataClassNew(101, "Prueba de Acceso", 1, "Prueba nueva") ExpertisApp.ExecuteTask(Of PrBase.DataClass)(AddressOf PrBase.ClassTest, StDataNew) De ésta manera podemos sobrescribir tareas de Expertis que reciben un tipo especial de datos siendo una clase propia, pero reconvertirla en extensibilidad para que se use con un objeto clase nuevo hecho por nosotros. Volver al Índice Sobreescritura de Documentos Cuando nos encontramos con el caso de necesitar aplicar extensibilidad sobre procesos o tareas relacionadas que manejan documentos de Expertis, vamos a marcar a continuación como lo llevaríamos a cabo. Para ello partimos de un documento Origen DocumentBase que estaría en un proyecto de origen de Solmicro y al que vamos a necesitar aplicar extensibilidad porque necesitamos agregar una tabla más hija a sus tablas hijas existentes. Por ello vemos cómo sería este DocumentBase: Public Class DocumentBase Inherits Document #Region "Datos Documento Base" 'Datatables de CabeceraBase Public Precios As DataTable Public Lineas As DataTable Public Function EntidadCabecera() As String Return GetType(CabeceraBase).Name End Function Public Function EntidadPrecios() As String Return GetType(PreciosBase).Name End Function Public Function EntidadLineas() As String Return GetType(LineasBase).Name End Function Public ReadOnly Property dtPrecios() As DataTable Get Return MyBase.Item(EntidadPrecios) End Get End Property Public ReadOnly Property dtLineas() As DataTable Get Return MyBase.Item(EntidadLineas) End Get End Property #End Region #Region "PrimaryKeys de DocumentBase" Public Function PrimaryKeyCab() As String() 64/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Return New String() {"IDBase"} End Function Public Function PrimaryKeyPrecios() As String() Return New String() {"IDPrecioBase"} End Function Public Function PrimaryKeyLineas() As String() Return New String() {"IDLineaBase"} End Function #End Region #Region " Creación de instancias " '//New a utilizar desde presentación (utilizado por el motor para realizar las actualizaciones de los elementos cabecera/lineas) Public Sub New(ByVal UpdtCtx As UpdatePackage) '// al crearse la bola desde el updatepackage, se debieran eliminar los conjuntos de datos que se van a tratar '// y dejar que el motor trate el resto LoadEntityHeader(False, UpdtCtx) LoadEntitiesChilds(False, UpdtCtx) End Sub '//New utilizado para obtener un Documento alamacenado en la BBDD. Public Sub New(ByVal ParamArray PrimaryKey() As Object) LoadEntityHeader(False, Nothing, PrimaryKey) LoadEntitiesChilds(False) End Sub Protected Overridable Sub LoadEntityHeader(ByVal AddNew As Boolean, Optional ByVal UpdtCtx As UpdatePackage = Nothing, Optional ByVal PrimaryKey() As Object = Nothing) If AddNew Then '//New de Procesos Dim oBusinessEntity As BusinessHelper = BusinessHelper.CreateBusinessObject(EntidadCabecera) Dim dtCabeceras As DataTable = oBusinessEntity.AddNew dtCabeceras.Rows.Add(dtCabeceras.NewRow) MyBase.AddHeader(EntidadCabecera, dtCabeceras) '//Creamos el HeaderRow ElseIf UpdtCtx Is Nothing Then '//New de PrimaryKey Dim oBusinessEntity As BusinessHelper = BusinessHelper.CreateBusinessObject(EntidadCabecera) Dim dtCabeceras As DataTable = oBusinessEntity.SelOnPrimaryKey(PrimaryKey) MyBase.AddHeader(Me.GetType.Name, dtCabeceras) Else '//New del formulario MyBase.AddHeader(Me.GetType.Name, UpdtCtx(EntidadCabecera).First) Dim PKCabecera() As String = PrimaryKeyCab() MergeData(UpdtCtx, EntidadCabecera, PKCabecera, PKCabecera, True) End If End Sub Protected Overridable Sub LoadEntitiesChilds(ByVal AddNew As Boolean, Optional ByVal UpdtCtx As UpdatePackage = Nothing) LoadEntityChild(AddNew, EntidadPrecios, UpdtCtx) LoadEntityChild(AddNew, EntidadLineas, UpdtCtx) End Sub Protected Overridable Sub LoadEntityChild(ByVal AddNew As Boolean, ByVal Entidad As String, Optional ByVal UpdtCtx As UpdatePackage = Nothing) Dim oEntidad As BusinessHelper = BusinessHelper.CreateBusinessObject(Entidad) Dim Dt As DataTable If AddNew Then '//New de Procesos Dt = oEntidad.AddNew ElseIf UpdtCtx Is Nothing Then '//New de PrimaryKey Dim PKCabecera() As String = PrimaryKeyCab() Dt = oEntidad.Filter(New FilterItem(PKCabecera(0), HeaderRow(PKCabecera(0)))) Else '//New del formulario '// al crearse la bola desde el updatepackage, se debieran eliminar los conjuntos de datos que se van a tratar '// y dejar que el motor trate el resto (MergeData) Dim PKCabecera() As String = PrimaryKeyCab() Dt = MergeData(UpdtCtx, Entidad, PKCabecera, PKCabecera, True) End If Me.Add(oEntidad.GetType.Name, Dt) End Sub #End Region 65/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis End Class Para este punto es importante que los eventos de LoadEntityHeader, LoadEntitiesChild y LoadEntityChild estén marcados como protected overridable Sub para que podamos disponer de ellos en el documento hijo que vamos a crear. Partiendo de este documento de origen creamos un nuevo documento hijo en nuestro proyecto de extensibilidad. Su principal pecurialidad es que nuestro documento herede del documento proyecto Base. Luego ya a este documento agregamos todo el sistema normal para que tenga reflejado la nueva tabla que estamos asociando al documento de origen. Public Class DocumentBaseNew Inherits ProjectBase.DocumentBase Public HijoNew1 As DataTable Public Function EntidadHijoNew1() As String Return GetType(HijoNew1).Name End Function Public ReadOnly Property dtHijoNew1() As DataTable Get Return MyBase.Item(EntidadHijoNew1) End Get End Property '//New a utilizar desde presentación (utilizado por el motor para realizar las actualizaciones de los elementos cabecera/lineas) Public Sub New(ByVal UpdtCtx As UpdatePackage) '// al crearse la bola desde el updatepackage, se debieran eliminar los conjuntos de datos que se van a tratar '// y dejar que el motor trate el resto LoadEntityHeader(False, UpdtCtx, Nothing) LoadEntitiesChilds(False, UpdtCtx) End Sub '//New utilizado para obtener un Documento alamacenado en la BBDD. Public Sub New(ByVal ParamArray PrimaryKey() As Object) LoadEntityHeader(False, Nothing, PrimaryKey) LoadEntitiesChilds(False) End Sub Protected Overrides Sub LoadEntityHeader(ByVal AddNew As Boolean, Optional ByVal UpdtCtx As UpdatePackage = Nothing, Optional ByVal PrimaryKey() As Object = Nothing) MyBase.LoadEntityHeader(AddNew, UpdtCtx, PrimaryKey) End Sub Protected Overrides Sub LoadEntitiesChilds(ByVal AddNew As Boolean, Optional ByVal UpdtCtx As UpdatePackage = Nothing) MyBase.LoadEntitiesChilds(AddNew, UpdtCtx) LoadEntityChild(AddNew, EntidadHijoNew1, UpdtCtx) End Sub End Class Como último punto sobreescribiriamos los procesos de LoadEntityHeader llamando al proceso padre del documento Base y sobreescribiríamos también el LoadEntitiesChild, llamando al proceso base del documento base y añadiendo nuestras llamadas a cargar nuestras nuevas tablas. A continuación tenemos cómo se vería una tarea que usa el DocumentBase dentro de un proceso relacionado con dicho documento. Public Class ProcesoBase <Task()> Public Shared Sub ProcessDocBase(ByVal data As DocumentBase, ByVal services As ServiceProvider) If Not data.dtLineas Is Nothing AndAlso data.dtLineas.Rows.Count > 0 Then For Each Dr As DataRow In data.dtLineas.Select 'Proceso Next End If End Sub 66/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis End Class En caso de necesitar sobrescribir esta tarea lo haremos con una nueva tarea en un proyecto nuestro. Tendremos que respetar que el tipo de entrada de la tarea sea el mismo que la de origen, en este caso de DocumentBase. Lo que haremos luego y como medida de control de errores es ver si el tipo de entrada de la tarea es nuestro tipo de documento DocumentBaseNew y en ese caso usar ya nuestro objeto DocumentBaseNew reconvirtiendolo cuando haga falta. De esta manera accedemos a la información mas concreta de nuestro nuevo documento. Public Class ProcesoBaseNew <Task()> Public Shared Sub ProcessDocNew(ByVal data As ProjectBase.DocumentBase, ByVal services As ServiceProvider) If Not data.dtLineas Is Nothing AndAlso data.dtLineas.Rows.Count > 0 Then If data.GetType Is GetType(DocumentBaseNew) Then If CType(data, DocumentBaseNew).dtHijoNew1 Is Nothing AndAlso CType(data, DocumentBaseNew).dtHijoNew1.Rows.Count > 0 Then For Each Dr As DataRow In CType(data, DocumentBaseNew).dtHijoNew1.Select 'Proceso Next End If End If End If End Sub End Class A continuación tendríamos un ejemplo de creación y llamada a la anterior tarea con estos documentos y con extensibilidad. Hay que fijarse que el tipo de documento que creamos es el nuestro DocumentBaseNew y que luego la llamada a la tarea sería como estaríamos haciendo y pasando como tipo de objeto de entrada el DocumentBase. Dim DocNew As New DocumentBaseNew(101) ExpertisApp.ExecuteTask(Of DocumentBase)(AddressOf ProcesoBase.ProcessDocBase, DocNew) Volver al Índice Ejemplos A continuación marcamos una serie de ejemplos de escritura y manejo de tareas y procesos de cara a la extensibilidad. Para ello se han creado dos proyectos de ejemplo: uno de origen simulando el proyecto de origen de uno estándar de expertis y otro nuevo siendo uno específico para nuestro cliente / proyecto. Para ello se han creado previamente las tareas y todos los datos y se han procesado contra el manager de expertis a través de la opción de Añadir Procesos y Tareas. 67/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Ejemplo de Sobreescritura de Tarea Tarea Origen: Localizada en una dll estándar de Expertis [Expertis.Business.ProjectBase] <Task()> Public Shared Sub AsignarValoresPorDefecto(ByVal data As DataRow, ByVal services As ServiceProvider) If data.RowState = DataRowState.Added OrElse data.RowState = DataRowState.Modified Then data("PrecioA") = 100 data("FechaAlta") = Today.Date End If End Sub Tarea Nueva: Localizada en una dll nuestra dedicada al proyecto [Expertis.Business.ProjectNew] <Task()> Public Shared Sub TaskOverWriteValoresPorDefecto(ByVal data As DataRow, ByVal services As ServiceProvider) If data.RowState = DataRowState.Added OrElse data.RowState = DataRowState.Modified Then data("PrecioA") = 200 data("FechaAlta") = Today.Date.AddDays(1) End If End Sub En el manager localizamos la tarea de origen y pulsamos en Sobrescritura y buscamos nuestra tarea nueva. 68/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Una vez hecho esto podemos guardar los datos y tendríamos hecha ya nuestra sobreescritura de tarea. 69/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Ejemplo de Tarea Después de Tarea Tarea Nueva: Localizada en una dll nuestra dedicada al proyecto [Expertis.Busines.ProjectNew] <Task()> Public Shared Sub TaskAfterValoresPorDefecto(ByVal data As DataRow, ByVal services As ServiceProvider) If data.RowState = DataRowState.Added OrElse data.RowState = DataRowState.Modified Then data("Tipo") = 0 data("Importe") = data("PrecioA") * 100 End If End Sub En el manager localizamos la tarea de origen en la que queremos establecer una nueva tarea después y la seleccionamos. Damos al botón de – para establecer la tarea después para esta tarea. 70/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Una vez hecho esto podemos guardar los datos y tendríamos hecha ya nuestra nueva tarea después de la tarea de origen dicha. Ejemplo de Nueva Tarea en Proceso Proceso Origen: Localizada en dll estándar de Expertis [Expertis.Business.ProjectBase] Protected Overrides Sub RegisterUpdateTasks(ByVal updateProcess As Solmicro.Expertis.Engine.BE.BusinessProcesses.Process) MyBase.RegisterUpdateTasks(updateProcess) updateProcess.AddTask(Of DataRow)(AddressOf AsignarClavePrimaria) updateProcess.AddTask(Of DataRow)(AddressOf AsignarValoresPorDefecto) End Sub Tarea Nueva: Localizada en una dll nuestra dedicada al proyecto [Expertis.Business.ProjectNew] 71/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis <Task()> Public Shared Sub TaskNewTaskOnProcess(ByVal data As DataRow, ByVal services As ServiceProvider) If data.RowState = DataRowState.Added OrElse data.RowState = DataRowState.Modified Then If data("Tipo") = 1 Then Dim StData As New StPublic(data("IDClave"), data("PrecioA")) ProcessServer.ExecuteTask(Of StPublic)(AddressOf TaskPublicTask, StData, services) End If End If End Sub Para agregar la nueva tarea en el listado de un proceso vamos al manager para localizar el proceso en cuestión. Y accedemos a su listado de tareas. Añadimos nuestra nueva tarea en el listado 72/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Una vez hecho esto podemos guardar los datos y tendríamos hecha ya nuestra nueva tarea en el proceso. Ejemplo de Sobrescritura de un Proceso de Entidad Proceso Origen: Localizada en dll estándar de Expertis [Expertis.Business.ProjectBase] Protected Overrides Sub RegisterUpdateTasks(ByVal updateProcess As Solmicro.Expertis.Engine.BE.BusinessProcesses.Process) MyBase.RegisterUpdateTasks(updateProcess) updateProcess.AddTask(Of DataRow)(AddressOf AsignarClavePrimaria) updateProcess.AddTask(Of DataRow)(AddressOf AsignarValoresPorDefecto) End Sub Proceso Nuevo: Localizada en una dll nuestra dedicada al proyecto [Expertis.Business.ProjectNew] 73/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Public Class PrNew Inherits Process(Of DataRow) Public Overrides Sub RegisterTasks() Me.AddTask(Of DataRow)(AddressOf AsignarClavePrimariaNew) Me.AddTask(Of DataRow)(AddressOf AsignarValoresPorDefectoNew) End Sub <Task()> Public Shared Sub AsignarClavePrimariaNew(ByVal data As DataRow, ByVal services As ServiceProvider) If data.RowState = DataRowState.Added Then If Length(data("IDClave")) = 0 Then data("IDClave") = AdminData.GetAutoNumeric End If End Sub <Task()> Public Shared Sub AsignarValoresPorDefectoNew(ByVal data As DataRow, ByVal services As ServiceProvider) If data.RowState = DataRowState.Added OrElse data.RowState = DataRowState.Modified Then data("PrecioA") = 200 data("FechaAlta") = Today.Date.AddDays(1) End If End Sub End Class Buscamos el proceso de origen que deseamos sobrescribir y pulsamos sobre el botón de sobrescritura. Seleccionamos nuestra dll con nuestro proceso nuevo para sobrescribir. 74/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Una vez hecho esto podemos guardar los datos y tendríamos hecha la sobreescritura de un proceso de entidad con uno nuevo nuestro. Consideraciones Generales El parámetro de Extensibilidad del manager de Expertis debe estar activo para que se lea la información funcional de las tablas de sobrescritura de procesos y tareas. Sólo debe de activarse este parámetro en caso de desear usar la extensibilidad de expertis. Si para el desarrollo para nuestro cliente solo hacemos cambios a nivel de presentación o bien no hacemos uso de la extensibilidad es mejor desactivar este parámetro. 75/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Funciona actualmente con BBDD de sistema, tablas xProcess y xProcessTask, tanto con datos como sin datos (vacías). Las tareas devuelven automáticamente como objeto el objeto que reciben en la entrada de la misma tarea. La primera tarea de los procesos, con el tipo de entrada que tenga establecido dictamina qué tipo de objeto manejará en el resto de las tareas de los procesos, no pudiendo mezclar tipos. Tipo de datos de envío a las tareas y retorno usaremos objetos de clase. Una clase si tiene embebido un DataRow da error en Remoting aunque esté configurada como Serializable la clase. Volver al Índice 76/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis 3.3. CAPA DE PRESENTACIÓN Introducción Capa de Presentación Las clases de mantenimiento son los componente centrales de la parte cliente, ya que proporcionan la interfaz de usuario, y se encargan de la gestión de datos en la parte cliente, complementándose con las operaciones que realiza Expertis.Engine.BE.BusinessEngine en la capa de negocio. Las clases de mantenimiento recopilan la información de todos los objetos que deben mantener y solicitan los datos necesarios a la capa de negocio. Como proveedor de datos, una clase de mantenimiento realiza el enlace a datos de todos los objetos y prepara la información para realizar las operaciones básicas con la base de datos (inserciones, actualizaciones y borrados). Todos los registros se manejan de forma desconectada y de forma genérica, las clases de mantenimiento utilizan objetos de los componentes Expertis.Engine.BE.BusinessEngine y Expertis.Engine.Global para realizar sus operaciones. Las clases SimpleMnto, CIMntoBase (o su clase derivada CIMnto) y GridMnto, se encuentran en el componente Expertis.Engine.UI.CommonClasses. Todas estas clases heredan de la clase base FormBase que se encuentra en el componente Expertis.Engine.UI.WinControls. Estas clases componen la mayor parte de la interfaz de presentación, de hecho en el fondo son clases que heredan de Windows.Form a las que se les incorpora una barra de herramientas (excepto la clase FormBase, que no tiene barra de herramientas). Las distintas clases de mantenimiento que heredan de FormBase particularizan su funcionamiento y se ajustan a las necesidades de cada tipo de mantenimiento creando nuevas propiedades y métodos, o sobrescribiendo parte de la interfaz que heredan de la propia clase FormBase. FormBase: Se utiliza, por ejemplo, en el desarrollo de formularios modales (esto permite tener formularios modales vinculados a datos). Por ser la clase base del resto de las clases de mantenimiento, no posee una barra de herramientas propia. SimpleMnto: Se utiliza para el desarrollo de mantenimientos tipo ficha o cabecera-líneas. Este tipo de mantenimiento presenta los datos de una tabla (principal) registro a registro. Dichas tablas suelen tener un gran número de registros. Estableciendo la propiedad EntityName permite realizar las operaciones básicas (inserciones, modificaciones y borrados). La propiedad NavigationFields establece el nombre del campo del origen de datos por el cual se van a realizar los movimientos entre registros. La propiedad ViewName establece el nombre del origen de datos, que por defecto es la tabla relacionada con la clase EntityName. Habitualmente este tipo de mantenimientos presenta información adicional de una o varias tablas relacionadas con la principal, que por lo general se mantienen en objetos de tipo Grid. Una barra de comandos estándar permite moverse de registro, buscar registros, insertar, actualizar y eliminar registros, etc. CIMnto: 77/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Se utiliza para el desarrollo de consultas interactivas. En general, este tipo de mantenimientos está compuesto básicamente por dos regiones: la primera región contiene los controles que conformarán el criterio de selección de la consulta; la segunda, contiene un Grid para presentar los resultados de la consulta. Opcionalmente, el Grid de presentación, puede presentar una columna de marcas, que permite la selección de registros. Una barra de comandos estándar permite realizar las acciones básicas de este tipo de mantenimiento: filtrar, limpiar los criterios de filtrado, exportar, ejecutar acción e imprimir. La clase CIMnto, hereda de CIMntoBase, y solo puede implementar consultas simples, es decir, de un solo Grid y unos criterios de selección. En la mayoría de los casos el desarrollo con CIMnto será suficiente. CIMntoBase: La clase CIMntoBase es más general y puede mantener en el mismo formulario varias consultas, cada una con su Grid, sus criterios de selección, etc., sin más que establecer su propiedad CIPrimaryObject. Requiere un mayor trabajo de programación que la utilización de la clase CIMnto. GridMnto: Esta clase implementa la interfaz necesaria para el desarrollo de mantenimiento de tipo tabla (o tipo Grid), en los que se muestra un conjunto de registros de tablas maestras, generalmente, de unas decenas registros, con la posibilidad de realizar inserciones, actualizaciones y borrados. La barra de comandos estándar permite realizar estas operaciones y algunas más, como imprimir y exportar datos. Volver al Índice Creación / Configuración de Proyectos de Presentación 1. Creación del Proyecto Forma Manual Para crear un componente de la Capa de Presentación, crear un nuevo de Proyecto de Windows -> Visual Basic, del tipo Biblioteca de Clases en VS2008. Establecer el nombre y la ubicación del Proyecto como en la imagen. Así mismo asegurarnos de elegir la Opción de Arriba que esté en .NetFrameWork 3.5 En la página de propiedades del proyecto se puede comprobar cómo el nombre del proyecto define por defecto un espacio de nombres. El framework de .NET utiliza los espacios de nombres para definir ámbitos de objetos relacionados. Estos ámbitos permiten organizar el código y proporciona una forma de crear tipos globalmente únicos. 78/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Para diferenciar el componente de negocio nuevo del resto de componentes de negocio estándares, podemos cambiar el espacio de nombres de la raíz como aparece en la imagen NOTA: El espacio de nombres de la raíz de los proyectos de negocio estándar de Expertis tiene la forma Solmicro.Expertis.Application.ERP.Nombre_Programa. Opciones de Compilación y Depuración del Proyecto Para la compilación de un proyecto de presentación hay que tener en cuenta la ubicación final de los ensamblados. Existen varias opciones pero lo más habitual es: A. B. Compilar directamente en el directorio de desarrollo (en este caso C:\ExpertisNet50t\Bin) Para ello, desde la página de propiedades del proyecto, en la sección Compilar se establece la Ruta de acceso de los resultados La segunda opción es compilar en el directorio bin del proyecto (el que está establecido por defecto), y después copiar “a mano” los ensamblados actualizados al directorio de desarrollo. NOTA: Existe un inconveniente en esta opción que consiste en que mientras se compila el proyecto no es posible tener abierto ningún otro proyecto que lo tenga referenciado. Durante la compilación se muestra un error que nos avisa de que el archivo está siendo utilizado por otro proceso. Esto es debido a que el directorio de compilación y al que apuntan las referencias del resto de proyectos es, habitualmente, el mismo. No tiene por qué suceder esto en el 100% de los casos. A veces el visual studio 2008 es inteligente y se entera de los cambios que ha habido, pero no es la mayoría de los casos. 79/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Si queremos compilar correctamente debemos cerrar todos los proyectos que tengan referenciado el proyecto que se quiere compilar. Referencias del Proyecto: En la mayoría de los casos las clases de presentación tienen que utilizar los servicios que les proporcionan los componentes de negocio y de datos, y de configuración de presentación del framework de Expertis. Para utilizar dichos servicios es necesario referenciar los siguientes componentes del Engine de Expertis Expertis.Engine.BE.BusinessEngine Expertis.Engine.Global Expertis.Engine.UI.CommonClasses Expertis.Engine.UI.Resources Expertis.Engine.UI.WinControls Además de éstas también necesitaremos referenciar las dlls de Janus. De las siguientes descritas tampoco harían falta referenciarlas todas, si alguna no tendríamos introducida en nuestro proyecto enseguida el visual Studio nos Avisa de la necesidad de esas referencias. Janus.Data.v3 Janus.Windows.ButtonBat.v3 Janus.Windows.CalendarCombo.v3 Janus.Windows.Common.v3 Janus.Windows.ExplorerBar.v3 Janus.Windows.GridEX.v3 Janus.Windows.TimeLine.v3 Janus.Windows.UI.v3 Para agregar una referencia al proyecto, accedemos a las propiedades del proyecto y vamos a la pestaña de Referencias. O bien desde el menú Proyecto -> Agregar referencia 80/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Una vez agregadas las referencias tenemos que asegurarnos en las propiedades de cada una de las dlls del motor que tienen las propiedades de Copia Local y Copia Específica a False. Hay que recordar que estas dos propiedades en todas las dlls que tenga nuestro proyecto siempre estén a falso. Tanto dlls del Engine de Expertis, como dlls de capa de negocio, de capa de presentación, de las de janus en presentación, etc.… todas las referencias sin excepción. El componente Expertis.Engine.BE.BusinessEngine permite establecer un vínculo entre la capa de presentación y la capa de negocio. 81/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis El componente Expertis.Engine.UI.CommonClasses contiene todos los tipos diferentes de formularios que nos aporta el Engine de Expertis. El componente Expertis.Engine.UI.WinControls contiene todos los controles secundarios del Engine de Expertis además de otros objetos y métodos para administrar Expertis, tales como búsquedas avanzadas, o el objeto ExpertisApp, etc.… El componente Expertis.Engine.UI.Resources contiene recursos propios del Engine de Expertis y que es necesitada de las anteriores dlls. Por ello es necesaria su referencia en los proyectos. El ensamblado Expertis.Engine.Global es una componente de uso general, tanto en la parte cliente, como en la parte de negocio, y dispone de un conjunto de clases publicas útiles en desarrollo. 2. Creación del Proyecto Forma Template Para crear nuestro proyecto de Presentación de Expertis nuevo partiendo de las plantillas personalizadas creadas por Solmicro, tendríamos que abrir el visual Studio y acudir a: Archivo -> Nuevo -> Proyecto. 82/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis En la ventana siguiente que tendríamos disponible. Nos posicionamos en tipos de proyecto en Visual Basic y luego nos fijamos que en las sección de Mis Plantillas dentro de Plantillas, tendremos disponibles los diferente tipos de proyectos de presentación, cada uno con un nombre descriptivo y del tipo que veremos luego a continuación. Volver al Índice 83/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Llamada a Tareas de Negocio desde Presentación Para llamar a Tareas de Negocio desde Presentación lo haremos con el objeto ExpertisApp, perteneciente al DLL de Expertis.Engine.UI.WinControls, y en el espacio de nombres de Expertis.Engine.UI. Es de tipo Shared con lo cual haciendo una importación a este espacio de nombres nos permitirá usarlo sin necesidad de instanciarlo. Este objeto ExpertisApp posee el método de ExecuteTask con el que podremos llamar y configurar la tarea que deseamos llamar. Especificando los parámetros de entrada, salida y dirección de la función. Vemos en el siguiente ejemplo la llamada a una tarea con un parámetro de entrada y llamándolo desde presentación. Private Sub CICurso_RecordUpdated(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.RecordUpdated Dim DtArticulo As DataTable DtArticulo = ExpertisApp.ExecuteTask(Of String, DataTable)(AddressOf ObtenerDatosArticulo, Me.CurrentRow("IDArticulo")) End Sub NOTA: a diferencia de la llamada de tareas en negocios, el parámetro de tipo ServiceProvider se omite en la llamada desde presentación puesto que dicho tipo de objeto no está disponible en la capa de Presentación. Volver al Índice Tipos de Formularios de Expertis 1. Formas de Creación de Formularios Podemos crear los diferentes formularios de expertis de la manera que más cómoda nos resulte y que pasaremos a explicar a continuación: Creación Manual Para crear un formulario de forma manual, en el proyecto existente de capa de presentación vamos al menú: Proyecto -> Agregar Nuevo Elemento. 84/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Después en el siguiente asistente seleccionaríamos: Elementos Comunes -> Windows Forms -> Windows Forms. Y establecemos un nombre para el nuevo formulario que vamos a crear y aceptamos. Una vez agregado el nuevo formulario lo buscamos en el explorador de soluciones del proyecto. Pulsamos el botón de mostrar todos los archivos. Una vez viendo todos los archivos expandimos el nivel de nuestro nuevo formulario y abrimos con doble click el fichero con nombre: Formulario.Designer.vb Teniendo abierto este fichero nos fijaremos en el principio del mismo y en la herencia que tiene: Inherits, y le cambiaríamos lo que tiene establecido por lo mostrado en la imagen. 85/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Dentro de ese nivel de Solmicro.Expertis.Engine.UI tendremos ahí disponibles y pondremos el modelo de formulario buscado: - CIMnto CIMntoBase SimpleMnto GridMnto FormBase Creación con Herencia Para crear un formulario que hereda de otro, desde el explorador de soluciones, botón derecho en el proyecto y seleccionar Agregar -> Agregar Nuevo Elemento. Después Seleccionar en Categorías: Windows Forms, y como plantilla Formulario Heredado. Establecer también el nombre del formulario nuevo y pulsar Agregar. 86/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis En el formulario de Selector de herencia pulsar Examinar: El formulario de dialogo nos permite seleccionar el componente donde está la clase de la cual se quiere heredar. En este ejemplo vamos a heredar de la clase GridMnto que está en el componente Expertis.Engine.UI.CommonClasses. La referencia debe apuntar al directorio de desarrollo, en este caso, C:\ExpertisNet50\Bin. 87/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis El siguiente formulario muestra todas las clases disponibles para crear un formulario heredado. Seleccionar (por ejemplo) GridMnto y aceptar. NOTA: cuando se crea el proyecto y se añade el primer formulario que hereda de alguna clase de mantenimiento de Expertis, se añaden automáticamente una serie de referencias a otros componentes del Engine de Expertis, a componentes Janus, y a componentes de Crystal Reports. En particular las referencias a Crystal Reports no son necesarias y se pueden eliminar. Creación con Template El formulario de dialogo nos permite seleccionar el componente donde está la clase de la cual se quiere Para crear un formulario que hereda de otro, desde el explorador de soluciones, botón derecho en el proyecto y seleccionar Agregar -> Agregar Nuevo Elemento. Después en el siguiente asistente seleccionaríamos: Elementos Comunes. Después en la sección central en la parte de abajo en Mis Plantillas tendríamos que ver la plantilla personalizada correspondiente de cada tipo formulario que tenemos en expertis. Seleccionaríamos el que necesitemos y le establecemos un nombre y pulsamos aceptar. 88/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Volver al Índice 2. Formulario Tipo Tabla Formulario de tipo tabla cuyo control principal sería un grid para el mostrado de datos en forma de tabla. Dispondremos asimismo de una barra de herramientas para opciones de búsqueda de registros, impresión, exportación, grabado de datos y acciones personalizadas. El uso general de este tipo de formulario es para representar en forma de listado el contenido de una tabla o vista. El uso más generalizado en expertis es para administrar tabla sencillas con pocos datos y pocas columnas. Tendremos que configurar el diseño de las columnas del grid o bien a través del Diseñador de Expertis o bien manualmente. Herencia de formulario de: Solmicro.Expertis.Engine.UI.GridMnto Tipo Template: GridMntoExpertis. El aspecto que tendría el formulario creado sería el siguiente: 89/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Propiedades Formulario Las propiedades principales y más importantes del formulario en tiempo de diseño tendríamos: EntityName Nombre de la entidad de expertis de la cargaremos los datos en el formulario. Debe coincidir con un nombre de entidad válido de Expertis. NavigationFields Propiedad para definir el campo del origen de datos del formulario por el que navegaremos a la hora de realizar la búsqueda de un registro por la búsqueda avanzada del Formulario. ViewName Propiedad para definir el origen de datos que se cargará en el formulario. Si se deja vacío se cargará la información de la tabla de la entidad asociada al formulario Las propiedades principales y más importantes del control en tiempo de ejecución tenemos: RecordsState Propiedad que nos permite saber en qué estado se encuentra el formulario dependiendo de la acción que haya hecho el usuario. De esta manera podemos saber si el formulario está en modo de nuevo registro, registro modificado, salvado,… CurrentData Datatable con toda la información que contiene el formulario y que visualizamos en el grid. Ok Botón de validar datos del formulario al que podemos simular e invocar su pulsación a través del método: InvokeOnClick. Cancel Botón de cancelar datos del formulario al que podemos simular e invocaar su pulsación a través del método: InvokeOnClick Requery Botón de refrescar datos del formulario al que podemos simular e invocar su pulsación a través del método: InvokeOnClick. Params Colección de parámetros/valores que posee el formulario y que se ha podido pasar en la apertura del formulario desde otro sitio de expertis. Esto nos permite enviar a un formulario información extra que necesitemos cuando abramos un formulario en cualquier punto de Expertis. Private Sub Me_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load If Not Me.Params Is Nothing Then Dim HtParam As Hashtable = Me.Params If HtParam.ContainsKey("Valor_Insertado") AndAlso Length(HtParam("Valor_Insertado")) > 0 Then Me.AdvParam.Value = HtParam("ValorInsertado") End If End If End Sub FomActions Colección de acciones que queramos tener en el formulario. Se agregan todas en orden en el que queramos que aparezcan. Para agregar un separador entre acciones poseemos el método del formulario AddSeparator para agregar en ese nivel de acciones un separador. Private Sub Me_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load 90/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Me.FormActions.Add("Accion_Primera", AddressOf AccionPrimera, ExpertisApp.GetIcon("MyIcon.ico")) Me.AddSeparator() Me.FormActions.Add("Accion_Segunda", AddressOf AccionSegunda, ExpertisApp.GetIcon("MyIcon2.ico")) End Sub Métodos principales BusinessCalling Método que se invoca antes de que se llamen a las reglas de negocio de cualquier entidad del formulario. Con lo cual siempre hace falta llevar a cabo un control de qué entidad llama a este evento del formulario para concretar las opciones para cada entidad. En este evento podremos trabajar con la información del current y context que manejan las reglas de negocio de Expertis. BusinessCalled Método que se invoca después de que se llamen a las reglas de negocio de cualquier entidad del formulario. Con lo cual siempre hace falta llevar a cabo un control de qué entidad llama a este evento del formulario para concretar las opciones para cada entidad. En este evento podremos trabajar con la información del current y context que manejan las reglas de negocio de Expertis. Navigating Evento que se ejecuta antes de que lleva a cabo el comando de navegación y al que podremos controlar qué acción se ha dado y poder cancelar el evento. Navigated Evento que se ejecuta después de que se lleve a cabo el comando de navegación dicho por el usuario. RecordStateChanged Evento que se ejecutará siempre que cambie el valor de la propiedad de la ventana: RecordsState. Esto nos permite poder llevar a cabo mecanismos de control cada vez que el estado del formulario cambie por alguna acción del usuario. RecordAdding, RecordAdded, RecordUpdating, RecordCanceling, RecordCanceled RecordUpdated, RecordDeleting, RecordDeleted, Métodos relacionado con la inserción, modificación, borrado y cancelación de registros en el formulario. Con mecanismos para los eventos de antes de llevar a cabo estas acciones con la variable e de poder cancelarlos con el Cancel. SetReportDataSource, SetReportDesignObjects, SetReportExportOptions, SetReportSelectionCriteria Eventos de informes en el formulario. Ver sección de Informes para el detalle de los eventos. Volver al Índice 3. Formulario Tipo Ficha Formulario de tipo ficha del cual es el que heredan todo el resto de formularios de expertis. No tiene controles presentes de base y serían para moldear por completo por nosotros. El uso general de este tipo de formulario es para representar formularios modales sencillos o complejos en expertis. Podemos usar este tipo de formularios con manejo de datos llevado a cabo por nosotros o bien seguir usando las propiedades estándar de entidad y vista que contiene el formulario. Herencia de formulario de: Solmicro.Expertis.Engine.UI.FormBase Tipo Template: FormBaseExpertis. El aspecto que tendría el formulario creado sería el siguiente: 91/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Propiedades Formulario Las propiedades principales y más importantes del formulario en tiempo de diseño tendríamos: 92/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis EntityName Nombre de la entidad de expertis de la cargaremos los datos en el formulario. Debe coincidir con un nombre de entidad válido de Expertis. NavigationFields Propiedad para definir el campo del origen de datos del formulario por el que navegaremos a la hora de realizar la búsqueda de un registro por la búsqueda avanzada del Formulario. ViewName Propiedad para definir el origen de datos que se cargará en el formulario. Si se deja vacío se cargará la información de la tabla de la entidad asociada al formulario Las propiedades principales y más importantes del control en tiempo de ejecución tenemos: RecordsState Propiedad que nos permite saber en qué estado se encuentra el formulario dependiendo de la acción que haya hecho el usuario. De esta manera podemos saber si el formulario está en modo de nuevo registro, registro modificado, salvado,… CurrentData Datatable con toda la información que contiene el formulario y que visualizamos en el grid. Ok Botón de validar datos del formulario al que podemos simular e invocar su pulsación a través del método: InvokeOnClick. Cancel Botón de cancelar datos del formulario al que podemos simular e invocaar su pulsación a través del método: InvokeOnClick Requery Botón de refrescar datos del formulario al que podemos simular e invocar su pulsación a través del método: InvokeOnClick. Params Colección de parámetros/valores que posee el formulario y que se ha podido pasar en la apertura del formulario desde otro sitio de expertis. Esto nos permite enviar a un formulario información extra que necesitemos cuando abramos un formulario en cualquier punto de Expertis. Private Sub Me_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load If Not Me.Params Is Nothing Then Dim HtParam As Hashtable = Me.Params If HtParam.ContainsKey("Valor_Insertado") AndAlso Length(HtParam("Valor_Insertado")) > 0 Then Me.AdvParam.Value = HtParam("ValorInsertado") End If End If End Sub FomActions Colección de acciones que queramos tener en el formulario. Se agregan todas en orden en el que queramos que aparezcan. Para agregar un separador entre acciones poseemos el método del formulario AddSeparator para agregar en ese nivel de acciones un separador. Private Sub Me_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load Me.FormActions.Add("Accion_Primera", AddressOf AccionPrimera, ExpertisApp.GetIcon("MyIcon.ico")) Me.AddSeparator() Me.FormActions.Add("Accion_Segunda", AddressOf AccionSegunda, ExpertisApp.GetIcon("MyIcon2.ico")) 93/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis End Sub Métodos principales UpdateData Método para provocar que se actualicen los datos del formulario asociado y actualizarlos en la base de datos llamando a los procesos de actualización de la entidad asociada en el formulario.l BusinessCalling Método que se invoca antes de que se llamen a las reglas de negocio de cualquier entidad del formulario. Con lo cual siempre hace falta llevar a cabo un control de qué entidad llama a este evento del formulario para concretar las opciones para cada entidad. En este evento podremos trabajar con la información del current y context que manejan las reglas de negocio de Expertis. BusinessCalled Método que se invoca después de que se llamen a las reglas de negocio de cualquier entidad del formulario. Con lo cual siempre hace falta llevar a cabo un control de qué entidad llama a este evento del formulario para concretar las opciones para cada entidad. En este evento podremos trabajar con la información del current y context que manejan las reglas de negocio de Expertis. Navigating Evento que se ejecuta antes de que lleva a cabo el comando de navegación y al que podremos controlar qué acción se ha dado y poder cancelar el evento. Navigated Evento que se ejecuta después de que se lleve a cabo el comando de navegación dicho por el usuario. RecordStateChanged Evento que se ejecutará siempre que cambie el valor de la propiedad de la ventana: RecordsState. Esto nos permite poder llevar a cabo mecanismos de control cada vez que el estado del formulario cambie por alguna acción del usuario. RecordAdding, RecordAdded, RecordUpdating, RecordCanceling, RecordCanceled RecordUpdated, RecordDeleting, RecordDeleted, Métodos relacionado con la inserción, modificación, borrado y cancelación de registros en el formulario. Con mecanismos para los eventos de antes de llevar a cabo estas acciones con la variable e de poder cancelarlos con el Cancel. SetReportDataSource, SetReportDesignObjects, SetReportExportOptions, SetReportSelectionCriteria Eventos de informes en el formulario. Ver sección de Informes para el detalle de los eventos. Volver al Índice 4. Formulario Tipo Mantenimiento Simple Formulario de tipo Simple cuyo objetivo es la visualización de registro a registro de un origen de datos, pudiéndonos mover entre registros con la barra de herramientas de desplazamiento. El uso general de este tipo de formulario es para representar formularios con datos de una tabla padre con datos de tablas hijas. Representando en una cabecera los datos del padre y los datos de los hijos en datagrid hijos del padre. Hay que tener en cuenta que este formulario nos crea directamente una barra de herramientas personalizada con botones de desplazamiento de registros, búsqueda avanzada y botones de validación, cancelación, exportación, acciones personalizadas, impresora,… Herencia de formulario de: Solmicro.Expertis.Engine.UI.SimpleMnto Tipo Template: SimpleMntoExpertis. El aspecto que tendría el formulario creado sería el siguiente: 94/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Propiedades Formulario Las propiedades principales y más importantes del formulario en tiempo de diseño tendríamos: 95/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis AllowDeleteCommand Propiedad para habilitar o no el botón de borrado de registro del formulario. AllowNewCommand Propiedad para habilitar o no el botón de nuevo registro del formulario. EntityName Nombre de la entidad de expertis de la cargaremos los datos en el formulario. Debe coincidir con un nombre de entidad válido de Expertis. LastUsedDescFields Especificación de qué campo del origen de datos queremos que se muestre y almcene en el listado de últimos usados de la búsqueda avanzada del formulario. NavigationFields Propiedad para definir el campo del origen de datos del formulario por el que navegaremos a la hora de realizar la búsqueda de un registro por la búsqueda avanzada del Formulario y movernos por los registros. ViewName Propiedad para definir el origen de datos que se cargará en el formulario. Si se deja vacío se cargará la información de la tabla de la entidad asociada al formulario Las propiedades principales y más importantes del control en tiempo de ejecución tenemos: RecordsState Propiedad que nos permite saber en qué estado se encuentra el formulario dependiendo de la acción que haya hecho el usuario. De esta manera podemos saber si el formulario está en modo de nuevo registro, registro modificado, salvado,… CurrentData Datatable con toda la información que contiene el formulario y que visualizamos en el grid. CurrentRow Datarow con el registro actual en el que se encuentra posicionado el formulario. Ok Botón de validar datos del formulario al que podemos simular e invocar su pulsación a través del método: InvokeOnClick. Cancel Botón de cancelar datos del formulario al que podemos simular e invocaar su pulsación a través del método: InvokeOnClick Requery Botón de refrescar datos del formulario al que podemos simular e invocar su pulsación a través del método: InvokeOnClick. Params Colección de parámetros/valores que posee el formulario y que se ha podido pasar en la apertura del formulario desde otro sitio de expertis. Esto nos permite enviar a un formulario información extra que necesitemos cuando abramos un formulario en cualquier punto de Expertis. Private Sub Me_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load If Not Me.Params Is Nothing Then Dim HtParam As Hashtable = Me.Params If HtParam.ContainsKey("Valor_Insertado") AndAlso Length(HtParam("Valor_Insertado")) > 0 Then Me.AdvParam.Value = HtParam("ValorInsertado") End If End If End Sub FomActions Colección de acciones que queramos tener en el formulario. Se agregan todas en orden en el que queramos que aparezcan. Para agregar un separador entre acciones poseemos el método del formulario AddSeparator para agregar en ese nivel de acciones un separador. Private Sub Me_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load Me.FormActions.Add("Accion_Primera", AddressOf AccionPrimera, ExpertisApp.GetIcon("MyIcon.ico")) 96/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Me.AddSeparator() Me.FormActions.Add("Accion_Segunda", AddressOf AccionSegunda, ExpertisApp.GetIcon("MyIcon2.ico")) End Sub Métodos principales UpdateData Método para provocar que se actualicen los datos del formulario asociado y actualizarlos en la base de datos llamando a los procesos de actualización de la entidad asociada en el formulario. BusinessCalling Método que se invoca antes de que se llamen a las reglas de negocio de cualquier entidad del formulario. Con lo cual siempre hace falta llevar a cabo un control de qué entidad llama a este evento del formulario para concretar las opciones para cada entidad. En este evento podremos trabajar con la información del current y context que manejan las reglas de negocio de Expertis. BusinessCalled Método que se invoca después de que se llamen a las reglas de negocio de cualquier entidad del formulario. Con lo cual siempre hace falta llevar a cabo un control de qué entidad llama a este evento del formulario para concretar las opciones para cada entidad. En este evento podremos trabajar con la información del current y context que manejan las reglas de negocio de Expertis. Navigating Evento que se ejecuta antes de que lleva a cabo el comando de navegación y al que podremos controlar qué acción se ha dado y poder cancelar el evento. Navigated Evento que se ejecuta después de que se lleve a cabo el comando de navegación dicho por el usuario. RecordStateChanged Evento que se ejecutará siempre que cambie el valor de la propiedad de la ventana: RecordsState. Esto nos permite poder llevar a cabo mecanismos de control cada vez que el estado del formulario cambie por alguna acción del usuario. RecordAdding, RecordAdded, RecordUpdating, RecordCanceling, RecordCanceled RecordUpdated, RecordDeleting, RecordDeleted, Métodos relacionado con la inserción, modificación, borrado y cancelación de registros en el formulario. Con mecanismos para los eventos de antes de llevar a cabo estas acciones con la variable e de poder cancelarlos con el Cancel. SetReportDataSource, SetReportDesignObjects, SetReportExportOptions, SetReportSelectionCriteria Eventos de informes en el formulario. Ver sección de Informes para el detalle de los eventos. Configuración de datos por Entidad / Vista o por Ejecución Para el mostrado de datos en una consulta interactiva podemos llevarlo a cabo de dos manera: uno siendo por entidad / Vista y otro asignando nosotros el origen de datos en ejecución. Para la configuración por entidad / vista no tendríamos mas que configurar un nombre de entidad y vista en el formulario para que nos cargue automáticamente datos de esta entidad / Vista. Si dejásemos solo el nombre de entidad y no poniendo vista, nos mostrará datos de la tabla que está configurada la entidad del formulario. Si no pusiésemos nombre de entidad y pusiésemos nombre de vista se mostrarían los datos de la vista configurada. Para la carga de datos a través de un proceso nuestro, lo que necesitaríamos es confirmar que el formulario no tiene establecido ni nombre de entidad ni nombre de vista, ambas propiedades en vacio. Luego prograríamos en el evento QueryExecuting del formulario el conformar el filtro que necesitamos y traer los datos de nuestro proceso. Private Sub CI_QueryExecuting(ByVal sender As Object, ByRef e As Solmicro.Expertis.Engine.UI.QueryExecutingEventArgs) Handles Me.QueryExecuting e.Filter.Add("IDCliente", FilterOperator.Equal, "00") e.Filter.Add("IDArticulo", FilterOperator.Equal, "ART001") Dim DtGrid As System.Data.DataTable = New BE.DataEngine().Filter("tbAuxDatos", e.Filter.InnerFilter) Me.Grid.Datasource = DtGrid Me.BindEditEvents(DtGrid) 97/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis End Sub Como se observa en el código de ejemplo, necesitamos establecer los datos que hemos procesado al origen de datos del Grid del formulario de consulta interactiva y además ejecutar el comando de Me.BindEditEvents. Este comando sirve para indicar al formulario que el origen de datos del formulario es nuestro datatable procesado y así se entere la barra de herramientas para que funcione con nuestro datatable. Si no ejecutásemos este comando veríamos que la barra de herramientas no se activarían los botones. Además si en el formulario usamos el tema de marcas y activamos con la marca de UseCheck del formulario, necesitaremos el comando a continuación para que nos funcionase correctamente el tema de marcas con nuestro datatable cargado en ejecución. Sería un comando del DataGrid al que le pasamos nuestro DataTable para que lo procese y agregue las columnas de checks y esté enlazado con el datasource del Grid de la consulta interactiva. Private Sub CI_QueryExecuting(ByVal sender As Object, ByRef e As Solmicro.Expertis.Engine.UI.QueryExecutingEventArgs) Handles Me.QueryExecuting e.Filter.Add("IDCliente", FilterOperator.Equal, "00") e.Filter.Add("IDArticulo", FilterOperator.Equal, "ART001") Dim DtGrid As System.Data.DataTable = New BE.DataEngine().Filter("tbAuxDatos", e.Filter.InnerFilter) Me.Grid.DataSource = DtGrid Me.Grid.AddCheckColumnToDataSource(DtGrid, Nothing) Me.BindEditEvents(DtGrid) End Sub Volver al Índice 5. Formulario Tipo Consulta Interactiva Formulario de tipo Consulta Interactiva cuyo objetivo es la visualización de datos con la posibilidad de configuración de filtros para una obtención de resultados concreta. El uso general de este tipo de formulario es para representar información ya preparada en vistas de la base de datos con posibilidad de filtrar estos datos con los filtros que configuremos en la ventana o bien con el filtro dinámico. Herencia de formulario de: Solmicro.Expertis.Engine.UI.CIMnto Tipo Template: CIMntoExpertis. El aspecto que tendría el formulario creado sería el siguiente: 98/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Propiedades Formulario Las propiedades principales y más importantes del formulario en tiempo de diseño tendríamos: AllowDynamicFilter Propiedad para habilitar o no el filtrado dinámico en la consulta interactiva. AllowUpdate Propiedad para habilitar o no la posibilidad de actualización de datos en la consulta interactiva. Con esto nos mostrará u ocultará los botones de validación y cancelación de datos de la consulta. CheckFields Colección de columnas de guardado de datos junto con la propiedad de usar chequeos en la consulta interactiva. EntityName Nombre de la entidad de expertis de la cargaremos los datos en el formulario. Debe coincidir con un nombre de entidad válido de Expertis. FilterPanelVisible Propiedad para mostrar o no por defecto el panel de filtros de la consulta interactiva. KeyField Propiedad para definir el campo del origen de datos del formulario por el que navegaremos a la hora de realizar la ViewName Propiedad para definir el origen de datos que se cargará en el formulario. Si se deja vacío se cargará la información de la tabla de la entidad asociada al formulario UseCheck Propiedad para activar o desactivar el uso de chequeos en la consulta interactiva. Con esta opción nos mostrará / ocultará los correspondiente botones y columna relacionado con los chequeos. Las propiedades principales y más importantes del control en tiempo de ejecución tenemos: Ok Botón de validar datos del formulario al que podemos simular e invocar su pulsación a través del método: InvokeOnClick. Cancel Botón de cancelar datos del formulario al que podemos simular e invocaar su pulsación a través del método: InvokeOnClick Params Colección de parámetros/valores que posee el formulario y que se ha podido pasar en la apertura del formulario desde otro sitio de expertis. Esto nos permite enviar a un formulario información extra que necesitemos cuando abramos un formulario en cualquier punto de Expertis. Private Sub Me_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load If Not Me.Params Is Nothing Then Dim HtParam As Hashtable = Me.Params If HtParam.ContainsKey("Valor_Insertado") AndAlso Length(HtParam("Valor_Insertado")) > 0 Then Me.AdvParam.Value = HtParam("ValorInsertado") End If End If 99/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis End Sub FomActions Colección de acciones que queramos tener en el formulario. Se agregan todas en orden en el que queramos que aparezcan. Para agregar un separador entre acciones poseemos el método del formulario AddSeparator para agregar en ese nivel de acciones un separador. Private Sub Me_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load Me.FormActions.Add("Accion_Primera", AddressOf AccionPrimera, ExpertisApp.GetIcon("MyIcon.ico")) Me.AddSeparator() Me.FormActions.Add("Accion_Segunda", AddressOf AccionSegunda, ExpertisApp.GetIcon("MyIcon2.ico")) End Sub ExecuteRequery Botón de ejecución de la consulta interactiva al que podemos simular e invocar su pulsación a través del método: InvokeOnClick. Métodos principales Execute Método para provocar la ejecución de la consulta interactiva simulando la pulsación del botón de prismáticos. BindEditEvents Método del formulario que nos permite agregar el origen de datos que estemos trabajando en el formulario. De esta manera el formulario activa la barra de herramientas y los botones reaccionan al origen de datos que le hemos pasado. Esto es para casos en el que el origen de datos es dinámico y por una ejecución de un proceso nuestro, no nos vale cargar información en el formulario a través de nombre de entidad y vista. Private Sub Grid_QueryExecuting(ByVal sender As Object, ByRef e As Solmicro.Expertis.Engine.UI.QueryExecutingEventArgs) Handles MyBase.QueryExecuting Dim FilDatos As New Filter Dim DtGrid As DataTable = New BE.DataEngine().Filter("VistaDatos", FilDatos) Me.BindEditEvents(DtGrid) Me.Grid.DataSource = DtGrid End Sub BusinessCalling Método que se invoca antes de que se llamen a las reglas de negocio de cualquier entidad del formulario. Con lo cual siempre hace falta llevar a cabo un control de qué entidad llama a este evento del formulario para concretar las opciones para cada entidad. En este evento podremos trabajar con la información del current y context que manejan las reglas de negocio de Expertis. BusinessCalled Método que se invoca después de que se llamen a las reglas de negocio de cualquier entidad del formulario. Con lo cual siempre hace falta llevar a cabo un control de qué entidad llama a este evento del formulario para concretar las opciones para cada entidad. En este evento podremos trabajar con la información del current y context que manejan las reglas de negocio de Expertis. RecordStateChanged Evento que se ejecutará siempre que cambie el valor de la propiedad de la ventana: RecordsState. Esto nos permite poder llevar a cabo mecanismos de control cada vez que el estado del formulario cambie por alguna acción del usuario. CheckingRecord Método para controlar cuando se esté chequeando o deschequeando un registro, usando con el sistema de chequeos del Grid. Para ello podremos controlar el estado del check a través de la propiedad e.CheckState, teniendo en cuenta que el evento es de la acción que se va a llevar a cabo, no de la acción ya hecha. Con lo cual tendremos que analizar el valor de esta propiedad negándola. Tengamos en cuenta que este evento se llamará tanto en la acción de chequear como deschequear un registro y antes de que lleve esta acción a su valor final. Para ello tendremos en la variable e de entrada toda la información necesaria: - E.CheckState: nos da la información de la situación actual de la columna check del registro que ha - E.Row: todo el registro del Grid que se está llevando la acción de chequeo o deschequeo - E.Cancel: propiedad para cancelar por completo el evento de check/uncheck del registro. invocado este evento y con lo cual sabremos qué acción futura se va a hacer. Private Sub CIMntoExpertis1_CheckingRecord(ByVal sender As Object, ByVal e As Solmicro.Expertis.Engine.UI.CheckingEventArgs) Handles CIMntoExpertis1.CheckingRecord 100/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis If e.CheckState = CheckStates.UnChecked Then If e.Row.Cells("Estado").Value = 1 Then e.Cancel = True End If End If End Sub RecordChecked Método que se invocará después de que se haya chequeado o deschequeado un registro. Para ello tendremos en la variable e de entrada toda la información necesaria: - E.CheckState: nos da la información de la opción de chequeo / deschequeo que se ha llevado a cabo en el - E.Row: todo el registro del Grid que se está llevando la acción de chequeo o deschequeo registro actual. Private Sub CIMntoExpertis1_RecordChecked(ByVal sender As Object, ByVal e As Solmicro.Expertis.Engine.UI.CheckedEventArgs) Handles CIMntoExpertis1.RecordChecked If e.CheckState = CheckStates.Checked Then If e.Row.Cells("Estado").Value = 1 Then ExpertisApp.GenerateMessage("Se ha seleccionado un registro con Estado 1", Windows.Forms.MessageBoxButtons.OK, Windows.Forms.MessageBoxIcon.Information) End If End If End Sub CheckingAllRecord Evento para cuando hayamos hecho un chequear o deschequear todos los registros del Grid. Esta acción será para las dos opciones realizadas y antes de que pueda llevar a cabo la acción, con lo cual nos posibilita poder cancelar el evento dependiendo de las circunstancias que necesitemos. Para ello tendremos en la variable e de entrada toda la información necesaria: - E.CheckAction: nos da la información de la acción de chequeo o deschequeo llevada a cabo. - E.Cancel: propiedad para cancelar por completo el evento de checkall/uncheckall del registro. Private Sub CIMntoExpertis1_CheckingAllRecord(ByVal sender As Object, ByVal e As Solmicro.Expertis.Engine.UI.CheckingAllEventArgs) Handles CIMntoExpertis1.CheckingAllRecord If e.CheckAction = UI.CheckAction.Check Then If Me.txtEstado.Text = 1 Then ExpertisApp.GenerateMessage("No se pueden seleccionar todos los registros", Windows.Forms.MessageBoxButtons.OK, Windows.Forms.MessageBoxIcon.Information) e.Cancel = True End If End If End Sub AllRecordChecked Evento para cuando haya completado la acción de chequear o deschequear todos los registros del Grid. Para ello tendremos en la variable e de entrada toda la información necesaria: - E.CheckAction: nos da la información de la acción de chequeo o deschequeo llevada a cabo. Private Sub CIMntoExpertis1_AllRecordChecked(ByVal sender As Object, ByVal e As Solmicro.Expertis.Engine.UI.AllCheckedEventArgs) Handles CIMntoExpertis1.AllRecordChecked If e.CheckAction = UI.CheckAction.Check Then ExpertisApp.GenerateMessage("Se han seleccionado todos los registros.", Windows.Forms.MessageBoxButtons.OK, Windows.Forms.MessageBoxIcon.Exclamation) End If End Sub QueryExecuting Evento para configurar los filtros que se van a aplicar a la consulta del origen de datos establecido en la consulta interactiva. Para ello disponemos en la variable e la propiedad Filter para agregar todos los filtros que deseemos. Sobre todo tendremos que configurar y añadir en este punto aquellos filtros configurados en el panel de criterios de selección para recoger los datos configurados por el usuario. Private Sub CIMntoExpertis1_QueryExecuting(ByVal sender As Object, ByRef e As Solmicro.Expertis.Engine.UI.QueryExecutingEventArgs) Handles Me.QueryExecuting e.Filter.Add("IDClave", FilterOperator.Equal, Me.AdvClave.Value) e.Filter.Add("DescClave", FilterOperator.Equal, Me.txtDescClave.value) e.Filter.Add("FechaAlta", FilterOperator.GreaterThanOrEqual, Me.ClbFechaDesde.Value) e.Filter.Add("FechaAlta", FilterOperator.LessThanOrEqual, Me.ClbFechaHasta.Value) 101/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis End Sub QueryExecuted Evento para cuando se haya completado la ejecución de la consulta interactiva y por si deseamos ejecutar procesos. Generalmente solemos dar uso a este evento para el tema de cálculo de totales del grid que mostramos en la consulta interactiva para el usuario. FilterClearing Evento para capturar cuando se ha dado al botón de limpiar los controles del panel de criterios de selección y antes de que lleve a cabo esta limpieza. FilterCleared Evento para cuando se haya completado la ejecución de la acción de limpieza de los controles del panel de criterios de selección. RecordAdding, RecordAdded, RecordUpdating, RecordCanceling, RecordCanceled RecordUpdated, RecordDeleting, RecordDeleted, Métodos relacionado con la inserción, modificación, borrado y cancelación de registros en el formulario. Con mecanismos para los eventos de antes de llevar a cabo estas acciones con la variable e de poder cancelarlos con el Cancel. SetReportDataSource, SetReportDesignObjects, SetReportExportOptions, SetReportSelectionCriteria Eventos de informes en el formulario. Ver sección de Informes para el detalle de los eventos. Volver al Índice 6. Formulario Tipo Consulta Interactiva Padre Formulario de tipo Consulta Interactiva Padre cuyo objetivo es el mismo que una consulta interactiva normal pero en este caso no nos da un grid principal en el diseño ni una sección del filtros en la ventana. Esto es para que podamos diseñar a nuestras necesidades el formulario. El uso general de este tipo de formulario es para representar formularios con datos de varias vistas en diferentes grids. Siendo luego el grid que mostremos el principal de la ventana y por el que funcionaría la barra de herramientas del formulario. Herencia de formulario de: Solmicro.Expertis.Engine.UI.CIMntoBase Tipo Template: CIMntoBaseExpertis. El aspecto que tendría el formulario creado sería el siguiente: 102/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Como propiedades y eventos generales de esta poseerá los mismos que el formulario de tipo Consulta Interactiva, puesto que como ya hemos comentado este formulario es el padre de la Consulta Interactiva. Lo que tenemos que tener en cuenta principalmente con este tipo de formulario, es el crear como necesitemos el formulario y que a la hora de la ejecución de la consulta en el método QueryExecuting, hagamos un análisis de si la propiedad CIPrimaryObject del formulario no esté vacía y asignarle el DataGrid que se está visualizando en ese momento en el formulario. Private Sub CIMntoBaseExpertis1_QueryExecuting(ByVal sender As Object, ByRef e As Solmicro.Expertis.Engine.UI.QueryExecutingEventArgs) Handles Me.QueryExecuting If Me.CIPrimaryObject Is Nothing Then Me.CIPrimaryObject = Me.Grid1 Select Case Me.TabGrids.SelectedTab.Key Case "Principal" Me.CIPrimaryObject = Me.Grid1 Case "Secundario" Me.CIPrimaryObject = Me.Grid2 End Select End Sub Esto es para poder decir al formulario cuál es el objeto principal en la pantalla y con el que funcionará los botones de las barras de herramientas y los eventos. Hemos de tener en cuenta también que cada vez que hagamos la asignación de la propiedad CIPrimaryObject automáticamente el motor llama al evento QueryExecuting del formulario. Otra forma para establecer cuál el es el DataGrid principal de una Consulta Interactiva Padre sería a través del método siguiente: Private Sub CIMntoBaseExpertis1_QueryExecuting(ByVal sender As Object, ByRef e As Solmicro.Expertis.Engine.UI.QueryExecutingEventArgs) Handles Me.QueryExecuting If Me.CIPrimaryObject Is Nothing Then Me.CIPrimaryObject = Me.Grid1 Select Case Me.TabGrids.SelectedTab.Key Case "Principal" Me.SetCIPrimaryObject(Me.Grid1, False) Case "Secundario" Me.SetCIPrimaryObject(Me.Grid2, False) End Select End Sub Con este comando conseguimos el mismo efecto, pero en vez de ejecutar el evento QueryExecuting de la consulta de manera automática, lo hará dependiendo del valor del 2º parámetro, pudiendo especificar False para que no lleve a cabo la ejecución automática de la consulta Volver al Índice Controles de Expertis en Presentación 1. Agregar los Controles de Expertis al Cuadro de Herramientas Crear una ficha nueva al cuadro de herramientas del entorno de desarrollo de Visual Studio, para ello, botón derecho sobre el cuadro de herramientas, Agregar nueva ficha, y asignar un nombre a la ficha, por ejemplo, Expertis. 103/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Para agregar los controles a la nueva ficha, botón derecho, Agregar o quitar elementos… A continuación conviene ordenar los elementos por el espacio de nombres al que pertenecen. Los controles de Expertis pertenecen al espacio de nombres Solmicro.Expertis.Engine.UI. Marcar los siguientes elementos: AdvSearch Button CalendarBox CheckBox ComboBox CounterTextBox Frame Grid GridBase Label ListBox NumericTextBox Panel RadioButton Tab TextBox UnderLineLabel Y aceptar. NOTA: Es importante usar siempre los controles de expertis. Si el que necesita para su desarrollo existe del tipo de Expertis, use ese primero sino acuda a otros controles del framework / thirdparties. Es esencial usar el tipo de expertis de cara para la herramienta de traducciones ya que para procesar lo que se tiene que traducir se coge solo de controles de tipo Expertis. Volver al Índice 104/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis 2. AdvancedSearch Control de búsqueda avanzada de expertis. Control que nos permite acceder a datos de entidades con sistema de filtrados para localizar un valor concreto. Podremos configurar búsquedas avanzadas sueltas en cualquier formulario que necesitemos y además embeberlas en datagrid configurando ciertas columnas para que sean de tipo AdvSearch. No permite la carga de tablas externas o vistas, solo a través de la configuración de nombre de entidad y vista en el control. Propiedades Control Las propiedades principales y más importantes del control en tiempo de diseño tenemos: ASSelectedFields Listado de relación de controles con campos donde queremos descargar información relacionada con la entidad de la búsqueda avanzada. Este listado nos permite definir en qué controles del formulario que campos queremos mostrar de esta entidad cuando seleccionemos un valor en la búsqueda avanzada. DisplayField Campo del origen de datos de la entidad de la búsqueda avanzada que queremos que se muestre en la caja de texto. Si se omite este campo el campo mostrado en la búsqueda avanzada será el descrito en SecondaryDataFields. EntityName Nombre de la entidad de expertis de la cargaremos los datos en la búsqueda avanzada. Debe coincidir con un nombre de entidad válido de Expertis. PrimaryDataFields Campo del formulario padre en el que se encuentra situada la búsqueda avanzada para la relación del control con el formulario contenedor. Este campo sería el coincidente con uno perteneciente al origen de datos del formulario o control padre. Esta propiedad deberá permanecer en vacío si es un control de búsqueda avanzada que usamos en una consulta interactiva, o bien en cualquier formulario que no tenga una conexión con un formulario padre. SecondaryDataFields Campo de la búsqueda avanzada para la relación de la búsqueda avanzada con el formulario padre contenedor. Este campo sería el coincidente con uno de la entidad de la búsqueda avanzada. Esta propiedad siempre ha de estar rellenada y correctamente configurada con el campo correcto para el correcto funcionamiento de la búsqueda avanzada. ViewName Nombre de la tabla – vista de la que tomará los datos la búsqueda avanzada. Generalmente podrá ir en vacío, al dejarlo vacío funcionará como origen de tabla la tabla de la entidad puesta en la propiedad EntityName. Si especificamos otro origen funcionará con este otro origen. DataBindings - Value Conexión de bindeo del control con un campo del formulario padre en el que se encuentre. Aconsejamos para los controles de tipo búsqueda avanzada el realizarlo a la propiedad value, más que a la propiedad text. Las propiedades principales y más importantes del control en tiempo de ejecución tenemos: Value Propiedad por la que obtendremos el campo de valor asociado a la propiedad SecondaryDataFields del control de búsqueda avanzada. 105/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Text Propiedad por la que obtendremos el campo de texto asociado a la propiedad SecondaryDataFields o si estuviera configurado el campo de DisplayField el correspondiente a este. SelectedRow Propiedad por la que podremos obtener todo el datarow asociado al valor que tenga el control de búsqueda avanzada. Métodos principales NotInList Método que se invoca cuando se detecta que se ha insertado un valor en la caja de texto de la búsqueda avanzada, que no existe en la tabla de la entidad configurada. Por defecto el motor siempre sacará un mensaje de error de registro no existente y no nos permitirá aceptar este valor para la búsqueda avanzada. Con lo cual si lo que queremos es no mostrar este mensaje genérico o mostrar otro más personalizado, escribiremos un código parecido marcado a continuación. Private Sub AdvSearch1_NotInList(ByVal sender As Object, ByVal e As Solmicro.Expertis.Engine.UI.NotInListEventArgs) Handles AdvSearch1.NotInList e.Handled = True ExpertisApp.GenerateMessage("No existe el Valor introducido.", Windows.Forms.MessageBoxButtons.OK, Windows.Forms.MessageBoxIcon.Exclamation) e.Cancel = True End Sub OpenningAdvSearch Método que se llama en cuanto pulsamos al botón de la búsqueda avanzada para mostrar la pantalla de configuración de filtros y resultados. Se dispone de este método para poder cancelar esa apertura por si se desea. Private Sub AdvSearch1_OpenningAdvSearch(ByVal sender As Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles AdvSearch1.OpenningAdvSearch If Me.TextBox1.Text = "00" Then e.Cancel = True End If End Sub SetPredefinedFilter Método para establecer filtros a la búsqueda avanzada. Este método será invocado cada vez que entremos a escribir en la caja de texto de la búsqueda avanzada, o bien abramos la pantalla de configuración de filtros y resultados. Para ello en este método agregamos filtros como de un objeto filter de expertis se tratara Private Sub AdvSearch1_SetPredefinedFilter(ByVal sender As Object, ByVal e As Solmicro.Expertis.Engine.UI.AdvSearchFilterEventArgs) Handles AdvSearch1.SetPredefinedFilter e.Filter.Add("IDClave", FilterOperator.Equal, "00") End Sub SelectionChanged Método que se ejecuta cuando seleccionamos un registro de la pantalla de configuración de filtros y resultados y también se ejecuta cuando validamos un valor introducido en la caja de texto de la búsqueda avanzada. Esto nos permite acceder a todo el registro seleccionado coincidente con el valor introducido para lo que necesitemos. Private Sub AdvSearch1_SelectionChanged(ByVal sender As Object, ByVal e As Solmicro.Expertis.Engine.UI.AdvSearchSelectionChangedEventArgs) Handles AdvSearch1.SelectionChanged If e.Selected.Rows(0)("Tipo_Clave") = "01" Then ExpertisApp.GenerateMessage("No se puede seleccionar del tipo 01.", Windows.Forms.MessageBoxButtons.OK, Windows.Forms.MessageBoxIcon.Exclamation) End If End Sub Configuración en Formularios de una búsqueda avanzada. La propiedad EntityName es el nombre de la clase del componente de negocio que se va a encargar de realizar las búsquedas. La propiedad PrimaryDataFields es el nombre del campo del proveedor de datos del control, con el cual se relacionan los datos sobre los que actúa el propio control. 106/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis La propiedad SecondaryDataFields es el nombre del campo del esquema de datos relacionado con EntityName, con el que se relaciona con el valor de PrimaryDataFields. La propiedad DisplayField es el nombre del campo del esquema de datos relacionado con EntityName, cuyo valor se muestra en la caja de texto de la búsqueda. Por defecto es el valor de SecondaryDataFields. La propiedad ViewName es el nombre del origen de datos sobre el que se realizan las búsquedas. Si no tiene valor, es igual a la tabla relacionada con EntityName. La configuración básica de la búsqueda avanzada difiere según la clase de mantenimiento. En una clase SimpleMnto en la que el control esta enlazado con el origen de datos del formulario es necesario establecer EntityName, PrimaryDataFields y SecondaryDataFields. En una clase CIMnto la búsqueda no está enlazada al origen de datos de la clase de mantenimiento con lo que al menos hay que dar valores a EntityName y SecondaryDataFields. NOTA: La configuración de una búsqueda avanzada consta de dos partes. Una parte corresponde al diseño del control y la otra parte se realiza en tiempo de ejecución. La configuración en diseño es común para todos los usuarios; la configuración en tiempo de ejecución es particular para cada usuario. Para poder realizar la configuración en tiempo de ejecución es necesario actualizar los metadatos de la base de datos de sistema con la estructura de las tablas involucradas. Configuración en DataGrids de una búsqueda avanzada. El control Grid de Expertis mantiene su propia colección de controles AdvSearch. Para asociar una búsqueda avanzada a una de las columnas de Grid, desde la sección Grids del diseñador de Expertis, botón derecho sobre la columna en cuestión, seleccionar la opción Set Adv. Search En la solapa Adv.Search se puede configurar las búsquedas definidas en el Grid. La propiedad EntityName es el nombre de la clase de negocio asociada a la tabla sobre la que se van a realizar las búsquedas. La propiedad SelectedField es el nombre del campo cuyo valor se va a volcar sobre la celda del Grid. ViewName permite establecer un origen de datos personalizado (por defecto el origen de datos es la tabla asociada a EntityName). 107/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis El panel inferior dentro de esta solapa permite configurar el volcado de los valores del registro seleccionado en la búsqueda avanzada sobre otras columnas del Grid. En la imagen anterior se muestra un ejemplo: el valor del campo DescArticulo se volcara sobre la columna Descripción. Volver al Índice 3. CounterTextBox Control de contadores de expertis para mostrar el listado de contadores disponibles de la entidad del formulario donde esté alojado el control. Este control no dispone de propiedades ni de métodos específicos para su configuración, ya que toda la administración de esta información la hace de manera automática el motor. Propiedades Control DataBindings - Text La única propiedad que tenemos que tener bien configurada para este control sería el databinding en text. Tendremos que configurar aquí el campo final que descargaría los contadores y el valor que deseamos ver ya compuesto. Para toda esta configuración necesitaríamos tener en nuestra tabla un campo que fuese clave principal de tipo numérico o autonumérico. Luego otro campo de tipo NContador donde almacenaríamos el valor de contador final. Y por último un campo llamado IDContador donde se guardará la información de qué IDContador del maestro de contadores usamos. Para el uso y configuración final de contadores lo explicaremos más adelante en otro apartado. Volver al Índice 108/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis 4. Combobox Control de Listado de datos. Nos permite cargar la información de tabla o vista relacionada con la entidad de expertis que configuremos en sus propiedades en diseño o bien suministrándole el datatable de datos que queramos y de cualquier origen de tabla o vista. Propiedades Control Las propiedades principales y más importantes del control en tiempo de diseño tenemos: EntityName Nombre de la entidad de expertis de la cargaremos los datos en la búsqueda avanzada. Debe coincidir con un nombre de entidad válido de Expertis. PrimaryDataFields Campo del formulario padre en el que se encuentra situada la búsqueda avanzada para la relación del control con el formulario contenedor. Este campo sería el coincidente con uno perteneciente al origen de datos del formulario o control padre. Esta propiedad deberá permanecer en vacío si es un control de búsqueda avanzada que usamos en una consulta interactiva, o bien en cualquier formulario que no tenga una conexión con un formulario padre. SecondaryDataFields Campo de la búsqueda avanzada para la relación de la búsqueda avanzada con el formulario padre contenedor. Este campo sería el coincidente con uno de la entidad de la búsqueda avanzada. Esta propiedad siempre ha de estar rellenada y correctamente configurada con el campo correcto para el correcto funcionamiento de la búsqueda avanzada. RelationMode Modo de relación del control con el formulario padre en el que se encuentre alojado. Para esta propiedad tendremos 3 opciones posibles: - NoRelation: el control no tiene relación de ningún tipo con el formulario padre y para su carga de datos es administrada completamente por nosotros. Aunque tuviera los datos de relación y configuración no funcionaría correctamente el control - ChildMode: modo de relación con el formulario padre. De esta manera la carga de datos la administrará el motor de expertis. - ComplementaryMode: modo complementaria con el formulario padre. De esta manera el motor de expertis si nos cargaría de manera automática el control su origen de datos pero sin relación. Sería todo el contenido de la tabla – vista configurada en el control. ViewName Nombre de la tabla – vista de la que tomará los datos la búsqueda avanzada. Generalmente podrá ir en vacío, al dejarlo vacío funcionará como origen de tabla la tabla de la entidad puesta en la propiedad EntityName. Si especificamos otro origen funcionará con este otro origen. ComboStyle Opción de modo de manejo del control combobox, cambiando la manera en la que nos permite editar el control combobox. Para esta propiedad tendremos 2 opciones posibles: - Combo: el control combobox muestra el listado de datos que tiene a través del botón despegable y cargando en la caja de texto del control el campo establecido en DisplayMember. Pero con esta opción nos permite editar el contenido de esta caja de texto del control 109/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis - DropDownList: el control combobox muestra el listado de datos que tiene a través del botón despegable y cargando en la caja de texto del control el campo establecido en DisplayMember. Pero no nos permite modificar el contenido de la caja de texto. ColumnAutoresize Accesible este propiedad desde el diseñador de combo (DropDown Designer). Nos permite indicar que todas las columnas mostradas en el control tendrán un ancho automático hasta ocupar el máximo tamaño que tiene el control combobox DisplayMember Propiedad en la que establecemos que campo del origen de datos se utiliza para el mostrado en la caja de texto del control y el campo que accederemos a través de la propiedad Text. ValueMember Propiedad en la que establecemos que campo del origen de datos se utiliza para valor que se almacena en el control y es el campo que accederemos a través de la propiedad Value. Las propiedades principales y más importantes del control en tiempo de ejecución tenemos: Text Valor de la caja de texto que posee el control al que podemos obtener este valor o establecerlo. Value Valor del control que tiene seleccionado para el valor text. Podremos obtener este valor o establecerlo. DataSource Origen de datos del control combobox. Generalmente será un Datatable, pero se puede establecer tanto un datatable como un dataview. Es una propiedad tanto de escritura como de lectura. Es a la que acudiremos para poder obtener todo ese datatable que tiene como origen de datos el control o bien establecerle uno en los casos de configuración manual y que no se administran por nombre de entidad – vista. Métodos principales ValueChanged Método que se activará cada vez que cambie el contenido de la propiedad Value del control. TextChanged Método que se activará cada vez que cambie el contenido de la propiedad Text del control. Diseñador de Combobox Para el control Combobox disponemos de una herramienta de diseño visual para una mayor configuración y personalización del control. Para acceder a este diseñador bastará con que demos botón derecho del ratón encima del control combobox -> DropDown Designer. 110/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Después de pinchar a esta opción tendremos disponible el diseñador del Combobox y todas las posibilidades que nos ofrece: Aquí tendremos disponibles más opciones generales de configuración de todo el control combobox en sí y otras como: configurar la colección de columnas, diseños de columnas, condiciones de formato, colección de columnas de ordenamiento, grupos, etc… Para conocer más de este configurador y opciones acudir al manual de Combobox de los controles Janus. Configuración en Diseño de un control ComboBox. La propiedad EntityName es el nombre de la clase del componente de negocio asociado al origen de datos del control. La propiedad PrimaryDataFields es el nombre del campo del proveedor de datos del control, con el cual se relacionan los datos sobre los que actua el propio control. La propiedad SecondaryDataFields es el nombre del campo del esquema de datos relacionado con EntityName, con el que se relaciona con el valor de PrimaryDataFields. La propiedad ViewName es el nombre del origen de datos sobre el que se realizan las búsquedas. Si no tiene valor, es igual a la tabla relacionada con EntityName. La propiedad ValueMember establece el valor que se guarda internamente. Este valor es el que se utiliza para vincular internamente los elementos con el valor del combo. NOTA: Si no se configura, la propiedad ValueMember es el nombre de la primera columna del origen de datos del ComboBox. La propiedad RelationMode es un valor de tipo Solmicro.Expertis.Engine.RelationMode que establece el tipo de relación del control con su proveedor de datos (generalmente un formulario de Expertis). Si RelationMode es NoRelation (este es el valor por defecto) los datos que se solicitan al componente del Engine de la capa de negocio, Expertis.Engine.BE.BusinessEngine, no están ligados con el formulario (se obtienen todos los registros de la entidad correspondiente a la propiedad EntityName). Los datos se obtienen la primera vez que son solicitados por parte del formulario, y en las posteriores solicitudes del formulario ya no se recuperan datos para dicho ComboBox. Trabajando de esta manera no se deben establecer las propiedades PrimaryDataFields y SecondaryDataFields. Se deberá configurar la propiedad ValueMember para indicar el campo del origen de datos que se enlazará con el control. Si RelationMode es ComplementaryMode los datos del ComboBox si están ligados con el formulario. Para el enlace se utilizan las propiedades PrimaryDatafields y SecondaryDataFields. El ComboBox 111/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis recibe datos en cada movimiento de navegación del formulario. Se deberá configurar la propiedad ValueMember para indicar el campo del origen de datos que se enlazará con el ComboBox. NOTA: En cualquiera de los dos comportamientos existe la posibilidad de aplicar un filtro a los datos del ComboBox utilizando la propiedad Filter. El control ComboBox, por defecto, muestra todos los campos de la tabla o vista que se ha establecido en la propiedad ViewName. Sin embargo, es probable que el origen de datos tenga más información de la que en realidad conviene mostrar en el combo. Por esta razón, habitualmente es necesario configurar las columnas que se van a mostrar. Hay dos opciones Equivalentes. La primera consiste en abrir el configurador del Combo, haciendo botón derecho sobre el control, Configure MultiColumnCombo Esta opción abre un asistente con el que se pueden configurar las columnas del control. En el primer paso seleccionar la opción DataSource is not available at design time En el segundo paso es posible añadir, modificar y eliminar las columnas del combo 112/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis En el último paso es posible establecer las propiedades ValueMember con el nombre del campo cuyo valor se guarda internamente, y DisplayMember, con el nombre del campo cuyo valor se va a mostrar. La segunda opción consiste en abrir el diseñador del control, haciendo botón derecho sobre el control, seleccionar DropDown Designer NOTA: Esta opción es la que se suele utilizar cuando se quiere modificar el diseño del combo una vez que se ha creado un primer layout para el control. En la sección Columns del diseñador es posible definir las columnas de la lista 113/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Asignar un origen de datos por código y con Datatable La propiedad DataSource permite asignar un origen de datos personalizado. También es posible configurar las propiedades ValueMember y DisplayMember por código, como se muestra en este código de ejemplo Dim dt As DataTable dt = New Moneda().Filter() If dt.Rows.Count > 0 Then cmbIDMoneda.DataSource = dt End If cmbIDMoneda.ValueMember = "IDMoneda" cmbIDMoneda.DisplayMember = "IDMoneda" Asignar un origen de datos por código y con Enumerados El control ComboBox puede mostrar también una lista de valores correspondientes a un enumerado de Expertis. Para asignar el enumerado como origen de datos del ComboBox se utiliza la clase EnumData. El siguiente ejemplo asigna el enumerado CursoEstadoContabilizacion a un control ComboBox llamado cmbEstado cmbEstado.DataSource = New EnumData("CursoEstadoContabilizacion") NOTA: Si el ComboBox muestra una lista de enumerado conviene establecer la propiedad ComboStyle igual a DropDownList. De esta forma no es posible editar directamente en el control, y el usuario está obligado a seleccionar un elemento existente en la lista. Volver al Índice 114/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis 5. CalendarBox Control de mostrado de calendarios y fechas. Se aconseja para cualquier campo de base de datos de tipo fecha el asociarlo a un control de este tipo. Propiedades Control Las propiedades principales y más importantes del control en tiempo de diseño tenemos: DateFormat Propiedad para definir el formato del campo fecha de cómo será mostrado y manejado en el control. Para esta propiedad tenemos las siguientes opciones: - Short: formato corto de fecha. - Long: formato largo de fecha. - Time: mostrado sólo de la parte de hora de una fecha. - DateTime: mostrado de la fecha en formato conjunto de fecha con hora. - Custom: configuración personalizada del formato de la fecha, esta propiedad funciona conjuntamente con la propiedad CustomFormat. CustomFormat Podemos definir una máscara en esta propiedad para establecer un formato personalizado de la fecha que queremos mostrar. Esta propiedad solo funcionará cuando la propiedad DateFormat esté a Custom. Las propiedades principales y más importantes del control en tiempo de ejecución tenemos: Text Valor de la caja de texto que posee el control al que podemos obtener este valor o establecerlo. Value Valor del control que tiene seleccionado para el valor text. Podremos obtener este valor o establecerlo. Métodos principales TextChanged Método que se activará cada vez que cambie el contenido de la propiedad Text del control. ValueChanged Método que se activará cada vez que cambie el contenido de la propiedad Value del control. Volver al Índice 115/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis 6. NumericTextBox Control de búsqueda avanzada de expertis. Control que nos permite acceder a datos de entidades con sistema de filtrados para localizar un valor concreto. Podremos configurar búsquedas avanzadas sueltas en cualquier formulario que necesitemos y además embeberlas en datagrid configurando ciertas columnas para que sean de tipo AdvSearch. Propiedades Control Las propiedades principales y más importantes del control en tiempo de diseño tenemos: Decimal Digits Número de posiciones decimales que se permiten y se formatean en el control. Por defecto tendremos un valor de -1 que indicamos al control que queremos usar el número de decimales que esté configurada en la configuración regional de la máquina. Para manejar el control con números enteros podremos establecer el valor a 0. FormatMask Tipo de máscara del control para diversos tipos de datos: - General: formato general de texto, se permite introducción de datos no numéricos. - Currency: formato para datos numéricos de monedas. Nos agregará el símbolo de la moneda a la derecha del control. Este símbolo se cogerá de la configuración regional de la máquina en ejecución. - Number: formato para datos numéricos normales. - Percent: formato para datos numéricos de porcentajes. Nos agregará el símbolo de porcentaje a la derecha del control. FormatString Cadena personalizada de máscara de entrada para establecer un formato de entrada personalizado a lo que necesitemos. NullBehavior Propiedad para controlar la introducción y manejo de nulos en el control. Tendremos 3 opciones posibles: - NoNulls: no permite nunca introducción de valores nulos. Si no se introduce nada se tomará como valor por defecto el 0. - AllowNull: se permite la introducción de nulos, siendo este nulo el tipo de nulo estándar. - AllowDBNull: se permite la introducción de nulos, siendo este nul el tipo de nulo proveniente de base de datos. ValueType Propiedad para establecer el tipo de valor numérico que manejará el control. Siendo posible definir en esta propiedad todos los tipos de datos numéricos de bases de datos: enteros, decimales, enteros 16, enteros 64 etc… Las propiedades principales y más importantes del control en tiempo de ejecución tenemos: Text Valor de la caja de texto que posee el control al que podemos obtener este valor o establecerlo. Value Valor del control que tiene seleccionado para el valor text. Podremos obtener este valor o establecerlo. Métodos principales TextChanged Método que se activará cada vez que cambie el contenido de la propiedad Text del control. ValueChanged Método que se activará cada vez que cambie el contenido de la propiedad Value del control. Volver al Índice 116/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis 7. TextBox Control de caja de texto. Control para poder mostrar campos de contenido texto para su visualización o edición. Propiedades Control Las propiedades principales y más importantes del control en tiempo de diseño tenemos: PasswordChar Propiedad para definir el carácter que se mostrará ocultando los valores que el usuario va introduciendo. De esta manera podemos definir un control textbox en un control de tipo contraseña. Las propiedades principales y más importantes del control en tiempo de ejecución tenemos: Text Valor de la caja de texto que posee el control al que podemos obtener este valor o establecerlo. Métodos principales TextChanged Método que se activará cada vez que cambie el contenido de la propiedad Text del control. Volver al Índice 117/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis 8. Grid Control DataGrid de Expertis para el mostrado horizontal de datos. Propiedades Control Las propiedades principales y más importantes del control en tiempo de diseño tenemos: AdvSearchColumns Colección de columnas del grid que están configuradas como búsquedas avanzadas. CheckFields Colección de columnas del grid que están configuradas como columnas de almacenaje de datos junto con las marcas de chequeados. EntityName Nombre de la entidad de expertis de la cargaremos los datos en el Grid. Debe coincidir con un nombre de entidad válido de Expertis. KeyField Nombre del Campo Clave de la entidad configurada del Grid, es obligatorio rellenar este campo cuando se usa conjuntamente con la opción de UseCheck = True (Usar columna de Marcas). PrimaryDataFields Campo del formulario padre en el que se encuentra situado el grid para la relación del control con el formulario contenedor. Este campo sería el coincidente con uno perteneciente al origen de datos del formulario o control padre. Esta propiedad deberá permanecer en vacío si es un control de grid que está en cualquier formulario que no tenga una conexión con un formulario padre. SecondaryDataFields Campo del grid para la relación del grid con el formulario padre contenedor. Este campo sería el coincidente con uno de la entidad del grid. Si no existiera conexión con un formulario padre puede permanecer en vacío esta propiedad. 118/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis RelationMode Modo de relación del control con el formulario padre en el que se encuentre alojado. Para esta propiedad tendremos 3 opciones posibles: - NoRelation: el control no tiene relación de ningún tipo con el formulario padre y para su carga de datos es administrada completamente por nosotros. Aunque tuviera los datos de relación y configuración no funcionaría correctamente el control - ChildMode: modo de relación con el formulario padre. De esta manera la carga de datos la administrará el motor de expertis. - ComplementaryMode: modo complementaria con el formulario padre. De esta manera el motor de expertis si nos cargaría de manera automática el control su origen de datos pero sin relación. Sería todo el contenido de la tabla – vista configurada en el control. ViewName Nombre de la tabla – vista de la que tomará los datos el grid Generalmente podrá ir en vacío, al dejarlo vacío funcionará como origen la tabla de la entidad puesta en la propiedad EntityName. Si especificamos otro origen funcionará con este otro origen. UseCheck Opción del Grid para especificar que se desea usar la columna de Check de Expertis en el Grid. Habilitándose para ello una serie de opciones en el Grid y de Métodos relacionados con los marcajes. RequeryManually Opción para especificar en el grid que los datos se solicitarán a la base de datos cuando nosotros lo requerimos (True) o bien lo haga automáticamente el motor (False). Las propiedades principales y más importantes del control en tiempo de ejecución tenemos: DataSource Origen de datos del DataGrid, siendo el tipo de datos más general y común en expertis el DataTable o DataView. Es una propiedad que podremos tanto establecer valor como recoger el contenido del mismo. RowCount Propiedad que nos permite obtener el número total de registros que posee el origen de datos del Grid. Col Forma de obtener el índice de columna que está posicionado la celda actual seleccionada. Row Forma de obtener el índice del registro que está posicionada la celda actual seleccionada. Actions Colección de acciones locales personalizadas configuradas en el Grid y donde podemos ir agregando las diferentes acciones que necesitemos. NewTopRowPosition Propiedad que nos da la información del índice de registro en el que está posicionada la fila de nuevo registro. Este dato lo usaremos generalmente en el evento EditingCell del Grid para saber cuándo aplicar bloqueos de columnas de registros en el grid. CheckedRecords Datatable de los registros que se hayan seleccionado en el datagrid. Esta propiedad sería funcional junto con las propiedades y sistema de chequeo dentro del Grid. El datagrid nos proporcionará un datatable de aquellos registros que se hayan seleccionado y con los datos que tuvieran en el momento del chequeo. Hay que tener en cuenta este detalle porque seleccionando un registro y si posteriormente modificamos alguno de esos datos, éstos cambios no se reflejarán posteriormente en el CheckedRecords. CheckedRecordsCount Propiedad que nos dirá el total de registros chequeados en el grid y que coincidirá con el recuento total de registros presentes en el CheckedRecords. Esta propiedad será funcional con el sistema de chequeos del Grid. Filter Opción para establecer un filtrado al origen de datos cargado en el datagrid. De esta manera podremos asociarle un objeto Filter de Expertis. 119/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Métodos principales invocables en código AddSeparator Nos permitirá agregar un separador a la colección de acciones locales personalizadas del DataGrid y agregándola a la siguiente posición de la colección. Requery Método que nos permite volver a solicitar la carga de datos del origen de datos establecido en el DataGrid. Este evento funcionaría conjuntamente con la propiedad RequeryManually establecida a True. De esta manera un datagrid no solicitaría los datos hasta que ejecutásemos este método Requery. Como parámetro opcional de este comando, nos permite especificar directamente en la llamada un objeto Filter de expertis para que dentro de la solicitud que se hace en ese momento de los datos sea con un filtro. Dim FilRequery As New Filter FilRequery.Add("IDClave", FilterOperator.Equal, "00") Me.Grid1.ReQuery(FilRequery) 120/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis GetValue Forma de obtener el valor de la columna que indiquemos en el registro que esté posicionado en ese momento en el datagrid. Dim StrDesc As String = Me.Grid1.GetValue("DescClave") SetValue Forma de establecer valor a la columna que indiquemos en el registro que esté posicionado en ese momento en el datagrid. Me.Grid1.SetValue("DescClave", "Descripción Nueva") InvokebusinessRules Alternativamente con el comando anterior descrito puede que necesitemos después de establecer el valor en un columna de esta manera, el que se invoquen las reglas de negocio de la entidad del DataGrid (proceso GetBusinessRules de Entidad de Negocio). Esto es que al ser un establecimiento del valor de una columna por código el datagrid no se entera que igual tenga que llamar a las reglas de negocio. Para ello disponemos de este método. De esta manera especificaremos el nombre de columna que queremos invocar las reglas de negocio, el valor original del campo y el valor nuevo que queremos establecer. Me.Grid1.InvokeBusinessRules("IDClave", "NuevoValor", "ValorOriginal") De esta manera conseguiremos garantizar que se ejecuten las reglas de negocio siempre y en todo momento y siempre que veamos que sea necesario. CheckRecord Método que funcionará de forma conjunta con el sistema de chequeos del Grid. Nos permite chequear el registro en el que esté posicionado en ese momento en el Grid. UnCheckRecord Método que funcionará de forma conjunta con el sistema de chequeos del Grid. Nos permite deschequear el registro en el que esté posicionado en ese momento en el Grid. CheckAllRecords Método que funcionará de forma conjunta con el sistema de chequeos del Grid. Nos permite ejecutar el chequeo de todos los registros del origen de datos del Grid. UnCheckAllRecords Método que funcionará de forma conjunta con el sistema de chequeos del Grid. Nos permite ejecutar el deschequeo de todos los registros del origen de datos del Grid. Métodos principales AdvSearchNotInList Método que se invocará en el código cuando en una columna que sea de tipo búsqueda avanzada, el registro insertado no exista en el origen de datos. El motor de expertis saca directamente un mensaje de error advirtiendo que no existe el dato introducido en la base de datos y no permitiendo el salvar este dato introducido. Para ello tenemos este método disponible para poder cancelar esa acción o bien mostrar un mensaje más personalizado o bien llevar a cabo la ejecución de lo que necesitemos. Para toda la información para llevar a cabo esto acudiremos a la variable e de entrada del evento: - E.Value: valor incorrecto introducido por el usuario. Generalmente en este evento se utiliza para mostrar el - E.Handled: estableciéndolo a True haremos que el motor cancele su control y mensaje de error. Esto - E.Cancel: estableciéndolo a True cancelaremos todo el evento del NotInList y haremos que no se permita - E.Key: nos da la información de la clave de la columna de búsqueda avanzada que ha invocado al método. valor en el mensaje personalizado de error. puede ser porque queremos que en la búsqueda avanzada que se ejecuta no salga ningún mensaje de error por parte del motor y permitir el valor no existente. el aceptar el valor incorrecto introducido por el usuario en la búsqueda avanzada. Private Sub Grid1_AdvSearchNotInList(ByVal sender As Object, ByVal e As Solmicro.Expertis.Engine.UI.AdvSearchNotInListEventArgs) Handles Grid1.AdvSearchNotInList Select Case e.Key Case "IDClave" e.Handled = True ExpertisApp.GenerateMessage("La Clave | no existe en la base de datos", Windows.Forms.MessageBoxButtons.OK, Windows.Forms.MessageBoxIcon.Exclamation, e.Value) e.Cancel = True 121/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis End Select End Sub AdvSearchSelectionChanged Cada vez que se busque un dato introducido en la búsqueda avanzada se invocará este método en el cual podemos obtener todo el registro seleccionado de la entidad de la búsqueda avanzada. Para ello tendremos en la variable e de entrada toda la información necesaria: - E.Key: nos da la información de la clave de la columna de búsqueda avanzada que ha invocado al método. - E.Selected: DataTable con un solo row con el contenido de todo el registro que hemos seleccionado en la búsqueda avanzada. Private Sub Grid1_AdvSearchSelectionChanged(ByVal sender As Object, ByVal e As Solmicro.Expertis.Engine.UI.GridAdvSearchSelectionChangedEventArgs) Handles Grid1.AdvSearchSelectionChanged Select Case e.Key Case "IDClave" Me.TxtDescClave.Text = e.Selected.Rows(0)("DescClave") End Select End Sub AdvSearchSetPredefinedFilter Evento para establecer filtros predeterminados a las búsquedas avanzadas, de esta manera cuando se ejecuten aplicarán siempre y en todo momento los filtros configurados en este evento. Para ello tendremos en la variable e de entrada toda la información necesaria: - E.Key: nos da la información de la clave de la columna de búsqueda avanzada que ha invocado al método. - E.Filter: Filtro de expertis a configurar para establecer un filtro predeterminado para la búsqueda - E.ForcePredefinedFilter: variable booleana con la que podemos forzar a la columna de búsqueda avanzada avanzada. invocada el que vuelva a obtener los datos de la búsqueda con el filtro configurado en este evento. Private Sub Grid1_AdvSearchSetPredefinedFilter(ByVal sender As Object, ByVal e As Solmicro.Expertis.Engine.UI.GridAdvSearchFilterEventArgs) Handles Grid1.AdvSearchSetPredefinedFilter Select Case e.Key Case "IDClave" e.Filter.Add("Estado", FilterOperator.Equal, 1) End Select End Sub UpdatingCell Método que se invoca antes de actualizar por completo y aceptar el valor introducido en una celda del grid. Para ello tendremos en la variable e de entrada toda la información necesaria: - E.Column: nos da la información de la de la columna que ha invocado al método. - E.InitialValue: valor inicial de la celda de la columna que tenía antes de la actualización. - E.Value: valor actual introducido en la celda de la columna. - E.Cancel: propiedad para cancelar por completo el evento previo de actualización de la celda. Private Sub Grid1_UpdatingCell(ByVal sender As Object, ByVal e As Janus.Windows.GridEX.UpdatingCellEventArgs) Handles Grid1.UpdatingCell Select Case e.Column.Key Case "IDClave" If e.InitialValue = 0 AndAlso e.Value = 1 Then ExpertisApp.GenerateMessage("No se puede cambiar el estado de 0 a 1.", Windows.Forms.MessageBoxButtons.OK, Windows.Forms.MessageBoxIcon.Information) e.Cancel = True End If End Select End Sub CellUpdated Método que se invoca después de actualizar el valor introducido en una celda del grid. Para ello tendremos en la variable e de entrada toda la información necesaria: - E.Column: nos da la información de la de la columna que ha invocado al método. Private Sub Grid1_CellUpdated(ByVal sender As Object, ByVal e As Janus.Windows.GridEX.ColumnActionEventArgs) Handles Grid1.CellUpdated Select Case e.Column.Key Case "IDClave" 122/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis ExpertisApp.GenerateMessage("Valor Actulizado", Windows.Forms.MessageBoxButtons.OK, Windows.Forms.MessageBoxIcon.Exclamation) End Select End Sub EditingCell Método que se invocará en cuanto nos posicionemos en una celda para la edición de su valor. Generalmente en este evento lo que solemos programar es un control para ver si el usuario puede modificar o no a nivel de celda esta columna dependiendo de valores dinámicos. Para ello tendremos en la variable e de entrada toda la información necesaria: - E.Column: nos da la información de la de la columna que ha invocado al método. - E.Value: valor actual de la celda de la columna. - E.Cancel: propiedad para cancelar por completo el evento de edición de la celda. Private Sub Grid1_EditingCell(ByVal sender As Object, ByVal e As Janus.Windows.GridEX.EditingCellEventArgs) Handles Grid1.EditingCell Select Case e.Column.Key Case "IDClave" If e.Value > 0 Then e.Cancel = True End If End Select End Sub CheckingRecord Método para controlar cuando se esté chequeando o deschequeando un registro, usando con el sistema de chequeos del Grid. Para ello podremos controlar el estado del check a través de la propiedad e.CheckState, teniendo en cuenta que el evento es de la acción que se va a llevar a cabo, no de la acción ya hecha. Con lo cual tendremos que analizar el valor de esta propiedad negándola. Tengamos en cuenta que este evento se llamará tanto en la acción de chequear como deschequear un registro y antes de que lleve esta acción a su valor final. Para ello tendremos en la variable e de entrada toda la información necesaria: - E.CheckState: nos da la información de la situación actual de la columna check del registro que ha - E.Row: todo el registro del Grid que se está llevando la acción de chequeo o deschequeo - E.Cancel: propiedad para cancelar por completo el evento de check/uncheck del registro. invocado este evento y con lo cual sabremos qué acción futura se va a hacer. Private Sub Grid1_CheckingRecord(ByVal sender As Object, ByVal e As Solmicro.Expertis.Engine.UI.CheckingEventArgs) Handles Grid1.CheckingRecord If e.CheckState = CheckStates.UnChecked Then If e.Row.Cells("Estado").Value = 1 Then e.Cancel = True End If End If End Sub RecordChecked Método que se invocará después de que se haya chequeado o deschequeado un registro. Para ello tendremos en la variable e de entrada toda la información necesaria: - E.CheckState: nos da la información de la opción de chequeo / deschequeo que se ha llevado a cabo en el - E.Row: todo el registro del Grid que se está llevando la acción de chequeo o deschequeo registro actual. Private Sub Grid1_RecordChecked(ByVal sender As Object, ByVal e As Solmicro.Expertis.Engine.UI.CheckedEventArgs) Handles Grid1.RecordChecked If e.CheckState = CheckStates.Checked Then If e.Row.Cells("Estado").Value = 1 Then ExpertisApp.GenerateMessage("Se ha seleccionado un registro con Estado 1", Windows.Forms.MessageBoxButtons.OK, Windows.Forms.MessageBoxIcon.Information) End If End If 123/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis End Sub CheckingAllRecord Evento para cuando hayamos hecho un chequear o deschequear todos los registros del Grid. Esta acción será para las dos opciones realizadas y antes de que pueda llevar a cabo la acción, con lo cual nos posibilita poder cancelar el evento dependiendo de las circunstancias que necesitemos. Para ello tendremos en la variable e de entrada toda la información necesaria: - E.CheckAction: nos da la información de la acción de chequeo o deschequeo llevada a cabo. - E.Cancel: propiedad para cancelar por completo el evento de checkall/uncheckall del registro. Private Sub Grid1_CheckingAllRecord(ByVal sender As Object, ByVal e As Solmicro.Expertis.Engine.UI.CheckingAllEventArgs) Handles Grid1.CheckingAllRecord If e.CheckAction = UI.CheckAction.Check Then If Me.txtEstado.Text = 1 Then ExpertisApp.GenerateMessage("No se pueden seleccionar todos los registros", Windows.Forms.MessageBoxButtons.OK, Windows.Forms.MessageBoxIcon.Information) e.Cancel = True End If End If End Sub AllRecordChecked Evento para cuando haya completado la acción de chequear o deschequear todos los registros del Grid. Para ello tendremos en la variable e de entrada toda la información necesaria: - E.CheckAction: nos da la información de la acción de chequeo o deschequeo llevada a cabo. Private Sub Grid1_AllRecordChecked(ByVal sender As Object, ByVal e As Solmicro.Expertis.Engine.UI.AllCheckedEventArgs) Handles Grid1.AllRecordChecked If e.CheckAction = UI.CheckAction.Check Then ExpertisApp.GenerateMessage("Se han seleccionado todos los registros.", Windows.Forms.MessageBoxButtons.OK, Windows.Forms.MessageBoxIcon.Exclamation) End If End Sub RecordAdded, RecordUpdated, AddingRecord, RecordAdded, DeletingRecord, RecordsDeleted Eventos generales relacionados con la inserción, modificación y borrado de registros dentro del grid. Tendremos disponibles tanto los eventos anteriores a llevar a cabo la acción correspondiente como después de haber llevado a cabo la acción. En los eventos anteriores a las acciones disponemos dentro de la variable e su propiedad Cancel para poder cancelar el evento anterior. FormattingRow Evento que ejecutará el grid ante cambios fromateo y de orígenes de datos en el cual podremos aplicar estilos personalizados por columna y celda. Nos permitirá analizar la información por celda que se está procesando y su valor y poder cambiar sus propiedades de diseño visual. - E.Row: todo el registro del Grid que se está llevando la acción de formateo Private Sub Grid1_FormattingRow(ByVal sender As Object, ByVal e As Janus.Windows.GridEX.RowLoadEventArgs) Handles Grid1.FormattingRow If Me.TxtEstado.text = 1 Then e.Row.Cells("DescClave").FormatStyle.ForeColor = Drawing.Color.Aqua End If 124/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis End Sub Diseñador de Grid Para el control Grid disponemos de una herramienta de diseño visual para una mayor configuración y personalización del control. Para acceder a este diseñador bastará con que demos botón derecho del ratón encima del control Grid -> GridEX Designer. Esta opción nos abrirá el diseñador específico del DataGrid y todo su conjunto de propiedades y funcionalidades especiales que nos proporciona el Grid de Expertis. Dentro de las opciones del Datagrid tendremos disponibles de todo tipo y para mayor información sobre todo lo que contiene este grid acudir a la ayuda del GridEx de los controles de Janus System. Volver al Índice 125/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis 9. UnderLineLabel Control para el mostrado de contenido e campos pero sin permitir edición y con una barra de subrayada fija para todo el control. Propiedades Control Las propiedades principales y más importantes del control en tiempo de diseño tenemos: DataBindings - Text Propiedad de bindeo del control con la propiedad text del control. Las propiedades principales y más importantes del control en tiempo de ejecución tenemos: Text Valor de la caja de texto que posee el control al que podemos obtener este valor. Métodos principales TextChanged Método que se activará cada vez que cambie el contenido de la propiedad Text del control. Volver al Índice 10. Label Control para establecer etiquetas por el formulario y para definir para controles. Propiedades Control Las propiedades principales y más importantes del control en tiempo de diseño tenemos: Text Valor de la caja de texto que posee el control al que podemos obtener este valor Volver al Índice 126/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis 11. RadioButton Control para mostrar estado de verdadero o falso dentro de un grupo de este tipo de controles para escoger solo una opción. Este control viene acompañado con un label por defecto para el nombre de la opción accesible a través de la propiedad Text. Propiedades Control Las propiedades principales y más importantes del control en tiempo de diseño tenemos: CheckAlign Propiedad para definir dónde se alinea la parte visual del control: derecha, izquierda, centro, …… Checked Propiedad para establecer u obtener el estado verdadero o falso de este control. Text Propiedad del texto que se visualizará conjunto con el control DataBindings - BindableValue Propiedad de Bindeo del control. Aconsejamos utilizar esta propiedad para el bindeo y no aconsejamos usar la propiedad Checked en este bindeo. Las propiedades principales y más importantes del control en tiempo de ejecución tenemos: Checked Propiedad para establecer u obtener el estado verdadero o falso de este control. Métodos principales CheckedChanged Método que se invocará cada vez que cambie el valor de checked del control. Volver al Índice 127/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis 12. CheckBox Control para mostrar estado de verdadero, falso o nulo dentro de un grupo de este tipo de controles para escoger una o varias opciones. Este control viene acompañado con un label por defecto para el nombre de la opción accesible a través de la propiedad Text. Propiedades Control CheckAlign Propiedad para definir dónde se alinea la parte visual del control: derecha, izquierda, centro, …… Checked Propiedad para establecer u obtener el estado verdadero o falso de este control. Text Propiedad del texto que se visualizará conjunto con el control ThreeState Opción para configurar si se desea utilizar el tercer estado de Nulo o no se admite valores nulos en este control. DataBindings - BindableValue Propiedad de Bindeo del control. Aconsejamos utilizar esta propiedad para el bindeo y no aconsejamos usar la propiedad Checked en este bindeo. Las propiedades principales y más importantes del control en tiempo de ejecución tenemos: Checked Propiedad para establecer u obtener el estado verdadero o falso de este control. Métodos principales CheckedChanged Método que se invocará cada vez que cambie el valor de checked del control. Volver al Índice 128/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis 13. Otros Controles Panel Control aglutinador de controles en el que no se visualiza nada en tiempo de ejecución de dicho control. Nos sirve para mantener agrupados controles sin que se note en la ejecución final por parte del usuario Frame Control aglutinador de controles que se visualiza con un marco y un título de control. Nos sirve para mantener agrupados controles visualizándonos con el marco y un título descriptivo para el usuario final. Tab Control de pestañas para organizar la información y controles del usuario. Para este control disponemos con el botón derecho del ratón encima del control las opciones de Add Tab y Remove Tab, para añadir y eliminar rápidamente más pestañas a este control. 129/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Asimismo disponemos de un diseñador de todas las pestañas de este control. Dicho diseñador disponemos de él en la ventana de propiedades -> Propiedad TabPages. Volver al Índice 130/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Acciones Locales Formularios Las Acciones Locales de Expertis es una funcionalidad que nos permite generar acciones personalizadas localmente en el formulario en las que programemos. De esta manera podemos desarrollar funcional adicional a un formulario para el usuario final que no se engrose dentro del diseño y formato del propio formulario. Para esta funcionalidad tenemos disponibles en todos los formularios de Expertis (a excepción del FormBase) una colección de acciones locales donde podremos ir agregando las acciones que creamos oportunas. Esta colección sería: Me.FormActions. En esta colección iremos agregando todas las acciones locales que deseemos y necesitemos, teniendo en cuenta que en el orden en que las programemos será en el orden de visualización que veremos en el resultado final. . También hemos de tener en cuenta de programar el alta de estas acciones solo una vez en la pantalla puesto que si lo hacemos más dinámico podemos estar haciendo que se dupliquen, tripliquen,… las acciones del formulario. Private Sub SimpleMntoExpertis1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load Me.FormActions.Add("Cargar Factura", AddressOf CargarFactura, ExpertisApp.GetIcon("xico.ico")) End Sub Private Sub CargarFactura() 'Proceso de Cargar una Factura End Sub La parte del código de agregado de una acción especificaremos la descripción visual que veremos en el listado de acciones, el proceso que se ejecutará cuando se seleccione la acción y optativamente la especificación de un icono visual para su mostrado. Junto con todo esto podemos hacer más visual y ordenadas las acciones locales especificando líneas de separación entra las acciones (AddSeparator). Para ello bastaría con el comando siguiente entre las acciones que deseemos que aparezca un separador. Recordemos que hemos comentado antes que en el orden en el que estén programados las acciones así se agregarían en ese orden en la colección y en su mostrado en pantalla y lo mismo sería para los separadores. Este comando hay que fijarse que lo tenemos disponible dentro de los métodos y propiedades del formulario. Private Sub SimpleMntoExpertis1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load Me.FormActions.Add("Cargar Factura", AddressOf CargarFactura, ExpertisApp.GetIcon("xIco.ico")) Me.AddSeparator() Me.FormActions.Add("Nueva Factura", AddressOf NuevaFactura, ExpertisApp.GetIcon("xIco.ico")) End Sub Private Sub CargarFactura() 'Proceso de Cargar una Factura End Sub Private Sub NuevaFactura() 'Proceso de Nueva Factura End Sub DataGrids 131/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Con el desarrollo ya explicado para las acciones locales de formularios tendremos lo mismo posible por cada Datagrid que tengamos en Expertis. De esta manera nos permite mostrar un menú contextual personalizado con acciones que necesitemos por cada registro que seleccionemos con botón derecho en el Grid. Para esta colección de acciones personalizadas por DataGrid la tendríamos en: Grid.Actions. En esta colección iremos agregando las diferentes acciones que deseemos mostrar en el Grid. Recordemos que se mostrarán el mismo orden en el que las agreguemos en el código fuente. También hemos de tener en cuenta de programar el alta de estas acciones solo una vez en la pantalla puesto que si lo hacemos más dinámico podemos estar haciendo que se dupliquen, tripliquen,… las acciones del grid. Private Sub SimpleMntoExpertis1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load Me.Grid1.Actions.Add("Cargar Factura", AddressOf CargarFactura, ExpertisApp.GetIcon("xIco.ico")) End Sub Private Sub CargarFactura() 'Proceso de Cargar una Factura End Sub La parte del código de agregado de una acción especificaremos la descripción visual que veremos en el listado de acciones, el proceso que se ejecutará cuando se seleccione la acción y optativamente la especificación de un icono visual para su mostrado. Junto con todo esto podemos hacer más visual y ordenadas las acciones locales especificando líneas de separación entra las acciones (AddSeparator). Para ello bastaría con el comando siguiente entre las acciones que deseemos que aparezca un separador. Recordemos que hemos comentado antes que en el orden en el que estén programados las acciones así se agregarían en ese orden en la colección y en su mostrado en pantalla y lo mismo sería para los separadores. Este comando hay que fijarse que lo tenemos disponible dentro de los métodos y propiedades del DataGrid. Private Sub SimpleMntoExpertis1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load Me.Grid1.Actions.Add("Cargar Factura", AddressOf CargarFactura, ExpertisApp.GetIcon("xIco.ico")) Me.Grid1.AddSeparator() Me.Grid1.Actions.Add("Nueva Factura", AddressOf NuevaFactura, ExpertisApp.GetIcon("xIco.ico")) End Sub Private Sub CargarFactura() 'Proceso de Cargar una Factura End Sub Private Sub NuevaFactura() 'Proceso de Nueva Factura End Sub Volver al Índice Acciones Globales Las Acciones Globales de Expertis es una funcionalidad que nos permite crear genéricamente en un sitio de nuestro código una funcionalidad que podremos disponer en cualquier programa que dispongamos. Asimismo es una utilidad para tener contraladas acciones de expertis con el tema de permisos de usuario de Expertis. De esta manera podremos hacer que acciones de Expertis sean visibles o no dependiendo del rol del usuario. Para ello el sitio común donde se alojan las acciones globales de Expertis son en: Expertis.Application.ERP.GlobalActions.dll. Para cada acción hace falta crear un fichero de tipo clase y que tenga la implementación que marcamos en el código a continuación: Implements Expertis.Engine.IAction. 132/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis El único método que nos brinda este IAction es el Execute el cual se corresponderá como respuesta al evento de pulsar a esa correspondiente acción de Expertis. Éste método nos da los siguientes parámetros de entrada e información: entityname Nombre de la entidad de la ventana que lo ha invocado, de esta manera podremos saber y diferenciar si han sido facturas o albaranes, etc… programID El Guid del programa que ha invocado esta acción, de esta manera podemos controlar y programar funciones específicas para una misma acción, dependiendo de si lo ha llamado un programa u otro. record Datatable con la información del registro de la ventana que ha invocado la acción global. Siempre será un datatable, de manera que si lo ha invocado una consulta interactiva vendrán tantos registros como hayamos seleccionado en el grid si es de marcas o bien si no es de marcas todo el datasource del grid que veamos en ese momento en pantalla. Para mantenimientos de tipo simple nos vendrá un datatable con un datarow del registro actual en el que estemos posicionados. Para mantenimientos de tipo grid nos vendrá todo el datasource del datagrid de ese formulario. Para mantenimientos de tpo consulta interactiva nos vendrá todo el datasource del datagrid de ese formulario, independientemente del uso o no de marcas en el grid. Para el registro de estas acciones globales se lleva a cabo en el manager de Expertis, para inventariar dicha acción y darle permisos y asociarlas a lso formulario de expertis que deseamos. Para ello acudimos al Manager de Expertis y vamos a la sección de: Objetos -> Acciones. Aquí veremos ya las acciones globales ya existentes de Expertis, tanto como dar de alta nuevas, modificar las existentes o borrarlas. Si Deseamos agregar una nueva acción global, aconsejamos hacerlo a través del método automático del menú de: Programas -> Añadir Acciones 133/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Con esto conseguimos agregar de manera automática y rápida las acciones de la dll de Expertis donde las hubiésemos agregado. Como datos que podemos ver dentro de una acción tendríamos lo siguiente: Descripción Descripción de la Acción global, que será el texto que veremos colgado dentro de las acciones del/los formularios que estará colgada dicha acción global. Imagen Icono visual que aparecerá al lado de la descripción de la Acción Global en los formularios. Ensamblado Ensamblado donde se encuentra dicha Acción Global. 134/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Asociar A Opción a seleccionar para configurar en qué formularios de Expertis queremos que aparezca la Acción Global en la que nos hemos posicionado. Para esto tenemos los siguientes valores: - AllPrograms: sería para asociarlas a todos los formularios de expertis. CIMntoPrograms: sería para asociarla a todos los formularios de Tipo CIMnto de Expertis. GridMntoPrograms: sería para asociarla a todos los formularios de Tipo GridMnto de Expertis. SimpleMntoPrograms: sería para asociarla a todos los formularios de tipo SimpleMnto de Expertis. SpecifiedPrograms: con esta opción solo se asociaría dicha acción al listado de programas especificados en la pestaña de programas. Clase Clase dentro del ensamblado que sería la acción global de expertis. Índice para Agrupar Número de índice único entre todos las acciones globales, para que se agrupen y de esta manera crear grupos de Acciones Globales. Orden en el Grupo Número de Orden que ocuparía la acción global dentro del índice del Grupo que hemos marcado anteriormente. En la sección e Grupos es donde podremos establecer para la acción global en la que estamos, los diferentes grupos de expertis a los que queremos dar permisos para visualizar y ejecutar dicha Acción. Volver al Índice 135/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Parámetros Formularios Los parámetros de los formularios nos permiten manejar cierta información extra en la ventana de manera que en el momento de la carga de la ventana desempeñemos ciertas acciones. Éste es el uso general que suele darse en expertis, siendo en formularios simples la idea de añadir mas información en la ventana y dependiendo de esta información llevar a cabo una acción en el formulario. O bien en formularios de consultas interactivas nos sirve para que un formulario aparezca filtrado por una serie de filtros cuando carguemos la ventana. Para ello disponemos en los formularios de expertis de la propiedad Me.Params. Es un objeto declarado como tipo object para que podamos manejarlo con el tipo de objeto qué queramos usar. El tipo de objeto mas común usado en Expertis sería de tipo HashTable. Para esto lo primero que hacemos es preparar los parámetros que queremos enviar al abrir un formulario y enviándoselos en la apertura: Dim HashParams As New Hashtable HashParams.Add("IDArticulo", "001") HashParams.Add("IDCliente", "00") ExpertisApp.OpenForm("CPV", , HashParams) Después en el formulario de destino hacemos las comprobaciones de si existen parámetros en la apertura de la ventana y de si existiendo parámetros coinciden los tipos y valores esperados. Con ello ya pasamos a ejecutar lo que necesitamos: Private Sub CIMntoBase_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load If Not Me.Params Is Nothing Then If TypeOf Me.Params Is Hashtable Then Dim HashParams As Hashtable = Me.Params If HashParams.ContainsKey("IDArticulo") Then Me.AdvArticulo.Value = HashParams("IDArticulo") If HashParams.ContainsKey("IDCliente") Then Me.AdvCliente.Value = HashParams("IDCliente") End If End If End Sub Volver al Índice Componentes de Motor Capa Presentación 1. Componente BE.DataEngine Componente de comunicación del motor entre la capa de presentación y la capa de negocio. De este componente sobre todo usaremos el método Filter que nos permitirá traernos datos de la base de datos de la siguiente manera: Dim FilArt As New Filter FilArt.Add("IDArticulo", FilterOperator.Equal, "Tuerca") Dim ClsBE As New BE.DataEngine Dim DtArt As DataTable DtArt = ClsBE.Filter("tbCursoArticulo", FilArt) Volver al Índice 2. Componente ExpertisApp Componente del Engine de Expertis exclusivo para la capa de presentación de Expertis. Nos brindará diversos métodos y propiedades muy útiles para la capa de presentación de Expertis. Pasamos a enumerar los métodos y propiedades más importantes. ExpertisApp.GenerateMessage: Método para generar mensajes en pantalla desde presentación. Podemos usarla para mostrar cualquier tipo de mensaje. Pudiendo escribir el mensaje en sí, los tipos de botones a mostrar, el tipo de icono del mensaje y parámetros para la composición de mensajes personalizados. 136/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis ExpertisApp.GenerateMessage("El Artículo | se ha dado de Alta correctamente.", Windows.Forms.MessageBoxButtons.OK, Windows.Forms.MessageBoxIcon.Information, "Tuerca") ExpertisApp.OpenForm: Método para abrir formularios de expertis desde presentación. Especificando el Alias del programa de Expertis (que podemos verlo en la consola de administración de expertis, pudiendo filtrar la ventana de manera predeterminada, y pasando además parámetros a la propia ventana que abrimos. ExpertisApp.OpenForm("ARTCURSO", New FilterItem("IDArticulo", FilterOperator.Equal, "Tuerca", FilterType.String), ) ExpertisApp.CloseForm: Método para cerrar formularios de expertis desde presentación. ExpertisApp.CloseForm("ARTCURSO") ExpertisApp.OpenReport: Método para abrir objetos reports definidos en la capa de presentación. Dim RptArt As New Report("RPTART") ExpertisApp.OpenReport(RptArt) ExpertisApp.ExecuteTask: Método para ejecutar tareas de Negocio en la capa de Presentación. Dim DtArt As DataTable DtArt = ExpertisApp.ExecuteTask(Of String, DataTable)(AddressOf GetInfoArticulo, "Tuerca") ExpertisApp.GetIcon: Método para obtener un objeto de tipo drawing.icon, especificando el nombre del icono que existirá en el directorio por defecto configurado en Expertis como directorio de recursos de imágenes. Me.FormActions.Add("Abrir Articulo", ExpertisApp.GetIcon("xArticulos.ico")) AddressOf AccionAbrirArticulo, Volver al Índice Configuración del Manager para procesar Capa Presentación Debemos recordar en todo momento que después de generar nuestros nuevos programas de presentación de Expertis, debemos de registrarlas en el manager de expertis para que consten inventariadas en su sistema, para un correcto funcionamiento de la aplicación y disponibilidad de uso. Para ello acudiremos al manager de expertis e iremos a la sección: Objetos -> Programas. En el menú superior de Procesos tendremos un proceso automático de agregado de Programas indicándole en qué dll tenemos alojada el/los programa/s que queremos pasar. Si no siempre tendremos la opción manual de inserción de un nuevo programa. Para mayor información sobre las propiedades de un programa acudir al manual de la Consola de Administración de Expertis 5.0. 137/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Para ello acudiremos al manager de expertis e iremos a la sección: Objetos -> Acciones. En el menú superior de Procesos tendremos un proceso automático de agregado de acciones indicándole en qué dll tenemos alojada la/s clase/s que queremos pasar. Si no siempre tendremos la opción manual de inserción de una nueva entidad. Como último punto tenemos que tener en cuenta que si para nuestros proyectos la parte de presentación vamos a llevar a cabo el uso de la herencia. Hemos de introducir los formularios padres en la sección de Negocios para que éstos se actualicen automáticamente cuando demandemos la nueva ventana heredada. Para ello acudimos a la sección de negocios de Expertis: 138/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Volver al Índice 139/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis 4. PROGRAMACIÓN GENERAL Enumerados Los enumerados de expertis serían lista de valores con descripción que usan para mostrar en la aplicación. Teniendo disponibles los enumerados en cualquier parte de la aplicación y con sistema de traducciones. Como veremos a continuación los enumerados a pesar de lo sencillo de su definición requiere algo de desarrollo y control en expertis, para poder así tener disponible un sistema de traducciones para estos valores que se ven en los formularios de los usuarios finales. Alta de Enumerados Todos los enumerados de Expertis se encuentran disponibles en el Proyecto: Expertis.Business.BusinessEnum.BusinessEnum. Con lo cual daremos de alta los enumerados en este proyecto, no habría problema de cara para la extensibilidad. También se pueden generar los enumerados propios en el proyecto que consideremos conveniente, no hay porqué crearlos obligatoriamente solo en este estándar. Una vez generados los enumerados en la correspondiente DLL, los daremos de alta en el sistema de expertis. Abrir la consola de administración de Expertis. Desde el menú Procesos -> Agregar Enumerados El cuadro de dialogo permite seleccionar la DLL que contiene las definiciones de los enumerados. En el caso del Estándar de Expertis, estos se encuentran en Expertis.Business.BusinessEnum. 140/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Una vez agregados los Enumerados podemos establecer las descripciones y traducciones de los enumerados en la pestaña de Traducciones de cada Enumerado. Propiedad Enums La propiedad Enums de la clase Solmicro.Expertis.Engine.UI.ExpertisApp define un DataTable que contiene toda la información de los enumerados de Expertis. De esta forma el programador tiene disponibles todos los enumerados que contiene la tabla xEnumerate de la base de datos de sistema. Las columnas de este DataTable son Name MemberName Value Language Text Nombre del enumerado Nombre de cada uno de los miembros Valor numérico del miembro ID del idioma del usuario La descripción traducida Clase EnumData La clase EnumData, que se encuentra en el componente Solmicro.Expertis.Engine.UI.WinControls, se ha creado expresamente para la gestión de los enumerados de Expertis. En el fondo define un DataTable que contiene los valores correspondientes al enumerado especificado (a diferencia de la propiedad Enums de ExpertisApp, que contiene todos los enumerados). 141/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Esta clase es especialmente útil a la hora de asignar listas de enumerados como origen de datos para controles de Expertis, como un ComboBox, o un lista de valores en un columna de un grid. Por ejemplo, esta línea de código asigna el enumerado CursoEstadoContabilizacion al control ComboBox cmbEstado cmbEstado.DataSource = New EnumData("CursoEstadoContabilizacion") Para asignar una lista de valores a una columna del Grid se utiliza el método shared PopulateValueList de la clase EnumData. En el siguiente ejemplo se asignar una lista de valores del mismo enumerado que en el ejemplo anterior a una columna de un Grid con nombre Estado EnumData.PopulateValueList("CursoEstadoContabilizacion", Grid.Columns("Estado")) O de forma alternativa EnumData.PopulateValueList(GetType(CursoEstadoContabilizacion), Grid.Columns("Estado")) NOTA: Cuando la columna de un Grid tiene asociada una lista de valores la propiedad EditType de la columna puede ser igual a EditType.Combo, o bien EditType.DropDownList. La diferencia entre las dos es que DropDownList no nos permitirá editar en la celda del Grid, lo que obliga a seleccionar un elemento de la lista. Si el valor es EditType.Combo y se introduce un valor que no está dentro de la lista de valores posibles, la celda no perderá el foco y se mantendrá en modo de edición (de hecho no pierde el foco hasta introducir un valor valido o cancelar la edición en curso). En este caso el control Grid de Janus dispone de un evento llamado NotInList por si se quiere validar los valores introducidos. Clase EnumData.EnumView Dentro de la clase enumdata tendremos un método especial llamado: EnumView. Con este método lo que nos permite es que el motor de expertis nos devuelva a un datatable todo el conjunto de datos del enumerado que hayamos solicitado, pero no nos modificaría nada a nivel de diseño de objetos. Esto lo que nos permite es poder configurar el diseño del ComboBox u objeto donde lo carguemos como queramos. Para ello tendremos que tener en cuenta sobre todo que en este datatable tendremos dos columnas que serían las más importantes: - Text: la columna con la descripción del enumerado y que sería la columna que estableceríamos para visualizar como dato al usuario final. - Value: la columna con el valor del enumerado y que sería la columna que estableceríamos como origen de datos principal y el que guardaríamos en base de datos. Volver al Índice Objeto Filter En Expertis disponemos dentro de la DLL del Engine de Expertis: Expertis.Engine.Global.Dll, el objeto Filter. Objeto que nos permite componer condiciones de filtrado de una manera más fácil y manejable que escribir las sentencias Where de SQL. Es un objeto que usaremos en los métodos que nos brindan los objetos del Engine de Expertis para llevar a cabo filtrados en vistas, en tablas, en entidades,… El objeto Filter se puede componer de manera principal con tipo AND u OR de la siguiente manera: Dim FilAND As New Filter Para definir de tipo OR accedemos a la sobrecarga de la definición NEW del objeto. Dim FilOR As New Filter(FilterUnionOperator.Or) Para ya introducir campos de condición dentro del objeto Filter lo haríamos de la siguiente manera: Dim FilAND As New Filter FilAND.Add("IDArticulo", FilterOperator.Equal, "Tuerca", FilterType.String) Dim DtArt As DataTable = New CursoArticulo().Filter(FilAND) Vemos que el comando Add del objeto Filter se compone de varias partes y sobrecargas. La más completa sería la descrita anteriormente. Se compondría primero del Nombre del Campo a filtrar. Siguiente sería el tipo de condición que queremos evaluar. Siguiente valor sería el valor en sí para evaluar. Y como último parámetro el tipo del campo a evaluar. Luego vemos que este objeto Filter lo aplicamos a la entidad CursoArtículo y el método Filter de la entidad. De esta manera obtendremos de la entidad CursoArtículo (Tabla tbCursoArtículo) los datos cuyo IDArtículo sea igual a Tuerca. Como valores posibles en el tipo de condición tendríamos: 142/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis - FilterOperator.Equal: condición = FilterOperator.GreaterThan: condición > FilterOperator.GreaterThanOrEqual: condición >= FilterOperator.LessThan: condición < FilterOperator.LessThanOrEqual: condición <= FilterOperator.NotEqual: condición <> Como valores posibles en el tipo de campo tendríamos: - FilterType.Boolean: tipo de campo Boolean o Bit de la base de datos. FilterType.Guid: tipo de campo UniqueIdentifier de la base de datos. FilterType.DateTime: tipo de campo Date o DateTime de la base de datos. FilterType.String: tipo de campo char, varchar, nvarchar de la base de datos. FilterType.Numeric: condición <= Otro método disponible que tendremos en el objeto Filter sería el Compose. Esto lo que nos haría sería traducirnos en una cadena string todo el objeto Filter que hayamos compuesto. Como parámetro para especificar en el método Compose sería el tipo de lenguaje en que queramos que nos componga la cadena. Dim StrFil As String = FilAND.Compose(New AdoFilterComposer) "IDArticulo = 'Tuerca'" En este caso hemos usado el tipo AdoFilterComposer. Nos compondría la cadena en formato de ADO .Net. Éste sería un tipo que tendríamos disponible tanto en la capa de Presentación como en la capa de Negocio de Expertis. Para componer en otras sintaxis lo haríamos en la capa de Negocio de Expertis Utilizando el objeto AdminData y con el método ComposeFilter: Dim StrFil As String = AdminData.ComposeFilter(FilAND) "IDArticulo = 'Tuerca'" Además de todo esto poseemos objetos de tipo FilterItem para poder especificar condiciones especiales para los objetos Filter: StringFilterItem Objeto ítem para campos de tipo Char, Varchar, nVarchar, …. Dim FilAND As New Filter FilAND.Add(New StringFilterItem("IDArticulo", "Tuerca")) DateFilterItem Objeto ítem para campos de tipo Date o Date Time Dim FilAND As New Filter FilAND.Add(New DateFilterItem("FechaArticulo", Today.Date)) NumberFilterItem Objeto ítem para campos de tipo Integer, Decimal, …. Dim FilAND As New Filter FilAND.Add(New NumberFilterItem("CantidadArticulo", 15)) BooleanFilterItem Objeto ítem para campos de tipo Boolean o Bit. Dim FilAND As New Filter FilAND.Add(New BooleanFilterItem("ArticuloActivo", True)) GuidFilterItem Objeto ítem para campos de tipo UniqueIdentifier. Dim FilAND As New Filter FilAND.Add(New GuidFilterItem("IDArticulo", New Guid())) LikeFilterItem Objeto ítem para componer una cláusula de condición de tipo LIKE de SQL. Dim FilAND As New Filter FilAND.Add(New LikeFilterItem("IDArticulo", "Tuerca")) 143/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis IsNullFilterItem Objeto ítem para componer una cláusula de condición de tipo IS NULL de SQL. Dim FilAND As New Filter FilAND.Add(New IsNullFilterItem("IDArticulo", False)) BetweenFilterItem Objeto ítem para componer una cláusula de condición de tipo Between de SQL. Dim FilAND As New Filter FilAND.Add(New BetweenFilterItem("FechaAlta", New Date(2010, 1, 1), Today.Date, FilterType.DateTime)) NoRowsFilterItem Objeto ítem para componer una cláusula de condición de 1 = 2. Esto lo hacemos así para obtener de una tabla o vista sólo la estructura de los datos y no traer de la base de datos ningún registro. Dim FilAND As New Filter FilAND.Add(New NoRowsFilterItem) InListFilterItem Objeto ítem para componer una cláusula de condición de Tipo InList de SQL. Dim FilAND As New Filter Dim StrIDS(1) As String StrIDS(0) = "Tuerca" StrIDS(1) = "Llave" FilAND.Add(New InListFilterItem("IDArticulo", StrIDS, FilterType.String)) Volver al Índice Contadores Los contadores de expertis nos permiten definir un sistema para generación automática de códigos de clave primaria para entidades. Por ejemplo, nos permite así definir un contador clave para las facturas tanto de ventas como de compras, siguiendo un formato que deseemos y una numeración que también la que queramos. Siendo el uso general te de estos contadores en temas de logística y pudiendo reiniciar su enumeración con cada nuevo año fiscal. Como primero paso acudiremos a la ventana de administración de contadores para dar de alta un contador, el que deseemos. Generalmente esta ventana estará colgada dentro del punto de menú de: Configuración -> Empresa -> Empresa -> Contadores -> Contadores En la parte de programación tendremos que realizar los siguientes pasos para que funcione nuestro contador para la entidad que deseemos. 144/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Primero hemos de crear en la base de datos en la tabla de la entidad que deseamos usar un contador, un campo NContador que contendrá el número de contador final que formemos. Generalmente este campo suele ser de tipo nvarchar(25). Crearemos también en la tabla de la entidad en cuestión un campo IDContador para contener el IDContador con el que fue formado el NContador. Generalmente este campo suele ser de tipo nvarchar(10). En el diseño de la ventana que mostraremos este campo NContador lo que tenemos que hacer es alojar un objeto de tipo CounterTextBox de Expertis y la única propiedad que tenemos que configurar correctamente sería su DataBinding –Text con el campo de NContador como enlace. Ponemos como ejemplo la pantalla de Factura de Venta. En la parte de código fuente tendremos que crear en la parte de nuevo registro de nuestra entidad una tarea para asignar ya el valor provisional siguiente del contador en la serie para que el usuario lo vea en pantalla. Tendremos que programar el proceso de RegisterAddNewTaks (AddNewForm antiguamente) para reflejar correctamente el valor del contador en la propuesta de un nuevo registro de nuestra entidad. Para ello habría que hacer algo parecido a como ponemos a continuación y con código como ejemplo de Facturas de Venta: Public Overrides Function AddNewForm() As DataTable Dim dt As DataTable = MyBase.AddNewForm ProcessServer.ExecuteTask(Of DataRow)(AddressOf FillDefaultValues, dt.Rows(0), New ServiceProvider) Return dt End Function <Task()> Public Shared Sub FillDefaultValues(ByVal data As DataRow, ByVal services As ServiceProvider) ProcessServer.ExecuteTask(Of DataRow)(AddressOf ProcesoComunes.AsignarIdentificadorFactura, data, services) ProcessServer.ExecuteTask(Of DataRow)(AddressOf NegocioGeneral.AsignarCentroGestion, data, services) ProcessServer.ExecuteTask(Of DataRow)(AddressOf AsignarContador, data, services) ProcessServer.ExecuteTask(Of DataRow)(AddressOf AsignarNumeroFacturaProvisional, data, services) ProcessServer.ExecuteTask(Of DataRow)(AddressOf AsignarDatosDeclaraciones, data, services) ProcessServer.ExecuteTask(Of DataRow)(AddressOf ProcesoComunes.AsignarFechaFactura, data, services) ProcessServer.ExecuteTask(Of IPropertyAccessor)(AddressOf ProcesoComunes.AsignarEjercicioContableFactura, New DataRowPropertyAccessor(data), services) ProcessServer.ExecuteTask(Of DataRow)(AddressOf ProcesoComunes.AsignarFechaParaDeclaracion, data, services) ProcessServer.ExecuteTask(Of DataRow)(AddressOf AsignarTipoFactura, data, services) ProcessServer.ExecuteTask(Of DataRow)(AddressOf AsignarEstadoFactura, data, services) ProcessServer.ExecuteTask(Of DataRow)(AddressOf AsignarArqueoCaja, data, services) ProcessServer.ExecuteTask(Of DataRow)(AddressOf NegocioGeneral.AsignarMarcaIVAManual, data, services) ProcessServer.ExecuteTask(Of DataRow)(AddressOf NegocioGeneral.AsignarMarcaVtosManuales, data, services) End Sub <Task()> Public Shared Sub AsignarContador(ByVal data As DataRow, ByVal services As ServiceProvider) Dim CE As CentroEntidad CE.CentroGestion = data("IDCentroGestion") & String.Empty CE.ContadorEntidad = CentroGestion.ContadorEntidad.FacturaVenta data("IDContador") = ProcessServer.ExecuteTask(Of CentroEntidad, String)(AddressOf CentroGestion.GetContadorPredeterminado, CE, services) End Sub 145/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis <Task()> Public Shared Sub AsignarNumeroFacturaProvisional(ByVal data As DataRow, ByVal services As ServiceProvider) If Length(data("IDContador")) > 0 Then Dim dtContadores As DataTable = ProcessServer.ExecuteTask(Of String, DataTable)(AddressOf Contador.CounterDt, GetType(FacturaVentaCabecera).Name, services) Dim adr As DataRow() = dtContadores.Select("IDContador = " & Quoted(data("IDContador"))) If Not IsNothing(adr) AndAlso adr.Length > 0 Then data("NFactura") = adr(0)("ValorProvisional") Else 'Si no está bien configurado el Contador de Facturas de Venta en el Centro de Gestión, 'cogemos el Contador por defecto de la entidad Factura Venta Cabecera. Dim dtContadorPred As DataTable = ProcessServer.ExecuteTask(Of String, DataTable)(AddressOf Contador.CounterDefault, GetType(FacturaVentaCabecera).Name, services) If Not dtContadorPred Is Nothing AndAlso dtContadorPred.Rows.Count > 0 Then data("IDContador") = dtContadorPred.Rows(0)("IDContador") adr = dtContadores.Select("IDContador = " & Quoted(data("IDContador"))) If Not IsNothing(adr) AndAlso adr.Length > 0 Then data("NFactura") = adr(0)("ValorProvisional") End If End If End If End If End Sub Una vez programada la parte de propuesta de un nuevo registro. Tendríamos que programar la parte de actualización de inserción del registro. De manera que a la hora de grabar el registro en la base de datos de nuestra entidad comprobemos y verifiquemos que el NContador que tenemos que insertar es correcto. Esto es porque trabajando diversos usuarios a la vez en la plataforma es posible que el NContador que tenemos en la propuesta de la ventana haya sido ya recogido por otro usuario, con lo cual no sería correcto grabar el mismo NContador y tendríamos que seguir con el siguiente número disponible en la serie. Para ello escribiríamos una tarea en el proceso de RegisterUpdateTasks de nuestra entidad para llevar a cabo este control y manejo. Ponemos a continuación código de ejemplo de la entidad FacturaVenta: Protected Overrides Sub RegisterUpdateTasks(ByVal updateProcess As Engine.BE.BusinessProcesses.Process) MyBase.RegisterUpdateTasks(updateProcess) updateProcess.AddTask(Of UpdatePackage, DocumentoFacturaVenta)(AddressOf ProcesoFacturacionVenta.CrearDocumento) updateProcess.AddTask(Of DocumentoFacturaVenta)(AddressOf ProcesoFacturacionVenta.AsignarNumeroFactura) updateProcess.AddTask(Of DocumentoFacturaVenta)(AddressOf ProcesoFacturacionVenta.AsignarDatosFiscales) updateProcess.AddTask(Of DocumentoFacturaVenta)(AddressOf ProcesoComunes.AsignarCentroGestion) updateProcess.AddTask(Of DocumentoFacturaVenta)(AddressOf ProcesoComunes.ActualizarCambiosMoneda) updateProcess.AddTask(Of DocumentoFacturaVenta)(AddressOf ProcesoFacturacionVenta.TratarPromocionesLineas) updateProcess.AddTask(Of DocumentoFacturaVenta)(AddressOf ProcesoFacturacionVenta.CalcularImporteLineasFacturas) updateProcess.AddTask(Of DocumentoFacturaVenta)(AddressOf ProcesoFacturacionVenta.CalcularRepresentantes) updateProcess.AddTask(Of DocumentoFacturaVenta)(AddressOf ProcesoFacturacionVenta.CalcularAnalitica) updateProcess.AddTask(Of DocumentoFacturaVenta)(AddressOf ProcesoFacturacionVenta.CalcularBasesImponibles) updateProcess.AddTask(Of DocumentoFacturaVenta)(AddressOf ProcesoFacturacionVenta.CalcularTotales) updateProcess.AddTask(Of DocumentoFacturaVenta)(AddressOf ProcesoFacturacionVenta.CalcularPuntoVerde) updateProcess.AddTask(Of DocumentoFacturaVenta)(AddressOf ProcesoFacturacionVenta.CalcularVencimientos) updateProcess.AddTask(Of DocumentoFacturaVenta)(AddressOf ProcesoFacturacionVenta.AsignarClaveOperacion) updateProcess.AddTask(Of DocumentoFacturaVenta)(AddressOf Business.General.Comunes.BeginTransaction) updateProcess.AddTask(Of DocumentoFacturaVenta)(AddressOf ProcesoFacturacionVenta.ActualizarAlbaran) updateProcess.AddTask(Of DocumentoFacturaVenta)(AddressOf Business.General.Comunes.UpdateDocument) updateProcess.AddTask(Of DocumentoFacturaVenta)(AddressOf Business.General.Comunes.MarcarComoActualizado) updateProcess.AddTask(Of DocumentoFacturaVenta)(AddressOf ProcesoFacturacionObras.ActualizarObras) updateProcess.AddTask(Of DocumentoFacturaVenta)(AddressOf ProcesoFacturacionVenta.ActualizarOTs) updateProcess.AddTask(Of DocumentoFacturaVenta)(AddressOf ProcesoFacturacionVenta.ActualizarQLineasPromociones) End Sub <Task()> Public Shared Sub AsignarNumeroFactura(ByVal fra As DocumentoFacturaVenta, ByVal services As ServiceProvider) If fra.HeaderRow.RowState = DataRowState.Added Then If Not IsDBNull(fra.HeaderRow("IDContador")) Then Dim StDatos As New Contador.DatosCounterValue StDatos.IDCounter = fra.HeaderRow("IDContador") StDatos.TargetClass = New FacturaVentaCabecera 146/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis StDatos.TargetField = "NFactura" StDatos.DateField = "FechaFactura" StDatos.DateValue = fra.HeaderRow("FechaFactura") StDatos.IDEjercicio = fra.HeaderRow("IDEjercicio") & String.Empty fra.HeaderRow("NFactura") = ProcessServer.ExecuteTask(Of Contador.DatosCounterValue, String)(AddressOf Contador.CounterValue, StDatos, services) End If End If End Sub Para llevar a cabo los controles y actualizaciones relacionados con contadores disponemos de clase Contador en el proyecto: Expertis.Business.General.Contador, dentro de la cual tenemos disponibles diversos métodos y propiedades para el manejo de contadores, dependiendo de la situación y necesidad que tengamos en el momento. Volver al Índice Parámetros Los parámetros de Expertis nos permiten almacenar cierta información de configuración y valores permanentes que necesitemos en toda la aplicación. Expertis ya tiene de base una serie de parámetros para diversas funcionalidades dentro de la aplicación y para que la aplicación actúe de ciertas formas. Nosotros podremos dar de alta nuevos parámetros de Expertis según la necesidad que tengamos. Como primer paso tendríamos que acudir a la ventana de Expertis de Parámetros para definir un parámetro con las características que necesitemos. Generalmente esta ventana estará colgada dentro del punto de menú de: Configuración -> Empresa -> Parametrización -> Parámetros -> Parámetros. 147/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis A nivel de programación tendremos en el proyecto de: Expertis.Business.General.Parametro todos los parámetros generales de Expertis aquí definidos. Lo que básicamente programamos en esta parte es una lectura de ese parámetro de la tabla de parámetros de expertis para acudir a estos métodos siempre que necesitemos y no estar programando siempre un acceso a la tabla de parámetros y recordando el valor del ID del Parámetro. Public Function SituacionActividadCRM() As String Dim Dt As DataTable = SelOnPrimaryKey("CRMSITACT") If Not Dt Is Nothing AndAlso Dt.Rows.Count > 0 Then Return Dt.Rows(0)("Valor") Else : Return String.Empty End If End Function Public Function ValidarCambioFechaFacturas() As Boolean Dim Dt As DataTable = SelOnPrimaryKey("VALCAMF") If Not Dt Is Nothing AndAlso Dt.Rows.Count > 0 Then Return CBool(Dt.Rows(0)("Valor")) Else : Return False End If End Function Para nuestros desarrollos podemos programarlo en otra entidad nueva para todos los parámetros específicos que necesitemos y así seguir manteniendo la extensibilidad de Expertis. Una vez programados solo acudimos a nuestra dll desarrollada y llamar al método del parámetro que hayamos creado. Volver al Índice Agrupaciones Concepto de Agrupación A la hora de hacer agrupaciones de elementos para crear uno nuevo (por ejemplo, agrupar albaranes de venta para crear una factura de venta), básicamente lo que se hace en las tareas de agrupación es que dado un 148/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis DataTable (creado dentro de la tarea), a través de unas clases que veremos a continuación obtendremos un array de elementos “Cabecera-lineas” a partir de los cuales podremos formar un Documento. Los elementos “cabecera-lineas” en Expertis 4.1 son 2 datatables que contenían uno todas las cabeceras y otro todas las líneas. En Expertis 5.0, son varios objetos que cada uno de ellos formará una Factura, en el caso del ejemplo que veremos. Es decir, la agrupación nos devolverá un array de elementos en el que cada uno de ellos contiene la información mínima del origen para montar una cabecera de factura y las líneas de la misma. (Array de elementos FraCabAlbaran, que contiene otro array de FraLinAlbaran) Esto se puede hacer de una manera “automática”, gracias a varias clases (IGroupUser, GroupHelper) y métodos. De manera, que definiendo las columnas que deben abrir factura nueva y las clases que van a montar los elementos del array a devolver, recorriendo los registros a agrupar se monta el array. - - - En la tarea GetGroupColumns, indicaremos las columnas que abren factura. Como vemos, el caso del IDAlbaran será opcional. En la clase GroupUserAlbaranes (que implementa la interfaz IGroupUser), definiremos qué tipos se van a montar para retornar. En este caso, FraCabAlbaran y FraLinAlbaran, y le indicaremos que incluya los elementos de tipo FraLinaAlbaran en un array en FraCabAlbaran. Con el array de columnas que retorna la tarea GetGroupColumns y el objeto de tipo GroupUserAlbaranes, creamos una clase de tipo GroupHelper (en el caso de las facturas se crean 2 dependiendo de si la agrupación es por cliente o por albarán) A partir de las rows del DataTable origen, y con las tareas y tipos que acabamos de definir, el método Group de la clase GroupHelper, es capaz de hacer las agrupaciones correspondientes . Ejemplo de Creación y Manejo de Agrupaciones <Task()> Public Shared Function AgruparAlbaranes(ByVal data As DataPrcFacturacionGeneral, ByVal services As ServiceProvider) As FraCabAlbaran() Dim dtLineas As DataTable 'se seleccionan todas las lineas de albaran no facturadas Dim strViewName As String = "vNegComercialCrearFactura" If data.IDAlbaranes.Length > 0 Then Dim values(data.IDAlbaranes.Length - 1) As Object data.IDAlbaranes.CopyTo(values, 0) Dim oFltr As New Filter oFltr.Add(New InListFilterItem("IDAlbaran", values, FilterType.Numeric)) oFltr.Add(New NumberFilterItem("EstadoFactura", FilterOperator.NotEqual, enumavlEstadoFactura.avlFacturado)) dtLineas = New BE.DataEngine().Filter(strViewName, oFltr) End If If Not dtLineas Is Nothing AndAlso dtLineas.Rows.Count > 0 Then Dim p As New Parametro Dim fvcFecha As enumfvcFechaAlbaran = p.FacturacionFechaAlbaran() Dim oGrprUser As New GroupUserAlbaranes(data.DteFechaFactura, fvcFecha) Dim strCondicionPago As String = p.CondicionPago Dim grpAlb As DataColumn() = ProcessServer.ExecuteTask(Of DataGetGroupColumns, DataColumn())(AddressOf GetGroupColumns, New DataGetGroupColumns(dtLineas, enummcAgrupFactura.mcAlbaran), services) Dim grpClte As DataColumn() = ProcessServer.ExecuteTask(Of DataGetGroupColumns, DataColumn())(AddressOf GetGroupColumns, New DataGetGroupColumns(dtLineas, enummcAgrupFactura.mcCliente), services) Dim groupers(1) As GroupHelper groupers(enummcAgrupFactura.mcAlbaran) = New GroupHelper(grpAlb, oGrprUser) groupers(enummcAgrupFactura.mcCliente) = New GroupHelper(grpClte, oGrprUser) For Each rwLin As DataRow In dtLineas.Rows groupers(rwLin("AgrupFactura")).Group(rwLin) Next Return oGrprUser.Fras Else ApplicationService.GenerateError("No hay datos a Facturar. Revise sus Albaranes.") End If End Function 149/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis <Task()> Public Shared Function GetGroupColumns(ByVal data As DataGetGroupColumns, ByVal services As ServiceProvider) As DataColumn() Dim columns(8) As DataColumn columns(0) = data.Table.Columns("IDCliente") columns(1) = data.Table.Columns("IDFormaPago") columns(2) = data.Table.Columns("IDCondicionPago") columns(3) = data.Table.Columns("IDBancoPropio") columns(4) = data.Table.Columns("IdMoneda") columns(5) = data.Table.Columns("EDI") columns(6) = data.Table.Columns("IDDireccion") columns(7) = data.Table.Columns("IDDireccionFra") columns(8) = data.Table.Columns("IDClienteBanco") If data.Agrupacion = enummcAgrupFactura.mcAlbaran Then ReDim Preserve columns(9) columns(9) = data.Table.Columns("IDAlbaran") End If Return columns End Function Volver al Índice ProviderNeededData El objeto ProviderNeededData es elobjeto de Expertis que es un proveedor de Datos y nos permite de esta manera poder llevar a cabo la carga de información extra en un formulario de Expertis, cuando no queremos mostrar los datos en un Grid de Expertis o bien en algún objeto proveedor de Datos. El uso más general dado en Expertis para este objeto sería para mostrar datos de una entidad en un formulario pero en cajas de textos y labels en una pestaña. Para lograr esto hacemos uso de este tipo de objetos que puede cargarnos la información que necesitamos en los objetos que indiquemos, siendo información no contenido en la entidad principal del formulario ni en la vista u origen de datos del formulario principal. Para ello instanciamos en el formulario donde deseamos utilizar este objeto una instancia del mismo: Private NdData As ProviderNeededData En la carga del formulario llevaríamos a cargo la configuración del objeto ProviderNeededData: Private Sub Me_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load If Not Me.DesignMode Then LoadNedeedData() End If End Sub Private Sub LoadNedeedData() NdData = New ProviderNeededData NdData.Name = "Data" NdData.EntityName = "Entidad_Data" Dim s(0) As String s(0) = "IDClavePrimaria" NdData.PrimaryDataFields = s NdData.SecondaryDataFields = s NdData.RelationMode = RelationMode.ChildMode NdData.ViewName = "vFrmData" NdData.UpdateOrder = -1 Me.AddDataItem(NdData) End Sub Entre las propiedades principales que posee y que tenemos que configurar estarían: Name Nombre interno EntityName Nombre de entidad de la que deseamos manejar los datos. PrimaryDataFields / SecondaryDataFields Nombre de los campos de relación entre el objeto ProviderNeededData y el formulario actual. RelationMode 150/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Modo de relación del objeto ProviderNeededData con el formulario principal. ViewName Nombre de la vista / table de Origen de datos del Objeto ProviderNeededData. UpdateOrder Orden en la actualización y manejo de datos del ProviderNeededData con respecto a otros objetos ProviderNeededData que hubieran en el formulario. Por defecto: -1. Fijemonos que la última línea es para agregar nuestro ProviderNeededData al origen de datos del formulario. De esta manera en la solicitud de movimiento de registros en el formulario se encargará el motor de llevar a cabo la carga automática de los datos que queremos del ProviderNeededData. Esto se hace con el Me.AddDataItem. Una vez configurado el objeto pasaríamos a establecer los bindeos entre los controles del formulario y el control providerneededdata. Para esto necesitamos una variable local para controlar este bindeo se lleve a cabo solamente una vez en el formulario. De manera que sea solo la primera vez en la solicitud de moverse a un registro en el formulario. Private MakeBinding As Boolean Una vez declarada la variable pasamos a establecer el código de Bindeo en el movimiento de registro del formulario. Private Sub MntoObras_Navigated(ByVal sender As Object, ByVal e As Solmicro.Expertis.Engine.UI.NavigatedEventArgs) Handles MyBase.Navigated BindingData() End Sub Private Sub BindingData() If Not MakeBinding Then Me.AddBinding(Me.AdvClave, "Value", "IDClavePrimaria") Me.AddBinding(Me.TxtDescClave, "Text", "DescClavePrimaria") Me.AddBinding(Me.UlblDescEstado, "Text", "IDEstado") MakeBinding = True End If End Sub Private Sub AddBinding(ByVal control As Control, ByVal propertyName As String, ByVal dataMember As String) If (dataMember = "codtrabajo") Or (dataMember = "Desctrabajo") Then control.Enabled = False Else : control.Enabled = True End If control.DataBindings.Add(propertyName, Me.ndTrabajos, dataMember) End Sub Se puede observer que establecemos la unión entre un control, especificando el nombre de la propiedad a la que queremos bindear, el campo que establecemos en el tercer parámetro. Volver al Índice Login en Expertis para Ejecutables Externos Se puede llevar a cabo en el desarrollo de un ejecutable propio el llevar a cabo el logeo en expertis y mantener viva una sesión contra expertis. De esta manera podemos realizar ejecutables propios usando los datos de Expertis. Para esto tenemos a través de dos maneras: una sencilla de abrir simplemente la sesión sin configurar nada más y otra que nos permite especificar más parámetros. Para la primera manera sencilla lo que necesitamos sobre todo es tener configurado un fichero .config con el mismo nombre y extensión de nuestro ejecutable, a modo de como tiene el ejecutable de Expertis: Expertis.Engine.UI.Shell.exe.Config. Y la configuración de este fichero sería la misma que la de expertis, conteniendo todo el tema de la configuración de remoting. Con esto correctamente configurado y existente bastaría con que hiciéramos el siguiente comando en la carga del formulario: Private Sub Me_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load ExpertisApp.Open() End Sub Una vez abierta la sesión también lo único que tendríamos que tener en cuenta sería en cerrar esta sesión una vez que se cierre el programa. Para ello programaríamos lo siguiente: 151/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Private Sub Me_Disposed(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Disposed ExpertisApp.CloseSession() End Sub Para una mayor especificación y control de este logeo en expertis podríamos hacerlo a través de otra manera con el siguiente código: Private Sub Login() Dim Aut As New AuthenticationInfo Aut.Authentication = AuthenticationMode.ExpertisAuthentication Aut.UserName = "PARAMETRO_VUESTRO_USER" Aut.Pwd = "PARAMETRO_VUESTRO_PASSWORD" Dim ClsApp As New ApplicationService Dim Tok As TokenInfo = ClsApp.Login(Aut, "Nombre_Máquina") ExpertisApp.GetSessionDescriptor(SessionInfo.All) ExpertisApp.CheckBusinessVersion() System.Runtime.Remoting.Messaging.CallContext.SetData(SessionInformation.SessionSlot, New SessionInformation(Tok.Token)) End Sub Se explica el contenido de cada línea y lo necesario para llevar a cabo todo el sistema. Fijarse en todo este código que establecemos un Login para cuando se hace la apertura de nuestro ejecutable y tendremos un LogOut cuando se cierre la aplicación para el cierre de sesión y el liberar el Token. Volver al Índice Cambio de Base de Datos en MultiEmpresa En Expertis es posible cambiar la conexión actual de la base de datos para posicionarnos en otra base de datos y poder trabajar con ella. Este concepto es para poder llevar a cabo conceptos de MultiEmpresa que manejamos en Expertis. Para ello bastará que el proceso que queremos que se ejecute con otra base de datos de Expertis, se programe en una tarea de Negocio de Expertis. En dicha tarea tiene que tener obligatoriamente como primera línea de código la descrita en el código fuente a continuación. Con ello establecemos la conexión a otra base de datos que tiene que estar inventariada en el sistema de expertis en Bases de Datos. Hay que tener en cuenta que antes de cambiar la conexión lo que tenemos es que tratar de cerrar todas las transacciones pendientes anteriores de la conexión actual que tenemos. Para ello llevamos a cabo el comando AdminData.CommitTx() para realizar esto. Este comando lo tenemos detallado mas adelante en este apartado. <Task()> Public Shared Sub ChangeDataBase(ByVal data As DataTable, ByVal services As ServiceProvider) 'Obligatorio como primera instrucción de Negocio que llamemos sea la siguiente AdminData.CommitTx() AdminData.SetSessionConnection("Nombre_Base_Datos_Destino") 'Tu proceso en esa otra Base de Datos. For Each Dr As DataRow In data.Select '....... Next 'Al finalizar la tarea de negocio y irse de esta tarea el motor restablecerá la conexión de expertis con la anterior, sino podemos establecer la conexión de nuevo por la base de datos de origen AdminData.CommitTx() AdminData.SetSessionConnection("Nombre_Base_Datos_Origen") End Sub Una vez que acabe todo la tarea y se acabe la ejecución de la misma, el motor se encargará de volver a establecer la conexión originaria de expertis. Con este sistema asi podemos generar datos en otras bases de datos y cuando manejamos el concepto de MultiEmpresa. Volver al Índice Transacciones 152/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Tenemos diversas maneras en Expertis para llevar a cabo un control de los procesos que hagamos sean transaccionales o no, y en donde lo necesitemos. En primera instancia, si deseamos que cualquier comunicación desde un formulario de expertis, todo sea ya transaccional en las llamadas de este formulario con el negocio de la entidad asociada, sólo tenemos que activar la propiedad CreateTransaction del formulario. Con esto y como comentamos, cualquier comunicación desde el formulario con la entidad de expertis, se hará de forma transaccional. Otra manera que tenemos para llevar a cabo transacciones a nivel de listado de tareas, bien sea por listado de tareas de un Update o Delete de una entidad, o bien del listado de tareas de un proceso de expertis, disponemos de unas tareas específicas para llevar esto a cabo que serían las siguientes: ProcessServer.ExecuteTask(Of Object)(AddressOf Business.General.Comunes.BeginTransaction, Nothing, services) Con esta tarea abriríamos transacción donde quisiéramos y con dicha tarea la podemos agregar en cualquier listado de tareas de un Update o Delete o en listado de tareas de un proceso de expertis. ProcessServer.ExecuteTask(Of Boolean)(AddressOf Business.General.Comunes.CommitTransaction, False, services) Con esta tarea cerraríamos la última transacción abierta. De esta manera si abrimos por ejemplo 3 transacciones nos cerraría la 3º transacción última abierta. Esta tarea se puede usar en listado de procesos de expertis pero no podemos agregarla en listado de tareas de Update o de Delete. ProcessServer.ExecuteTask(Of Boolean)(AddressOf Business.General.Comunes.RollbackTransaction, False, services) Con esta tarea haríamos un deshacer la última transacción abierta. De esta manera si abrimos por ejemplo 3 transacciones nos desharían la 3º transacción última abierta. Esta tarea se puede usar en listado de procesos de expertis, pero no podemos agregarla en listado de tareas de Update o de Delete. NOTA: Hay que tener en cuenta que abriendo las transacciones en la capa de negocio, Éstas se cerrarán siempre 100% en cuanto abandonásemos la capa de negocio de Expertis. Esto es porque el Engine de expertis se encarga siempre que cuando se acabe la ejecución de expertis en capa de negocio y volver a presentación, se cierren las transacciones pendientes. Volver al Índice Filtrado Horizontal Descripción de Componente de Filtrado Horizontal Utilidad para disponer de funcionalidad de perfiles a un filtrado horizontal personalizable sobre los mantenimientos. Cuando hablamos de personalizable nos referimos a que se pueda definir/implementar el filtrado horizontal a aplicar sobre los mantenimientos en función de la entidad y programa. Creación de la Interfaz y descripción de los Componentes Para ello se ha definido el siguiente interfaz: Interface Profile Implements Solmicro.Expertis.Engine.IProfile Public Function GetProfileType(ByVal Entity As String) As ProfileType Implements GetProfileType Se define el tipo de filtro para cada entidad 153/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Public Function GetProfileFilter(ByVal Entity As String, ByVal IdUsuario As System.Guid) As ProfileFilter Implements GetProfileFilter Esta es la función donde hay que programar el filtrado para cada entidad. Los parámetros que recibe esta función son entidad y usuario ProfileType Enumerado que puede tomar los valores: SimpleProfile: tipo simple. ComplexProfile: tipo complejo. NoProfile: sin perfil. ProfileFilter Clase que representará el filtro del perfil asociado a la entidad y que se aplicará sobre registros asociados a la entidad. Se compone de los siguientes componentes: FilterType As ProfileType: es el tipo del filtro del perfil asociado a la entidad (Simple o complejo) SimpleFilter As IFilter: será el filtro del perfil asociado a la entidad en caso de que el tipo sea simple. ComplexFilter As ComplexFilter: será el filtro del perfil asociado a la entidad en caso de que el tipo sea complejo. ComplexFilter Filtro de perfil que podemos asociar cuando deseemos que sea de tipo complejo. Se compone de los siguientes componentes: Source As String: Vista que definirá el conjunto de registros asociados a la entidad que podrán ser visualizados. Dicha vista se cruzará con en los datos asociados a la entidad. LinkFields As Links: Campos del origen de datos asociado a la entidad y de la vista por los cuales se hará el cruce. WhereClause As IFilter: es donde realmente vamos a filtrar esa vista. Aquí le tendremos que establecer un objeto de tipo filtro. Structure Links Estructura con la cual se establece una relación entre los campos de la pantalla (indicados en el punto anterior) y los que devuelve la vista de filtrado.. FormFileds() As String: es donde se establece el campo o los campos del formulario que identifican de forma única al registro de la entidad. ProfileFields() As String: donde se identifica el campo o los campos que identifican de forma única el registro de la vista Ejemplo de Clase de Filtrado Horizontal: ProfileManager. Ejemplo de filtrado horizontal para el módulo de Recursos Humanos. En él se está generando para las entidades de RHOperario, Operario y RHOperarioContrato un tipo de filtrado complejo y para el resto de entidades no se hace control de filtrado horizontal. Para ello se usa el tipo NoProfile en la función de GetProfileType. Después en la función de GetProfileFilter se configura para las entidades de Operario y RHOperario, el usar la vista ProfileOperario unida con la tabla del entidad a través de los campos de IDOperario, filtrando por el IDUsuario actual. De esta manera en el acceso a estas entidades el usuario de expertis solo ve sus datos correspondientes. Para la siguiente entidad de RHOperarioContrato se hace lo mismo pero usando otra vista: ProfileOperarioContrato y definiendo como campos de unión los suyos necesarios: IDOpContrato. Configuración del Manager de Expertis para Filtrado Horizontal Hay que Completar y definir los siguientes parámetros en el manager de Expertis para el funcionamiento del Filtrado Horizontal. Para ello acudir a: Aplicación -> Configuración de Aplicación -> Descripción del Componente del Filtrado Horizontal 154/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis En el ensamblado figuraría el nombre de la dll donde va incluida la clase Profilemanager y en Clase iría el nombre completo de la clase (dentro del proyecto de negocio en el que se haya incluido). Volver al Índice Extensibilidad en Mensajería y Alertas de Expertis Introducción Utilidad para disponer de funcionalidad de perfiles a un filtrado horizontal personalizable sobre los mantenimientos. La idea es heredar de AlertExtensionBase y sobrescribir los métodos que te hagan falta (aquellos en los que no puedas hacer algo mediante el interfaz de diseño). Los métodos son: public function Recipients(ByVal args As AlertExtensionArgs) As datatable Añade destinatarios a la alerta (predeterminado null) public function MatchesCondition(ByVal args As AlertExtensionArgs) As boolean Comprueba si la alerta (insert, update, delete) cumple las condiciones (predeterminado true) public function TimedMatches(ByVal args As AlertExtensionArgs) As DataTable Devuelve los registros que cumplen la alerta temporal public function Message(ByVal args As AlertExtensionArgs) As string Compone el mensaje a enviar (pred. null). Si null, toma el mensaje del diseñador. public sub ExecuteAction(ByVal args As AlertExtensionArgs) Los parámetros que se reciben son () Public Class AlertExtensionArgs Public Alert As AlertBusiness Public Match As DataRowView Public RecordKey As String Public Trigger As AlertTrigger Public Schema As DataTable End Class ' ' ' ' ' El objeto alerta que se está comprobando El registro de datos que se está tratando Campos clave (no recuerdo bien) Detonante de la alerta (insert, update, delete, temporal…) Esto creo que no se usa mucho, esquema de BBDD del registro Esta clase hay que programarla en un Business 155/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Ejemplo Programación de una Alerta que salta cuando el precio de factura compra de un artículo es mayor que el precio estándar. Imports Solmicro.Expertis.Engine.BE.Alerts Public Class ExtensibilidadAlerta Inherits AlertExtensionBase Public Overrides Function MatchesCondition(ByVal args As Engine.BE.Alerts.AlertExtensionArgs) As Boolean Dim drv As DataRowView = args.Match If Length(drv.Row("IDArticulo")) > 0 Then Dim IDArticulo As String = drv.Row("IDArticulo") Dim dtArticulo As DataTable = New BE.DataEngine().Filter("tbMaestroArticulo", New StringFilterItem("IDArticulo", drv.Row("IDArticulo")), "") If dtArticulo.Rows.Count > 0 Then Return drv.Row("PrecioA") > dtArticulo.Rows(0)("PrecioEstandarA") End If End If Return False End Function Public Overrides Function Message(ByVal args As Engine.BE.Alerts.AlertExtensionArgs) As String Dim drv As DataRowView = args.Match Return ParseFormatString("El precio de última compra del Artículo {0} es mayor que el precio estándar", Quoted(drv.Row("IDArticulo"))) End Function End Class 5. PROYECTOS EXPERTIS Proyectos de Presentación Expertis.Application.ERP.ActualizacionAlbaranCompra 156/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Proyecto de Presentación que contiene los datos de Presentación de actualizaciones de Albaranes de Compra del Modulo de Compras Expertis.Application.ERP.ActualizacionAlbaranVenta Proyecto de Presentación que contiene los datos de Presentación de actualizaciones de Albaranes de Venta del Modulo de Ventas. Expertis.Application.ERP.Agrupaciones Proyecto de Presentación que contiene los datos de Presentación del Módulo de Agrupaciones. Expertis.Application.ERP.AlbaranCompra Proyecto de Presentación que contiene todo lo relacionado con los Albaranes de Compra. Expertis.Application.ERP.AlbaranVenta Proyecto de Presentación que contiene todo lo relacionado con los Albaranes de Venta. Expertis.Application.ERP.Almacenes Proyecto de Presentación que contiene todo lo relacionado con los Almacenes de Expertis. Expertis.Application.ERP.Alquiler Proyecto de Presentación que contiene todo lo relacionado con el módulo de Alquileres. Expertis.Application.ERP.AnalisisFoss Proyecto de Presentación de ventana de Analisis Foss de Módulo de Bodegas. Expertis.Application.ERP.AnalisisRiesgo Proyecto de Presentación de formularios de Analisis de Riesgo de Clientes para las ventas. Expertis.Application.ERP.Articulos Proyecto de Presentación de Formulario de Artículos y formularios relacionados como Tipos de Artículos. Expertis.Application.ERP.Aseguradora Proyecto de Presentación de Formulario de Aseguradoras. Expertis.Application.ERP.BancosPropios Proyecto de Presentación de Formulario principal de Expertis de Bancos Propios. Expertis.Application.ERP.Bodega Proyecto de Presentación de todos los formularios del Módulo de Bodegas. Expertis.Application.ERP.BodegaAnalisisFinca Proyecto de Presentación de formularios de Análisis de Fincas de Bodegas. Expertis.Application.ERP.Calendar Proyecto de Presentación de Herramienta de Calendarios de Expertis. Expertis.Application.ERP.Calibraciones Proyecto de Presentación de Formularios de Calibraciones de Maquinaria. Expertis.Application.ERP.Calidad 157/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Proyecto de Presentación de todos los formularios relacionados con el módulo de Calidad. Expertis.Application.ERP.Cargo Proyecto de Presentación de Formulario de Cargos de Clientes, Proveedores y Cuentas de CRM. Expertis.Application.ERP.Categoria Proyecto de Presentación de Formulario de Categorías. Expertis.Application.ERP.CausaRechazo Proyecto de Presentación de Formulario de Causas y Rechazos de Producción. Expertis.Application.ERP.CentroCoste Proyecto de Presentación de Formulario de Centros de Coste de Expertis. Expertis.Application.ERP.CentroGestion Proyecto de Presentación principal de Formulario de Centros de Gestión de Expertis. Expertis.Application.ERP.Centros Proyecto de Presentación de Formulario de Centros de Trabajo de Expertis. Expertis.Application.ERP.CFDisplay Proyecto de Presentación de Herramienta de visualización de datos que se compone con ERP.Visor. Expertis.Application.ERP.CIDisplay Proyecto de Presentación de Herramienta de visualización de recursos de Producción. Expertis.Application.ERP.CierreInventario Proyecto de Presentación de Formulario de Cierres de Inventario de Stocks de Expertis. Expertis.Application.ERP.CierreIVA Proyecto de Presentación de Formulario de Cierre de IVA de Expertis. Expertis.Application.ERP.Clientes Proyecto de Presentación de Mantenimiento de Clientes y formularios relacionados con Clientes. Expertis.Application.ERP.CobroCont Proyecto de Presentación de Cobros de Tesorería. Expertis.Application.ERP.CobroSinAg Proyecto de Presentación de formulario de Seguimiento y consulta de cobros. Expertis.Application.ERP.CommonClasses Proyecto de Presentación que aglutina la funcionalidad de muchos formularios y funcionalidad diversa de todo expertis. Expertis.Application.ERP.CompClteProv Proyecto de Presentación de Compensación de Cobros y Pagos. Expertis.Application.ERP.Concepto 158/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Proyecto de Presentación del mantenimiento de Conceptos de Facturas de Venta. Expertis.Application.ERP.CondicionEnvio Proyecto de Presentación de Maestro de Condiciones de Envio de Ventas. Expertis.Application.ERP.CondicionPago Proyecto de Presentación de Maestro de Condiciones de pago deFinanciero. Expertis.Application.ERP.Configurador Proyecto de Presentación del módulo de Configurador de producto de Expertis. Expertis.Application.ERP.ConsRiesgoClte Proyecto de Presentación de formulario de Consulta de Riesgo de Cliente en Ventas. Expertis.Application.ERP.ConsultaPC Proyecto de Presentación de consultas interactivas de Pedidos de Compra. Expertis.Application.ERP.ConsultaProyectos Proyecto de Presentación de consultas interactivas de Proyectos / Obras. Expertis.Application.ERP.ConsultaPV Proyecto de Presentación de consultas interactivas de Pedidos de Venta. Expertis.Application.ERP.Contador Proyecto de Presentación del Maestro de Contadores de Expertis. Expertis.Application.ERP.Contrato Proyecto de Presentación del Maestro de Contratos. Expertis.Application.ERP.ControlCaja Proyecto de Presentación del Módulo de TPV. Expertis.Application.ERP.ControlPrd Proyecto de Presentación de Herramienta Táctil de introducición de partes de trabajo de Producción. Expertis.Application.ERP.ControlPresencia Proyecto de Presentación de los diferentes Formularios para hacer entradas y salidas de Control de Presencia Expertis.Application.ERP.ConversionGenerica Proyecto de Presentación de Formularios de Conversiones Genéricas. Expertis.Application.ERP.CosteStd Proyecto de Presentación de formularios relacionado con el cálculo de Coste Estándar de Artículos. Expertis.Application.ERP.DatosEmpresa Proyecto de Presentación de los Datos Principales de la Empresa, tales como datos registrales, logos, etc… Expertis.Application.ERP.Departamento 159/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Proyecto de Presentación de mantenimiento de Departamentos relacionados con el Operario. Expertis.Application.ERP.DesajusteStock Proyecto de Presentación de mantenimientos de muestra de Desajustes de Stocks. Expertis.Application.ERP.DiaPago Proyecto de Presentación del Formulario de Días de Pago de condiciones económicas. Expertis.Application.ERP.DiarioContable Proyecto de Presentación que contiene todos los formularios relacionados con el módulo Financiero Expertis.Application.ERP.Disponibilidad Proyecto de Presentación con los diversos formularios de disponibilidades de artículos, materiales, … Expertis.Application.ERP.Empresa Proyecto de Presentación que contiene todos los formularios relacionados con el módulo de CRM Expertis.Application.ERP.Encuestas Proyecto de Presentación de Formulario de Encuestas de Marketing Expertis.Application.ERP.EntregasACuenta Proyecto de Presentación de formularios de Entregas a Cuenta de Clientes y Proveedores. Expertis.Application.ERP.EstadisticaCompras Proyecto de Presentación principal de formularios de Consulta Interactiva de Estadisticas de Compras Expertis.Application.ERP.EstadisticaRetencion Proyecto de Presentación de formularios de Consulta Interactiva de Estadisticas de Retenciones Expertis.Application.ERP.EstadisticaRetraso Proyecto de Presentación de formularios de Consulta Interactiva de Estadisticas de Retrasos Expertis.Application.ERP.EstadisticaVentas Proyecto de Presentación de formularios de Consulta Interactiva de Estadisticas de Ventas Expertis.Application.ERP.EstadoTarifa Proyecto de Presentación de mantenimiento de Estados de Tarifas Expertis.Application.ERP.EstrucGraf Proyecto de Presentación de Formulario de Representación gráfica de Estructura de Artículos. Expertis.Application.ERP.EtiRecepcion Proyecto de Presentación de mantenimiento de Etiquetas de Recepción de Pedidos. Expertis.Application.ERP.Expediciones Proyecto de Presentación de Expediciones de Ventas. Expertis.Application.ERP.FactElecCorreo 160/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Proyecto de Presentación que contiene toda la funcionalidad de Correo Electrónica y Facturación Electrónica Expertis.Application.ERP.FacturacionCompra Proyecto de Presentación del Proceso de Generación de Facturas de Compra. Expertis.Application.ERP.FacturacionVenta Proyecto de Presentación del Proceso de Generación de Facturas de Venta. Expertis.Application.ERP.FacturaCompra Proyecto de Presentación de Mantenimiento de Facturas de Compra. Expertis.Application.ERP.FacturaVenta Proyecto de Presentación de Mantenimiento de Facturas de Venta. Expertis.Application.ERP.FicheroDAA Proyecto de Presentación de Generación de Ficheros DAA de Módulo de Bodegas. Expertis.Application.ERP.FormaEnvio Proyecto de Presentación de Mantenimiento de Formas de Envío de Expertis. Expertis.Application.ERP.FormaPago Proyecto de Presentación de Mantenimiento de Formas de Pago de Expertis. Expertis.Application.ERP.Gasto Proyecto de Presentación de Mantenimiento de Gastos. Expertis.Application.ERP.GDProgramas Proyecto de Presentación de Módulo de Gestión Documental de Expertis. Expertis.Application.ERP.GeneracionFicheros Proyecto de Presentación de Módulo de Generación de Ficheros de la AEAT, XML, Facturae, … Expertis.Application.ERP.GestionContactos Proyecto de Presentación de Mantenimiento de Gestión de Contactos de Expertis. Expertis.Application.ERP.GestionEDI Proyecto de Presentación de Módulo de Generación de Ficheros EDI de Expertis. Expertis.Application.ERP.GlobalActions Proyecto de Presentación que contiene todas las Acciones Globales definidas en Expertis. Expertis.Application.ERP.GlobalActionsOffice Proyecto de Presentación que contiene todas las Acciones Globales de Office Definidas en Expertis. Expertis.Application.ERP.Graphics Proyecto de Presentación que contiene todo lo relacionado con Gráficos de Expertis y Cuadros de Mando. Expertis.Application.ERP.Help 161/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Proyecto de Presentación que contiene la ayuda de Expertis que se agrega a la barra de herramientas Expertis.Application.ERP.Hora Proyecto de Presentación de Mantenimiento de Horas de Expertis. Expertis.Application.ERP.Idioma Proyecto de Presentación de Mantenimiento de Idiomas de Expertis. Expertis.Application.ERP.ImportacionDatos Proyecto de Presentación de Módulo de Importación de Datos de Expertis. Expertis.Application.ERP.ImpresionAlbaranVenta Proyecto de Presentación de formularios relacionados con las Impresiones de Albaranes de Venta. Expertis.Application.ERP.ImpresionFacturasVenta Proyecto de Presentación de formularios relacionados con las impresiones de Facturas de Venta. Expertis.Application.ERP.ImpresionPedidoCompra Proyecto de Presentación de formularios relacionados con las Impresiones de Pedidos de Compras. Expertis.Application.ERP.Incidencia Proyecto de Presentación de Incidencias de Calidad de Expertis. Expertis.Application.ERP.IncidenciaAlquiler Proyecto de Presentación de Incidencias relacionadas con el Módulo de Alquiler. Expertis.Application.ERP.InformeTesoreria Proyecto de Presentación de Informes relacionados con el Módulo de Tesorería. Expertis.Application.ERP.Inmovilizado Proyecto de Presentación de Módulo de Inmovilizado de Expertis de Elementos amortizables, amortizaciones, etc… Expertis.Application.ERP.Intrastat Proyecto de Presentación de formularios de Intrastat de Ventas y Compras. Expertis.Application.ERP.IvaCompra Proyecto de Presentación de formularios relacionados con la Declaración de IVA de Compra. Expertis.Application.ERP.IvaVenta Proyecto de Presentación de formularios relacionados con la Declaración de IVA de Venta. Expertis.Application.ERP.LecturaContAlquiler Proyecto de Presentación de mantenimiento de Lectura de Contadores de Maquinaria de Alquiler. Expertis.Application.ERP.LiquidacionRepresentante Proyecto de Presentación de formularios de Liquidaciones de Ventas de Representantes. Expertis.Application.ERP.Mailing 162/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Proyecto de Presentación de formularios de Generación de Etiquetas de clientes y proveedores. Expertis.Application.ERP.Mercado Proyecto de Presentación de Mantenimiento de Mercados usado en clientes y proveedores Expertis.Application.ERP.MmtoStocks Proyecto de Presentación de formularios relacionados con la Administración y Consulta de Stocks de Expertis. Expertis.Application.ERP.MntoActivo Proyecto de Presentación de formularios de Activos de Módulo de Alquileres – Maquinarias. Expertis.Application.ERP.MntoMaestro Proyecto de Presentación de mantenimiento Correctivo – Preventivo GMAO de Expertis. Expertis.Application.ERP.ModosTransporte Proyecto de Presentación de formularios de Modos de Transporte de Envíos de Venta. Expertis.Application.ERP.Moneda Proyecto de Presentación de mantenimiento principal de Monedas de Expertis. Expertis.Application.ERP.ObraPresup Proyecto de Presentación de formularios de Módulo de Presupuestos de Proyectos / Obras. Expertis.Application.ERP.ObraPromo Proyecto de Presentación de formularios de Módulo de Obras Promotoras. Expertis.Application.ERP.Obras Proyecto de Presentación de formularios de Módulo de Proyectos / Obras. Expertis.Application.ERP.Observacion Proyecto de Presentación de formulario de Mantenimiento de Observaciones de Expertis. Expertis.Application.ERP.OfertaComercial Proyecto de Presentación de formularios de Módulo Comercial de Expertis. Expertis.Application.ERP.OfertaCompra Proyecto de Presentación de formularios de Ofertas de Módulo de Compras. Expertis.Application.ERP.Oficio Proyecto de Presentación de mantenimiento de Oficios de Personal de Expertis. Expertis.Application.ERP.Operaciones Proyecto de Presentación de Operaciones de Módulo de Producción. Expertis.Application.ERP.Operario Proyecto de Presentación de formulario principal de Mantenimiento de Operarios de Expertis. Expertis.Application.ERP.OrdenFabricacion 163/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Proyecto de Presentación de formularios de Moódulo de Producción de Expertis. Expertis.Application.ERP.PagoCont Proyecto de Presentación de formularios relacionados con Pagos del Módulo Financiero Expertis.Application.ERP.Pais Proyecto de Presentación de formulario Principal de Mantenimiento de Paises de Expertis. Expertis.Application.ERP.Parametro Proyecto de Presentación de formularios de Mantenimientos de Parámetros de Expertis. Expertis.Application.ERP.PartidaEstadistica Proyecto de Presentación de formularios usados para las Declaraciones de iva intrastat. Expertis.Application.ERP.PedidoCompra Proyecto de Presentación de Mantenimiento de Pedidos de Compra de Expertis. Expertis.Application.ERP.PedidoVenta Proyecto de Presentación de Mantenimiento de Pedidos de Venta de Expertis. Expertis.Application.ERP.PlanifCompra Proyecto de Presentación de formularios de Módulo de Planificación de Compras. Expertis.Application.ERP.PlanificadorRecursos Proyecto de Presentación de formularios de Planificador de Recursos de Producción / Obras / … Expertis.Application.ERP.PlanifProduccion Proyecto de Presentación de formularios de Módulo de Planificación de Producción. Expertis.Application.ERP.PrepararExp Proyecto de Presentación de formularios de Preparación de Expediciones de Ventas. Expertis.Application.ERP.Presupuesto Proyecto de Presentación de Módulo de Presupuestos Comerciales de Expertis. Expertis.Application.ERP.Prevision Proyecto de Presentación de Módulo de Previsiones de Ventas de Expertis. Expertis.Application.ERP.Programa Proyecto de Presentación de Módulo de Programas de Venta de Expertis. Expertis.Application.ERP.ProgramaCompra Proyecto de Presentación de Módulo de Programas de Compra de Expertis. Expertis.Application.ERP.Promocion Proyecto de Presentación de formularios de Mantenimiento de Promociones de Ventas. Expertis.Application.ERP.PromocionCurso 164/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Proyecto de Presentación de formularios de Mantenimiento de Promociones de Ventas en Curso. Expertis.Application.ERP.Proveedores Proyecto de Presentación principal del Mantenimiento de Proveedores de Expertis. Expertis.Application.ERP.PuntoVerde Proyecto de Presentación principal de Mantenimiento de Punto Verde de reciclajes. Expertis.Application.ERP.RecepcionPedidos Proyecto de Presentación principal de Recepción de Pedidos de Compras. Expertis.Application.ERP.Representante Proyecto de Presentación principal de Mantenimiento de Representantes de clientes de ventas. Expertis.Application.ERP.RH Proyecto de Presentación que contiene todos los formularios del móulo de Recursos Humanos. Expertis.Application.ERP.Secciones Proyecto de Presentación principal de Mantenimiento de Secciones de Expertis. Expertis.Application.ERP.SimulacionTesoreria Proyecto de Presentación de formularios de Situación de Cartera de bancos a futuro. Expertis.Application.ERP.SituacionBancos Proyecto de Presentación de Formularios de Situación de nuestros bancos y saldos. Expertis.Application.ERP.SolicitudCompra Proyecto de Presentación principal de Mantenimiento de Solicitudes de Compras. Expertis.Application.ERP.Subcontratacion Proyecto de Presentación de formularios relacionados con la subcontratación de compras. Expertis.Application.ERP.Tarifa Proyecto de Presentación principal de Tarifas de Expertis. Expertis.Application.ERP.TarifaCurso Proyecto de Presentación principal de Tarifas en Curso de Expertis. Expertis.Application.ERP.Tasa Proyecto de Presentación principal del Mantenimiento de Tasas. Expertis.Application.ERP.TesoreriaContabilidad Proyecto de Presentación de Formularios de Contabilidad del Módulo Financiero - Tesorería Expertis.Application.ERP.TesoreriaPorBanco Proyecto de Presentación de Formulario de Estado de Bancos Propios en Periodos. Expertis.Application.ERP.Tipos 165/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Proyecto de Presentación de formularios de mantenimientos de Tipos de Expertis. Expertis.Application.ERP.TrazabilidadFactura Proyecto de Presentación de formularios relacionados con la Trazabilidad de Facturas Compras / Ventas Expertis.Application.ERP.UDMedida Proyecto de Presentación de Mantenimiento principal de Unidades de Medidas de Expertis. Expertis.Application.ERP.UsoMaquinaria Proyecto de Presentación de Mantenimiento principal de Usos de Maquinaria de Expertis. Expertis.Application.ERP.Varios Proyecto de Presentación de Mantenimiento principal de Formulario de Varios de Expertis. Expertis.Application.ERP.Vendedor Proyecto de Presentación de Mantenimiento principal de Formulario de Vendedores de Expertis. Expertis.Application.ERP.VisorInmuebles Proyecto de Presentación de formularios relacionados con el Visor de Inmuebles. Expertis.Application.ERP.VisorOFs Proyecto de Presentación de formularios relacionados con el Visor de Ordenes de Fabricación. Expertis.Application.ERP.Zona Proyecto de Presentación de Mantenimiento principal de Zonas de Expertis. Volver al Índice Proyectos de Negocio Expertis.Business.BC3 Proyecto de Negocio sobre el fichero BC3 en Presupuestos del Módulo de Proyectos. Expertis.Business.Bodega Proyecto de Negocio que contiene todo lo relacionado con el módulo de Bodegas de Expertis. Expertis.Business.BusinessEnum Proyecto de Negocio que contiene todos los enumerados de Expertis. Expertis.Business.Calidad Proyecto de Negocio que contiene todo lo relacionado con el módulo de Calidad de Expertis. Expertis.Business.Comercial Proyecto de Negocio que contiene todo lo relacionado con las Ofertas Comerciales de Expertis. Expertis.Business.Compra Proyecto de Negocio que contiene todo lo relacionado con las Ofertas, Solicitudes y Contratos de Compra de Expertis. Expertis.Business.Configurador Proyecto de Negocio que contiene todo lo relacionado con el Configurador de Producto de Expertis. 166/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Expertis.Business.ControlPresencia Proyecto de negocio que contiene todo lo relacionado con la Herramienta de Control de Presencia de Expertis. Expertis.Business.CRM Proyecto de Negocio que contiene todo lo relacionado con el módulo de CRM – Empresa de Expertis. Expertis.Business.EDI Proyecto de Negocio que contiene todo lo relacionado con el Módulo de Ficheros de EDICOM de Expertis. Expertis.Business.Ficheros Proyecto de Negocio que contiene todo lo relacionado con la generación de ficheros planos de hacienda, fichero Facturae, ficheros XML de Bodegas, etc…. Expertis.Business.Financiero Proyecto de Negocio que contiene todo lo relacionado con el módulo Financiero de Expertis: Contabilizaciones, plantillas, diario contable, etc… Expertis.Business.GD Proyecto de Negocio que contiene todo el sistema de Gestión Documental de Expertis. Expertis.Business.General Proyecto de Negocio que contiene toda una serie de clases generales de uso en todos los módulos de negocio de Expertis y funcionalidades generales de Expertis. Expertis.Business.Help Proyecto de Negocio que contiene todo lo relacionado con la Ayuda de Expertis del menú principal. Expertis.Business.ImportacionDatos Proyecto de Negocio que contiene todo lo del módulo de Importación de Datos del CRM. Expertis.Business.Mnto Proyecto de Negocio que contiene todo lo relacionado con el módulo de Correctivo / Preventivo GMAO de Expertis. Expertis.Business.Negocio Proyecto de Negocio general que contiene la gran mayoría de entidades y funcionalidades de Expertis. Sobre todo se encuentran los procesos de facturaciones, albaranar, etc… de los módulos de ventas y compras de expertis, entre otros… Expertis.Business.Obra Proyecto de Negocio que contiene todo lo relacionado con el Módulo de Proyectos de Expertis, de Presupuestos de Expertis y de Promotoras. Expertis.Business.Planificacion Proyecto de Negocio que contiene todo lo relacionado con la planificación MRP de Compras y la Planificación MRP de Producción. Expertis.Business.PlanificadorRecursos Proyecto de Negocio para la herramienta del Planificador general de recursos usado en varios puntos de Expertis. Expertis.Business.Produccion Proyecto de Negocio que contiene todo lo relacionado con el módulo de Producción / Fabricación. 167/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Expertis.Business.Promo Proyecto de Negocio que contiene todo lo relacionado con las promotoras de Expertis. Expertis.Business.RH Proyecto de Negocio que contiene todo lo relacionado con el Módulo de Recursos Humanos de Expertis. Expertis.Business.TPV Proyecto de Negocio que contiene todo lo relacionado con el Módulo de TPV de Expertis. Expertis.Business.Visor Proyecto de Negocio que contiene todo lo relacionado con el visor de recursos, fincas, etc… de Expertis. Volver al Índice Proyectos de Motor Expertis.Engine.BE.BusinessEngine Contiene los elementos básicos para la ejecución de aplicaciones construidas con (EE) Expertis.Engine.DAL Contiene los elementos de acceso a datos independientes del origen de datos. El componente principal de este ensamblado es Solmicro.Expertis.Engine.DAL.AdminData, que encapsula toda la lógica de lectura y actualización de datos. Expertis.Engine.Global Es un ensamblado que contiene utilidades y elementos comunes tanto para la capa de presentación como para la capa de negocio. Expertis.Engine.License Proyecto de motor que se encarga de la licencia del Expertis que se ejecuta. Expertis.Engine.SqlDAL / Expertis.Engine.ODPNetDAL Son las implementaciones de los proveedores de datos específicos para Sql Server y Oracle respectivamente. Básicamente contienen una clase que implementa la interfaz Solmicro.Expertis.Engine.DAL.IAdminData, que define los métodos necesarios que debiera implementar un proveedor de datos para (EE) Expertis.Engine.UI.CommonClasses Contiene las plantillas de formularios para aplicaciones construidas sobre (EE) Expertis.Engine.UI.Design Proyecto de motor necesaria solo en el Bin de Expertis de un desarrollador. No es necesario en un Bin de Cliente final. Funciona conjuntamente con el Expertis.Designer. Expertis.Engine.UI.Resources Contiene exclusivamente iconos y texto propios de (EE). Expertis.Engine.UI.WinControls Contiene todos los controles gráficos empleados por (EE), sobre los cuales se ha implementado las características necesarias para su correcta integración con el resto de componentes de (EE), así como un conjunto de reglas estéticas unificadas. Contiene también la clase Solmicro.Expertis.Engine.UI.ExpertisApp que proporciona métodos para configurar y lanzar el entorno de ejecución de cualquier aplicación construida con (EE), así como métodos de interacción con la capa de negocio útiles para los desarrolladores. Entre las tareas importantes que realiza esta clase, 168/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis está la configuración de la aplicación para que funcione correctamente de forma distribuida, esto es, la configuración de Remoting Volver al Índice 169/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis 6. VARIOS Objeto DataTable Para el objeto DataTable en su uso en Expertis, tendremos que tener claro y muy presente siempre los estados en los que vayan los Rows que componen el DataTable de cara a cómo funcionen luego con los procesos de una entidad. Para ello los DataRows poseen una propiedad llamada: RowState que describe el estado en el que se encuentra una DataRow. También tenemos el método GetChanges de un DataTable y pudiendo especificar qué tipo de estados para obtener un DataTable con los cambios exactos del tipo que queramos y comprobar también de esta manera si un DataTable posee cambios del tipo que le digamos. Para añadir nuevos DataRows a un DataTable existente tenemos varias formas: - Método Normal Por el procedimiento normal lo que haríamos sería generar un DataRow con la estructura del DataTable al que va a ser agregado y añadirlo dentro de la colección de Rows del DataTable. Dim DtNew As New DataTable Dim DrNew As DataRow = DtNew.NewRow DrNew("IDClave") = "00" DrNew("DescClave") = "Prueba" DtNew.Rows.Add(DrNew) - Método Normal con ItemArray Por el procedimiento normal con ItemArray podríamos agregar un DataRow perteneciente a otro DataTable y agregarlo como nuevo al Datatable nuestro de destino. Los dos DataTables tienen que coincidir en estructura de datos, tanto en número de columnas como en el propio orden de las columnas. Dim DtOrigen As New DataTable Dim DtDestino As New DataTable DtDestino.Rows.Add(DtOrigen.Rows(0).ItemArray) - Método ImportRow Método de un DataTable el cual nos permite importar por completo un DataRow existente en un DataTable, respetándonos de ese DataTable tanto la estructura como los datos y sobre todo el RowState de ese DataRow en concreto. Dim DtOrigen As New DataTable Dim DtDestino As New DataTable DtDestino.ImportRow(DtOrigen.Rows(0)) - Método LoadDataRow Método de un DataTable el cual nos permite actualizar la información de un DataRow en un DataTable existente y que contenga ya ese DataRow para llevar a cabo la actualización. Si dicho DataRow no existiese lo agregaría como nuevo en nuestro DataTable. Dim DtOrigen As New DataTable Dim DtDestino As New DataTable DtDestino.LoadDataRow(DtOrigen.Rows(0).ItemArray, True) Volver al Índice Modificadores a Métodos Para ver una enumeración de los diferentes atributos que posee un proceso o función ver la ayuda de msdn de Microsoft. http://msdn.microsoft.com/es-es/library/sect4ck6(v=VS.90).aspx Volver al Índice 170/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Atributo Shared Para el atributo Shared y especificaciones de este tipo de atributo ver la ayuda de msdn de Microsoft. http://msdn.microsoft.com/es-es/library/zc2b427x(v=VS.90).aspx Nosotros en Expertis usamos este atributo para todas las tareas de Expertis, ya sean tareas que pertenecen a procesos o bien tareas que son públicas. Es obligatorio el uso de este atributo para las tareas de Expertis. Todo aquello que no sea una tarea y sea de tipo público en una clase de negocio no puede llevar el atributo Shared o bien tendremos errores en remoting. Volver al Índice Genéricos Los genéricos permiten personalizar un método, clase o interfaz para el tipo de datos preciso sobre el que actúa. Un sitio en el que se utiliza es en las clases para el cacheo en el ServiceProvider. La clase EntityInfoCache(en Expertis.Busines.General) está preparada para trabajar con genéricos, lo cual nos permite decir el tipo de datos que va a contener. Dim Clientes As EntityInfoCache(Of ClienteInfo) = services.GetService(Of EntityInfoCache(Of ClienteInfo))() Si no tuviéramos los genéricos, tendríamos que haber creado un clase que herede de EntityInfoCache por cada clase que quisiéramos cachear (ClienteInfoCache, ProveedoreInfoCache,……) http://msdn.microsoft.com/es-es/library/w256ka79.aspx Volver al Índice ? Atributo Nulo en Variables Para que las variables que definimos en expertis (sean del tipo que sean) se puede establecer el atributo final con ? para remarcar que se desea que esa variable se instancie de base como nothing en contenido. Esto es visible y utlizado sobre todo cuando queremos que variables de tipo numérico no cojan como valor por defecto en su definición el 0.Por circunstancias del desarrollo y control del desarrollo vemos que no queremos que las variables vengan con un 0 por defecto y mejor con un valor a nothing. Private mAplicarAnalitica As Boolean? Uno de los tipos de variables que no admiten este uso del atributo nulo sería el String con este tipo de variables nos daría error. Volver al Índice Componente BackgroundWorker Elemento de Visual Studio 2008 del Framework 2.0 en adelante. Nos permite a través de la configuración de un objeto más visual, la posibilidad de ejecutar procesos en otros hilos. De esta manera podremos seguir teniendo la ejecución principal del programa y ejecutar otro proceso en otro hilo. Esto surge por necesidades de ir ejecutando actualizaciones en alguna ventana de estado, o log o barra de progreso. Para agregar este control, lo tenemos en el Cuadro de Herramientas del Visual Studio, sección de Componentes: 171/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis El Resultado que veríamos de agregar este control a nuestro formulario lo veríamos en la sección de objetos de formulario de la parte de abajo dentro del Visual Studio. Propiedades / Eventos /Métodos Propiedades principales: o Tiempo de Diseño: WorkerReportsProgress: propiedad para indicar si el control irá reportando el progreso del avance del proceso que se está ejecutando en este hilo. Esta propiedad sobre todo lo que provocaría es que haría caso del método ReportProgress y de lo que programemos en el evento ProgressChanged. WorkerSupportsCancellation: propiedad en la que especificamos si el control permite cancelación por parte del usuario. Esto sería que haría caso del método CancelAsync que podemos usar en el control. 172/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis o Tiempo de Ejecución: IsBusy: propiedad que nos indica si está realmente en ejecución el proceso asíncrono que hemos mandado o bien está parado. If BgWork.IsBusy Then 'Ejecución de Proceso End If CancellationPending: propiedad que nos indica si se ha llevado a cabo cancelación por parte del usuario y está pendiente de llevarla a cabo. Para esto sería si hemos ejecutado el método CancelAsync If BgWork.CancellationPending Then 'Ejecución de Proceso End If Eventos principales: o DoWork: evento en el que programaremos la ejecución del proceso que deseamos en ese otro hilo de ejecución. Este evento responderá a la llamada del método RunWorkerAsync donde lo hagamos en nuestro código. '2º.- Validar si hay Facturas sin Vencimientos If DescuadreVencimientos(e.Argument) Then BlnError = True BgWork.ReportProgress(20) System.Threading.Thread.Sleep(500) Podemos observer en este código de ejemplo como en el evento DoWork usamos de la variable e.Argument para recoger el argumento que enviamos en el método RunWorkerAsync (en este caso un DataTable). o ProgressChanged: evento que podemos ya reportar esos status, pasos, log, barra de progreso que tengamos para representar la ejecución de nuestro proceso en otro hilo. Este evento responderá a la llamada en el código que hagamos al método ReportProgress. Select Case e.ProgressPercentage Case 10 MFrmProgress.LblInfo.Text = "Verificando Vencimientos..." MFrmProgress.UIPrgProgreso.Value = 10 End Select Como se puede ver en el código de ejemplo controlamos el valor del porcentaje reportado a través de la variable e.ProgressPercentage que habríamos enviado y con lo cual hacer las respectivas actualizaciones que necesitemos. o RunWorkerCompleted: evento que se llamará una vez se haya completado todo el proceso del backgroundworker, en el que podremos observar si la ejecución fue correcta, o se canceló o bien ocurrió algún error. If e.Cancelled Then 'Se canceló el proceso ElseIf Not e.Error Is Nothing Then 'Se devolvió un error 173/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Else Dim BlnCorrecto As Boolean = e.Result End If Dentro de la variable e de este evento dispondremos de 3 propiedades para controlar los estados anteriormente comentados siendo: Cancelled (Si se canceló la ejecución), Error (se terminó la ejecución por causa de un error) y Result (Resultado final correcto devuelto por nuestro proceso y el DoWork). Métodos principales: o CancelAsync: método por el que podemos cancelar la ejecución del proceso del backgroundworker. Esto provocaría que se ejecute el evento RunWorkerCompleted. BgWork.CancelAsync() o RunWorkerAsync: método para comenzar la ejecución programada para el backgroundworker en el evento DoWork. Podremos pasar un parámetro de entrada al método para cierta información que deseemos enviar al evento DoWork. BgWork.RunWorkerAsync(DtGrid) Se puede observar que en la llamada pasamos un DataTable ya que es lo que necesitamos luego en el evento DoWork para manejar. o ReportProgress: método por el cual podemos ir reportando el porcentaje en entero del progreso total de nuestro proceso. Este método provocaría que s ejecute el evento ProgressChanged. BgWork.ReportProgress(40) Información de MSDN de BackgroundWorker: http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker(v=vs.90).aspx Volver al Índice LINQ To SQL La tecnología de Linq To SQL es una tecnología que aparece tímidamente por Expertis en esta versión actual. De momento se han implementado en ciertos apartados de Expertis, pero su uso todavía no es generalizado. Pero como en algunos casos podemos encontrarnos este tipo de metodología convendría saber algo acerca de este Linq. Os ponemos a vuestra disposición la información que nos aporta Microsoft sobre esto: http://msdn.microsoft.com/en-us/library/bb308959 Volver al Índice 174/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis 7. REMOTING Consideraciones La comunicación remota en Expertis se hace a través del modelo SingleCall. Esto significa que puedo tener todas las instancias que quiera en el servidor (similar a COM+), ya que es el servidor el que controla la vida del objeto. Los objetos del servidor sólo viven durante la ejecución de un proceso. CLIENTE Dim A as new MiClase A.M1 A.M2 SERVIDOR objeto A Los métodos M1 y M2, puede que sean servidor por 2 instancias distintas en el servidor. Todo objeto que sea invocable remotamente debe heredar de MarshallByRef (En Expertis, deben heredar de ContextBoundObject que a su vez hereda de MarshallByref, que junto con el atributo Transactional aseguran en control de transacciones de Expertis). Las conexiones a la BBDD duran como mucho lo que dura la ejecución de un método. La DAL cuando requiere una conexión, la crea y se la asocia a la sesión (en su caché). El Transactional lo que hace es “poner una barrera” que hace que cuando termine el proceso mire si se ha hecho o no el Commit o Rollback. Si no lo ponemos, podemos dejar sesiones abiertas en la caché de sesiones de la DAL o que cerremos antes de tiempo la conexión. Tipos de Clases: Tradicionales. Remotas (modelo Single Call). Sin estado, salvo excepciones. Viajeras (serializables). Con estado. No pueden tener código de acceso a datos, porque van a acceder a la DAL desde presentación. - Hay que tener en cuenta, que si se hace referencia desde presentación a un objeto remoto, se ejecutará el código en el cliente. ¿Por qué tiene que estar la dll de Negocio en el puesto cliente? Por qué en tiempo de ejecución el cliente debe poder saber cuál es el interfaz de la clase remota, ya que realmente no tendremos un objeto, sino un proxy. No se puede parametrizar un tipo de objeto de entrada de una tarea de negocio que no sea Serializable. El viaje entre la capa de negocio y la de presentación no está permitido para muchos tipos de objetos y esto es marcado por Microsoft. Enviar como tipo de objeto desde presentación a negocio un DataRow no está permitido ya que esto nos provocaría error de serialización en remoting, ya que el DataRow no es un objeto serializable. Marcar como Serializable las clases que enviamos como objetos de entrada de una tarea pública de negocio. No se puede enviar DataRow en un objeto Clase, aun estando marcado el objeto clase como Serializable. Las entidades dadas de alta en el manager tienen que tener la marca de Publicar para que se publiquen efectivamente en remoting. Al usar el sistema de tareas de Expertis no hace falta si tenemos una Clase de Negocio que no es entidad y que alberga tareas públicas el definirla con la Herencia con ContextBoundObject. Esto solo haría falta si tuviésemos una clase de Negocio de Expertis con Procesos o Funciones públicas pero sin ser tareas. Para ello necesitaríamos de establecer la herencia con ContextBoundObject y con el atributo Transactional. Volver al Índice Errores Comunes Errores más comunes y frecuentes que nos mostrará en Expertis si hemos hecho una programación inadecuada para Remoting: - El objeto XX no está marcado como Serializable. Errores derivados haciendo referencia a algo de la serialización. No se encuentra el fichero System.Config de Expertis. Volver al Índice 175/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Configuración de Remoting de puesto Cliente y Servidor Para llevar a cabo la configuración del Remoting en nuestro ámbito tendríamos que tener en cuenta las siguientes consideraciones: Parte Servidor - Debemos instalar el programa Expertis.Host de la versión 5.0 en el equipo servidor de nuestra red interna. Cuando instalamos este Expertis.Host debemos elegir un directorio en donde hayamos alojado previamente el Bin de Expertis con el que trabajará el servidor. Este Bin de la parte Servidor es el que tenemos que tener presente el fichero System.Config, que es el que se usará para conectarse a la Base de Datos de Sistema de Expertis dónde coger toda la información relacionada con Expertis: - En este fichero podemos observar las propiedades de la conexión contra la base de datos de sistema. Para ello especificaremos: o Data Source = Nombre del servidor donde se encuentra la BD de Sistema. o Initial Catalog = Nombre de la BD de Sistema. o User / Pass = Datos del usuario para llevar a cabo la conexión contra la BD. - En el servidor el fichero de Expertis.Engine.UI.Shell.Exe.Config no tendría uso y no lo usaría la parte servidor. Parte Cliente - En el cliente dispondremos del mismo bin de Expertis que hubiésemos alojado en la parte Servidor pero sin que esté presente el fichero System.config. Este fichero se ha de quitar en el Bin de la parte de cliente. En el fichero Expertis.Engine.UI.Shell.Exe.Config es donde especificaremos los datos de conexión del cliente con el servidor de Remoting: 176/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis o o o o o o Remoting Mode = parámetro con diversas opciones, que sobre todo nos interesa para poder activar /desactivar (Automatic / Disabled) que el cliente se conecta por Remoting y no en modo local. Remoting Channel = parámetro que nos permite especificar el tipo de canal usado del Remoting. Generalmente si usamos el servicio de Expertis.Host será canal tcp. Y si usamos como Remoting el IIS usaremos el canal http o https. (Por defecto en blanco será TCP). Remoting Host = Nombre el servidor donde se encuentra nuestro servidor de Remoting. Remoting Port = Número de puerto por el que hemos configurado que se comuniquen nuestro cliente con el servidor. RemotingCompression = Opción para habilitar / deshabilitar que los paquetes de comunicación entre el servidor y el cliente vayan comprimidos y con ello para aumentar la velocidad de transmisión de los paquetes. ExceptionDetails opción para habilitar / deshabilitar que en caso de error no controlado en expertis, nos aparezca un error con un mayor nivel de detalle. Esta opción la damos por defecto a False para que en una primera instancia de error no salga un error con tanto detalle que asuste al usuario final y no entiendo nada. Cuando en nuestro desarrollo ocurra algo y el error que nos comentan son sin esta opción de detalle, y efectivamente la información es escasa, Podemos activar esta opción para ver en ese caso un mayor nivel de detalle y así visualizar más rápidamente el error dado. Volver al Índice 177/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis 8. INFORMES Introducción a Informes en Expertis El desarrollo que se hace con un informe viene condicionado en principio por la forma en que se va a abrir. Existen dos formas de abrir un informe, una, automatizada, que consiste en vincular el informe a un programa y abrirlo desde el comando de impresión de la barra de comandos de un mantenimiento, y dos, personalizada, utilizando la clase Report de Expertis. Desde el punto de vista de programación las diferencias fundamentales que hay entre las dos formas son: - La forma de interactuar y de intercambiar información con el informe. Si el informe se abre por vínculo con un programa la manera de pasar información al informe se basa en programar ciertos eventos de las clases de mantenimiento. Si el informe se abre por código no se lanza ningún evento, en su lugar se dispone de la clase Report de Expertis para programar. - La automatización de ciertas propiedades y el tipo de informe. Si el informe se abre por vínculo con un programa, el tipo de informe juega un papel importante, ya que permite al motor de Expertis establecer de forma automática una serie de propiedades, por ejemplo los criterios de selección o el origen de datos. Si el informe se abre por código el tipo del informe no tiene relevancia y todas las propiedades las debe establecer el programador. En cualquier caso el informe tiene que ser reconocido por Expertis, y para ello es necesario introducir cierta información en algunas tablas de la base de datos de sistema. En lo referente a los proyectos de presentación no hay que incluir ninguna referencia de Crystal Reports. En los puestos cliente finales es necesario instalar el runtime de Crystal. Dentro del paquete de distribución de Expertis se incluye un instalador (CrystalReportsXI.msi) que realiza esta función. Volver al Índice Tipos de Informes 1. Registro Actual El motor de informes construye un filtro con el valor de la o las claves primarias del registro actual, para la entidad asociada a la clase de mantenimiento. El criterio de selección resultante se aplica sobre el origen de datos del informe. Es válido abrir este tipo de informes desde un mantenimiento simple (de hecho este tipo de informes está creado especialmente para este tipo de mantenimientos). En un mantenimiento en Grid también funcionaria para la línea del Grid que estuviera seleccionada en ese momento. Este tipo de informes no se abren desde las consultas interactivas. Crear un informe con una conexión OLE DB (ADO) tal y como se indica en el apartado E.2 del apéndice. Seleccionar como origen de datos la tabla tbCursoMaestroCliente 178/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Realizar un diseño sencillo del informe seleccionando algunos campos de la tabla. Guardar el informe como CursoCliente.rpt y desde la consola de administración dar de alta un informe de tipo Registro Actual y alias CURCLI. Desde la consola de administración de la aplicación dar los permisos necesarios al informe y vincular el informe al mantenimiento de clientes creado en el apartado 4.2. 179/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Volver al Índice 2. Criterio Selección Este tipo está creado para utilizarlo en las consultas interactivas. El motor construye un filtro en base a los criterios de selección de la consulta interactiva. El filtro se aplica al origen de datos del informe, ya sea el que tiene diseñado o bien el que se le establezca por código. Aunque está pensado para las consultas interactivas, también es posible lanzar este tipo de informes desde los otros tipos de mantenimientos, sin ningún tipo de restricción, el motor se limita a lanzar los eventos para que podamos interactuar con el informe. Crear una vista con el nombre vrptCursoConsultaFactura con el siguiente diseño Crear un informe con una conexión OLE DB (ADO) tal y como se indica en el apartado E.2 del apéndice, seleccionando la vista anterior como origen de datos del informe. 180/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Realizar un diseño sencillo del informe seleccionando algunos campos de la tabla. Guardar el informe como CursoConsultaFactura.rpt y utilizando la consola de administración dar de alta un informe de tipo criterio de selección, y alias CURCIFV. Desde la consola de administración de la aplicación dar los permisos necesarios al informe y vincular el informe a la consulta de facturas creada en el apartado 4.4. Comprobar en depuración como se ejecuta el evento QueryExecuting de la clase de mantenimiento. Volver al Índice 3. Tabla Auxiliar Este tipo de informes se utiliza para imprimir de forma masiva, o cuando se quieren distinguir varias copias de un mismo informe, y se pueden lanzar desde los mantenimientos simples o desde consultas interactivas que utilicen marcas. Este tipo de informes no se abren desde los mantenimientos tipo Grid. Ver también propiedad LinkField de la clase Report, y en el apartado Algunos temas de diseño, Diseño de informes de tipo Impresión de tabla auxiliar. Diseño de informes nuevos. Un diseño correcto del origen de datos es lo más importante en este tipo de informes. Cuando se diseña la vista que sirve como origen de datos debemos hacer obligatoriamente lo siguiente: 1. Incluir la tabla xPrintingAuxiliarTable de la base de datos de usuario. 2. Establecer un vínculo entre la tabla principal de la vista y la tabla xPrintingAuxiliarTable. El campo de la tabla principal que se vincula debe tener valores únicos, por ejemplo, un campo primary key de tipo auto numérico. El vínculo debe hacerse con el campo NumericLink o TextLink en función del tipo de dato que contiene el campo de la tabla principal que se vincula. 3. Incluir los campos IdProcess y NumberOfCopies de la tabla xPrintingAuxiliarTable. Ejemplo: Cuando se lanza un informe de este tipo, el motor de informes se encarga, primero, de crear un identificador de proceso y guardar en la tabla xPrintingAuxiliarTable los registros con ese identificador, y segundo, se encarga de aplicar un criterio de selección de registros en base a dicho identificador. Cuando el informe se abre, recupera el conjunto de registros de la vista filtrados por el identificador de proceso, y la relación establecida entre las tablas xPrintingAuxiliarTable y la tabla principal hace el resto. Por defecto, el motor de Expertis se encarga de saber cuál es el campo NumericLink o TextLink, de tal forma que si es un mantenimiento simple (o en Grid), considerara como campo de enlace la clave primaria de la entidad asociada a la clase de mantenimiento (propiedad EntityName de FormBase). Cuando los registros de la tabla xPrintingAuxiliarTable no son necesarios se eliminan para el identificador de proceso en cuestión. Si solo se ha mostrado la vista previa del informe, esto ocurre justo cuando se cierra el 181/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis formulario de la vista previa, bien sea directamente o bien porque se cierra Expertis. En el caso de que se haya realizado alguna acción de exportación los registros se eliminan justo después de ejecutar la orden de exportación. Si en el tiempo que dura el pre visualización, o la exportación, la aplicación se cierra anormalmente, los registros no se eliminaran de xPrintingAuxiliarTable. Por esta razón, y aunque no es crítico ni será lo habitual, puede ser conveniente realizar comprobaciones periódicas del contenido de esta tabla, por parte de los administradores de la aplicación, con objeto de que no crezca demasiado. Los registros que queden sin borrar no afectan en modo alguno al funcionamiento de otros informes. En algunos casos es necesario cambiar el comportamiento por defecto y se hace necesario escoger otro campo de enlace diferente. En ese caso es posible establecer el campo de enlace en la configuración del informe o alternativamente por código. Este nombre se almacena en el campo LinkField de la tabla xReport de la base de datos de sistema y se establece desde la consola de administración. Si queremos modificar esta propiedad por código, deberemos utilizar la propiedad LinkField que posee la clase Report, o que posee también la clase ReportDataSourceEventArgs que aparece como argumento de evento en el evento SetReportDataSource de la clase de mantenimiento. Por ejemplo, siguiendo el ejemplo anterior, el valor de LinkField seria IDAlbaran, aunque en este caso no sería necesario configurarlo en xReport, ya que este informe se lanza desde el mantenimiento de Albaranes, y el motor de informes se encarga de determinar que la clave principal asociada al mantenimiento es IDAlbaran. Volver al Índice 4. RecordSet Se toma como origen de datos un conjunto de registros al cual tiene acceso la clase de mantenimiento. Es válido abrir este tipo de informes desde un mantenimiento en Grid o desde una consulta interactiva. En ambos casos, por defecto, se utiliza el origen de datos del Grid para pasar los datos al informe. También se puede hacer una selección múltiple de filas en el Grid para que solo aparezca esa selección en el informe. Este tipo de informes no se abren desde los mantenimientos simples. Volver al Índice 5. Sin Filtro El informe toma como origen de datos el que tiene asignado en diseño, o el que se le proporciona por código, con la peculiaridad de que no utilizara ningún criterio de selección. Este tipo de informes se puede lanzar desde cualquier tipo de mantenimiento. Volver al Índice 6. Personalizado Este tipo de informes se puede utilizar en todos los tipos de mantenimiento, sin ninguna restricción, y es el tipo por defecto cuando se da de alta un informe en Expertis. El informe toma como origen de datos el que tenga diseñado o el que se le proporcione por código. Volver al Índice Configuración del Manager de Datos de Informes Para ello acudiremos al manager de expertis e iremos a la sección: Objetos -> Informes. Para el agregado de infromes se hace de forma manual a través del botón Añadir. Luego en él cumplimentaremos la información necesaria acerca del informe, tales como alias, una descripción, nombre de archivo y tipo de informe. Asimismo no olvidemos fijo el tema de permisos del informe y de asociarlo al programa en concreto 182/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Volver al Índice Servicio de Informes La utilización de este servicio permite que los informes estén disponibles en una única ubicación para todos los puestos cliente, con lo que no es necesario mantenerlos en cada uno de ellos. El servicio de informes también permite que los informes de Expertis se resuelvan y se conecten en el servidor, en lugar de que esto suceda en el equipo cliente. Esta opción puede resultar útil cuando, por razones generalmente de seguridad, no es posible una conexión cliente-servidor de datos y solo sea el servidor host el que puede acceder al gestor de datos. Cuando se utiliza el servicio de informes lo que viaja al puesto cliente es una copia del informe ya resuelto, con los datos incluidos, se almacena de forma temporal y se elimina cuando ya no es necesaria. La configuración del servicio de informes se realiza desde la consola de administración, desde la sección Aplicación y en Configuración de Aplicación. 183/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis El campo Usar Servicio de Informes tiene tres valores: Si, no y por defecto. El valor por defecto equivale a no. En este cuadro se resumen las opciones disponibles, junto con la posibilidad de estar en un entorno de remoting. Remoting NO UseReportService NO ReportPath Vacio <dir> \\Recurso_Compartido NO SI Vacio <dir> \\Recurso_Compartido SI NO Vacio <dir> \\Recurso_Compartido SI SI Vacio <dir> \\Recurso_Compartido Especificación Directorio especificado por <dir>, recurso compartido o vacio que equivale al directorio por defecto \Bin\Informes. Ubicación de los informes Siempre relativa al cliente. Conexión: Cliente Directorio especificado por <dir>, recurso compartido o vacio que equivale al directorio por defecto \Bin\Informes Ubicación de los Informes siempre relativa al Cliente Conexión: Cliente. Directorio especificado por <dir>, recurso compartido o vacio que equivale al directorio por defecto \Bin\Informes. Ubicación de los informes siempre relativa al Cliente. Conexión: Cliente. Direcotrio especificado por <dir>, recurso compartido o vacio que equivale al directorio por Defecto \Bin\Informes. Ubicación de los Informes siempre relativa al Servidor (Host). Conexión: Servidor (Host) En la opción de Modo de Ejecución tendremos 3 valores posibles: - Default: Modo por Defecto que equivaldría al modo Normal. Normal: Modo Normal de trabajo con informes. Se devuelve de equipo servidor a los clientes un objeto de tipo report. LightClient: Modo Cliente Light de trabajo con Informes. Se devuelve de equipo servidor a los clientes un objeto de tipo PDF. 184/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis NOTA: Desde la consola de administración el servicio de informes se puede establecer a nivel global para toda la aplicación (internamente la tabla que mantiene estos datos es xApplication), pero también se puede establecer una configuración particular para cada máquina desde la sección Maquinas de la consola de administración (en este caso la tabla es xMachine). Esto puede ser particularmente útil, por ejemplo, cuando una misma base de datos de sistema es compartida por puestos cliente en producción y puestos de desarrollo. Por lo general en los puestos de desarrollo se modifican y se prueban los informes de forma local y no utilizan el servicio de informes. Volver al Índice Tipos de Conexión Todos los informes que se utilizan en Expertis y se generan con Crystal Reports se diseñan con el mismo tipo de conexión. Para crear un informe nuevo, seleccionar Nuevo Informe en blanco desde Crystal Reports y crear una nueva conexión OLE DB (ADO) Seleccionar el proveedor de datos Microsoft OLE DB Provider for SQL Server y establecer las propiedades de conexión para la base de datos de desarrollo que se esté utilizando 185/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Cuando se diseñan nuevos informes con Crystal Reports 11 el tipo de conexión va a ser OLE DB (ADO), proveedor SQLOLEDB. Este tipo de conexión es válido tanto si el informe toma directamente el origen de la base de datos o bien si va a ser proporcionado por código. NOTA: En la mayoría de los informes diseñados para versiones anteriores de Expertis el tipo de conexión ya viene de Crystal Reports 10 y 9 como OLE DB (ADO), de forma que, en principio, no hay que actualizarlos. Esto se puede comprobar desde el diseñador de Crystal Reports en el Menú Base de Datos --> Establecer Ubicación. Es posible que haya informes de versiones anteriores con el proveedor MSDASQL en lugar de SQLOLEDB. Este tipo de proveedor no da problemas y lo podemos dejar así. Volver al Índice Eventos Informes Las clases de mantenimiento SimpleMnto, GridMnto, CIMntoBase (y por herencia CIMnto) disponen de los eventos que se lanzan cuando se abren informes desde el comando de impresión de la barra de comandos. La clase FormBase no dispone de estos eventos, entre otras cosas, porque no tiene una barra de comandos y no se ha diseñado ninguna acción específica que se pueda vincular a la apertura de un informe. Para abrir un informe desde un FormBase (un formulario modal por ejemplo), necesitaríamos un evento o acción, como el evento Click de un control Button, para poder programar la clase Report de Expertis y utilizar el método OpenReport de dicha clase. El orden de ejecución de los eventos es el siguiente (1) SetReportDesignObjects SetReportSelectionCriteria SetReportOptions 186/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis SetReportDataSource ReportExported (2) Cada evento salta para el informe principal (1), y para cada uno de los subinformes que pueda tener. Todos los eventos, excepto ReportExported, disponen de una propiedad que permite cancelar la ejecución de todo el proceso. (1)Para algunos tipos de informe, no se ejecutan todos los eventos, pero el orden siempre se mantiene. (2)Solo se lanza para el informe principal ReportExported Ocurre después de exportar un informe. Acciones de exportación se consideran: guardar el informe en disco enviar el informe adjunto por mail imprimir el informe por impresora Recibe un argumento del tipo ReportExportedEventArgs que contiene los datos del evento. Esta clase proporciona la propiedad Status, de tipo ReportExportStatus, que indica si la exportación se ha ejecutado, y un valor de tipo ReportExportDestinationType que indica el tipo de exportación NOTA: Hay que tener en cuenta que el proceso de exportación se compone de dos acciones, primero, la ejecución de la orden de exportación, y segundo, enviar el informe al contexto particular de exportación. La propiedad Status indica únicamente si se ha podido ejecutar la orden de exportación. La ejecución con éxito del segundo paso depende de otros factores que la aplicación no puede controlar, como pueden ser por ejemplo, que el informe se queda atascado en la impresora o que el informe que va adjunto en un mail quede encolado en el servidor de correo. SetReportDataSource Ocurre antes de abrir un informe asociado a la lista de informes del comando de impresión. Recibe un argumento del tipo ReportDataSourceEventArgs que contiene los datos relacionados con este evento. Este evento permite asignar al informe un origen de datos personalizado por medio de la propiedad DataSource del ReportDataSourceEventArgs. Este evento también permite configurar las opciones de impresión de los informes de tipo Tabla Auxiliar (número de copias, origen de las copias, etc). SetReportDesignObjects Ocurre antes de abrir un informe asociado a la lista de informes del comando de impresión. Recibe un argumento del tipo ReportDesingObjectsEventArgs que contiene los datos relacionados con este evento. Este evento permite asignar y modificar valores de todos los objetos contenidos en el diseño del (formulas, parámetros, campos de ordenación y subinformes) por medio de las ReportDesignObjectsEventArgs. informe propiedades de SetReportOptions Ocurre antes de abrir un informe asociado a la lista de informes del comando de impresión. Recibe un argumento del tipo ReportOptionsEventArgs que contiene los datos relacionados con este evento. Este evento permite configurar por medio de las propiedades del ReportOptionsEventArgs, varias opciones como por ejemplo, opciones de impresión, el canal de exportación (mail, disco duro, impresora), el formato de exportación (excel, word, ...), etc. También permite controlar el estado del formulario de vista previa y la posibilidad de mostrar formularios de decisión para el usuario. SetReportSelectionCriteria Ocurre antes de abrir un informe asociado a la lista de informes del comando de impresión. Recibe un argumento del tipo ReportSelectionCriteriaEventArgs que contiene los datos relacionados con este evento. Permite personalizar el criterio de selección que se aplicara sobre el origen de datos del informe, por medio de las propiedades Filter o RecordSelecionFormula del ReportSelectionCriteriaEventArgs. Volver al Índice 187/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis 9. HERRAMIENTAS DE EXPERTIS Consola de Administración Para conocer a fondo la consola de administración de Expertis acudir al manual concreto de ayuda y manejo que se dispone en la ayuda de expertis o bien en la web de documentos de ayuda de Expertis. Pasaremos a marcar algunos puntos rápidos y de mayor conocimiento para un desarrollador de Expertis. 1. Autenticación en Expertis [Cambio de Usuario] Existen dos tipos de autenticación: Autenticación de Windows. Se iniciará la sesión con el usuario con el que se ha iniciado la máquina. Autenticación de Expertis. Al iniciar la sesión pedirá la introducción de un usuario de Expertis y su contraseña. En las bases de datos de sistema que se proporcionan siempre existe el usuario ‘Expertis’. Este usuario permite realizar las primeras configuraciones de la aplicación a nivel general, por ejemplo, cambiar el tipo de autenticación del sistema, gestionar nuevos usuarios, bases de datos de usuario, etc. Para realizar el desarrollo y las pruebas con mayor comodidad y rapidez es conveniente dar de alta un usuario nuevo con autenticación de Windows y cambiar el tipo de autenticación. Para ello, ejecutar la consola de administración de Expertis y autenticarse con Expertis Acudiríamos a la sección de Seguridad en la barra lateral de Opciones, y después en la opción de Usuarios: 188/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Daríamos al botón de Nuevo en la barra de herramientas y nos dejaría la pantalla de la siguiente manera: Veríamos que nos agrega una nueva línea en el Grid de Usuarios y nos marca los siguientes campos a rellenar en la sección de abajo. Rellenamos los datos como especificamos a continuación: - Pestaña Editar Usuario: 1. Usuario: Solmicro-Curso\Sol-Curso 2. Autenticación: WindowsAutentication 3. Idioma: Castellano 4. Grupo: Solmicro Admins 5. Base de Datos: xExpertisCurso 6. Menú: Curso 5.0 7. Empresa: Solmicro 8. Ver menú Contextual en Grids: V 9. Bloqueado: Vacío. Y damos al botón Guardar de la barra de herramientas. Nos aseguramos de que ha sido correctamente guardado el nuevo usuario y en la pestaña de Bases de Datos esté dado de alta la base de datos de xExpertisCurso. Como siguiente paso pasamos a cambiar el modo de autenticación de Expertis en 189/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Seleccionamos en Modo de Autenticación a WindowsAutentication Guardar los cambios pendientes y comprobamos que se puede ejecutar la aplicación. 2. Actualización / Inserción de Entidades NOTA: Para ejecutar esta acción es necesario tener la DLL del proyecto de negocio compilada y actualizada. Abrir la consola de administración de Expertis. Desde el menú Procesos -> Agregar Entidades El cuadro de dialogo permite seleccionar la DLL que contiene las clases de negocio 190/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis 3. Actualización / Inserción de Programas Para dar de alta un programa, abrir la consola de administración de Expertis. Desde la barra de herramientas, Nuevo, Programa Establecer las siguientes propiedades: Título: Es el texto que aparece en los grupos de menú. El siguiente texto es opcional y es el texto del formulario en sí Alias (Opcional): Es un identificador del programa. Se utiliza cuando el programa se abre desde otro programa utilizando el método OpenForm de la clase ExpertisApplication Título en Pantalla: y es el texto del formulario en sí Ensamblado: El nombre del archivo DLL. Clase: Es el nombre completo de la clase dentro del espacio de nombres que define la raíz del espacio de nombres del proyecto Tipo: El valor por defecto es Windows.Forms. No modificar este valor por defecto Imagen: Nombre de un recurso de la carpeta de recursos del directorio de instalación 191/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Para que el programa sea accesible para el usuario es necesario incluir dicho programa en el conjunto de programas de un rol de Expertis. Para ello en el programa pinchar en la pestaña de Grupos, dar al botón de Añadir de la barra de herramientas y nos aparecerá para seleccionar un rol del grupo de roles definidos en Expertis. El siguiente paso es habilitar un acceso al programa desde un elemento de menú. Para ello, ir a la sección Menú, seleccionar el Menú 5.0. 192/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Agregamos en algún punto del menú el programa pinchando en la Opción Añadir de la sección de Lista de Programas. Seleccionamos el programa. Aceptamos y damos a Guardar en la barra de herramientas. 193/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis 4. Actualización / Inserción de Informes Para dar de alta un informe, abrir la consola de administración de Expertis. En la sección de Objetos nos posicionamos en Informes. Pulsamos el botón Añadir de la barra de herramientas del Manager y pasaremos a introducir los datos del Nuevo Informe. 194/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Establecer las siguientes propiedades Alias (opcional): Sirve para identificar el informe. Si el informe se vincula a un programa no se utiliza, ya que la clase de mantenimiento que abre el informe sabe de antemano cual es el informe que tiene que abrir, sin embargo, el alias es imprescindible si se va a utilizar la clase Report para abrir el informe por código. NOTA: no confundir este alias con el alias que se asigna al informe en diseño. El alias de diseño lo utiliza internamente Crystal para construir el criterio de selección, para la formulación de parámetros, formulas, etc. El alias de la base de datos solo será necesario en la creación de la instancia de la clase Report. Descripción: Es el texto que aparece en la lista de informes del comando de impresión de la clase de mantenimiento, y que también aparece como título en el formulario de la vista previa. Fichero: Es el nombre del archivo diseñado con Crystal Reports, con extensión .rpt incluida. No es necesario incluir la ruta completa. Tipo (opcional): Es uno de los siguientes valores: Numero 1 2 3 4 5 6 Tipo CurrentRecord RecordSet SelectionCriteria AssistantTable FilterLess Custom Descripción Registro Actual ADO.NET – XML Criterio de Selección Tabla de Impresión Auxiliar Sin Filtro Personalizado El tipo por defecto es el personalizado. Impresora (Opcional): Nombre de la impresora que se utilizara por defecto para la impresión del informe. Si no se especifica ninguna se utilizara la impresora predeterminada. Enlace (Opcional): El nombre del campo que actúa como campo de enlace entre la tabla principal del origen de datos del informe y la tabla xPrintingAuxiliarTable. Ver en Tipos de informes, informes de tipo Impresión de tabla auxiliar. Entidad (Opcional): Entidad que se utilizará en el filtrado horizontal. Tanto si el informe se abre desde un programa como si se abre por código, este debe tener los permisos necesarios para su ejecución. Los pasos a seguir para vincular un informe a un rol son exactamente los mismos que los seguidos con los programas. Finalmente, si el informe se va a abrir desde el comando de impresión de la barra de comandos de un mantenimiento será necesario vincularlo a un programa. Si el informe se va a abrir únicamente por código no es necesario. Si un informe ya está vinculado a un programa, también se puede utilizar de forma personalizada y abrirlo por código. 5. Actualización / Inserción de Enumerados 195/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis NOTA: Para ejecutar esta acción es necesario tener el compilado actualizado del proyecto de negocio donde están definidos los enumerados. Abrir la consola de administración de Expertis. Desde el menú Procesos -> Agregar Enumerados El cuadro de dialogo permite seleccionar la DLL que contiene las definiciones de los enumerados. En el caso del Estándar de Expertis, estos se encuentran en Expertis.Business.BusinessEnum. Una vez agregados los Enumerados podemos establecer las descripciones y traducciones de los enumerados en la pestaña de Traducciones de cada Enumerado. 196/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis 6. Actualización / Inserción de Procesos y Tareas Abrir la consola de administración de Expertis. Desde el menú Programas -> Agregar Procesos y Tareas El cuadro de dialogo permite seleccionar la DLL que queramos procesar sus procesos y tareas y con lo cual siendo una dll de parte de negocio. Una vez procesada la DLL tendremos disponibles sus procesos y tareas y podríamos ya llevar a cabo el reemplazo de tareas, tarea antes y después, etc… 197/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Volver al Índice DataBase Comparer Herramienta para desarrolladores para la comparación de estructuras de datos entre bases de datos. Nos permitirá ver todas las diferencias a nivel estructural entre dos bases de datos a niveles, campo, tabla, vista, función, procedimiento almacenado, índices, etc… Asimismo de las diferencias detectadas nos permitirá generar scripts de dichas diferencias. Bien sea de manera global o bien de manera particular por cada cambio. Para ello, tendremos que establecer qué base de datos de origen y qué base de datos de destino vamos a comparar. Lo tendremos en el menú conectar para establecer las dos bases de datos. 198/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis En la ventana de conexión estableceremos todos los datos necesarios para llevar a cabo la conexión tanto con la B.D. de Origen como con la B.D. de Destino. 199/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Una vez establecidas las conexiones daremos al botón de comparar e iremos viendo los pasos que va haciendo en la comparación y esperaremos a que termine el proceso. Terminado ya el proceso de comparación podremos ir viendo por secciones qué cambios nos ha detectado. Pudiendo ver el script personalizado de cada cambio con el botón Ver Detalle. Asimismo podremos generar un script con todos los cambios pulsando en Generar Fichero. 200/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Volver al Índice Expertis.Tools.Translator Para la traducción de los textos, mensajes, etc.. contenidos dentro de expertis, se dispone de una herramienta muy sencilla llamada: Expertis.Tools.Traslator. Con ello solo bastará con pasarle las dlls o carpeta para que nos coja el contenido de dichas dlls para procesar todos los textos, mensajes, etc.. contenidos en esa dll. El proceso lo que hará será volcar toda esa información en la base de datos de sistema a la que estamos conectados. Es por ello que con el programa viene un fichero de configuración en el que editaremos y posicionaremos contra nuestra base de datos de sistema. Una vez procesado todo acudiremos en el manager a la sección de: Objetos -> Textos. 201/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis O bien: Objetos -> Mensajes. Ahí procederemos a buscar los textos o mensajes correspondientes que sabemos de la aplicación que queremos traducir y pasaríamos a insertar las traducciones en los idiomas que necesitemos. Volver al Índice Expertis.Tools.CRConnectionUpdater Herramienta para actualizar la cadena de conexión de los informes de Crystal Reports. Para entender la carga de proceso en la ejecución de un informe, veamos los pasos que sigue Crystal Reports en la ejecución de un informe: 1. 2. 3. Carga del propio motor de Crystal Reports. Trabajo de reconexión del informe. Trabajo dentro del propio informe que consiste en el procesamiento de los datos, ejecución de fórmulas, agrupamiento, etc. Si el origen de datos del informe es calculado, hay que tener en cuenta además la programación que proporciona los datos al informe. 202/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Respecto al punto 2, cuando un informe de Crystal se ejecuta contra un servidor diferente al servidor contra el que fue diseñado, el trabajo de reconexión que hace Crystal puede retardar la apertura del informe. Esta herramienta permite actualizar los informes del cliente con una conexión válida para ese cliente en cuestión. 1. Propiedades de conexión Antes de lanzar el proceso es obligatorio especificar los parámetros de conexión. La herramienta comprueba si es una conexión valida en el cliente, ya que el proceso de actualización obliga a los informes a que se conecten con la nueva conexión, de lo contrario no es posible guardarlos con la nueva configuración. 2. Carpetas Carpeta Origen donde están ubicados los informes que se quieren actualizar. Carpeta de destino donde se dejaran los informes ya actualizados. Los informes originales no se modifican. 203/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Al elegir la carpeta de origen se nos cargará en la sección de informes todos los informes detectados en dicho directorio y pudiendo elegir qué informes deseamos actualizar y cuáles no. NOTA: Cuidado, porque si el directorio de origen coincide con el destino los informes se sobrescribirán. 3. Actualizar Lanza el proceso. Dado que los informes deben volver a conectarse para ser guardados con la conexión nueva, el proceso puede tardar, de manera que hay que pensar en el número de informes a actualizar, y el momento de lanzar el proceso, tener en cuenta que se está haciendo un trabajo contra el servidor de SQL, y además, aunque no consume mucha CPU de la máquina que lanza el proceso, existen momentos puntuales en los que sí. Durante el proceso es posible que algunos informes den un error de conexión (no existe el origen de datos, la vista no está actualizada, etc.). Estos casos hay que tratarlos de forma manual. Después de terminar, la herramienta deja un fichero, CRConnectionUpdater.log, con un resumen del proceso. Este fichero se abre con cualquier editor de texto. 204/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis Volver al Índice FederatedSearch & SmartTags Información de Búsqueda Federada La Información de la conexión de la Búsqueda Federada se guarda en el fichero de Configuración del Expertis.Host. Nombre del Fichero: Expertis.Host.Exe.Config Hay que comprobar la Línea: <value>http://devsaas:8000/FederatedSearch/</value> Nota: Importante Nombre de Servidor y Puerto. El nombre que va antes del puerto es del servidor donde está instalado el servicio de Expertis.Host. La composición normal del Fichero Expertis.Host.Config sería: <?xml version="1.0"?> <configuration> <!-- configSections: applicationSettings, Expertis.Host.My.MySettings --> <configSections> <sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> <section name="Expertis.Host.My.MySettings" type="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false"/> </sectionGroup> </configSections> <!-- Diagnostic: --> <system.diagnostics> <sources> <!-- This section defines the logging configuration for My.Application.Log --> <source name="DefaultSource" switchName="DefaultSwitch"> <listeners> <add name="FileLog"/> <!-- Uncomment the below section to write to the Application Event Log --> <!--<add name="EventLog"/>--> 205/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis </listeners> </source> </sources> <switches> <add name="DefaultSwitch" value="Information"/> </switches> <sharedListeners> <add name="FileLog" type="Microsoft.VisualBasic.Logging.FileLogTraceListener, Microsoft.VisualBasic, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" initializeData="FileLogWriter"/> <!-- Uncomment the below section and replace APPLICATION_NAME with the name of your application to write to the Application Event Log --> <!--<add name="EventLog" type="System.Diagnostics.EventLogTraceListener" initializeData="APPLICATION_NAME"/> --> </sharedListeners> </system.diagnostics> <!-- Startup: --> <startup> <supportedRuntime version="v2.0.50727"/> </startup> <!-- applicationSettings: Namespace: httpBaseNS --> <applicationSettings> <Expertis.Host.My.MySettings> <setting name="httpBaseNS" serializeAs="String"> <value>http://devsaas:8000/FederatedSearch/</value> </setting> <setting name="ServiceName" serializeAs="String"> <value>ExpertisHost50</value> </setting> <setting name="DisplayName" serializeAs="String"> <value>Expertis Host 5.0</value> </setting> </Expertis.Host.My.MySettings> </applicationSettings> <!-- Servicios de web: --> <system.serviceModel> <!-- Bindings: WebHttpBinding --> <bindings> <webHttpBinding> <binding name="WebHttpBinding"> <security mode="TransportCredentialOnly"> <transport clientCredentialType="Windows" /> </security> </binding> </webHttpBinding> </bindings> <!-- Services --> <services> <!-- Service: ExpertisSearchFeed --> <service behaviorConfiguration="ServiceBehavior" name="Solmicro.Expertis.Host.SyndicationService.FederatedSearch.ExpertisSearchFeed"> <!-- Endpoint: webHttpBinding --> <endpoint address="ExpertisFeed" behaviorConfiguration="ExpertisFeedBehavior" binding="webHttpBinding" bindingConfiguration="WebHttpBinding" contract="Solmicro.Expertis.Host.SyndicationService.FederatedSearch.ISearchFeed" /> </service> <!-- Service: ExpertisSearchItem --> <service behaviorConfiguration="ServiceBehavior" name="Solmicro.Expertis.Host.SyndicationService.FederatedSearch.ExpertisSearchItem"> <!-- Endpoint: webHttpBinding --> <endpoint address="" behaviorConfiguration="ExpertisFeedBehavior" binding="webHttpBinding" contract="Solmicro.Expertis.Host.SyndicationService.FederatedSearch.ISearchItem" /> 206/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis </service> </services> <!-- Behaviors --> <behaviors> <!-- ServiceBehaviors: ServiceBehavior --> <serviceBehaviors> <behavior name="ServiceBehavior"> <serviceMetadata httpGetEnabled="True" policyVersion="Policy15" /> <serviceDebug includeExceptionDetailInFaults="false" /> </behavior> </serviceBehaviors> <!-- EndpointBehaviors: ExpertisFeedBehavior --> <endpointBehaviors> <behavior name="ExpertisFeedBehavior"> <webHttp/> </behavior> </endpointBehaviors> </behaviors> </system.serviceModel> </configuration> Configuración de los Elementos a Buscar Desde el Manager de Expertis, en la opción de menú: Objetos -> Entidades buscamos la entidad que deseemos. En la entidad posicionada activamos la casilla de Búsqueda Federada. Junto con esta opción debemos configurar el Campo correspondiente a Descripción. Éste campo sería sobre el que se hacen las búsquedas. Autenticación de Expertis Es Obligatorio el uso de Autenticación de Windows en Expertis cuando usemos el servicio de Búsqueda Federada. . Fichero xslTemplate.xslt En la Carpeta bin del Servidor (donde esté alojada el Expertis.Host) tendremos que tener alojado el fichero: xslTemplate.xslt (Fichero Suministrado por Solmicro). Servicio de Búsqueda de Windows 7 En Windows 7 podemos registrar servicios de Búsqueda. Esto se hace a través de unos ficheros con extensión .osdx. Solmicro suministra un fichero osdx para instalar en el equipo deseado búsquedas para expertis. Para ello solo hace falta hacer doble click sobre el fichero .osdx suministrado. SMART TAGS Con esta utilidad podemos obtener información de la base de datos de Expertis para ayudarnos, por ejemplo, a redactar una carta. Imaginemos que estamos escribiendo un texto y necesitamos información de un cliente. Instalamos el paquete de Smart Tag y luego lo activamos (si no se ha hecho automáticamente) Volver al Índice Doble Expertis Host en Servidor Se necesita mínimo de FrameWork 2.0 instalado en la máquina El Expertis.Host y su fichero Config que se adjuntan son de versión Expertis 5.0, pudiendo instalar anteriormente un Expertis host 4.1 con su instalable o bien otro Host de Expertis 5.0 con su instalable. El fichero Expertis.Host.Exe y su config los colocaremos donde esté el bin de expertis que queremos que sea de remoting y que va a dar servicio. 207/208 Versión 1.4 / Mayo 2014 Manual Programación Expertis En el fichero Config editaremos los siguientes datos dentro de la sección de ApplicationSettings y dando los nombres que queramos y diferentes a los nombres de otros Expertis.Host que puedan estar instalados en el listado de servicios del Windows donde estamos ejecutando. <setting name="ServiceName" serializeAs="String"> <value>ExpertisHost50</value> </setting> <setting name="DisplayName" serializeAs="String"> <value>Expertis Host 5.0</value> </setting> Dando al ServiceName otro diferente al de por defecto y al DisplayName otro diferente al de por defecto. Acudir al directorio de la máquina: C:\Windows\Microsoft.NET\Framework\v2.0.50727 y verificar que existe el programa InstallUtil Una vez confirmado arrancar el ms-dos de Windows y lo arrancamos, si fuera un sistema Windows con control UAC ejecutamos con botón derecho encima -> Ejecutar como administrador, sino nos dará error en la instalación por temas de permisos En el ms-dos nos movemos al directorio anteriormente marcado: C:\Windows\Microsoft.NET\Framework\v2.0.50727 y ejecutaríamos el siguiente comando: C:\Windows\Microsoft.NET\Framework\v2.0.50727\InstallUtil UBICACION_DEL_EJECUTABLE_DE_EXPERTIS.HOST.EXE. Por ejemplo: C:\Windows\Microsoft.NET\Framework\v2.0.50727\InstallUtil C:\Expertis50\Bin\Expertis.Host.Exe Debe estar localizado el Expertis.Host.Exe del paquete que distribuimos con el fichero config que también damos y posicionar estos ficheros en el directorio Bin de Expertis que va a ser el remoting de la red. Si deseáramos en algún momento desinstalar este Expertis.Host instalado de una manera especial bastaría con volver a arrancar ms-dos y acudir a la utilidad de InstallUtil, como los pasos anteriormente marcados y ejecutar el siguiente comando: C:\Windows\Microsoft.NET\Framework\v2.0.50727\InstallUtil /u UBICACION_DEL_EJECUTABLE_DE_EXPERTIS.HOST.EXE. Por ejemplo: C:\Windows\Microsoft.NET\Framework\v2.0.50727\InstallUtil /u C:\Expertis50\Bin\Expertis.Host.Exe Volver al Índice 208/208 Versión 1.4 / Mayo 2014