À partir de la version 2023.1.2
Comment définir un tableau calculé ?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
:
À 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 :