Mostrando entradas con la etiqueta Ln4. Mostrar todas las entradas
Mostrando entradas con la etiqueta Ln4. Mostrar todas las entradas

lunes, 21 de noviembre de 2011

Ejecución de Meta4Objects planificados en el Job Scheduler II

Hace tiempo que no escribía post de desarrollo. La verdad es que he estado bastante liado con un motón de cosas y simplemente hacía referencia a noticias del mundo Meta4. Mis disculpas.

Retomo en este caso un post antiguo para ampliarlo. El post era Ejecución de Meta4Objects planificados en el Job Scheduler y trataba de como planificar la ejecución de Meta4Objects desde código LN4.

Ese post tenía la limitación de no dejar al usuario elegir el modo de planificación. Recordemos que tenemos: Inmediato, Cíclico, Plan anual o Lista de fechas.


En esta ocasión nos valdremos de un objeto de presentación, un Action_bp con una tarea específica: JSForPresentations, que nos ayudará en este propósito.

Lo que haré será primero desde un botón invocar la ejecución de un método que informa una propiedad (de ámbito nodo y tipo Long en este ejemplo) que luego se pasa a presentación y se incluye en un parámetro de la tarea JSForPresentations. Este código concatena una llamada LN4 por in-dirección a través del método clcExecuteLN4JIT

El código de este método que llamaré CXX_PLANIFICACION_PROCESO es:

MsT3 = "MI_M4OBJ"
MsNodo = "MI_NODO de MI_M4OBJ"
MsMetodo = "CXX_PROCESO"
MsAlias = "MI_ALIAS"

MsDQ = CHR(Double_quote)

PRP_LN4_CODE = "{·Execute LN4 Code·,LN4_CODE,·"
PRP_LN4_CODE = PRP_LN4_CODE + "DefineInstanceEx(" + MsDQ + MsAlias + MsDQ + "," + MsDQ + MsT3 + MsDQ + ", M4_AUTOLOAD_OFF, M4_INSTANCE_NOT_SHARED, " + MsDQ + MsDQ + ", M4_ORGANIZATION_L2_TYPE_ANY):"
PRP_LN4_CODE = PRP_LN4_CODE + "sCode = " + MsDQ + MsAlias + "!" + MsNodo + "." + MsMetodo + "()"+ MsDQ + ":"
PRP_LN4_CODE = PRP_LN4_CODE + "clcExecuteLN4JIT(sCode)·}"

Return (M4_SUCCESS)

Es importante el caracter "punto" ("·", tecla shift + 3)

Realmente estamos haciendo: MI_ALIAS!CXX_PROCESO() una vez hubiéramos declarado el Alias de Meta4Object.

Aparte de esto, en una presentación, crearé dentro de un botón y su evento click el siguiente código:

 BEGIN Button bttXXXX

  Idchannel = "CXX_XXXX"
  Idnode = "CXX_XXXX"
  Text = "Planificación desde Presentación"
  BEGIN Evclick Evclick1
    BEGIN Action_method amthdCXX_PLANIFICACION_PROCESO
      Iditem = "CXX_PLANIFICACION_PROCESO"
    END
    BEGIN Action_set asBoxName
      Set = "*C*BOXNAME := 'Planificación del proceso XXX'"
    END
    BEGIN Action_set asBoxList
      Set = "*C*BOXLIST := [PRP_LN4_CODE]

    END
    BEGIN Action_bp bpJobScheduler
      Idbp = "JSForPresentations"
      Load = False
      Localcontext = False
    END

  END
END


Al pulsarse, este botón, se ejecuta el método CXX_PLANIFICACION_PROCESO que genera el contenido de la propiedad PRP_LN4_CODE para después pasarlo al parámetro BOXLIST que hará que se incluya en la tarea JSForPresentations y así poder gestionarse la planificación sin las "ataduras" del anterior post.

Espero que os sirva!!

lunes, 10 de mayo de 2010

Calcular responsable y su mail

Desde hace ya un tiempo los clientes me piden que, tras ciertas acciones de un empleado en el Portal del Empleado (SSE), se remita un correo de cortesía a su responsable avisando de esta acción. [Obviamente cuando son procesos fuera de los flujos estándar]

Bueno el tema podría ser realizar una pequeña carga de un nodo con la Unidad a la que el empleado pertenece, revisar su responsable, los emails de ambos y lanzar el mail, pero vamos a "simplificarlo" usando el Meta4Object estándar SSE_VALIDADORES.

Primero es necesario generar dos alias de Meta4Object, uno para el SSE_VALIDADORES y otro obviamente para el Meta4Object MAIL:

MAIL:


SSE_VALIDADORES:

Después crearemos un método, conectado, por ejemplo antes del PERSIST_TREE() con un código semejante a este:

SSE_VALIDADORES!SSE_VALIDADORES.BEGIN()
MsIdPersona = [campo del ID de la Persona i.e. STD_ID_HR]
SSE_VALIDADORES!SSE_VALIDADORES.SSE_CALC_EMAIL(MsIdPersona,"SSE_EMAIL")

MsMailEmpleado = SSE_VALIDADORES!SSE_VALIDADORES.SSE_EMAIL
MsEmpleado = SSE_VALIDADORES!SSE_VALIDADORES.SCO_GB_NAME
SSE_VALIDADORES!SSE_VALIDADORES.ID_HR_PAR = MsIdPersona
SSE_VALIDADORES!SSE_VALIDADORES.SSE_CALC_RESPONSABLE("WORKUNIT10")
MsIdPersonaResp = SSE_VALIDADORES!SSE_VALIDADORES.SSE_ID_PERSON_RESP
MsMailResponsable = SSE_VALIDADORES!SSE_VALIDADORES.SSE_EMAIL_RESP

Este código nos deja en:

  • MsEmpleado el Nombre del empleado
  • MsMailEmpleado el email del empleado
  • MsIdPersonaResp el ID del responsable
  • MsMailResponsable el email del responsable

Luego con generar un mail ya estaría:

MAIL!MAIL.COMPOSE()
MAIL!MAIL.FROM = MsMailEmpleado
MAIL!MAIL.CC = MsMailEmpleado
MAIL!MAIL.DESTINATION = MsMailResponsable
MAIL!MAIL.SUBJECT = "Aviso de cambio en ...."
MAIL!MAIL.BODY = "Este correo electrónico se remite de forma automática desde el Portal del Empleado para avisarte de que " + MsEmpleado + " ha realizado ..."
MAIL!MAIL.SENDALL()



Espero que os sirva!!

viernes, 14 de agosto de 2009

[Colaboración de Dailos Herrera Bencomo - General de Software de Canarias (GSC) - Grupo Microfusión] Número a letra desde Ln4

Dailos Herrera Bencomo de General de Software de Canarias (GSC) - Grupo Microfusión (http://www.gsc.es), me ha enviado la información necesaria para crear un post que creo que os resultará muy interesante. Se trata de poder transformar un campo moneda (número) a letra desde LN4.

Exite en la aplicación un formato que se puede usar en reports/informes que permite el cambio número a letra, pero sólo se puede usar desde allí. ¿Qué pasa si queremos sacarlo en un Word, en un Excel o incluso en una presentación? Pues bien, Dailos ha buscado la forma y me ha permitido publicarlo en blog:

En un access adjunto (7.1Sp2), podeis encontrar los objetos y los transfer necesarios:

Meta4Object: CGC_MONEDA_A_LETRAS
Estructura de Nodo: CGC_MONEDA_A_LETRAS

Métodos:

  1. CGC_NUM_A_LETRA: Hace el cambio de moneda a letra
  2. CONVERTIR_A_LETRA: Hace la llamada al método anterior y formatea la salida según los argumentos:
  • ARG_MONEDA: Moneda a convertir
  • ARG_CASE: "U" o "L" formatea la salida en Mayúsculas o Minísculas, respectivamente, "U" por defecto
  • ARG_CURR: "1" o "0" muestra o no la palabra "EURO/S - CENTIMO/S", respectivamente, "0" por defecto (Si se elije mostrar EUROS/CENTIMOS acaba en "UN" y si se elije NO mostrar EUROS/CENTIMOS acaba en "UNO")
  • ARG_SIGNO: "1" o "0" muestra o no la palabra "MENOS", respectivamente, si se trata de un número negativo, "0" por defecto.
Aquí teneis el enlace al Fichero de MsAccess

Espero que os sea útil.

jueves, 25 de junio de 2009

Descubrir elementos de sesión sin definir Alias

¿Cuantas veces has tenido que crearte un Alias y su resolución para poder acceder al valor de otro Meta4Object?

Aquí os dejo un "truco" para hacerlo en 3 líneas; en este caso se obtiene el ID_PERSON del usuario logado, pero se pueden hacer muchas más cosas...

DefineInstance("SCH_SESSION","SCH_SESSION", 0, 3)
Code ="return(SCH_SESSION!ROOT_SESSION.ID_PERSON)"
sIdPerson = ClcExecuteLN4JIT(Code)


Espero que os sirva

sábado, 20 de junio de 2009

Asignación masiva de valores del Periodo de RH

He tenido que realizar este desarrollo que quizás alguien necesite, ya que se necesitaba cargar información en la base de datos, por ejemplo el sueldo de los empleados, en la tabla de Valores del Periodo de RH.




A partir de la versión 7 existe ya una carga másiva de Incidencias del Periodo de RH, pero son eso "incidencias" para una paga en concreto no para dar valores desde una fecha en adelante.




Necesitais descargar un fichero access (ASIGNACION_MASIVA_VALORES.rar) y ejecutar las siguientes sentencias, através de la RAMDL (Ojo el MDB está en versión V7.1Sp2 con HF6, si estais por delante os servirá subiendolo de verisión, si estais por detrás tendreis que subir la versión del entorno)




Es necesario disponer ya de la versión 7 de las tablas de valor ya que se basa en ellas para hacer la carga.




Sentencias:



TRANSFER "NODE STRUCTURE"."SRCSL_PY_VT_DATA_HR_PERIOD_VAL" FROM ORIGIN TO DESTINATION\
TRANSFER "META4OBJECT"."CSL_PY_VT_HR_PERIOD_VAL_MASS" FROM ORIGIN TO DESTINATION\
TRANSFER "PRESENTATION"."CSL_PY_VT_HR_PERIOD_VAL_MASS" FROM ORIGIN TO DESTINATION\
TRANSFER "MENU OPTION"."MN_CSL_PY_VT_HR_PERIOD_VAL_MAS" FROM ORIGIN TO DESTINATION\
TRANSFER "BUSINESS PROCESS"."BP_CSL_PY_VT_HR_PERIOD_VAL_MAS" FROM ORIGIN TO DESTINATION\





Este proceso debería generarte una nueva opción de menú en: Nómina \ Tablas de Valor \ Valores del periodo de RH \ Entrada masiva de valores del Periodo de RH que se puede ver en la siguiente imagen:

¡¡¡¡¡ NOTA IMPORTANTE !!!!!
Para el caso que he tenido que realizar ha funcionando correctamente pero no se ha realizado un plan de pruebas exhaustivo y no puedo asegurar al 100% que funcione en todos los casos... tomadlo como una ayuda

Espero que os sirva!!

domingo, 26 de octubre de 2008

[Colaboración de Jaime González de Zárate - SIC S.A.] Invocación a servicio SOAP externo a Meta4

Mi compañero Jaime González de Zárate de SIC S.A. (http://www.sicsa.es/), me ha enviado la información necesaria para crear un post que creo que os resultará muy interesante. Se trata de poder invocar Web Services a través de SOAP.

El objetivo de este post es mostrar cómo la aplicación Meta4 también puede funcionar como un cliente SOAP que realiza peticiones a un determinado servicio SOAP y traspasa los datos requeridos a los Meta4Objects ya definidos.

Meta4 como cliente SOAP tiene algunas restricciones, ya que no es capaz de consumir todos los servicios SOAP que existen descritos por un WSDL cualquiera. Esto es así, porque Meta4 no puede convertir una estructura de datos arbitraria en un Meta4Object, solamente soporta un subconjunto de tipos.

Meta4 como cliente SOAP es capaz de interpretar los tipos básicos más significativos de SOAP http://www.w3.org/tr/xmlschema-0/ , así como un subconjunto de tipos complejos.

Los tipos complejos que Meta4 puede consumir deben ser estructuras mixtas o vectores de una dimensión de estructuras mixtas. Se define estructura mixta como un objeto compuesto por tipos básicos, estructuras simples (compuestas únicamente por tipos básicos) u otras estructuras mixtas.

Esto significa que Meta4 no es capaz de consumir matrices multidimensionales o vectores de tipos básicos.

Con respecto a los ficheros, Meta4 no los consume. Pero existe una excepción: si los ficheros provienen de una implementación concreta (Axis DataHandler), Meta4 los consume sin ningún problema, tanto de entrada como de salida.

Principalmente hay dos tipos de servicios:
  • rpc/encoded
  • document/literal

Por el momento Meta4 no consume servicios Document/Literal.

Para realizar el ejemplo que se desarrollará en este documento utilizaremos una arquitectura que consta de los siguientes componentes atendiendo a la Guía de Certificaciones:

  • Contenedor Web: Tomcat 5.0.28
  • Motor SOAP: AXIS 1.1
  • Java Virtual Machine: j2sdk1.4.2

Además utilizaremos un “TCPMonitor” (ver punto 4 del documento) que es una utilidad que escucha en un puerto y monitoriza todo lo que se reciba y se mande por él, y lo redirecciona automáticamente al puerto correcto.

Como el documento es largo en vez de añadirlo como Post lo adjunto. Link

Como podreis ver no resulta tan sencillo como aparece en la documentación de Meta4. Si alguien lo ha conseguido de otra forma y quiere compartirla estaré encantado de escribirlo en el blog... así como conseguir que sea Meta4 PeopleNet quien provea de estos Web Services (SOAP).

Espero que sea útil.
SEGURO QUE LO ES... Muchas gracias Jaime!!

miércoles, 22 de octubre de 2008

[Colaboración de Lucas Gutiérrez Jaramillo - Ceiba Software House] Cambiar el color de las celdas de Excel desde PeopleNet

Lucas Gutiérrez Jaramillo de Ceiba Software House (http://www.ceiba.com.co/), me ha enviado la información necesaria para crear un post que creo que os resultará muy interesante. Se trata de poder cambiar propiedades de celdas de un Excel desde una regla LN4 de Meta4 PeopleNet, en este caso el color.

Antes de empezar es muy recomendable que leais también el post Macros Excel en LN4.

Lo primero consiste en heredar el objeto de Excel, para no trabajar sobre el original, luego se creará una nueva estructura de nodo para obtener el objeto "Interior" de la celda a la que queremos colorear. Esta estructura estará ubicada dentro de un nodo hijo del nodo EXCEL_CELLS, ya que este dependerá de la celda seleccionada. Esta estructura se llamará CCB_EXCEL_INTERIOR.


Estructura final, con métodos y propiedades


La nueva estructura debe conectarse con las su padre de la siguiente manera para que las referencias sean correctas.


Conectores

Las estructuras deben tener una propiedad para apuntar a cada nivel según su jerarquía en el árbol del objeto por cada nivel se agrega un grandparent (abuelo) mas.

Una vez teniendo la estructura correctamente se crean los métodos para la obtención del objeto "Interior". Estos dos métodos son: GETINTERIOR y GETINTERIORINT

GETINTERIOR es un metodo del tipo LN4, que crea un nuevo registro y luego llama al método GETINTERIORINT que es el que realmente hace el llamado al objeto de Excel. A continuación se ilustra como es este método:


Método GETINTERIOR


Código de GETINTERIOR

GETINTERIORINT es el wrapper (envolvente) del método de la dll que hace el verdadero llamado a Excel para obtener el objeto Interior. Este método hace el llamado a la función GetObjectFromProperty. Esta función obtiene el objeto Interior de la propiedad Interior (Llevan el mismo nombre) del objeto Range, el cual es el tipo de objeto que se obtiene desde PeopleNet al llamar el metodo EXCEL_CELLS.GetCell(x,y) del objeto Excel. Según esto, primero se debe llamar obtener la celda (Objeto Range en Excel) y luego obtener el interior de la celda (Objeto Interior en Excel).

Método GETINTERIORINT

Código de GETINTERIORINT

Por último el método COLORINDEX, este método es el wrapper del método de la dll que cambia la propiedad ColorIndex del objeto Inerior. Este método en la dll se llama OLE_Property, este hace el llamado a la propiedad según el nombre del método, por eso el método debe llamarse igual que la propiedad que se desea modificar (No es case sensitive). Si se deseara modificar otra propiedad de este objeto simplemente se crea el método con el nombre de la propiedad que se desea modificar. Se debe tener en cuenta que si esta propiedad es un objeto, debe obtenerse el objeto de la misma manera que se obtiene el objeto Interior, y no puede asignarse directamente.

Método COLORINDEX

Código de COLORINDEX

Por último, Lucas comenta: "mucho de lo que se dice en este post son conclusiones obtenidas sobre la marcha al momento de implementar esta funcionalidad, todas basadas en mi trabajo anterior en interacciones con Excel desde otras aplicaciones, y en como hasta ahora he visto que se trabaja en PeopleNet. Es así como pueden estar erróneas y si es del caso estoy abierto a que cualquiera que conozca el verdadero funcionamiento me corrija.

Espero que les sea útil."
SEGURO QUE LO ES... Mucha gracias Lucas

miércoles, 17 de septiembre de 2008

Macros Excel en LN4

(Sacado del CSS de Meta4 y ampliado)

El número de métodos del objeto Excel es muy limitado, por lo que en ocasiones, se puede requerir la utilización de nuevos métodos de EXCEL accesibles vía OLE, a través de la OLEEXEC.DLL.

El Meta4Object Excel instancia un objecto aplicación en el nodo raíz y una colección Workbooks en el nodo hijo. En esa colección no se soportan más que unos pocos métodos (Add, close ...), dado que los métodos de operaciones con hojas de cálculo, no están implementados a nivel de colección, sino a nivel de instancia, la cual sin embargo no está accesible.

Así pues lo primero, tras una llamada de la colección a "Add", que es cuando se crea la nueva hoja de cálculo, es cuando se puede obtener el handle de objeto Workbook instanciado dentro de la colección Workbooks. Como no se tiene referencia directa, se puede obtener, por ejemplo, utilizando la jerarquía de clases de Excel, utilizando la propiedad "ActiveWorkbook" de la clase "Application", para obtener el Handle de la hoja de cálculo. Si hacemos llamadas en el nodo raíz, nos devolvería el Handle en la misma propiedad que donde se ha almacenado el handle propio de la clase aplicación, y se perdería. 

  • Créate un Meta4Object nuevo, CSL_EXCEL que herede del Meta4Object EXCEL estándar. (Podrías tocar el propio Meta4Object EXCEL estándar pero mejor hacerlo así)
  • Mapealo y colocalo en el arbol de ejecución, para que las llamadas a EXCEL se hagan siempre contra tu Meta4Object.
  • Crea un nuevo nodo nodo y su estructura de nodo, que se debe crear a la misma altura que EXCEL_WORKBOOKS, por ejemplo ACTIVE_WORKBOOK. Se añaden las propiedades ERRORS, InterfacePointer y ParentInterfacePointer como en el nodo EXCEL_WORKBOOKS. En la tercera, se almacena el puntero del nodo padre a través del conector, conectando con la propiedad InterfacePointer del nodo raíz para leer el handle de la clase Application (nodo EXCEL).


  • Para implantar la llamada a la propiedad "ActiveWorkbook", debe llamarse a la función GetObjectFromProperty. Para ello, se crea un método (por ejemplo GET) de tipo DLL que referencie el recurso "OleExec.dll", método "GetObjectFromProperty", con un parámetro.
  • Para realizar la llamada, crea un método  (por ejemplo INICIALIZAR) de tipo ln4 en el mismo nodo, realizar el siguiente código; 
AddRegister()
MoveTo(Count()-1)
Get("ActiveWorkbook")
  • Sobre éste nodo, con el valor de InterfacePointer conseguido, se pueden realizar llamadas a los métodos de la clase "WorkBook", creando un método que ejecute la llamada "SaveAs". El método debe llamarse EXACTAMENTE IGUAL que la función que se quiera invocar a través de OLE. En este caso SAVEAS, con código DLL, y recurso "OleExec.dll", método "OLE_Execute" (se llama a la ejecución OLE del método cuyo nombre venga determinado por el identificador del item). Se debe indicar que tenga un parámetro que será la ruta de grabación. Posteriormente podrá ser invocado de la siguiente manera:

EXCEL!ACTIVE_WORKBOOK.INICIALIZAR()
EXCEL!ACTIVE_WORKBOOK.SAVEAS(“c:\MiArchivoExcel.xls”)

Adjunto la definición de los métodos creados:
Método GET:

Método INICIALIZAR:
Método SAVEAS:




Espero que os sirva...

viernes, 12 de septiembre de 2008

Función DELAY en LN4

Me temo que hasta la versión 7.1 SP002 no se libera una función LN4 que permita hacer un DELAY, una pausa de x segundos. Parece que entonces se llamara SLEEP

De todas formas se puede crear una fucnión, un método, que simule este comportamiento. Para ello, create un método llamados DELAY, de ámbito nodo y con un argumento ARG_NUM_SEGUNDOS de tipo numérico sin decimales, y le añade este código:

MnNumSegundos = ARG_NUM_SEGUNDOS  
MdSalida = DateAdd(TodayNow(), MnNumSegundos , M4_SECOND ) 
While MdSalida >= TodayNow()     
  'Bucle de tiempo 
WEnd 
Return M4_SUCCESS  

Para ejecutarlo luego,  sólo necesitas indicarle cuantos segundos quieres que esté "esperando":

DELAY(5)

Fácil, ¿no?

lunes, 8 de septiembre de 2008

Planificación de ejecución de Meta4Objects

Sois bastantes los que me habéis preguntado cómo se puede delegar en el Planificador de Tareas (Job Scheduler) la ejecución de métodos de un Meta4Object.

Aquí redacto una forma de hacerlo. Esta forma no permite al usuario "final" la planificación de tareas de forma sencilla... necesita tener un poco de conocimiento. De todas formas para permitir a un usuario planificar ejecuciones contra el Planificador de Tareas desde un método Ln4, puedes consultar este post "Ejecución de Meta4Objects planificados en el Job Scheduler"

Imaginemos que disponemos de un Meta4Object llamado CXX_MI_META4OBJECT que en su nodo principal, CXX_MI_NODO, dispone de un método CXX_GESTION que realiza la carga del nodo y si hay información resultante de la carga envía un mail. Queremos que se ejecute todos los días a las 00:00 para controlar cierta información.

Nota: Haz click en las imagenes para verlas más grandes

a) Accederemos, inicialmente al Planificador de Tareas:



b) Pulsaremos en "Nuevo" para crear una nueva Tarea:


c) Rellenaremos todos los datos de la primera pestaña de la definición:

Son:
  • Planificación: Crearemos un ID Planificación nuevo: (i.e.) CXX_PLANIFICACION
  • Descripción: Crearemos una descripción que nos inforque que es lo que hace
  • Prioridad: En general "Normal" pero en función de tus necesidades puedes cambiarlo ("No urgente","Urgente"  o "Muy urgente")
  • Cola de ejecución: Podemos elegir entre los M4AppServers conectados a nuestra Base de Datos para decidir quien lo debe ejecutar. Podemos elegir, por ejemplo, un M4AppServer que corra sobre una máquina Windows para ejecutar exportaciones a Excel que una máquina UNIX o AIX sería imposible.

d) Rellenaremos todos los datos de la segunda pestaña de la definición:


Modificaremos:
  • Modo: "Inmediato" para una única ejecución, "Cíclico" hasta 500 ejecuciones que sigan algun patrón (todos los días, todos los martes,...), "Plan Anual" para ejecuiones que sigan planes anuales (1er, o último día meses pares, primer lunes de cada mes, cada 25 de cada mes,...) o "Lista de fechas" planficiaciones hechas para fechas concretas sin seguir patrón.
  • En cada uno de los casos existe diferentes opciones de planificación.
e) Rellenaremos todos los datos de la tercera pestaña de la definición, donde elegiremos una tarea llamada "Execute LN4 Code":



f) Rellenaremos todos los datos de la cuarta pestaña de la definición: 


Haz click en el campo de texto "Valor / Fuente" y pegaremos el siguiente código (link):




g) Rellenaremos todos los datos de la quinta pestaña de la definición, donde podremos indicar para que Sociedad se debe ejecutar este método (en mi caso sólo tengo una): 


h) Por último, inidicaremos en la sexta pestaña de la definición si deseamos, o no, estadísticas de la ejecución.  


Pulsaremos en "Finalizar" y PeopleNet nos avisará de la planificación de esta tarea


Ya está... espero que sea interesante.

jueves, 29 de mayo de 2008

Ejecución de Meta4Objects planificados en el Job Scheduler

Un truco que quizás ya sepais pero que viene bien tenerlo en cuenta. Se trata de poder ejecutar un método de un Meta4Object usando el Job Scheduler.


1er Caso: Ejecución de un método a través de una tarea


Este es el sencillo, creamos una tarea con código LN4 y le añadimos el código:


'Proceso:
Code = ""
MsT3 = "MI_M4OBJ"
MsNodo = "MI_NODO de MI_M4OBJ"
MsMetodo = "MI_METODO de MI_NODO de MI_M4OBJ"
DefineInstance(MsT3,MsT3,0,1)
Code=MsT3 + "!" + MsNodo + "." + MsMetodo + "()"
X=clcExecuteLN4JIT(Code)
Return(X)


De esta forma se ejecuta el método ID_ITEM del nodo ID_NODE del Meta4Object ID_CHANNEL. Planificamos luego con el Job Scheduler la ejecución de esta tarea como necesitemos.


Como podeis ver el método de este ejemplo no tiene parámetros.

Para añadir parámetros:
'Parámetros:
MsIDHR = MsDQ + STD_ID_HR + MsDQ
'Proceso:
MsDQ = CHR(Double_quote)
Code = ""
MsT3 = "MI_M4OBJ"
MsNodo = "MI_NODO de MI_M4OBJ"
MsMetodo ="MI_METODO de MI_NODO de MI_M4OBJ"
DefineInstance(MsT3,MsT3,0,1)
Code= MsT3 + "!" + MsNodo + "." + MsMetodo + "("+ MsIDHR + ")"
X=clcExecuteLN4JIT(Code)
Return(X)

Nota: Puedes consultar el post "Planificación de ejecución de Meta4Objects" para ver cómo se puede planificar este tipo de tareas en el Job Scheduler.

2º Caso: Ejecución de un método introducciendo valores desde un Meta4Object


Este caso me encanta y lo uso mucho... se trata de meter código en un Meta4Object y que se ejecute mediante el Job Scheduler. Por ejemplo lo uso para la generación de informes a texto muy grandes (contabilidad, nómina) y que los envíe a una dirección de correo electrónico que le indico (podría valer para Excel pero el servidor debe disponer de Ms Officce instalado):

'Parámetros:

MsMaildondeEnviar = "oscar.lopezgrandmontagne@gmail.com"
MsFechaCalculo = ToString(DT_PAYMENT,0)

'Proceso:
MsT3 = "MI_M4OBJ"
MsNodo = "MI_NODO de MI_M4OBJ"
MsMetodo = "MI_METODO de MI_NODO de MI_M4OBJ"

MsAlias = "NEW_" + MsT3
MsDQ = CHR(Double_quote)
MsCodeJS = "DefineInstance(" + MsDQ + MsAlias + MsDQ + "," + MsDQ + MsT3 + MsDQ + ", 0, 1):"
MsCodeJS = MsCodeJS + "MsDate = " + MsDQ + MsFechaCalculo + MsDQ + ":"
MsCodeJS = MsCodeJS + "MsMail = " + MsDQ + MsMaildondeEnviar + MsDQ + ":"
MsCodeJS = MsCodeJS + "MsCode = " + MsDQ + MsAlias + "!" + MsNodo + "." + MsMetodo + "(MvDate,MvMail)"+ MsDQ +":"
MsCodeJS = MsCodeJS + "MsReturn = clcExecuteLN4JIT(MsCode," + MsDQ + "MvDate" + MsDQ + ",MsDate," + MsDQ + "MvMail" + MsDQ + ",MsMail):"
MsCodeJS = MsCodeJS + "Return(MsReturn)"
MsTarea = JOB_SCHEDULER!N_JOB_GROUP_DEFS.SUBMIT_JOB("EJECUCION MI INFORME", MsCodeJS ,"ASAP")
SetLog(0,16,110,11,ToString(Format(MsTarea ,0)))
Return (M4_SUCCESS)


Hay que definir un Alias de Meta4object "JOB_SCHEDULER", para poder planificar la tarea.
Espero que os sirva de ayuda


martes, 27 de mayo de 2008

Ejecución de un script SQL desde Meta4

Usando el método EXECUTEREALSQL que ya definimos en otro post, es posible usar un método que lance un script de SQL como si de un TOAD se tratara.

Haremos lo siguiente:

  • En un método (ambito cliente), primero abriremos un fichero de texto (scipt.sql) y, segundo, dejaremos el contenido en la variable MsScript:


MsFile = "C:\temp\script.sql"
OpenFile(MsFile,handle)
ReadFile(handle, chr(0), MsScript)

  • Leeremos el fichero que separa las sentencias por ";" y las ejecutaremos usando el método EXECUTEREALSQL:

MsRest = MsScript
While length(MsRest )>0
MnSeparador = indexof(MsRest,";",0)
If MnSeparador <> M4_ERROR Then
MsToExec = Mid(MsRest ,0,MnSeparador )
MsRest = Mid(MsRest,MnSeparador + 1, length(MsRest)-MnSeparador -1)
EXECUTEREALSQL = MsToExec
MnRdo = EXECUTEREAL(0)
If MnRdo = M4_ERROR Then MessageBox("ERROR",MsToExec)
Else
EXECUTEREAL = MsScript + ";"
MnRdo = EXECUTEREALSQL (0)
If MnRdo = M4_ERROR Then MessageBox("ERROR",MsToExec)
EndIf
WEnd

Return M4_SUCCESS

Espero que os sirva

lunes, 5 de mayo de 2008

EXECUTEREALSQL

La ejecución del Método EXECUTEREALSQL permite interactuar directamente con la Base de Datos física, para, por ejemplo, ejecución de PL/SQL o sentencias directatas contra objetos tales como INSERT, UPDATE y DELETE.

Para ello hay que crear un concepto llamado EXECUTEREALSQL de ámbito Nodo, Tipo Long. En las propiedades avanzadas ponemos “Argumentos variables” a “”. Como regla creamos una de tipo CPP y en su método le indicamos que vamos a usar es: “executerealsql”. Creamos un argumento llamado ID_CONN de tipo número y tamaño 4.

En un método aparte creamos una sentencia a lanzar contra la base de datos y lo ejecutamos de la siguiente forma:

MsSQL = "INSERT INTO NUESTRA_TABLA (PK,CAMPO1,CAMPO2,CAMPO3) VALUES ('" + STD_ID_PERSON+"','" + STD_N_FAMILY_NAME_1 + "," + STD_N_FIRST_NAME + "'," + ToString(EDAD,0) + ",'" + MsDate + "')"

EXECUTEREALSQL = MsSQL
MsRdo = EXECUTEREALSQL(0)


En este ejemplo metemos en una tabla un valor numérico: “EDAD” y una fecha como cadena “MsDate”; para componer la fecha podemos usar:

MdDate = Today()
MsDay = ToString(DxDay(MdDate),0)
MsMonth = ToString(DxMonth(MdDate),0)
MsYear = ToString(DxYear(MdDate),0)
MsDate = MsDay + "/" + MsMonth + "/" + MsYear


Si queremos usar varias sentencias seguidas podemos encapsularlas en un PL y entonces la llamada será:

MsSQL = "BEGIN NUESTRO_PL ('" + ARGUMENTO1+"', '" + ARGUMENTO2+"','");END;"

EXECUTEREALSQL = MsSQL
MsRdo = EXECUTEREALSQL(0)

O podemos hacer varias llamadas enlacadas:

MsSQL = "DELETE NUESTRA_TABLA"

EXECUTEREALSQL = MsSQL
MsRdo = EXECUTEREALSQL(0)

If MsRdo <> M4_ERROR Then
MsSQL = "INSERT INTO NUESTRA_TABLA (PK,CAMPO1,CAMPO2,CAMPO3) VALUES ('" + STD_ID_PERSON+"','" + STD_N_FAMILY_NAME_1 + "," + STD_N_FIRST_NAME + "'," + ToString(EDAD,0) + ",'" + MsDate + "')"

EXECUTEREALSQL = MsSQL
MsRdo = EXECUTEREALSQL(0)
EndIf
Tiene un problema y es que las cosas que controla la Base de Datos Lógica, digase, completitud, datos "no null", fechas,... las debemos controlar nosotros. Además sino lo hacemos nosotros los campos de control de ID_SECUSER, ID_APPROLE o DT_LAST_UPDATE no se actualizan.
Ojo con usarla de "mala manera" con entornos con AUDITORIA ya que tampoco se actualiza.

viernes, 28 de marzo de 2008

CXX_AUX_ITEMS para Estructuras de Nodo con Herencia

En el post dedicado a la exportación genérica a Excel (link) o a texto (link), no me fijé en un pequeño detalle, y es que la sentencia de la estructura de nodo,CXX_AUX_ITEMS, que recupera los items a exportar de una estructura de nodo no funciona de forma correcta cuando ésta ha sido heredada.


Aquella era:

mientras que debería ser para cualquier estructura de nodo (heredada o no):

Los cambios residen en:

  • Añadir la tabla lógica "SCH_TIS_INHERIT" (usando una relación personalizada sin unión, de momento entre ningún campo)
  • Cambiar el filtro para que: "A.ID_TI = @ARG_ID_TI" pase a ser: "( A.ID_TI = @ARG_ID_TI Or ( A.ID_TI = B.ID_TI_BASE And B.ID_TI = @ARG_ID_TI ))"

Espero que os sirva. Yo ya la usé el pasado lunes :-)

sábado, 1 de marzo de 2008

WebServices y Meta4 (SOAP)

Esta vez no voy a publicar una "ayuda" sino que la voy a pedir... :-(

Según la documentación de Meta4, PeopleNet es capaz de proveer y consumir WebServices, siento decir que "según la documentación" por que lo estamos intentando hacer y no hay manera.

Si alguien ha trabajado con WebServices y Meta4 (SOAP) por favor, que se ponga en contacto conmigo: oscar.lopezgrandmontagne@gmail.com, para que nos ayude, ya que lamentablemente desde soporte de Meta4 no pueden hacerlo... Es algo URGENTE porque tengo al cliente esperando.

MUCHAS GRACIAS!!!

miércoles, 30 de enero de 2008

Exportación genérica a fichero de texto

Para completar el post que escribí sobre la Exportación genérica a Ms Excel (link) escribo este otro para ver como tener un método que te exporte las cosas a un fichero de texto plano.

Yo lo uso, entre otros casos, cuando en un cliente, con servidor en entorno Unix (Solaris o AIX)quieren consultas en Ms Excel, pero éstas son muy grandes y claro en el servidor no las pueden sacar. Yo monto una exportación en servidor a texto y luego la envío por correo... Bueno es un ejemplo, pero hay más...

A lo que voy que me lío :-)

Debes leer el post al que me refería antes (Exportación genérica a Ms Excel). Haces lo mismo, pero la regla del método CXX_EXPORT_EXCEL la cambias por esta: CXX_EXPORT_TXT. (Yo las suelo poner las dos... y que se el usuario quien elija, ¿no?)

Esto te saca a un txt el contenido de un nodo completo.

Ahora, si en el método cambias el código:


MsCaracterSep = ";"

por

MsCaracterSep = Chr(M4_TAB)

y quitais el "encabezado":


InitFile(MsFile,MsTitle)
ConcatFile(MsFile,"")


y el "pie":


ConcatFile(MsFile,"")
ConcatFile(MsFile,"Fecha impresión: " + MsDay + "/" + MsMonth + "/" + MsYear + " " + MsHour)


...se puede abrir con Ms Excel, sin problemas de importación.

Como siempre, espero que os sirva...

lunes, 21 de enero de 2008

Ejecutable externo desde una regla de un método

Para llamar a un ejecutable externo desde una regla de un método LN4, esto es lo que se hace:
  1. Crear un método de tipo DLL, cuyo recurso empleado sea "m4jsutils" y el método "ExecuteProgram". Hay que definir también un argumento de tipo Long.
  2. Una vez creado este método tan solo hay que llamarlo desde el que se desee ejecutar, pasandole la ruta y el nombre del programa externo, por ejemplo:

EJECUTAR("c:\winnt\system32\notepad.exe")

ó

CXX_RUTA_EJECUTABLE = "c:\winnt\system32\notepad.exe"
EJECUTAR(CXX_RUTA_EJECUTABLE)


Donde EJECUTAR es el método que registra la DLL y donde CXX_RUTA_EJECUTABLE puede ser una propiedad o campo por la que introducir la ruta en Tiempo de ejecución desde la presentación.

Nota (gracias a Franco Tarchini, Colombia): para rutas con directorios cuyo nombre sea mayor de 8 caracteres hay que usar los 6 primeros caracteres de dicho directorio más el caracter "~" (alt + 126) y un número correlativo al número de directorios que contengan esa raiz de 6 caracteres. Por ejemplo:

"c:\Archivos de programa\" equivale a "c:\Archiv~1\"

Espero que os sea de utilidad...

viernes, 18 de enero de 2008

Certificado de Haberes en PDF para el ESS - Portal del Empleado

(Ampliando el post: Obtener un informe de Meta4 en el ESS/MSS)

En estas fechas son muchos los clientes que nos piden que podamos sacar el Certificado de haberes en el Portal. En algunas versiones del Portal ya está incluído pero no sale en PDF de tal forma que un empleado pueda llevarselo e imprimirselo... (incluso sería posible firmarlo digitalmente usando librerias externas como iText)

Estos son los pasos para poder obtener el Certificado en PDF en el ESS.

  • Partimos del Meta4Object estándar "SSP_RP_CERT_HAB" o del que hayamo heredado en nuestro cliente:

  • Creamos en el nodo SSP_RP_C_HABERES una propiedad SSE_EJECUCION, de ámbito nodo, no visible, cadena variable de tamaño 1, con valor po defecto 0, que rellenaremos cuando ejecutamos el informe desde el ESS - Portal del empleado.

  • Creamos un Alias de Meta4Object (si no lo está creado ya) para el Meta4Object SCH_SESSION, en el nodo SSP_RP_C_HABERES, para recuperar el ID Persona del empleado logado al ESS - Portal del empleado.

  • Creamos un método también en el nodo SSP_RP_C_HABERES llamado SSE_FILTRO, ámbito nodo, tipo número de 1 posición entera, y que contendrá el siguiente código: link (NOTA: si tiene herencia hay que sobrescribir la regla para que tire del nodo que corresponda si dicho nodo está tocado)

  • Creamos el conector para que ejecute el método SSE_FILTRO antes del LOAD_PRG o de la LOAD_BLK (en la regla indicamos que si es del ESS - Portal del empleado ejecute dicho método y si no es del ESS - Portal del empleado que se quede como está).

  • Creamos un link en la página correspondiente desde la cual queremos ejecutar el Informe. Yo lo haré desde el portal (/sse_generico/espanol/generico_portal.jsp) mediante:

<li><a class="enlacefuncional" title="Certificado 10T" href="/servlet/CheckSecurity/JSP/sse_g2/sse_g2_certpdf.jsp?estado=21">Certificado 10T</a></li>

  • Creamos una página similar a la que aparece a continuación y que es llamada por el link de la anterior: sse_g2_certpdf.jsp (NOTA: Esta página puede mejorar sensiblemente, ya que aparece como un paso intermedio entre el link y la visualización del pdf. Si quisiera saltarse el paso no vale con un simple openwindow cuando se abre la página porque no le da tiempo al pdf a crearse y sale a medias. Deberíamos poner un retardo y luego abrir la página.)

Si usais una plantilla o logos o imágenes para "pintar" el certificado, recordad que esto archivos deben estar colocados en las rutas de reports (en la parte de color y b&w) del servidor de aplicaciones de Meta4 que genera el report/informe.

Espero que os salga bien y si alguien está interesado en saber como firmar digitalmente reports/informes de Meta4 en el ESS/MSS como este, que por favor, que deje un comentario en el post.

viernes, 30 de noviembre de 2007

Teoría: Indirección

La indirección, permite entre otras muchas cosas multiplicar la potencia de muchos procesos...

Los ejemplos más claros son los de guardar en una tabla de parametrización una serie de registros con información de TI (Estructura de nodo) y campos, de tal forma que al recorerlos podamos generar nuevas salidas.

Existe por otro lado una leve desventaja y es que Meta4 PeopleNet, no puede generar dependencias por indirección, por lo que perderemos la funcionalidad de la pestaña de los items "Dependencias" para aquellos items que, como ya he dicho, se vean involucrados en llamadas de indirección.

Las funciones Ln4 más comunes que se suelen usar son:

  1. Call

    • Para llamadas a métodos o conceptos; Call(Argumentos, Nodo, Metodo); por ejemplo: Call(0,"CXX_NODO","MOVETO") o Call("CXX_NODO","BEGIN"). Hasta se pueden anidar: Call(Call("CXX_NODO","GETCURRENT") + 1 ,"CXX_NODO","MOVETO")

  2. GetItem
    • Para poder recuperar valores de campos, conceptos o propiedades GetItem(Nodo,Item,Registro); por ejemplo: GetItem("CXX_NODO","CAMPO1",0). También se puede usar GetItem("CXX_NODO","CAMPO1",-1) para recuperar valores de ámbito nodo o bloque.

  3. SetItem
    • Para poder insertar valores en campos, conceptos o propiedades SetItem(Nodo,Item,Registro,Valor); por ejemplo: SetItem("CXX_NODO","CAMPO1",0,NullValue()).

Otras funciones muy usadas serían las que nos permitirán saber desde código Ln4 el ID del nodo o del Meta4Object en el que nos encontramos: GetThisNodeID() y GetChannelID() respectivamente.

Un ejemplo de tratamiento de datos con indirección lo tenéis en: Post:Exportación genérica a Ms Excel

jueves, 29 de noviembre de 2007

Importación desde un Ms Excel

La forma rápida que la gente hace es pasar la hoja de Ms Excel a texto y luego usar las importaciones... pero eso a veces no es posible porque lo debe hacer el usuario y no un desarrollador. (Recordemos que las importaciones son una herramienta del desarrollador (M4DevClient) y no de usuario (M4DistClient o RichWeb))

Yo utilizo una forma que la verdad es rápida y permite hacer comprobaciones según se importa información.

Un ejemplo; los usuario de RRHH reciben todas las semanas una hoja Ms Excel con un listado de los nuevos teléfonos dados por el dpt. de sistemas, es decir, vamos a importar números de teléfono de tipo "Oficina" de un hoja Ms Excel donde el formato es el siguiente: DNI (en la columna A) y Teléfono (en la columna B).


Para ello crearemos un M4Object CXX_IMPORTAR_TELEFONOS con 3 nodos:

CXX_IMP_TEL_ROOT (Nodo principal) -> No tendrá campos, servirá para la ejecución de la importación. Creamos:

  • una propiedad llamada CXX_EXCEL_FILE; de ámbito nodo y tipo long (es donde el usuario podrá dejar la ruta al excel a importar que se pedirá en presentación)
  • un método llamado CXX_IMPORT de ámbito nodo, con el siguiente código: >CXX_IMPORT.TXT

CXX_AUX_PERSONA (Nodo libre) -> Cargaremos los datos de la persona por DNI (STD_SSN).

  • Añadiremos una propiedad: PRP_STD_SSN, de ámbito nodo, tipo cadena variable de 11 posiciones y NO visible.
  • La sentencia será: SELECT @STD_ID_PERSON = A.STD_ID_PERSON, @STD_SSN = A.STD_SSN FROM &STD_PERSON A WHERE (A.STD_SSN = @PRP_STD_SSN).
  • Crearemos un método: CXX_GET_ID_PERSON(ARG_STD_SSN cadena variable de 11 posiciones) ambito nodo, tipo cadena variable de 9 posiciones. El código será el siguiente: CXX_GET_ID_PERSON.TXT

CXX_IMP_AUX_PHONE (Nodo libre) -> Guardaremos el nuevo teléfono.

  • La sentencia será: SELECT @STD_ID_PERSON = A.STD_ID_PERSON, @STD_DT_START = A.STD_DT_START, @STD_DT_END = A.STD_DT_END, @STD_ID_LOCATION_TYPE = A.STD_ID_LOCATION_TYPE, @STD_ID_LINE_TYPE = A.STD_ID_LINE_TYPE, @STD_PHONE = A.STD_PHONE FROM &STD_PHONE_FAX A

La presentación, CXX_IMPORTAR_TELEFONOS quedaría algo así como:



Como temas especiales los dos botones tendrían estos códigos OBL:

a) "Abrir explorador de windows" (Botón de la carpeta) bttBROWSER.txt

b) "Visualizar el documento" (Botón de la lupa) bttVIEW.txt

Espero que os sirva