martes, 4 de octubre de 2011

Dynamics AX: Modificar la companyinfo y arrancar el AOS

Hola de nuevo,

hoy vamos a hablar de una tabla dentro de Dynamics AX que puede darnos más de un quebradero de cabeza: la CompanyInfo.

En esta tabla se guardan datos de la empresa como el nombre, el CIF, la dirección, el teléfono, etc.
Es posible que queramos modificar esta tabla añadiendo más campos, por ejemplo, para marcar las empresas que cumplan cierta condición.
Como es una tabla más de Dynamics AX, para modificarla vamos al AOT y modificamos lo que necesitemos, sin embargo, puede ser que al modificarla no se pueda sincronizar con la base de datos, es decir, cambiamos la tabla en Dynamics AX pero en la base de datos (normalmente SQL Server) sigue estando la versión antigua sin los cambios que hemos hecho (por ejemplo, añadir un campo).

Esto suele pasar porque esta tabla se utiliza cada vez que abrimos Dynamics AX, y muchas veces queda bloqueada por alguna instancia, de tal manera que es imposible modificarla en la BBDD por estar bloqueada, pero sí nos deja modificarla en el AOT y por tanto queda una inconsistencia.

Si cometemos la torpeza de salir de Dynamics AX sin haber sincronizado la tabla, y reiniciar el AOS (servicio de Windows que provee la capa de servidor de Dynamics AX) lo que tendremos es que el AOS no consigue arrancar.. y ya no podemos entrar en Dynamics AX... ups!!!

¿Qué hacemos? Pues afortunadamente lo tenemos fácil, entramos en el SQL Server Management Studio, nos vamos a la instancia de BBDD que utiliza nuestro Dynamics AX, buscamos la tabla CompanyInfo y la modificamos en SQL Server a mano, que es algo que no se debe hacer pero que en este caso no tenemos más remedio. Si por ejemplo, hemos creado un campo nuevo que se llama "micampo" de tipo string, pues creamos ese mismo campo con ese nombre desde SQL Server, si nos acordamos de otra tabla de tenga ese mismo ExtendedDataType podemos mirarla para copiar todos los parámetros del campo y dejarlo igual (longitud, tipo de datos, etc.).

Y ya está, una vez hemos actualizado la tabla en SQL Server, iniciamos el AOS y, ahora sí, debería de funcionar sin problemas. No está de más, que una vez dentro de Dynamics AX, le demos a la tabla en el AOT con el botón derecho y sincronizar, por si acaso se nos ha olvidado poner algo en SQL Server.

Hasta otra.

martes, 27 de septiembre de 2011

Dynamics AX y fieldnum dinámico pasado por parámetro

En Dynamics AX tenemos una función del sistema que se llama "fieldnum" que nos devuelve  el identificador de un campo de una tabla dada:

fieldnum(nombreTabla, nombreCampo)

Por ejemplo, si tenemos la tabla "ProjTable", y el campo de la tabla "ProjId", la siguiente sentencia:

fieldnum(ProjTable, ProjId)

nos devolverá el identificador de dicho campo.

Hay muchas tablas de Dynamics AX que se guardan identificadores de campo de otras tablas, una de ellas es la DocuField, que se guarda los campos de la tabla para la gestión documental de Dynamics AX.

Imaginemos que queremos rellenar la tabla Docufield como sigue:




Aquí estamos suponiendo que la tabla TablaDatosDocumento tiene al menos 20 campos y se llaman Campo1, Campo2, Campo3, ... , Campo20.
Nos tenemos que fijar en la línea 15 en la que se utiliza la función fieldnum, pero en lugar de pasarle la tabla y el nombre del campo, le pasamos la tabla y una variable con el nombre del campo.

Bien, pues esto ¡¡NO FUNCIONA!!, fieldnum no es dinámico y no se le pueden pasar variables, los id's de las tablas los calcula en tiempo de compilación, por eso sólo podemos pasarle nombre de tabla y nombre de campo. Si compilamos el código de arriba nos dará un error de compilación.

Entonces, ¿qué hacemos? Miremos el siguiente código:



Ahora sí que sí, esto es otra cosa, afortunadamente tenemos la función fieldName2Id a la que le pasamos el id de la tabla (con la función tablenum) y una cadena con el nombre del campo.

Espero que os sea útil.
Nos leemos.

martes, 26 de julio de 2011

Saber en qué instancia de Dynamics AX (Axapta) estás

Comienzo mi andadura en este blog con un pequeño "truco" para Microsoft Dynamics AX.
Normalmente se suele tener más de una instancia de AX:
- Una que llamamos "producción" donde los usuarios trabajan, donde están todos los datos reales de nuestro ERP
- Y luego una o más instancias para el equipo de desarrolladores. Yo recomiendo dos: una donde se hacen los desarrollos que podríamos llamar "desarrollo" y otra que sea una copia exacta de "producción" donde probar los desarrollos una vez están terminados, esta copia exacta la llamamos "test".

La idea es sencilla, desarrollamos en la instancia de "desarrollo", cuando está acabado probamos en "test" con una copia de los datos y configuración reales, y si todo va bien ya subimos los cambios a "producción".

Sin embargo, es posible que nuestro desarrollo contenga partes que, por lógica de negocio, NO deban ejecutarse en "test" con datos reales. Por ejemplo, imaginemos que estamos desarrollando un proceso relacionado con clientes que al terminar manda un email a cada cliente implicado en dicho proceso.

En "desarrollo" no hay problema porque podemos modificar los datos a nuestro antojo, por tanto, le cambiamos el email a nuestros clientes por uno que sea del equipo de desarrollo y andando.
Pero en "test" los datos son los reales, y debemos probarlo con datos reales, así que... ¿qué hacemos?

Pues muy sencillo, necesitamos algo que nos diga en qué instancia de AX estamos. Para ello podemos crearnos un método estático que llamaremos "enProduccion()" en una clase que llamaremos "Utiles", que nos devolverá si estamos en la instancia de producción o no. Con esa información actuaremos en consecuencia, en nuestro ejemplo de los clientes podemos mandar el correo electrónico a un email de nuestra propiedad y NO al email del cliente.

Veamos el código del método enProducción de la clase Utiles:



Como vemos hacemos una llamada a SqlSystem::databaseBackendDesc() para que nos devuelva el nombre del servidor de BBDD, la instancia de la base de datos y el nombre de la base de datos.

Si no sabemos todos estos datos para sustituir la cadena "SERVIDORBBDD\\INSTANCIABBDD - nombre_de_bbdd", podemos hacer un job en producción y luego copiamos y pegamos:




Lo que nos devuelva este job lo copiamos y pegamos en nuestro método "enProduccion" para sustituir a la cadena "SERVIDORBBDD\\INSTANCIABBDD - nombre_de_bbdd".


Y por tanto en nuestro código podríamos utilizar este método estático antes de hacer algo que NO deberíamos hacer en un entorno de pruebas, como por ejemplo mandar un email a un cliente REAL:




Y eso es todo, espero que os sea útil.
¡¡¡Hasta pronto!!!