Comment définir un tableau calculé ? À partir de la version 2023.1.2

Un tableau calculé est un Smart Field structurant de type tableau ne contenant que des champs calculés contenant de la donnée ou des champs étendus. Il permet de présenter un tableau dynamique en vue d'édition.

Recommandation

Si vous n’êtes pas familier avec les champs calculés et leur fonctionnement, il est fortement recommandé de lire la documentation associée.

Prérequis

Afin de pouvoir suivre ce guide, il faut préalablement avoir créé une ou plusieurs Smart Structure(s). Il est également recommandé d'avoir défini des champs calculés pour se familiariser avec cette notion.

Prérequis techniques

  • Anakeen Platform 4 - 2023.1.2

Ajouter un tableau calculé

Reprenons l'exemple de la Smart Structure COMPUTED_MENU. Notre menu se compose d'une liste de PLAT et de BOISSON. Nous souhaiterions présenter dans la Smart Structure un tableau récapitulant l'ensemble des consommables ainsi que le pourcentage du prix total les concernant.

Définir un tableau calculé

Ajoutons un tableau calculé à notre Smart Structure COMPUTED_MENU :























 
 
 
 



















<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<smart:config xmlns:smart="https://platform.anakeen.com/4/schemas/smart/1.0">
    <smart:structure-configuration name="COMPUTED_MENU" label="Menu dynamique">
        <smart:icon file="menu.png"/>
        <smart:class>Cogip\Restauratec\SmartStructures\ComputedMenu\ComputedMenuBehavior</smart:class>
        <smart:fields>
            <smart:field-set name="menu_frame" type="frame" access="ReadWrite" label="Informations relatives au menu">
                <smart:field-text name="menu_title" needed="true" is-title="true" access="ReadWrite" label="Libellé"/>
                <smart:field-htmltext name="menu_description" access="ReadWrite" label="Description"/>
                <smart:field-set name="menu_composition" type="array" access="ReadWrite" label="Composition du menu">
                    <smart:field-docid access="ReadWrite" name="menu_plat" label="Plat" relation="PLAT"/>
                    <smart:extended-field-money name="menu_plat_price" access="Read" label="Prix du plat" >
                        <smart:copy relation-field="menu_plat" from-field="consommable_price_excl_vat" />
                    </smart:extended-field-money>
                    <smart:field-docid access="ReadWrite" name="menu_boisson" label="Boisson" relation="BOISSON"/>
                    <smart:extended-field-money name="menu_boisson_price" access="Read" label="Prix de la boisson" >
                        <smart:copy relation-field="menu_boisson" from-field="consommable_price_excl_vat" />
                    </smart:extended-field-money>
                    <smart:computed-field-money name="combined_price" access="Read" label="Somme"/>
                </smart:field-set>
                <smart:field-double name="menu_discount" access="ReadWrite" label="Remise applicable (%)"/>
                <smart:computed-field-money name="menu_price" access="Read" label="Prix (€)"/>
                <smart:computed-field-array name="computed_array" access="Read" label="Récapitulatif de la composition">
                    <smart:computed-field-docid access="Read" name="computed_id" label="Consommable" relation="CONSOMMABLE" is-key="true"/>
                    <smart:computed-field-double access="Read" name="computed_percent" label="Pourcentage du prix total"/>
                </smart:computed-field-array>
            </smart:field-set>
        </smart:fields>
        <smart:defaults/>
        <smart:computed>
            <smart:field-computed field="menu_price">
                <smart:field-callable function="::computeTotalPrice"/>
                <smart:field-argument type="field" name="prix_boissons">menu_boisson_price</smart:field-argument>
                <smart:field-argument type="field" name="prix_plats">menu_plat_price</smart:field-argument>
                <smart:field-argument type="field" name="remise">menu_discount</smart:field-argument>
            </smart:field-computed>
            <smart:field-computed field="combined_price">
                <smart:field-callable function="::computeCombinedPrice"/>
                <smart:field-argument type="field">menu_boisson_price</smart:field-argument>
                <smart:field-argument type="field">menu_plat_price</smart:field-argument>
            </smart:field-computed>
        </smart:computed>
    </smart:structure-configuration>
</smart:config>

Informations

Un tableau calculé doit contenir une seule et unique clé qui déterminera sa taille, celle-ci doit être un champ calculé retournant une valeur multiple. La définition de la clé se fait à l'aide de l'attribut @is-key.

Dans notre cas, la clé computed_id est la liste fusionnée des docid référencés dans menu_plat et dans menu_boisson. L'autre champ calculé computed_percent sera le pourcentage du prix par rapport au prix total.

Attention

Un tableau calculé ne peut contenir que des champs calculés contenant de la donnée ou des champs étendus.

Configurer le calcul des champs du tableau calculé

Ajoutons, comme dans le chapitre précédent, les dépendances et la fonction de calcul pour nos deux nouveaux champs calculés computed_id et computed_percent :










































 
 
 
 
 
 
 
 
 
 
 




<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<smart:config xmlns:smart="https://platform.anakeen.com/4/schemas/smart/1.0">
    <smart:structure-configuration name="COMPUTED_MENU" label="Menu dynamique">
        <smart:icon file="menu.png"/>
        <smart:class>Cogip\Restauratec\SmartStructures\ComputedMenu\ComputedMenuBehavior</smart:class>
        <smart:fields>
            <smart:field-set name="menu_frame" type="frame" access="ReadWrite" label="Informations relatives au menu">
                <smart:field-text name="menu_title" needed="true" is-title="true" access="ReadWrite" label="Libellé"/>
                <smart:field-htmltext name="menu_description" access="ReadWrite" label="Description"/>
                <smart:field-set name="menu_composition" type="array" access="ReadWrite" label="Composition du menu">
                    <smart:field-docid access="ReadWrite" name="menu_plat" label="Plat" relation="PLAT"/>
                    <smart:extended-field-money name="menu_plat_price" access="Read" label="Prix du plat" >
                        <smart:copy relation-field="menu_plat" from-field="consommable_price_excl_vat" />
                    </smart:extended-field-money>
                    <smart:field-docid access="ReadWrite" name="menu_boisson" label="Boisson" relation="BOISSON"/>
                    <smart:extended-field-money name="menu_boisson_price" access="Read" label="Prix de la boisson" >
                        <smart:copy relation-field="menu_boisson" from-field="consommable_price_excl_vat" />
                    </smart:extended-field-money>
                    <smart:computed-field-money name="combined_price" access="Read" label="Somme"/>
                </smart:field-set>
                <smart:field-double name="menu_discount" access="ReadWrite" label="Remise applicable (%)"/>
                <smart:computed-field-money name="menu_price" access="Read" label="Prix (€)"/>
                <smart:computed-field-array name="computed_array" access="Read" label="Récapitulatif de la composition">
                    <smart:computed-field-docid access="Read" name="computed_id" label="Consommable" relation="CONSOMMABLE" is-key="true"/>
                    <smart:computed-field-double access="Read" name="computed_percent" label="Pourcentage du prix total"/>
                </smart:computed-field-array>
            </smart:field-set>
        </smart:fields>
        <smart:defaults/>
        <smart:computed>
            <smart:field-computed field="menu_price">
                <smart:field-callable function="::computeTotalPrice"/>
                <smart:field-argument type="field" name="prix_boissons">menu_boisson_price</smart:field-argument>
                <smart:field-argument type="field" name="prix_plats">menu_plat_price</smart:field-argument>
                <smart:field-argument type="field" name="remise">menu_discount</smart:field-argument>
            </smart:field-computed>
            <smart:field-computed field="combined_price">
                <smart:field-callable function="::computeCombinedPrice"/>
                <smart:field-argument type="field">menu_boisson_price</smart:field-argument>
                <smart:field-argument type="field">menu_plat_price</smart:field-argument>
            </smart:field-computed>
            <smart:field-computed field="computed_id">
                <smart:field-callable function="::getAllConsommables"/>
                <smart:field-argument type="field" name="boissons">menu_boisson</smart:field-argument>
                <smart:field-argument type="field" name="plats">menu_plat</smart:field-argument>
            </smart:field-computed>
            <smart:field-computed field="computed_percent">
                <smart:field-callable function="::computeRelativePercent"/>
                <smart:field-argument type="field" name="id">computed_id</smart:field-argument>
                <smart:field-argument type="field" name="total">menu_price</smart:field-argument>
                <smart:field-argument type="field" name="remise">menu_discount</smart:field-argument>
            </smart:field-computed>
        </smart:computed>
    </smart:structure-configuration>
</smart:config>

Définissons nos deux nouvelles fonctions de calcul :





























 
 
 
 

 
 
 
 
 
 


<?php

namespace Anakeen\SmartStructures\ComputedMenu;

use Anakeen\Core\SEManager;
use Anakeen\Core\SmartStructure\Dynamic\DynamicUpdateRequest;
use Anakeen\Core\SmartStructure\Dynamic\DynamicUpdateResponse;

class ComputedMenuBehavior extends \Anakeen\SmartElement
{
    public function computeTotalPrice(DynamicUpdateRequest $request, DynamicUpdateResponse $response, $args): DynamicUpdateResponse
    {
        $total = 0;
        $consommablesPrice = array_merge($args['prix_boissons'], $args['prix_plats']);
        foreach ($consommablesPrice as $price) {
            if ($price !== null) {
                $total += $price;
            }
        }
        $total = $total * (1.0 - (floatval($args['remise'] ?? 0) / 100.0));
        return $response->setResult($total);
    }

    public function computeCombinedPrice(DynamicUpdateRequest $request, DynamicUpdateResponse $response, $args): DynamicUpdateResponse
    {
        return $response->setResult(($args[0] ?? 0) + ($args[1] ?? 0));
    }

    public function getAllConsommables(DynamicUpdateRequest $request, DynamicUpdateResponse $response, $args): DynamicUpdateResponse
    {
        return $response->setResult(array_merge(array_filter($args['boissons']), array_filter($args['plats'])));
    }

    public function computeRelativePercent(DynamicUpdateRequest $request, DynamicUpdateResponse $response, $args): DynamicUpdateResponse
    {
        $consommable = SEManager::getDocument($args['id']);
        $price = floatval($consommable->getAttributeValue('consommable_price_incl_vat') ?? 0) * (1.0 - (floatval($args['remise'] ?? 0) / 100.0));
        return $response->setResult(round(($price / floatval($args['total'])) * 100.0, 2));
    }
}

Déployons nos modifications et rendons-nous sur le formulaire de création de COMPUTED_MENU :

Mise à jour dynamique

À chaque ajout de plat, de boisson, à chaque duplication, réorganisation ou suppression de lignes, l'intégralité du tableau calculé est bien mis à jour 🎉 !

Et ensuite ?

Continuons sur la gestion des champs de notre Smart Structure au travers du guide :

Comment définir un paramètre de Smart Structure ?