View source | Discuss this page | Page history | Printable version   
Toolbox
Main Page
Upload file
What links here
Recent changes
Help

PDF Books
Add page
Show collection (0 pages)
Collections help

Search

Modules:Analytics FactTables/fr

Contents

Tables de Faits versus Tables de Transactions pour les Cubes

Openbravo facilite la définition de cubes à partir de toute table définie dans le Dictionnaire Applicatif d'Openbravo. Cela inclut toutes les tables transactionnelles existantes.

Il existe cependant un accord de principe dans le milieu des tables OLAP/Analytics, qui dit que définir des cubes sur la base de tables transactionnelles n'est pas la meilleure approche. Il existe plusieurs raisons à cela:

Donc, cela prend souvent tout son sens de définir une table à part dans le Dictionnaire Applicatif pour couvrir vos besoins analytiques. Openbravo fournit une infrastructure comportant des mécanismes standards pour mettre à jour les tables de faits et permet à du code personnalisé de participer au traitement standard de mise à jour des tables de faits. Ceci est expliquer dans ce document wiki.

Infrastructure table de faits Openbravo

L'infrastructure de la table de faits Openbravo est constituée de 2 parties:

Définir votre propre table de faits

Lors de la définition de votre table de faits vous devez suivre les étapes suivantes:

  1. créer la table de faits dans la base de données et la définir dans le Dictionnaire Applicatif, c'est fait de la même façon que pour tout autre table Openbravo, voir ce howto.
  2. implémenter une classe OBAnalyticsFactUpdater qui se charge de la création des enregistrements de faits à partir d'une table transactionnelle.

Dans cette section, nous approfondirons ce second sujet, en créant notre propre classe OBAnalyticsFactUpdater. D'abord elle doit étendre la classe standard OBAnalyticsFactUpdater. Étendre cette classe comporte plusieurs avantages:

Nous allons maintenant parcourir un exemple d’implémentation d'updater de fait, l'updater de fait que nous utilisons pour le Cube des Commandes de Ventes.

Vous commencez par étendre la classe OBAnalyticsFactUpdater:

public class OBAnalyticsFactOrderUpdater extends
    OBAnalyticsFactUpdater<OrderLine, AnalyticsFactOrder> {

Comme vous pouvez le voir, vous étendez la classe avec des génériques, elle définit à la fois la table transactionnelle principale et la table de faits comme des paramètres génériques. Dans cet exemple OrderLine est la table transactionnelle principale et AnalyticsFactOrder est la table de faits cible. De nombreuses méthodes dont vous aurez besoin pour implémenter/enrichir, font usage des mêmes génériques.

Dans l'étape suivante, vous devez implémenter plusieurs méthodes abstraites héritées de la classe de base. Nous allons les explorer séparément. D'abord, la méthode getData, qui doit retourner les enregistrements de table transactionnelle principale, dans ce cas les instances Orderline:

  protected ScrollableResults getData() {
    final Date fromDate = getLastUpdateRunDate();
    final String qryStr = "select ol from " + OrderLine.ENTITY_NAME
        + " ol where ol.client.id = :client and ol.active=true and ol."
        + OrderLine.PROPERTY_SALESORDER + ".active=true and ol." + OrderLine.PROPERTY_SALESORDER
        + "." + Order.PROPERTY_DOCUMENTSTATUS + "='CO' and (ol.updated >= :updated or ol."
        + OrderLine.PROPERTY_SALESORDER + ".updated >= :updated)";
    final Query qry = OBDal.getInstance().getSession().createQuery(qryStr);
    qry.setDate("updated", fromDate);
    qry.setString("client", OBContext.getOBContext().getCurrentClient().getId());
    return qry.scroll(ScrollMode.FORWARD_ONLY);
  }

Remarquer comment la méthode getLastUpdateRunDate est utilisée dans des requêtes pour toute modification/création d'objet depuis la dernière mise à jour de cette table de faits.

Donc l'updater nécessite aussi de supprimer les tables de fait qui sont devenus obsolètes, la méthode suivante fait cela:

  protected void purgeFacts() {
    // Note: no implicit joins are allowed in the where clause, an inner select is however allowed
    final String qryStr = "delete " + getFactEntityName()
        + " olFact where (olFact.updated < (select ol.updated from " + OrderLine.ENTITY_NAME
        + " as ol where ol.id = olFact." + AnalyticsFactOrder.PROPERTY_SALESORDERLINE
        + ") or olFact.updated < (select o.updated from " + Order.ENTITY_NAME
        + " as o where olFact." + AnalyticsFactOrder.PROPERTY_SALESORDERLINE + "."
        + OrderLine.PROPERTY_SALESORDER + ".id = o.id)) and olFact.client.id=:client";
    OBDal.getInstance().getSession().createQuery(qryStr)
        .setString("client", OBContext.getOBContext().getCurrentClient().getId()).executeUpdate();
  }

Remarquer la comparaison sur la colonne 'updated', vous pouvez choisir une même approche dans votre 'factupdater'.

La méthode suivante décrit la façon dont la classe de base permet la copie de la table transactionnelle vers la table de faits. Juste avant le nom de propriété, vous pouvez utiliser un chemin de propriété: salesOrder.businessPartner.businessPartnerCategory par exemple. Dans l'exemple ci-dessous le code utilise les noms de propriétés générés depuis les entités générées, cela donne plus de sécurité au moment de la compilation.

 
  protected Map<String, String> getPropertyMap() {
    final String orderPath = OrderLine.PROPERTY_SALESORDER;
    final String bpPath = OrderLine.PROPERTY_SALESORDER + "." + Order.PROPERTY_BUSINESSPARTNER;
    final String productPath = OrderLine.PROPERTY_PRODUCT;
 
    final Map<String, String> result = new HashMap<String, String>();
    result.put(OrderLine.PROPERTY_CLIENT, AnalyticsFactOrder.PROPERTY_CLIENT);
    result.put(OrderLine.PROPERTY_ORGANIZATION, AnalyticsFactOrder.PROPERTY_ORGANIZATION);
    result.put(bpPath, AnalyticsFactOrder.PROPERTY_BUSINESSPARTNER);
 
    ...
 
    return result;
  }

La dernière méthode qui peut être enrichie permet simplement de fournir à la classe de base le nom de l'entité de la table de faits:

  protected String getFactEntityName() {
    return AnalyticsFactOrder.ENTITY_NAME;
  }

Il existe plusieurs méthodes que vous pouvez enrichir dans votre classe de base, elles ont toutes une javadoc associée pour expliquer leur signification et leur but.

Etendre une Table de faits existante

Vous pouvez aussi ajouter de nouvelles colonnes de dimension à une table de faits. Openbravo lui-même fait cela en ajoutant des dimensions retail au cube des ventes ERP. Pour étendre une table de faits existante vous devez procéder aux étapes suivantes:

Dans cette section nous discuterons uniquement du troisième alinea, les deux autres sont couverts dans d'autres documents wiki (voir les liens dans les chacun de ces points).

Vous démarrez en créant une classe qui étend la classe OBAnalyticsFactObjectUpdater:

public class OBRetailAnalyticsOrderLineFactObjectUpdater extends
    OBAnalyticsFactObjectUpdater<OrderLine, AnalyticsFactOrder> {

Comme vous pouvez le voir vous enrichissez une classe avec des paramètres génériques. Ce sont la table transactionnelle principale (la source de la table de faits) et le type de la table de faits. En étendant la classe de base, Openbravo détectera automatiquement votre implémentation et l'appellera lorsque vous mettrez à jour les tables de faits.

Vous devez ensuite implémenter deux méthodes. La première demande si votre casse peut manipuler une table de faits spécifique. Cette méthode est nécessaire car tous les updaters étendant des faits sont appelés pour toutes les tables de faits.

  public boolean canHandleFact(OBAnalyticsFactUpdater<?, ?> factUpdater, Object sourceBob,
      Object factBob) {
    return sourceBob instanceof OrderLine && factBob instanceof AnalyticsFactOrder;
  }

Elle devrait retourner 'vrai' si votre classe est capable de traiter l'objet fait spécifique. Si vous retournez 'vrai' alors la méthode suivante est appelée par Openbravo. Cette méthode vous permet de mettre à jour la table de faits avec des propriétés supplémentaires:

  public void handleFact(OBAnalyticsFactUpdater<OrderLine, AnalyticsFactOrder> factUpdater,
      OrderLine orderLine, AnalyticsFactOrder orderLineFact) {
    if (orderLine.getSalesOrder().getObposApplications() != null) {
      orderLineFact.setOBRETANPOSTerminal(orderLine.getSalesOrder().getObposApplications());
      orderLineFact.setObretanTerminaltype(orderLine.getSalesOrder().getObposApplications()
          .getObposTerminaltype());
    }
    orderLineFact.setObretanBusinessdate(TimeDimensionProvider.getInstance().getTimeDimension(
        orderLine.getSalesOrder().getPOSSBusinessDate()));
  }

Valeur de Dimension Date/Heure dans les tables de faits

Les tables transactionnelles ont pratiquement toujours des propriétés/colonnes de date à considérer comme une dimension. Pour les dimensions date dans votre table de faits, vous ne devriez pas utiliser le type/référence date mais plutôt utiliser une référence de clé étrangère à la table TimeDimension. Remarquer que pour les tables de faits, il n'est pas nécessaire de créer une colonne date, seule la référence à l'entité TimeDimension est nécessaire.

Une clé étrangère vers la table TimeDimension a un avantage au niveau performance (ce n'est pas une fonction base de donnée) et un autre avantage qui est qu'il existe des membres dimension pour toutes les dates, et de ce fait 'aucun trou' dans les données dans les rapports.

Voir l'exemple de la table de faits des commandes de ventes, qui a plusieurs colonnes 'dates' qui sont en fait des références à la table TimeDimension.

Openbravo convertira automatiquement les valeurs dates/heures vers l'enregistrement TimeDimension lors de l'enrichissement de l'updtaer de fait. Donc il n'est pas nécessaire d'avoir une gestion personnalisée.

Comportement des Devises dans les Rapports Openbravo

De nombreuses mesures sont des montants évalués dans une devise spécifique. Si votre société utilise une seule devise ou si vous analysez toujours des données dans la devise transactionnelle alors il n'est pas utile de définir une devise spécifique pour les rapports.

Cette section décrit la fonctionnalité qui permet d'utiliser des devises dans les rapport et qui offre la souplesse de stocker les faits dans différentes devises.

Remarque pour les développeurs la fonctionnalité suivante doit être encouragée:

--> cette méthode devrait créer/copier l'instance, convertir tous les champs Bigdecimal qui ont la référence montant (ou d'autres références orientées montant)

--> ajouter éventuellement une méthode enrichie spécifique pour obtenir toutes les propriétés qui ont besoin d'être converties.

Les deux méthodes:

protected Date getCurrencyConversionDate(S sourceBob, F factBob) {
return null;
}
protected Currency getCurrency(S sourceBob, F factBob) {
// default behavior could be to find a property which is a currency and then return it 
return null;
}

Donc dans la boucle dans le OBAnalyticsFactUpdater vérifier si les Devises de rapport doivent être supportées, dans ce cas, créer différentes instances pour chaque devise de rapport et enregistrer-les.

Les colonnes Date/Heure représentent un mapping spécial dans Analytics. En effet, l'information est souvent analysée sur une année, un trimestre, un mois ou un ensemble de ces membres dimensionnels.

Retrieved from "http://wiki.openbravo.com/wiki/Modules:Analytics_FactTables/fr"

This page has been accessed 591 times. This page was last modified on 24 February 2015, at 16:40. Content is available under Creative Commons Attribution-ShareAlike 2.5 Spain License.