• Inicio
  • Novedades
  • Academia SAP
  • FAQ
  • Blog
  • Contacto
S4PCADEMY_Logo
  • Inicio
  • Novedades
  • Academia SAP
  • FAQ
  • Blog
  • Contacto
Twitter Linkedin Instagram

S4PCADEMY_Logo
  • Inicio
  • Novedades
  • Academia SAP
  • FAQ
  • Blog
  • Contacto
Twitter Linkedin Instagram
customactions  ·  dynamicexpressions  ·  sideeffects  ·  Technical Articles

CAP con elementos Fiori: efectos secundarios, acciones personalizadas, expresiones dinámicas

By s4pcademy 


Introducción

En una asignación reciente, tuve la oportunidad de usar el modelo de programación de aplicaciones en la nube y los elementos de Fiori para diseñar y crear una aplicación lista para la empresa. Usé algunos conceptos como expresiones dinámicas, efectos secundarios y acciones personalizadas en páginas de objetos. Sin embargo, encontrar material apropiado o referencias con ejemplos y comprender los conceptos requirió mucho tiempo. Intentaré describir brevemente estas ideas en esta publicación de blog para que otros puedan beneficiarse y ahorrar tiempo.

Breve explicación del escenario POC y sus recursos

Utilizaremos el proyecto de ejemplo «cap-fe-se-ca-de» que publiqué en GitHub aquí para explicar los temas. Repasemos rápidamente el proyecto y algunos de sus archivos clave.

Carpeta o Archivo Objetivo
aplicación/ Esto tiene 2 interfaces de interfaz de usuario, es decir, Clientes y Pedidos.
db/ El modelo de datos se define en schema.cds
srv/ Los servicios se definen en service.cds y la lógica se agrega a través de service.js. También capacidades.cds agrega/restringe diferentes capacidades de los servicios
aplicación/pedidos

Aplicación de interfaz de usuario basada en Fiori Elements para pedidos

anotaciones.cds:
contiene anotaciones para la página de lista y la página de objetos

anotaciones_se.cds:
contiene anotaciones relacionadas con los efectos secundarios

anotaciones_ca_de.cds:
contiene anotaciones relacionadas con acciones personalizadas y expresiones dinámicas

Las aplicaciones «Clientes» y «Pedidos» en la carpeta de la aplicación se crearon con Fiori Elements. Para comprender mejor los temas antes mencionados, nos concentraremos en la aplicación Pedidos. La primera vista en la aplicación Pedidos es una Página de lista y la segunda vista, que es la vista de detalles, es una Página de objeto, como se ilustra a continuación:

Pedidos%20-%20Lista%20Página Pedidos%20-%20Detalle%20Página
Pedidos – Página de lista Órdenes – Objeto Pagmi

Concepto-1: Efectos secundarios

Si un usuario modifica el contenido de un campo o realiza una acción, esta modificación puede tener un impacto en otros campos de la interfaz de usuario. Este comportamiento del sistema se denomina efecto secundario.

ejemplo: en orden, si ingresa cantidad y precio, el valor total se actualiza automáticamente. Este comportamiento se denomina efecto secundario.

Hay diferentes variaciones de los efectos secundarios. Exploremos uno por uno usando el archivo annotations_se.cds en la aplicación Pedidos.

Efecto secundario con propiedad de origen único y entidades de destino: En la página de detalles del pedido, cuando el usuario elige al cliente, también se deben actualizar automáticamente los detalles del cliente, como el nombre, el apellido y su dirección. Para lograr esto, se agrega la siguiente anotación en annotations_se.cds

using orderservice as service from '../../srv/service';
annotate service.Orders @(Common : {
    SideEffects #CustomerChanged : {
        SourceProperties : ['customer_ID'],
        TargetEntities   : [customer, customer.addresses]
    }
});

Según las anotaciones anteriores, cada vez que el usuario actualiza el campo ID_cliente, se activa este efecto secundario #CustomerChanged y se actualiza el campo relacionado con el cliente y la entidad de dirección del cliente.

Técnicamente, este efecto secundario da como resultado una llamada de actualización para actualizar el campo ID_cliente y una llamada de obtención para obtener los datos del cliente y la dirección del cliente.

Solicitud de lote con 2 llamadas

En este ejemplo, vimos cómo podemos afectar los campos de la interfaz de usuario que hacen referencia a las entidades de navegación, es decir, el Cliente y sus direcciones.

Efecto secundario con propiedad de fuente única y propiedades de destino: Cuando un usuario agrega un nuevo artículo a un pedido y proporciona la identificación del producto, el precio y la moneda deben obtenerse automáticamente del maestro del producto y completarse para la entidad del artículo. Además, cuando se completa tanto el producto como la cantidad, también se debe calcular el precio neto. Las anotaciones a continuación se utilizan para lograr esto:

annotate service.OrderItems @(Common : {
    SideEffects #ProductChanged  : {
        SourceProperties : ['product_id'],
        TargetProperties : ['price', 'currency_code', 'netprice']
    }
});

annotate service.OrderItems @(Common : {
    SideEffects #QuantityChanged : {
        SourceProperties : ['quantity'],
        TargetProperties : ['netprice']
    }
});

Tenga en cuenta que el efecto secundario provoca una llamada de obtención adicional y actualiza la interfaz de usuario con el resultado de la llamada. Pero no hace ninguna adición lógica. Para completar la funcionalidad que necesitamos, agregaremos lógica adicional a la primera llamada de parche que

  • consultará el maestro del producto y completará el precio y la moneda
  • calcule el precio neto y complételo en la entidad del artículo

Consulte el siguiente código definido en service.js.

this.before('PATCH', OrderItems, async req => {

  let productInfo, price, quantity, dbItemInfo;

  //When product is available, fill price and currency
  if (req.data.product_id != undefined && req.data.product_id != null) {
    productInfo = await cds.read(Products).byKey(req.data.product_id);
    req.data.price = productInfo.price;
    req.data.currency_code = productInfo.currency_code;
  }

  // Calculate Net Price
  dbItemInfo = await cds.read(OrderItems.drafts).where({ ID: req.data.ID });
  req.data.price > 0 ? price = req.data.price : price = dbItemInfo[0].price;
  req.data.quantity > 0 ? 
  quantity = req.data.quantity : quantity = dbItemInfo[0].quantity;
  if (price > 0 && quantity > 0) {
    req.data.netprice = price * quantity;
    req.data.netprice = Math.round((req.data.netprice + Number.EPSILON)*100);
    req.data.netprice = req.data.netprice / 100;
  }

});

Efecto secundario en una entidad de origen: El monto total del pedido debe actualizarse automáticamente a medida que se agregan artículos. En otras palabras, cada vez que se actualizan los artículos del pedido, se debe iniciar un efecto secundario para recuperar el total del pedido. Para lograr esto, use las anotaciones a continuación:

annotate service.Orders @(Common : {
    SideEffects #ItemChanged     : {
        SourceEntities   : [items],
        TargetProperties : ['totamount', 'currency_code']
    }
});

Como se ve en el código a continuación, la cantidad total del pedido debe actualizarse en la llamada de parche inicial del efecto secundario.

this.after('PATCH', OrderItems, async data => {

  let orderInfo = { totamount: 0 };
  let result = await cds.read(OrderItems.drafts)
                        .where({ ID: data.ID }).columns(['order_ID']);
  let dbItemInfos = await cds.read(OrderItems.drafts)
                             .where({ order_ID: result[0].order_ID });
  for (let i = 0; i < dbItemInfos.length; i++) {
    if (dbItemInfos[i].netprice > 0) {
      orderInfo.totamount = orderInfo.totamount + dbItemInfos[i].netprice;
    }
    orderInfo.currency_code = dbItemInfos[i].currency_code;
  }
  await cds.update(Orders.drafts, result[0].order_ID).set(orderInfo);

});

Concepto-2: Función de valores predeterminados

Los valores predeterminados se pueden proporcionar utilizando una «Función de valor predeterminado» al crear una nueva entidad o elemento.
Por ejemplo, el estado inicial de un pedido siempre se establece en «Abierto» cuando se crea.

La anotación para proporcionar ‘DefaultValueFunction’ es como se muestra a continuación:

annotate service.Orders with @(
    Common.DefaultValuesFunction : 'getOrderDefaults'
);

Aquí, ‘getOrderDefaults‘ es una función vinculada de la entidad de pedidos bajo el servicio de pedidos. Se define en el archivo service.cds y service.js.

//Definition [service.cds]
function getOrderDefaults() returns Orders;

//Implementation [service.js]
this.on('getOrderDefaults', async req => {
  return {status: 'Open'};
});

Concepto-3: Acciones personalizadas

El estado inicial de un pedido es ‘Abierto’. Podemos definir una acción personalizada para cambiar el estado de ‘Abierto’ a ‘En proceso’ y viceversa.

Se proporcionan dos acciones vinculadas y su lógica correspondiente en service.cds y service.js respectivamente, como se muestra a continuación:

//Definition [service.cds]
entity Orders    as projection on db.Orders actions {
    action setOrderProcessing();
    action setOrderOpen(); 
};

//Implementation [service.js]
this.on('setOrderProcessing', Orders, async req => {
  await cds.update(Orders, req.params[0].ID).set({status: 'In Process'});
});

this.on('setOrderOpen', Orders, async req => {
  await cds.update(Orders, req.params[0].ID).set({status: 'Open'});
});

Estas 2 acciones se pueden agregar en la interfaz de usuario como botones usando anotaciones como se proporciona en el archivo annotations_ca_de.cds.

annotate service.Orders with @(UI.Identification : [
    {
        $Type         : 'UI.DataFieldForAction',
        Label         : 'Set to In Process',
        Action        : 'orderservice.setOrderProcessing'
    },
    {
        $Type         : 'UI.DataFieldForAction',
        Label         : 'Set to Open',
        Action        : 'orderservice.setOrderOpen'
    }
]);

Concepto-4: Expresiones Dinámicas

Las expresiones dinámicas son pequeñas lógicas definidas en la anotación para controlar el comportamiento de la interfaz de usuario.

Ejemplo: si el estado del pedido es Abierto, entonces solo se ve el botón ‘Establecer en proceso’ y si el estado del pedido es En proceso, solo se ve el botón ‘Establecer en abierto’. Para lograr esto, podemos usar expresiones dinámicas.

Nota 1: OData admite expresiones dinámicas en las anotaciones. En CDS, estas expresiones dinámicas se proporcionan mediante representaciones JSON. Para obtener más información, consulte este documento.

annotate service.Orders with @(UI.Identification : [
    {
        $Type         : 'UI.DataFieldForAction',
        Label         : 'Set to In Process',
        Action        : 'orderservice.setOrderProcessing',
        ![@UI.Hidden] : {$edmJson : {$Ne : [{$Path : 'status'}, 'Open']}}
    },
    {
        $Type         : 'UI.DataFieldForAction',
        Label         : 'Set to Open',
        Action        : 'orderservice.setOrderOpen',
        ![@UI.Hidden] : {$edmJson : {$Eq : [{$Path : 'status'},'Open']}}
    }
]);

![@UI.Hidden] : {$edmJson: {$Ne: [{$Path : ‘status’}, ‘Open’]}}

$Path: Se refiere a la propiedad de la entidad
$Ne: no es igual al operador, otros valores son $Eq: igual a, $Le: menor o igual a, $Ge: mayor o igual a

La expresión dinámica anterior verifica si el estado no está abierto y luego devuelve verdadero.

Nota 2: Las expresiones dinámicas también pueden ser compuestas. Veamos un ejemplo:

Criticality: {$edmJson :{$If :[{$Eq :[{$Path : 'status'},'Open']}, 1, 3]}}

Una nueva expresión dinámica verifica si el estado está abierto y luego devuelve 1; de lo contrario, devuelve 3 para Criticidad.

Concepto-5: Acciones personalizadas con efectos secundarios

Como se explicó en el concepto anterior, hemos utilizado dos acciones para cambiar el estado del pedido. Sin embargo, una vez que se ejecuta la acción, el campo de estado en la interfaz de usuario también debería cambiar instantáneamente. Para lograr esto, podemos definir efectos secundarios para acciones personalizadas como se muestra a continuación.

En este caso, las anotaciones de efectos secundarios se proporcionan en el archivo service.cds.

entity Orders    as projection on db.Orders actions {

    @(  cds.odata.bindingparameter.name : '_it',
        Common.SideEffects : {TargetProperties : ['_it/status']}   )
    action setOrderProcessing();

    @(  cds.odata.bindingparameter.name : '_it',
        Common.SideEffects : {TargetProperties : ['_it/status']}   )
    action setOrderOpen();
    
};

Conclusión

Juntos, el modelo de programación de aplicaciones en la nube y los elementos Fiori mejoran la experiencia del desarrollador al mismo tiempo que aumentan la productividad y aceleran el desarrollo de aplicaciones listas para la empresa.

Se puede encontrar más información sobre Fiori Elements con el modelo de programación de aplicaciones en la nube aquí. Puede seguir mi perfil para recibir notificaciones de la próxima publicación de blog sobre CAP o Fiori Elements. Siéntase libre de proporcionar cualquier comentario que tenga en la sección de comentarios a continuación y haga sus preguntas sobre el tema en la comunidad de sap usando este Enlace.



Source link


accionesCAPcondinámicasefectoselementosexpresionesFioripersonalizadassecundarios

Artículos relacionados


Omnichannel Promotion Pricing  ·  Omnichannel Promotion Pricing Service  ·  Technical Articles
Precios de promoción omnicanal de SAP: habilite el procesamiento de salida con SAP Cloud Integration
#Chatbot  ·  #cpi  ·  Technical Articles
Creación de un bot con Power Virtual Agent de Microsoft en S/4 HANA local… con SAP BTP
enterprise support value maps  ·  expert guided implementation  ·  Product Information  ·  sap enterprise support  ·  sap enterprise support academy
Configuración de SAP Fiori para SAP S/4HANA: implementación guiada por expertos

Deja tu comentario Cancelar la respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

*

*

¿Qué es una empresa componible? ¿Y quién es el compositor?
Previo
Novedades de SAP for Me: disponibilidad del sistema
Siguiente

Madrid

Calle Eloy Gonzalo, 27
Madrid, Madrid.
Código Postal 28010

México

Paseo de la Reforma 26
Colonia Juárez,  Cuauhtémoc
Ciudad de México 06600

Costa Rica

Real Cariari
Autopista General Cañas, 
San José, SJ 40104

Perú

Av. Jorge Basadre 349
San Isidro
Lima, LIM 15073

Twitter Linkedin Instagram
Copyright 2022 | All Right Reserved.
Cookies Para que este sitio funcione adecuadamente, a veces instalamos en los dispositivos de los usuarios pequeños ficheros de datos, conocidos como cookies. La mayoría de los grandes sitios web también lo hacen.
Aceptar
Cambiar ajustes
Configuración de Cookie Box
Configuración de Cookie Box

Ajustes de privacidad

Decida qué cookies quiere permitir. Puede cambiar estos ajustes en cualquier momento. Sin embargo, esto puede hacer que algunas funciones dejen de estar disponibles. Para obtener información sobre eliminar las cookies, por favor consulte la función de ayuda de su navegador. Aprenda más sobre las cookies que usamos.

Con el deslizador, puede habilitar o deshabilitar los diferentes tipos de cookies:

  • Bloquear todas
  • Essentials
  • Funcionalidad
  • Análisis
  • Publicidad

Este sitio web hará:

Este sitio web no:

  • Esencial: recuerde su configuración de permiso de cookie
  • Esencial: Permitir cookies de sesión
  • Esencial: Reúna la información que ingresa en un formulario de contacto, boletín informativo y otros formularios en todas las páginas
  • Esencial: haga un seguimiento de lo que ingresa en un carrito de compras
  • Esencial: autentica que has iniciado sesión en tu cuenta de usuario
  • Esencial: recuerda la versión de idioma que seleccionaste
  • Functionality: Remember social media settings
  • Functionality: Remember selected region and country
  • Analytics: Keep track of your visited pages and interaction taken
  • Analytics: Keep track about your location and region based on your IP number
  • Analytics: Keep track of the time spent on each page
  • Analytics: Increase the data quality of the statistics functions
  • Advertising: Tailor information and advertising to your interests based on e.g. the content you have visited before. (Currently we do not use targeting or targeting cookies.
  • Advertising: Gather personally identifiable information such as name and location
  • Recuerde sus detalles de inicio de sesión
  • Esencial: recuerde su configuración de permiso de cookie
  • Esencial: Permitir cookies de sesión
  • Esencial: Reúna la información que ingresa en un formulario de contacto, boletín informativo y otros formularios en todas las páginas
  • Esencial: haga un seguimiento de lo que ingresa en un carrito de compras
  • Esencial: autentica que has iniciado sesión en tu cuenta de usuario
  • Esencial: recuerda la versión de idioma que seleccionaste
  • Functionality: Remember social media settings
  • Functionality: Remember selected region and country
  • Analytics: Keep track of your visited pages and interaction taken
  • Analytics: Keep track about your location and region based on your IP number
  • Analytics: Keep track of the time spent on each page
  • Analytics: Increase the data quality of the statistics functions
  • Advertising: Tailor information and advertising to your interests based on e.g. the content you have visited before. (Currently we do not use targeting or targeting cookies.
  • Advertising: Gather personally identifiable information such as name and location
Guardar y cerrar