Comment ajouter des données à visualiser ?
Prérequis
Afin de pouvoir suivre ce guide, il faut préalablement avoir créé une ou plusieurs Smart Structure(s). Il est également nécessaire d'avoir préparé l'environnement.
Définir des métriques sur une Smart Structure existante
Reprenons l'exemple de la Smart Structure Menu
. Nous souhaitons analyser et visualiser les métriques suivantes dans
nos tableaux de bord :
- prix du menu
- remise
- nombre de plats
Définition des métriques
Dans un premier temps, créons un nouveau fichier de configuration renseignant la liste de ces indicateurs ainsi que leur type :
src/vendor/Cogip/Restauratec/SmartStructures/Menu/MenuDashboard.xml
<?xml version="1.0" encoding="UTF-8"?>
<dashboard:table name="menu" xmlns:dashboard="https://platform.anakeen.com/4/schemas/dashboard-table/1.0">
<dashboard:field type='float' name='price' />
<dashboard:field type='float' name='discount' nullable='true' />
<dashboard:field type='integer' name='nb_plats' />
<dashboard:field type='date' name='creation' />
</dashboard:table>
Nous ajoutons également un champ creation
pour sauvegarder la date de création de chacun de nos menus, et ainsi
pouvoir visualiser l'évolution de nos métriques au cours du temps.
Informations
Ce fichier décrit la structure de la table qui sera créée dans la base de données dédiée à Superset. Pour consulter la liste des types et options disponibles consulter le manuel de référence.
Attention
Pensez à déployer vos modifications locales sur le serveur et à générer les stubs :
make deploy
make generate-stubs
Définition du calcul des métriques
Dans un premier temps, lions notre fichier de configuration à la Smart Structure Menu
. Pour cela, étendons la classe
MenuBehavior
en implémentant l'interface IDashboardElement
.
src/vendor/Cogip/Restauratec/SmartStructures/Menu/MenuBehavior.php
<?php
namespace Cogip\Restauratec\SmartStructures\Menu;
use Anakeen\Dashboard\IDashboardElement;
use Anakeen\Dashboard\ADashboardEntity;
class MenuBehavior extends \Anakeen\SmartElement implements IDashboardElement
{
public function registerHooks()
{
parent::registerHooks();
}
public static function getConfigurationFile(): string
{
return __DIR__ . '/MenuDashboard.xml';
}
public function aggregateData(ADashboardEntity|DashboardEntity &$entity) {}
}
getConfigurationFile()
doit retourner le chemin du fichier de configuration précédemment créé.
Il faut maintenant définir la façon dont ces métriques vont être calculées. Pour ce faire, implémentons la fonction
aggregateData()
.
src/vendor/Cogip/Restauratec/SmartStructures/Menu/MenuBehavior.php
<?php
namespace Cogip\Restauratec\SmartStructures\Menu;
use Anakeen\Dashboard\IDashboardElement;
use Anakeen\Dashboard\ADashboardEntity;
use SmartStructure\Fields\Consommable as ConsommableFields;
use SmartStructure\Fields\Menu as MenuFields;
use Anakeen\Core\SEManager;
class MenuBehavior extends \Anakeen\SmartElement implements IDashboardElement
{
public function registerHooks()
{
parent::registerHooks();
}
public static function getConfigurationFile(): string
{
return __DIR__ . '/MenuDashboard.xml';
}
public function aggregateData(ADashboardEntity|DashboardEntity &$entity)
{
$entity->price = $this->calculateTotalPrice();
$entity->discount = $this->getAttributeValue('menu_discount');
$entity->nb_plats = count($this->getAttributeValue(MenuFields::menu_plat));
$entity->creation = \DateTime::createFromFormat("Y-m-d H:i:s.u", substr($this->cdate, 0, 26));
}
private function calculateTotalPrice(): float
{
$consumables = array_merge(
array_values($this->getAttributeValue(MenuFields::menu_plat)),
array_values($this->getAttributeValue(MenuFields::menu_boisson))
);
$discount = $this->getAttributeValue(MenuFields::menu_discount);
$totalPrice = 0;
foreach ($consumables as $value) {
$smartElement = SEManager::getDocument($value);
if (!is_null($smartElement)) {
$smartField = $smartElement->getAttributeValue(ConsommableFields::consommable_price_incl_vat);
if (!is_null($smartField)) {
$totalPrice += smartField;
}
}
}
return $totalPrice * (1 - $discount / 100);
}
}
aggregateData()
doit définir comment sont calculés les indicateurs par rapport au Smart Element concerné. Le
calcul des indicateurs est réalisé de manière asynchrone par les workers de l'ETL, il est donc possible d'effectuer des
calculs bien plus complexes et coûteux que ceux présentés dans ce guide sans pour autant surcharger notre application.
Attention
Il est nécessaire de renseigner chaque champ qui n'a pas été défini comme nullable
dans le fichier de configuration.
Attention
Pensez à déployer vos modifications locales sur le serveur.
make deploy
Limitations et solutions
Attention
L'ETL met à jour les métriques des Smart Elements concernés en fonction de leur mdate
: les métriques sont recalculées
uniquement si le Smart Element est plus récent au sens de mdate
.
En l'état, si le prix d'un des plats du menu est modifié le prix total ne sera pas recalculé tant que le menu lui-même
n'aura pas été édité. Une solution possible est de modifier automatiquement le mdate
des menus concernés par le
changement de prix d'un plat donné. Pour ce faire, enregistrons une méthode qui sera appelée à chaque modification d'un
Smart Element Plat
:
src/vendor/Cogip/Restauratec/SmartStructures/Plat/PlatBehavior.php
<?php
namespace Cogip\Restauratec\SmartStructures\Plat;
use Anakeen\Core\Utils\Date;
use Anakeen\Search\Filters\ContainsValues;
use Anakeen\Search\SearchElements;
use Anakeen\SmartHooks;
class PlatBehavior extends \Anakeen\SmartElement
{
public function registerHooks()
{
parent::registerHooks();
$updateRelatedMenu = function () {
$search = new SearchElements('MENU');
$search->setLatest(true);
$search->addFilter(new ContainsValues(\SmartStructure\Fields\Menu::menu_plat, strval($this->initid)));
$res = $search->getResults();
foreach ($res as $se) {
$se->mdate = Date::getNow(true);
$se->modify();
}
};
$this->getHooks()->addListener(SmartHooks::POSTSTORE, $updateRelatedMenu);
$this->getHooks()->addListener(SmartHooks::POSTREVISE, $updateRelatedMenu);
$this->getHooks()->addListener(SmartHooks::POSTDELETE, $updateRelatedMenu);
$this->getHooks()->addListener(SmartHooks::POSTUNDELETE, $updateRelatedMenu);
}
}
Désormais lorsqu'un plat est modifié, tous les menus qui le contiennent voient leur date de modification (mdate) mise à jour. Ces menus sont alors traités à nouveau par l'ETL, assurant ainsi que leur prix est toujours à jour.
Recommandation
Modifiez de la même façon BoissonBehavior
.
Informations
Une autre solution est la définition de champs étendus. À partir de la version 2023.01
Importation des données
Pour mettre à jour les schémas des données traitées par l'ETL il suffit de redémarrer l'environnement :
make env-stop
make env-start
Désormais, l'ETL va maintenir à jour une nouvelle table menu
avec le prix, la date de création, la remise ainsi que le
nombre de plats de chacun des Smart Elements Menu
.
Recommandation
Pensez à créer quelques Smart Elements :
Attention
Le traitement est asynchrone. Par défaut l'actualisation a lieu toutes les minutes.