viernes, enero 23, 2015

Continuan las promociones 'Give me 5'

Debido al éxito obtenido, Microsoft decide continuar y ampliar  las promociones ‘Give me 5’ & 'Give me 5+2' para Microsoft Dynamics NAV

Las promociones "Give me 5" que terminaron el pasado 27 de diciembre se han visto prorrogadas y mejoradas para estos 2 próximo trimestres.
Este es el detalle:

1er trimestres 2015
- "Give Me 5 Starter" - Starter Pack mas 2 Usuarios full por EUR 3.750 para clientes en España.
- "Give Me 5 + 2 Extended" - Starter Pack mas el Extended Pack mas 4 Usuarios Full por EUR 12.000 para clientes en España.

2do trimestre 2015
- "Give Me 5 Starter" - Starter Pack mas 2 Usuarios Full por EUR 4.500 para clientes en España.
- "Give Me 5 + 2 Extended" - Starter Pack mas el Extended Pack mas 4 Usuarios Full por EUR 12.750 para clientes en España.

Además, para el 1er semestre de 2015, existe una promoción para los clientes existentes:

- "Extend NAV For Less" – Clientes existentes pueden licenciar Microsoft Dynamics NAV Extended Pack mas 1 Usuario Full por EUR 7.200

Si quieres ampliar esta información, contacta con Quonext

Modificaciones en 340 y 347 según IVA de Caja

Os dejo unos links al blog del equipo español de Soporte de Dynamics NAV en donde explican las modificaciones del 340 y 347 para cumplir con las últimas normas de la Agencia Tributaria.

Para 340: http://blogs.msdn.com/b/eneauve/archive/2015/01/22/modelo-340-modificaciones-adicionales-en-cuanto-al-criterio-de-iva-de-caja.aspx

Para 347: http://blogs.msdn.com/b/eneauve/archive/2015/01/22/modelo-347-iva-de-caja.aspx

sábado, enero 10, 2015

Y II, mejorar y extender el diseño de cualquier cliente de Dynamics NAV

Siguiendo con el post anterior, que recomiendo su lectura, de cómo mejorar y extender el diseño de Dynamics NAV, se nos plantea la necesidad evidente de permitir que el control Add-in sea accesible desde cualquier cliente, incluido Web y Tablet. Para ello seguí la siguiente documentación de MSDN.

Las diferencias con el control Windows Forms indicado en el post anterior es que aquí sólo utilizaremos el código C# como interfase para, desde C/AL, ejecutar el código Java Script que, éste sí, es ejecutable desde los clientes que no son nativos Windows.

Creando un Add-in para cualquier cliente

Empezaremos creando un proyecto C# desde Visual Studio de tipo Biblioteca de clases y añadiremos la referencia a la librería del cliente NAV que encontraras en el directorio donde tengas instalado el cliente:

Microsoft.Dynamics.Framework.UI.Extensibility

Ahora deberemos referenciarla en el código de la clase:

using Microsoft.Dynamics.Framework.UI.Extensibility;

Y empezamos a definir el interfase:

namespace CEDARTjs500x150
{
    [ControlAddInExport("CEDART.controls.labelJs500x150")]
    public interface CDRTlabelJs500x150
    {
        [ApplicationVisible]
        event ApplicationEventHandler ControlAddInReady;
 
        [ApplicationVisible]
        void SetHtml(string value);
        [ApplicationVisible]
        void SetImage(string name);
    }
}

Una vez definido el interfase, necesitamos dotar de código al control para que haga ciertas cosas, en nuestro caso, muy básico, lo que hace es que visualiza cualquier código HTML con la función SetHtml o visualiza una imagen con la función SetImage.

Siguiendo este ejemplo de MSDN podrás ver que es necesario crear una estructura de carpetas en el proyecto:


Me refiero a la carpeta Resources en la que podremos poner, básicamente 3 carpetas más, una con imágenes, otra con el código Java Script y otra con hojas de estilo. Fijaros también que en la carpeta Resources deberemos tener un fichero Manifest.xml que es el que indica donde está cada cosa.

Como veremos más adelante esta carpeta y su contenido empaquetado en un archivo .zip se deberá incluir al registrar el control en Dynamics NAV.

<?xml version="1.0" encoding="utf-8"?>
<Manifest>
  <ScriptUrls>
    <ScriptUrl>http://ajax.aspnetcdn.com/ajax/jQuery/jquery-2.1.3.min.js</ScriptUrl>
  </ScriptUrls>

  <Resources>
    <Image>LogoCEDART150.png</Image>
    <Script>Script.js</Script>
    <StyleSheet>Stylesheet.css</StyleSheet>
  </Resources>

  <Script>
    <![CDATA[
        $(document).ready(
           function() {
               InitializeLabel();
               Microsoft.Dynamics.NAV.InvokeExtensibilityMethod('ControlAddInReady', null);
           });
    ]]>
  </Script>

  <RequestedHeight>150</RequestedHeight>
  <RequestedWidth>500</RequestedWidth>
  <VerticalStretch>true</VerticalStretch>
  <HorizontalStretch>true</HorizontalStretch>
</Manifest>

En ScriptUrls podremos indicar scripts externos, que como podeis suponer podemos utilizar cualquiera de las librerías externas existentes, en mi caso he utilizado la conocidísima jQuery.

En Resources definiremos todos nuestros archivos utilizados en el proyecto, posteriormente lo veremos más en profundidad.

La parte Script es el código JavaScript que se va a ejecutar (jQuery en nuestro caso). Evidentemente que podríamos poner todo el código en esta sección, pero por cuestiones de Readability es preferible ponerlo en los archivos de script externos.

Como veies, en mi caso, lo que hace es que cuando el documento está "ready" se ejecuta una función para inicializar el control y acto seguido se dispara el evento ControlAddInReady. Fijaos que con la función InvokeExtensibilityMethod podemos disparar cualquier evento en NAV, previamente definido en el interfase en C#.

Finalmente en las 4 últimas propiedades definimos las dimensiones mínimas que debe tener el control y si debe permitir Stretch. Vuelvo a insistir en este punto que las capacidades de resizing tienen mucho por mejorar.

Es importante destacar que los controles diseñados en JavaScript no pueden disponer de propiedades, sólo métodos.

Contenido del paquete .zip de la carpeta Resources

Vamos ahora a centrarnos en los 3 tipos de ficheros que podemos incluir.

El primer tipo de contenido que podemos incluir en Resources son imágenes que podremos recuperar desde el código, tal como veremos más adelante.

El segundo tipo de contenido es Script que evidentemente contiene las funciones. Veamos un ejemplo:

function InitializeLabel() {
    SetHtml("controlId");
}

function SetHtml(value) {
    $('#controlAddIn').html(value);
}

function SetImage(name) {
    var imageURL = Microsoft.Dynamics.NAV.GetImageResource(name);
    $('#controlAddIn').html("<div><img src='" + imageURL + "'/></div>");
}

La primera función es la que se llama desde el Manifest.xml y es la encargada de inicializar el control.
La segunda es la que inserta cualquier texto o código HTML en el control.

La tercera nos permite tener acceso a cualquier imagen, que hayamos incluido en el paquete, mediante la función GetImageResource.

El tercer tipo de contenido son hojas de estilo. En StyleSheet incluiremos las hojas de estilo que vayamos a utilizar, creadas por nosotros o conseguidas de los numerosos recursos externos. Un ejemplo:

body
{
    font-family: Verdana;
    color: black;
    background-color: white;
}

p
{
    padding: 10px;
}

.title
{
    font-size: 14;
    font-weight: bold;
}

.normal
{
    font-size: 12;
    font-weight: normal;
}

.forbr
{
    font-size: 6;
}

Esto es todo lo que necesitamos para nuestro sencillo ejemplo. Vamos a compilarlo y a registrarlo en Navision.

Compilar el control Add-in y registrarlo en Dynamics NAV

Para compilar, deberéis seguir el ejemplo propuesto en el post anterior, toda la parte que explica cómo firmar y compilar el proyecto.

La parte donde explica como registrar el control hay que hacer lo mismo y adicionalmente lo siguiente: Como los controles Add-in pueden replicarse desde el servidor al cliente deberemos cargar la carpeta Resources para que pueda descargarse y ejecutarse localmente.

Para ello lo que haremos será empaquetarla en un archivo .zip y al registrar el control, mediante la acción de Importar importaremos el archivo.

Diseñar utilizando nuestro control Add-in

Diseñaremos una Page en la que incluiremos un Field que incluirá el control Add-in diseñado anteriormente:


Ya añadiremos el siguiente código en el evento Label3::ControlAddInReady()

CurrPage.Label3.SetHtml(
  '<p>' +
  '<span class="title">Ratios de liquidez</span>' +
  '<span class="forbr"><br /><br /></span>' +
  '<span class="normal">' +
  'La liquidez es la capacidad potencial que tiene la empresa para pagar sus obligaciones. ' +
  'La comparación entre la cantidad de riqueza disponible (activo circulante) y las deudas ' +
  'que habrá que atender a corto plazo ' +
  '(pasivo circulante) proporciona una medida de esta liquidez.</span>' +
  '<span class="forbr"><br /><br /></span>' +
  '<span class="normal">' +
  'Dependerá del grado de realización de los elementos del activo, ' +
  'es decir, si están cerca de su conversión en liquidez (derechos de cobro que venzan ' +
  'a corto plazo, existencias que se vayan a vender, etc.), y del grado de exigibilidad del pasivo, ' +
  'es decir, vencimiento de las deudas y necesidad de su devolución.</span>' +
  '</p>');

Compilamos y ejecutamos. Este es el resultado:


Y probamos desde el cliente Web, en mi caso: http://localhost/DynamicsNAV80/WebClient/list.aspx?page=60199 y este es el resultado:


Y desde el cliente tablet:


Vamos a probar ahora la visualización de una imagen incluida en el paquete, para ello vamos a sustuir el código de la Page por este:

CurrPage.Label3.SetImage('LogoCEDART150.png');

Compilamos y ejecutamos en los diferentes clientes:




Objetivo conseguido

Ahora somos capaces de visualizar cualquier contenido, utilizando comandos Html5, programando en JavaScript utilizando librerías como jQuery y hojas de estilos en cualquiera de los clientes de Dynamics NAV.

Cómo mejorar y extender el diseño en Dynamics NAV?

Recientemente necesitaba incluir un texto largo en una Page y utilizando el control del propio NAV con la opción de multlinea no terminaba de gustarme el resultado:


Entonces se me ocurrió que podía hacer un control Add-in que permitiera visualizar cualquier texto en una Page. Así que busqué información en mi muy a menudo consultado MSDN, aquí tenéis un poco de información sobre la arquitectura, y posteriormente estudié este artículo de MSDN y me atreví a desarrollar mi propio objeto Label con el que poder visualizar texto multilinea en un formato mejor.

Creando un control Add-in para el cliente Windows

Empecé creando un nuevo proyecto en Visual Studio en C# de tipo Biblioteca de clases. Añadí las 2 referencias a las librería de NAV que encontrarás en el directorio donde tengas instalado el cliente NAV:

Microsoft.Dynamics.Framework.UI.Extensibility
Microsoft.Dynamics.Framework.UI.Extensibility.WinForms

Y otras 2 al propio .NET Framework:

System.Windows.Forms
System.Drawing;

Así mismo las referencié en el código de la clase:

using Microsoft.Dynamics.Framework.UI.Extensibility;
using Microsoft.Dynamics.Framework.UI.Extensibility.WinForms;
using System.Windows.Forms;
using System.Drawing;

Y empecé a declarar la clase:

[ControlAddInExport("CEDART.controls.labelWF")]
public class CDRTlabelWF : WinFormsControlAddInBase

La primera línea es importante porque es la que utilizaremos posteriormente para declarar y registrar el Add-in dentro de NAV.

En cuanto a la segunda línea, podía haber utilizado la clase abstracta StringControlAddInBase en lugar de WinFormsControlAddInBase pero posteriormente me di cuenta que necesitaba que mi control admitiera resizing para que si el contenedor cambiaba de tamaño mi control debía adaptarse a este nuevo tamaño y al parecer la clase abstracta StringControlAddInBase no lo admite tal como veremos más adelante.

En este punto debo decir que según todas las pruebas que he efectuado y algunos comentarios que he leído en foros, los controles Add-in no se llevan muy bien con el resizing, con lo que será importante que lo defináis con unas dimensiones ajustadas a vuestro propósito.

Continuamos con el código de creación del control:

Label _label = new Label();
protected override void OnInitialize()
{
    base.OnInitialize();
    this.ApplySize(new DisplaySize(1, 100, 600), new DisplaySize(1, 20, 300));
}

protected override Control CreateControl()
{
    _label.AutoSize = true;
    _label.Click += (sender, args) => { ControlClick(_label, null); };
    _label.ParentChanged += (sender, args) =>
        {
            if (ControlAddInReady != null)
            {
                ControlAddInReady(_label, null);
            }
        };
     return _label;
}

Continuando con el resizing, necesitamos declarar la función onInitialize() para poder indicar los tamaños mínimos, iniciales y máximos que tomará el control en ancho y largo al iniciar y redimensionar la pantalla principal, en nuestro caso la pantalla del cliente NAV. Esto concretamente es lo que no admite la clase abstracta StringControlAddInBase.

Otra cosa importante es que desde C/AL no podemos hacer nada con el control hasta que esté creado, con lo que debemos disponer de un evento que nos informe cuándo nuestro control Add-in está listo y preparado para admitir que utilicemos sus funciones y propiedades. Esto es lo que hace la última parte del código cuando dispara el evento ControlAddinReady.

Este es el código de definición de los eventos:

[ApplicationVisible]
public event EventHandler ControlAddInReady;
[ApplicationVisible]
public event EventHandler ControlClick;

Como puedes ver he definido un evento que se dispara al dispararse el evento Click del control Label.

Continuamos con la definición de métodos y propiedades:

[ApplicationVisible]
public void SetForeColor(bool black, bool white, bool gray)
{
    if (black)
    {
        _label.ForeColor = Color.Black;
    }
    if (white)
    {
        _label.ForeColor = Color.White;
    }
    if (gray)
    {
        _label.ForeColor = Color.DarkGray;
    }
}

[ApplicationVisible]
public void SetBackColor(bool transparent, bool white, bool gray)
{
    if (transparent)
    {
        _label.BackColor = Color.Transparent;
    }
    if (white)
    {
        _label.BackColor = Color.White;
    }
    if (gray)
    {
        _label.BackColor = Color.LightGray;
    }
}

[ApplicationVisible]
public void SetFont(string family, int size, bool bold)
{
    if (family == null)
    {
        family = "Arial";
    }
    if (size == 0)
    {
        size = 9;
    }
    if (bold == true)
    {
        _label.Font = new Font(family, size, FontStyle.Bold);
    }
    if (bold == false)
    {
        _label.Font = new Font(family, size);
    }
}

[ApplicationVisible]
public string Caption
{
    get { return _label.Text; }
    set { _label.Text = value; }
}

En esta parte los límites son vuestra creatividad, podemos hacer tantas cosas con el control como se nos ocurran (o como se deje el propio control). No es olvidéis de poner la etiqueta [ApplicationVisible] antes de la declaración del evento, método o propiedad para que sea visible desde NAV.

Finalmente deberemos firmar el proyecto. Para ello iremos a las propiedades del proyecto y pulsaremos en la opción Firma para marcar la opción Firmar el ensamblado y crear un nuevo archivo de firma, al que le daremos un nombre y desmarcaremos la opción Proteger mi archivo de clave mediante contraseña:


Tan sólo nos queda compilar el control, pero para registrarlo en NAV deberemos conocer su clave pública, con lo que en las propiedades del proyecto accederemos a la opción Eventos de compilación y en la ventana de Línea de comandos del evento posterior a la compilación añadiremos el siguiente comando para que al compilar nos proporcione el ID de la clave pública:

"C:\Program Files (x86)\Microsoft SDKs\Windows\v8.1A\bin\NETFX 4.5.1 Tools\sn.exe" -T "$(TargetPath)"

Hay una parte del directorio que puede cambiar según vuestra versión de Windows o versión de .NET Framework que utilicéis. 

Con lo que finalmente, al compilar deberemos ver en la ventana Resultados algo similar a esto:
 
No la cerréis, vamos a necesitar el Token en seguida.
 
Registrando el control Add-in en el cliente Windows
 
Primero debemos copiar la librería DLL al directorio de Add-ins en NAV, en mi caso al utilizar NAV 2015 utilizaré el directorio:
 
C:\Program Files (x86)\Microsoft Dynamics NAV\80\RoleTailored Client\Add-ins
 
En el que podemos crear un directorio y copiar la librería desde el directorio (el que os indique vuestra ventana de Resultados), en mi caso:
 
C:\Users\Josep\Documents\Visual Studio 2013\Projects\CEDART\CEDARTwf\bin\Debug\CEDARTwf.dll
 
Abrimos NAV y buscamos Complementos de control para crear un nuevo registro en la tabla e informarlo como sigue:
 
El Nombre complemento control ha de ser idéntico al indicado en nuestro proyecto .NET en la definición [ControlAddInExport("CEDART.controls.labelWF")]

El Token de clave pública es el proporcionado al compilar el proyecto en la ventana Resultados o mediante otros métodos tal como se explica aquí.

Diseñar utilizando nuestro control Add-in

En este punto, y si todo ha ido bien, ya estamos en disposición de utilizar nuestro control Add-in para visualizar un texto dentro de una Page. Con lo que voy a utilizar la misma página mostrada al principio para reacondicionarla:

 
Lo que quiero es sustituir los 2 controles de textos actuales por los de nuestro Add-in, para ello voy a crear una línea adicional y lo pondré nombre Label1, después accederé a las propiedades e indicaré, en la propiedad ControlAddIn el Add-in utilizando el Assist (F6):

 
Accederemos al código (F9) y comprobaremos como disponemos de 2 nuevos eventos:
 
 
El primero se disparará cuando el control Add-in esté listo para ser utilizado y el segundo cuando se haga Click en el control. Vamos a poner código en el primero:

CurrPage.Label1.SetFont('', 14, TRUE);
CurrPage.Label1.Caption := 'Ratios de Liquidez';
 
Crearemos una segunda Label e igualmente introduciremos código en el evento ControlAddInReady:

CurrPage.Label2.Caption :=
  'La liquidez es la capacidad potencial que tiene la empresa ' + 
  'para pagar sus obligaciones. La comparación entre la cantidad ' + 
  'de riqueza disponible (activo circulante) y las deudas que ' + 
  'habrá que atender a corto plazo ' +
  '(pasivo circulante) proporciona una medida de esta liquidez.' +
  'Dependerá del grado de realización de los elementos del activo, ' +
  'es decir, si están cerca de su conversión en liquidez (derechos ' + 
  'de cobro que venzan a corto plazo, existencias que se vayan a ' + 
  'vender, etc.), y del grado de exigibilidad del pasivo, ' +
  'es decir, vencimiento de las deudas y necesidad de su devolución.';
 
Borramos los 2 controles anteriores, compilamos y ejecutamos la Page:
 

 
Mucho mejor que la inicial, ¿no os parece?:



Este Add-in al haber sido creado mediante Windows Forms no es ejecutable desde el cliente Web. En un segundo post os mostraré como construir el Add-in para que pueda ser ejecutado tanto en cliente Windows como en cliente Web.