lunes, 18 de julio de 2016

[JD Edwards] Custom Login Page

If you want customize your E1 Login Page you can access to resources in the next directory in web server:

/u01/oracle/middleware/oracle_home/user_projects/domains/e1_domain/servers/JASPD/stage/JASPD/app/webclient.war/share

When:
- /u01/oracle/middleware/oracle_home/: is a JD Edwards installation (in my case 9.2 tools)
- JASPD: web instance

In share directory you can find all resources as images (backgrounds, icons, etc.), pages, scripts, etc.

For example, I changed tipically "watermark-oracle.png" for a custom image as background.

It is cool!!!!

[JD Edwards] Personalizar Página Login

Si quieres personalizar tu página de login de E1 tu puedes acceder a sus recursos en el siguiente directorio del servidor web:

/u01/oracle/middleware/oracle_home/user_projects/domains/e1_domain/servers/JASPD/stage/JASPD/app/webclient.war/share

Donde:
- /u01/oracle/middleware/oracle_home/: es la instalación de JD Edwards (en mi caso tools 9.2)
- JASPD: instancia web

En el directorio share, tu puedes encontrar todos los recursos como imágenes (fondos, iconos, etc.), páginas, scripts, etc.

Por ejemplo, yo cambié el típico "watermark-oracle.png" por una imagen personalizada como fondo:

Ésto es chulo!!!!

lunes, 4 de julio de 2016

[SQLDeveloper] Open multiple tables

When working with databases, we usually use IDE applications for work more comfortable. With Oracle Database the most common is SQLDeveloper

SQLDeveloper allow us doing SQL sentences and graphically display database components: tables, views, triggers, procedures, functions, packages, etc.

Also, when we working with tables, we need view one or more tables at the same time. With SQLDeveloper default configuration each time when we open a table overwrite the same tab of table that we were viewing.

For change the configuration and we can view the tables in different tabs, it's very comfortable, there are activate the next check in preferences:

Tools->Preferences->Data Base-> Object View->Automatically Freeze Object Viewer Windows




And in this way we will see in different tabs:



I hope it will be useful for you!!!

[SQLDeveloper] Abrir varias tablas a la vez

Cuando trabajamos con base de datos, solemos utilizar un IDE para trabajar más cómodamente. Con base de datos Oracle el más habitual es SQLDeveloper.

SQLDeveloper nos permite realizar sentencias SQL así cómo visualizar gráficamente los componentes de la base de datos: tablas, vistas, disparadores, procedimientos, funciones, paquetes, etc.

Además, cuando trabajamos con tablas habitualmente necesitaremos consultar o realizar varias tablas a la vez. Con la configuración por defecto de SQLDeveloper cada vez que abrimos una tabla nos sobreescribe en la misma pestaña la que teníamos visualizando anteriormente.

Para cambiar la configuración y ver todas las tablas en diferentes pestañas, lo cual es bastante cómodo, hay que activar el siguiente check en preferencias:

Herramientas -> Preferencias -> Base de Datos -> Visor de Objetos -> Congelar Automáticamente Ventanas del Visor de Objetos




Y de ésta manera lo veremos en pestañas diferentes:



Espero os sea útil!!!

[JD Edwards] Reserva de Objeto

Cuando un usuario está trabajando con un documento y lo está editando, deberíamos siempre no permitir que ningún otro usuario pueda modificarlo para no se produzca incongruencias. Ésto es lo que se conoce como Reserva de Objetos o Reserva de Documentos.

En JDE en la mayoría de pantallas estándar ésto está implementado, pero cuando creamos una pantalla custom deberíamos tenerlo en cuenta.

¿Cómo JDE realiza ésto?

Muy sencillo, lo que simplemente hace es cuando alguien se propone a editar un documento inserta un registro en la tabla F00095 y no lo elimina hasta que el usuario abandona la edición. De ésta manera, cuando otro usuario entra en otra instancia de la misma aplicación comprueba si existe el registro en la tabla F00095, de ser así muestra un error y bloquea para no permitir editar.

¿Qué hay que hacer?


Bien, entonces utilizando la función estándar "F00095 Reserve Object" con el UKID "RRESERVE", y normalmente con los valores claves del documento que estemos trabajando, ésta función realiza 2 cosas: por un lado comprueba si ya está reservado o no, y en caso de que no inserta el registro, o lo que es lo mismo lo reserva. En caso de que esté reservado, utilizamos la función "Set Object Reservation Text Substitution Error" para mostrar un error en la pantalla y además sería más deseable y más limpio que bloqueáramos todos los campos de la pantalla.

Ejemplo:


0080       //
0081       //  # Reserva #
0082       //
0083       // Cogemos un UKID (RRESERVE) de la F00022
0084       //
0085       Get Next Unique Key ID
              "RRESERVE" -> BF szObjectName
              VA frm_UniqueKeyIDInternal_UKID <- BF mnUniqueKeyID
0086       //
0087       // Lo convertimos a string para pasarselo a la función de reserva parámetro
0088       // PID
0089       //
0090       Math Numeric to String, Convert
              VA frm_UniqueKeyIDInternal_UKID -> BF mnMathNumeric01
              VA frm_szUniqueIDRecReserve_PID <- BF szVideoConstant30A
0091       //
0092       // Cogemos como clave el id de incidencia
0093       //
0094       VA frm_GenericKey_GENKEY = [FI mnIdentificadorIncidencia]
0095       //
0096       // Lo reservamos, pasándole usuario, clave, tabla, PID Único
0097       //
0098       F00095 Reserve Object
              "F55N42IC" -> BF szNameObject
              VA frm_UserId_USER -> BF szUserId
              "1" -> BF cSuppressErrorMessage
              VA frm_szRecordReserveErrMsg_DTAI <- BF szErrorMessageID
              VA frm_ReserversNameAlpha_ALPH <- BF szReserversNameAlpha
              VA frm_GenericKey_GENKEY -> BF szGenericKey
              VA frm_szUniqueIDRecReserve_PID -> BF szApplication
              VA frm_szReserversAplication_PID <- BF szReserversApplication
              "1" -> BF cWarningError
0099       //
0100       // Si está reservado, nos lo indicará en ErrorMesageID. Entonces mostramos
0101       // error y deshabilitamos el OK y los campos
0102       //
0103       If VA frm_szRecordReserveErrMsg_DTAI is not equal to <Blank> And VA frm_szRecordReserveErrMsg_DTAI is not equal to <Null>
0104          Set Object Reservation Text Substitution Error
                 VA frm_ReserversNameAlpha_ALPH -> BF szReserversNameAlpha
                 VA frm_GenericKey_GENKEY -> BF szGenericKey
                 VA frm_szReserversAplication_PID -> BF szApplication
                 "2" -> BF cWarningError
0105          Disable Control(HC &OK)
0106          Disable Control(FC 2nd Address Number)
0107          Disable Control(FC Address Book Name)
0108          Disable Control(FC Electronic Address)
0109          Disable Control(FC Phone Number)
0110          Disable Control(FC Fuente Incidencia)
0111          Disable Control(FC Motivo Incidencia)
0112          Disable Control(FC Estado Incidencia)
0113          Disable Control(FC Departamento Incidencia)
0114          Disable Control(FC Comment)
0115          Disable Control(FC Conclusión)
0116       End If

Por supuesto, una vez que finalicemos con la edición (cuando pulsemos el botón OK o Cancel normalmente), tenemos que quitar la reserva (el registro de la F00095) para que no se quede bloqueado y podamos editarlo a futuro mediante la BSFN "F00095 Remove Business Object Reservation".

Ejemplo:

0040    // # Quitamos la reserva
0041    //
0042    // Si la variable PID devuelta es blanco, es porque lo hemos reservado, por lo
0043    // tanto quitamos la reserva pasando el usuario, tabla, clave y PID con el UKI
0044    // unico
0045    //
0046    If VA frm_szReserversAplication_PID is equal to <Blank>
0047       F00095 Remove Business Object Reservation
              VA frm_UserId_USER -> BF szUserId
              "F55N42IC" -> BF szNameObject
              VA frm_GenericKey_GENKEY -> BF szGenericKey
              VA frm_szUniqueIDRecReserve_PID -> BF szApplication
0048    End If
0049    //


Y con ésto minimizamos el impacto de que varios usuarios a la vez trabajen con el mismo documento, algo muy simple y que nos puede evitar de bastantes problemas a futuro!

[JD Edwards] Object Reserve

When a user is working and editing a document, we shouldn't allow other users can modify to avoid inconsistences. It is know as Object Reserve o Document Reserve in JD Edwards.

In the most standard JDE Applications it is implment, but when we create a custom application we should keep in mind

How it's made?

It's easy, jde simply insert a row in F00095 table when a user edit the document, and not deleted until user exit from edition. In this way, when other user in in another application instance check if exist the row in F00095 table, if is true show a error and blocking fields for not allow edit.

What is there to do?


Using "F00095 Reserve Object" business function standard with the UKID "RRESERVE", and normally with document keys values, this function doing 2 things: check if it is reserved or not, if not it reserverd insert a row and reserve. If it reserved, use the bsfn "Set Object Reservation Text Substitution Error" for set a error, and blocking all field of application.
Sample:


0080       //
0081       //  # Reserva #
0082       //
0083       // Cogemos un UKID (RRESERVE) de la F00022
0084       //
0085       Get Next Unique Key ID
              "RRESERVE" -> BF szObjectName
              VA frm_UniqueKeyIDInternal_UKID <- BF mnUniqueKeyID
0086       //
0087       // Lo convertimos a string para pasarselo a la función de reserva parámetro
0088       // PID
0089       //
0090       Math Numeric to String, Convert
              VA frm_UniqueKeyIDInternal_UKID -> BF mnMathNumeric01
              VA frm_szUniqueIDRecReserve_PID <- BF szVideoConstant30A
0091       //
0092       // Cogemos como clave el id de incidencia
0093       //
0094       VA frm_GenericKey_GENKEY = [FI mnIdentificadorIncidencia]
0095       //
0096       // Lo reservamos, pasándole usuario, clave, tabla, PID Único
0097       //
0098       F00095 Reserve Object
              "F55N42IC" -> BF szNameObject
              VA frm_UserId_USER -> BF szUserId
              "1" -> BF cSuppressErrorMessage
              VA frm_szRecordReserveErrMsg_DTAI <- BF szErrorMessageID
              VA frm_ReserversNameAlpha_ALPH <- BF szReserversNameAlpha
              VA frm_GenericKey_GENKEY -> BF szGenericKey
              VA frm_szUniqueIDRecReserve_PID -> BF szApplication
              VA frm_szReserversAplication_PID <- BF szReserversApplication
              "1" -> BF cWarningError
0099       //
0100       // Si está reservado, nos lo indicará en ErrorMesageID. Entonces mostramos
0101       // error y deshabilitamos el OK y los campos
0102       //
0103       If VA frm_szRecordReserveErrMsg_DTAI is not equal to <Blank> And VA frm_szRecordReserveErrMsg_DTAI is not equal to <Null>
0104          Set Object Reservation Text Substitution Error
                 VA frm_ReserversNameAlpha_ALPH -> BF szReserversNameAlpha
                 VA frm_GenericKey_GENKEY -> BF szGenericKey
                 VA frm_szReserversAplication_PID -> BF szApplication
                 "2" -> BF cWarningError
0105          Disable Control(HC &OK)
0106          Disable Control(FC 2nd Address Number)
0107          Disable Control(FC Address Book Name)
0108          Disable Control(FC Electronic Address)
0109          Disable Control(FC Phone Number)
0110          Disable Control(FC Fuente Incidencia)
0111          Disable Control(FC Motivo Incidencia)
0112          Disable Control(FC Estado Incidencia)
0113          Disable Control(FC Departamento Incidencia)
0114          Disable Control(FC Comment)
0115          Disable Control(FC Conclusión)
0116       End If

Of course, when user finished edition (when click OK or cancel button normally), we have to remove reserve (F00095 row) for not blocking and the users could edit in a future by the BSFN "F00095 Remove Business Object Reservation".

Sample:

0040    // # Quitamos la reserva
0041    //
0042    // Si la variable PID devuelta es blanco, es porque lo hemos reservado, por lo
0043    // tanto quitamos la reserva pasando el usuario, tabla, clave y PID con el UKI
0044    // unico
0045    //
0046    If VA frm_szReserversAplication_PID is equal to <Blank>
0047       F00095 Remove Business Object Reservation
              VA frm_UserId_USER -> BF szUserId
              "F55N42IC" -> BF szNameObject
              VA frm_GenericKey_GENKEY -> BF szGenericKey
              VA frm_szUniqueIDRecReserve_PID -> BF szApplication
0048    End If
0049    //


And This minimize the impact of multiple users to simultaneously work with the same document, it's very simple and we have avoid a lot of problems in the future!
And with this funcionality, minimaze the impact for edit some users in the same time

viernes, 1 de julio de 2016

[JD Edwards] Insert Javascript Code in Applications

In one of the latest projects, one of the requirements could easily be solved with JavaScript. But there was never inserted JavaScript code in an application of JD Edwards (I have not had this need).

I knew that it's possible insert HTML code in text blocks, but if you can add HTML code then you could embebed JavaScript!!

So, I was investigating and working in it, and I got add JavaScript in my JDE application!!!

Alert JavaScript from JD Edwards

In some post I read about for 8.90 and later versions you must enable security for it, but in my case I need with JD Edwards 9.2.

Code Example:

     evt_HTML_A030
     evt_iSegmentID_INT01
     evt_Message_ALPH
     evt_WebcenterContentLogin_URL
     OPT: Using Defaults
0001 //
0002 // Initialize Variables
0003 //
0004 VA evt_HTML_A030 = ""
0005 VA evt_iSegmentID_INT01 = 1
0006 //
0007 // Notify the tool that the Information text block contains encoded text.
0008 //
0009 Encode(FC Text Block 100, VA evt_HTML_A030, VA evt_HTML_A030)
0010 //
0011 // HTML & Javascript Code
0012 //
0013 //  
0014 VA evt_Message_ALPH = ""Hello JavaScript!!!""
0015 VA evt_HTML_A030 = concat([VA evt_HTML_A030],"<script type="text/javascript">")
0016 VA evt_HTML_A030 = concat([VA evt_HTML_A030],"function abrirVentana(){")
0017 VA evt_HTML_A030 = concat([VA evt_HTML_A030],"alert(")
0018 VA evt_HTML_A030 = concat([VA evt_HTML_A030],concat([VA evt_Message_ALPH],");"))
0019 VA evt_HTML_A030 = concat([VA evt_HTML_A030],"}")
0020 VA evt_HTML_A030 = concat([VA evt_HTML_A030],"</script>")
0021 VA evt_HTML_A030 = concat([VA evt_HTML_A030],"<button onclick="abrirVentana();">")
0022 VA evt_HTML_A030 = concat([VA evt_HTML_A030],"Alert</button>")
0023 VA evt_HTML_A030 = concat([VA evt_HTML_A030],"<script>")
0024 //
0025 // Add HTML & JS to segment
0026 //
0027 Add Segment(FC Text Block 100, VA evt_HTML_A030, <Default,Default,0,Default>, <No>, VA evt_iSegmentID_INT01)

The next steps will be create my own JavaScript library for separate and organize my JS code, and it allow will be more easier and faster to access JS functions.

Personally, I thint it opens up world of possibilities.

Welcome to Custom JD Edwards Applications, Javascript.

[JD Edwards] Insertar Javascript en Pantallas

En uno de los últimos proyectos realizados, una de las necesidades se podría resolver fácilmente con JavaScript. Pero nunca había insertado código javascript en una aplicación de JD Edwards (tampoco he tenido esa necesidad).

Lo que sí que sabía hasta el momento es que en los text blocks se podría insertar código HTML, pero si puedes insertar código HTML entonces se tenía que poder embeber código JavaScript!

Así que me puse a investigar y trabajar en ello, y pude añadir añadir Javascript!!!

Alert JavaScript from JD Edwards

En algunos post que leí comentan que para versiones superiores a 8.90 hay que habilitar seguridad para ello, en mi caso no fue necesario con JD Edwards 9.2.

Code Example:

     evt_HTML_A030
     evt_iSegmentID_INT01
     evt_Message_ALPH
     evt_WebcenterContentLogin_URL
     OPT: Using Defaults
0001 //
0002 // Initialize Variables
0003 //
0004 VA evt_HTML_A030 = ""
0005 VA evt_iSegmentID_INT01 = 1
0006 //
0007 // Notify the tool that the Information text block contains encoded text.
0008 //
0009 Encode(FC Text Block 100, VA evt_HTML_A030, VA evt_HTML_A030)
0010 //
0011 // HTML & Javascript Code
0012 //
0013 //  
0014 VA evt_Message_ALPH = ""Hello JavaScript!!!""
0015 VA evt_HTML_A030 = concat([VA evt_HTML_A030],"<script type="text/javascript">")
0016 VA evt_HTML_A030 = concat([VA evt_HTML_A030],"function abrirVentana(){")
0017 VA evt_HTML_A030 = concat([VA evt_HTML_A030],"alert(")
0018 VA evt_HTML_A030 = concat([VA evt_HTML_A030],concat([VA evt_Message_ALPH],");"))
0019 VA evt_HTML_A030 = concat([VA evt_HTML_A030],"}")
0020 VA evt_HTML_A030 = concat([VA evt_HTML_A030],"</script>")
0021 VA evt_HTML_A030 = concat([VA evt_HTML_A030],"<button onclick="abrirVentana();">")
0022 VA evt_HTML_A030 = concat([VA evt_HTML_A030],"Alert</button>")
0023 VA evt_HTML_A030 = concat([VA evt_HTML_A030],"<script>")
0024 //
0025 // Add HTML & JS to segment
0026 //
0027 Add Segment(FC Text Block 100, VA evt_HTML_A030, <Default,Default,0,Default>, <No>, VA evt_iSegmentID_INT01)

Los siguientes pasos será crear una librería JavaScript para tener el código por separado y que sea más sencillo y rápido poder acceder a las funciones JS.

Personalmente, creo que ésto abre un mundo de posibilidades.

Welcome to Custom JD Edwards, Javascript.