Nueva funcionalidad de precios en BC versión 16

Una de las novedades publicadas en la wave 1 de 2020, es decir, en la versión 16 de Dynamics 365 Business Central, ha sido un cambio relevante en la funcionalidad interna que calcula las tarifas y los descuentos. Se trata de una novedad que aún no está publicada en los entornos de producción, pero a la cual hemos tenido acceso como partners de la herramienta para testeo.

Realizar estas pruebas nos permite entender cómo este cambio impactará a nuestros clientes, qué conflictos se pueden generar y tenemos un año de margen para realizar los cambios necesarios. Eso sí, es importante destacar que la funcionalidad no está validada como definitiva y, por lo tanto, podría aún sufrir cambios adicionales hasta su publicación.

En este blog vamos a explicar las primeras conclusiones que hemos detectado a nivel técnico. Recuerda que si estás buscando una explicación funcional puedes encontrarla en la tercer sección de este blog.

1. Novedades de precios en Business Central: Nuevo objeto tipo Interface

Tras el lanzamiento de la versión 16 de Dynamics 365 Business Central, os habréis percatado que se ha presentado un nuevo tipo de objeto llamada Interface. Por ahora, concretamente sólo se utiliza para la nueva funcionalidad de cálculo de precios, pero seguramente con el tiempo extienda a otros módulos.

Si ya conoces este nuevo tipo de objeto, no dudes en revisar este artículo donde detallamos el cambio de cálculo de precios a nivel funcional y también a nivel técnico. Pero este tipo de objeto también es importante conocerlo por si se desea utilizar en las personalizaciones que podemos realizar como partners.

En primer lugar, destacar que se trata de un objeto sin numeración. Simplemente es un protocolo mediante el cual se define una estructura o una serie de procedimientos/funciones sin código asociado.

Una vez tenemos definida la interface, sus procedimientos se concretan en distintas codeunits que la implementan. De este modo, se permite hacer desarrollos que trabajan con la estructura y las características genéricas de la interface, sin importar cuál de sus implementaciones se está utilizando. Puede que ya estés familiarizado con este concepto ya que se usa en múltiples lenguajes de programación como Java, C#, PHP

En la siguiente imagen podemos observar como en A/L se ha creado la nueva interface Price Calculation, que tiene un conjunto de funciones, pero sin código asociado:

Implementación Interfaces

La implementación del código de estas funciones se realizan en codeunits que se tendrán que asociar a las interfaces según parámetro implements escrito después del nombre de la codeunit e indicando a qué interface queremos implementar.

En el siguiente ejemplo mostramos las dos codeunits de cálculo de precio de las dos versiones de Business Central que implementan a la interface Price Calculation:

Indica que en las codeunits 7002 y 7003 se tendrán que crear y desarrollar todas las funciones indicadas en la interface que a la que se implemente. Si no se cumple esta condición, la compilación dará error.

También cabe destacar que una codeunit puede implementar a múltiples interfaces, indicándolo con el parámetro implements más todas las interfaces separadas por ‘,’.

codeunit Id MyCodeunit implements Interface1, Interface2, Interface3

Para facilitar dicha implementación, en el icono de la bombilla o Show Fixes (Ctrl + .) se nos ofrece la opción Implement interface, que automáticamente arrastra todas las funciones de la interface que deberemos implementar.

Si la bombilla no se muestra o no se nos ofrece la opción de Implement interface es porque en el fichero settings se debe activar la opción Enable Code Analysis para la extensión AL Language extensión.

Implementación Interfaces desde objeto Enum

El último punto que nos queda por abordar es cómo saber cómo se selecciona la codeunit (o implementación de la interface) que se va a utilizar. Para ello se tiene que definir un objeto Enum con todas las opciones posibles implementadas, que también esté relacionado con la interface con el método implements.

Siguiendo el mismo ejemplo de la interface Price Calculation, su Enum es el siguiente:

Aquí vemos que solo asigna los dos valores de las implementaciones posibles (V16 y V15), más un valor en blanco o no definido (que lo asocia a la implementación V15).

En cada opción de la lista de los Enums tenemos que indicar a qué implementación está asociado este valor. Para ello se utiliza la nueva propiedad Implementation¸ en la que indicaremos el valor de la codeunit que implementa a la interface de la siguiente forma:

Implementation = “NOMBRE INTERFACE” = “NOMBRE CODEUNIT”

Finalmente, este valor Enum se muestra en la página de configuración que más nos convenga y se puede asociar a la variable Interface como una asignación directa desde el valor del campo enum.

2. Novedades de precios en Business Central: Proceso técnico

Entrando en materia, los desarrolladores de BC ya se habrán dado cuenta que en los códigos que afectan a las tablas de tarifas y descuentos (tanto de venta como de compra) aparece un warning del tipo Table ‘Sales Price’ is marked for removal. Reason: Replaced by the new implementation (V16) of price calculation.. Tag: 16.0.AL(AL0432).

Este mensaje se muestra para notificar a los partners que va a producirse un cambio en este punto de la aplicación. Llegados a este punto, el equipo técnico dispone de un año para adecuar las personalizaciones que afecten a esta funcionalidad para que no entren en conflicto.

Para entender el cambio, lo primero que se debe conocer es la utilización del nuevo tipo de objeto interface. Si desconocéis la existencia o las características de este objeto, os recomendamos primero abordar la primer sección donde entramos en detalle sobre sus características.

Si ya estás familiarizado con el funcionamiento y la lógica del objeto interface habrás podido comprender que, con esta nueva estructura, el cálculo del precio viene definido por la interface Price Calculation. Microsoft proporciona 2 implementaciones para esta interfaz: la de la versión 15 (codeunit 7003) o la de la versión 16 (codeunit 7002). Además, podemos extender la funcionalidad con cálculos de tarifas y descuentos completamente distintos a los estándares, definiendo nuevas codeunits que implementen la interface Price Calculation.

En el momento de calcular un precio o un descuento, por ejemplo en una línea de venta, en la versión NAV 2018 simplemente se llamaba a las funciones de la codeunit 7000 (Sales Price Calc. Mgt.).

Ahora utiliza las funciones Init y ApplyPrice de la interface Price Calculation y es la codeunit 7003 quien llama a la anterior codeunit 7000 (en el caso que tengamos activado que se aplique el cálculo v15 en la nueva tabla configuración de cálculo de precios).

Si revisamos detalladamente el código vemos que para calcular los precios en distintas tablas (líneas venta, compra, diario producto, proyecto, demanda o servicio) no se utilizan variables tipo RecordRef o Variant, sino que se trabaja con la interface Line With Price, que dependiendo del módulo en el que trabajemos, se inicializan distintas codeunits que implementan esta interface (7020: Sales Line – Price, 7021: Purchase Line – Price…).

Circuito técnico

El circuito técnico para calcular precios con la implementación V16 utiliza los mismos pasos. La diferencia es que las definiciones de las funciones de la interface Price Calculation (Init, ApplyPrice…) son distintas.

Para reflejar todos los objetos creados en esta funcionalidad y las implementaciones de interfaces hemos creado el siguiente esquema:

La principal diferencia, y el motivo principal por el cual aparece el warning, es que la tabla Sales Price se ha marcado como obsoleta. Es así ya que las tablas de precios de la versión 15 (Sales Price, Sales Line Discount, Purchase Price…) se han unificado en una única tabla con nombre Price List Line. Por este motivo, las extensiones que desarrolladas en la versión anterior se tendrán que rediseñar teniendo en cuenta esta nueva tabla.

Además, para traspasar los valores de las anteriores tablas a la nueva, también se tendrá que suscribir al correspondiente evento OnCopyFromXXX (OnCopyFromSalesPrice) de la codeunit CopyFromToPriceListLine asignando dicho campo.

Y tú, ¿crees que vas a tener algún conflicto producido por este cambio? ¿Habías prestado atención al aviso de Microsoft?

En conclusión, lo importante es entender cómo se ha estructurado la nueva funcionalidad de precios, tanto la v16, como los pequeños cambios de la v15 y, principalmente, cómo solucionar los errores de warnings, descritos en el primer párrafo.

3. Novedades de precios en Business Central: Proceso funcional

En esta sección vamos a explicar las primeras conclusiones que hemos detectado a nivel funcional y también de configuración de este rediseño de la funcionalidad de precios.

Aunque antes hablamos sobre cómo afecta a nivel técnico este cambio, es decir, a nivel de desarrollo, sí que es importante destacar que se ha creado una gran estructura con nuevas tablas, codeunits e interfaces. A nivel funcional destacamos las siguientes tablas:

  • Tabla Price Calculation Setup: sirve para indicar si se utiliza la versión 15 o la 16 de la solución. Para la 16, además podemos indicar si utilizamos el Método “precio más bajo” o algún otro en el caso que lo hayamos extendido con funcionalidad propia; a qué Tipo de documentos se aplica (Ventas, Compras, o ambos); y el tipo de línea,o Tipo de activo (Productos, Recurso…).

Por ejemplo, con la siguiente configuración tendremos activado el tipo de cálculo de precio de la versión 16 para compras y ventas de productos, pero el de la versión 15 para ventas de recursos.

  • Tabla Price Calculation Setup: arrastrando los campos de Método, Tipo, Tipo de activo e Implementación de la configuración anterior, podemos indicar qué tipo de implementación queremos seleccionar a nivel de Grupo origen (Cliente, Proveedor o Proyecto) y su código. También se puede hacer a nivel de Nº de activo, en el caso de que la configuración de la tabla superior esté separada por “activo”.

Por ejemplo, en la siguiente imagen observamos una configuración en la cual tenemos activado el tipo de cálculo de precio de la versión 16 para ventas del Cliente 10000.

  • Tabla Price List Line: es la equivalente a las anteriores tablas de precios venta, precios compra, descuentos venta… pero unificada toda en una sola. Según el campo Tipo Importe se indica si es precio, coste o descuento.

Con la combinación de Tipo procedencia mov. + Cód. procedencia mov. se indica si se quiere aplicar a todos los clientes/proveedores, uno en concreto, un grupo de precio/descuento… (lo que antes correspondía al campo Tipo Venta en precios y descuentos de venta).

Mediante la combinación de Tipo de activo + Nº activo se indica si queremos un producto, recurso, grupos… (lo que antes era el Tipo); y los demás campos de cantidad mínima, fechas, precio, coste… ya son los conocidos.

  • También es importante comentar que se ha creado el campo Método cálculo precio en clientes, proveedores o configuraciones de compra/venta. Las primeras pruebas indican que servirá por si en algún caso concreto queremos que se aplique un método distinto al del “precio más bajo”.

En conclusión, aunque a primera vista esta funcionalidad parezca un cambio muy grande, realmente el impacto debería ser mínimo, ya que creemos que las tablas de configuración en la mayoría de entornos simplemente será activar una línea para compras y otra para ventas, relacionadas con la implementación V16 y raramente se utilizará otra o con más detalle.

Por lo que se refiere a la tabla Price List Line, hay unos procesos (codeunit CopyFromToPriceListLine) que traspasan los registros de las antiguas tablas a esta nueva, por lo que tampoco debería resultar en ningún problema. Lo único importante es que la configuración de precios y tarifas a partir de la publicación de esta novedad está unificada en una tabla.