Continuando con nuestra serie de Business Events en Microsoft Dynamics 365 for Finance and Operations, toca hablar de la posibilidad de desarrollar nuestros propios eventos de negocio para ser capaces de notificar o interactuar con aplicaciones externas en casos que no están cubiertos por el catálogo de eventos de negocio.

Antes de comenzar con la creación del propio Business Event, hay ciertos aspectos que debemos tener en cuenta:

  • Los eventos de negocio deben ser duraderos, es decir, si una aplicación externa recibe una notificación de que cierta acción ha ocurrido, esta notificación debe ser fiable. Hay que hacer un diseño transaccional que asegure que este aspecto se cumplirá siempre.
  • Los eventos de negocio deben ser precisos, evitando enviar payloads (contenido del business event) genéricos en los que el receptor tenga que deducir el objetivo del business event.
  • Los eventos de negocio deben evitar el ruido, para conseguirlo se debe intentar lanzar el business event en un punto del código lo suficientemente específico para evitar realizar excesivas operaciones de filtrado.

Una vez tengamos claros estos puntos, podemos empezar a desarrollar, ¡que es a lo que hemos venido hoy! Para el ejemplo en cuestión, vamos a desarrollar un evento de negocio que sea lanzado cuando un cliente pase a estar No Bloqueado.

El primer paso será la creación del contrato de datos, que conformará el contenido del payload que enviaremos al exterior. Para ello creamos una clase que heredará de la BusinessEventContract

[DataContract]
class JATCustUnblockedBusinessEventContract extends BusinessEventsContract
{
    private CustAccount				custAccount;
    private CustName				custName;
    private Email					email;
    private LegalEntityDataAreaId	legalEntity;

    private void initialize(CustTable _custTable)
    {
        custAccount	= _custTable.AccountNum;
        custName	= _custTable.name();
        email		= _custTable.email();
        legalEntity	= _custTable.DataAreaId;
    }

	public static JATCustUnblockedBusinessEventContract newFromCustTable(CustTable _custTable)
    {
        JATCustUnblockedBusinessEventContract contract = new JATCustUnblockedBusinessEventContract();
        contract.initialize(_custTable);
        return contract;
    }

	private void new()
    {
    }

    [DataMember('CustAccount'), BusinessEventsDataMember("@SYS7149")]
    public CustAccount parmCustAccount(CustAccount _custAccount = custAccount)
    {
        custAccount = _custAccount;
        return custAccount;
    }

    [DataMember('CustName'), BusinessEventsDataMember("@SYS80991")]
    public CustName parmCustName(CustName _custName = custName)
    {
        custName = _custName;
        return custName;
    }

    [DataMember('Email'), BusinessEventsDataMember("@SYS5845")]
    public Email parmEmail(Email _email = email)
    {
        email = _email;
        return email;
    }

    [DataMember('LegalEntity'), BusinessEventsDataMember("@SYS129100")]
    public Email parmLegalEntity(LegalEntityDataAreaId _legalEntity = legalEntity)
    {
        legalEntity = _legalEntity;
		return legalEntity;
    }

}

En esta clase añadimos las propiedades privadas que conformarán el payload, así como los métodos parm para poder acceder a ellas y los métodos newFromCustTable e initialize para inicializar los valores de las propiedades con los datos del cliente que estamos desbloqueando. Como veis, los métodos parm van decorados con dos atributos que establecerán el nombre y la descripción de los campos que estarán visibles en el cuerpo del business event.

El segundo paso será la creación de una clase que heredará de la BusinessEventBase.

[BusinessEvents(classStr(JATCustUnblockedBusinessEventContract), 
	"@jatomas:CustomerUnblocked",
    "@jatomas:CustomerUnblocekdDesc",
    ModuleAxapta::Customer)]
public public class JATCustUnblockedBusinessEvent extends BusinessEventsBase
{
    private CustTable custTable;

	static public JATCustUnblockedBusinessEvent newFromCustTable(CustTable _custTable)
    {
        JATCustUnblockedBusinessEvent	businessEvent	= new JATCustUnblockedBusinessEvent();

        businessEvent.parmCustTable(_custTable);
        return businessEvent;
    }

	private CustTable parmCustTable(CustTable _custTable = custTable)
    {
        custTable	= _custTable;

        return custTable;
    }

	private void new()
    {
    }

	[Wrappable(true), Replaceable(true)]
	public BusinessEventsContract buildContract()
    {
        return JATCustUnblockedBusinessEventContract::newFromCustTable(custTable);
    }

}

Como podéis ver, decoramos el método buildContract con los atributos Wrappable(true) y Replaceable(true) para permitir la extensibilidad de este. Este método se ejecuta únicamente cuando un evento de negocio es activado o habilitado en una empresa.

Por último, solo nos quedaría establecer el punto concreto en el que se lanzará el evento en cuestión, y añadir las siguientes líneas de código en el mismo:

if (BusinessEventsConfigurationReader::isBusinessEventEnabled(classStr(JATCustUnblockedBusinessEvent)))
{
    JATCustUnblockedBusinessEvent::newFromCustTable(this).send();
}

De este modo, el evento de negocio será lanzado únicamente si se encuentra activo para la empresa en la que estamos trabajando.

Con todos estos pasos hechos, vamos a ver nuestro evento de negocio en el catálogo de eventos. Para ello vamos a Administración del sistema > Configurar > Eventos de negocio > Catálogo de eventos de negocio. Una vez dentro, pulsaremos sobre el menú Generar > Volver a generar catálogo de eventos de negocio. Tras unos segundos, veremos cómo aparece nuestro business event.

Una vez terminado, ya estará disponible para ser consumido del mismo modo que vimos en el artículo anterior.