Use DashBoard View in Tryton

Bonjour,

J’espère que vous allez tous bien.

J’aimerai savoir comment est-ce qu’un dashboard view est censé fonctionner.

J’essaie d’utiliser en créant une classe de cette manière :

class Dashboard_General(ModelSQL, ModelView):
    "Dashboard General Pour l'app"
    __name__="general.dashboard"

    # Date : Éléments général de la recherche 

    date_debut = fields.Date("Date de Début", required=True)
    date_fin = fields.Date("Date de Fin", required=True)

    # Elément 1 : Etat / Classement Ventes Totale par Assurance

    vente_assurance = fields.Boolean("Ventes Par Assurances", help="Cocher si vous voulez faire une actualisation des ventes par assurance")
    assurance_name = fields.Function(fields.Char("Assurance"), "get_classement_assurance_vente")
    total_vente =  fields.Function(fields.Float("Total des ventes."), "get_classement_assurance_vente")



    def default_date_debut():
        return date.today()
    
    def default_date_fin():
        return date.today()
    
    def get_classement_assurance_vente(self):

        if self.vente_assurance == True :

            list_of_save_elements = []
            listes_factures = []

            Ventes_Assurance = Pool().get("ventes.assurances")
            Ventes_ass = Ventes_Assurance.search([])
            Ventes_Assurance.delete(Ventes_ass)

            Invoices = Pool().get("account.invoice")
            Factures = Invoices.search([('invoice_date', '>=', self.date_debut), ('invoice_date', '<=', self.date_fin), ('state', 'in', ['paid', 'posted'])])

            for Facture in Factures:
                if Facture.number not in listes_factures:
                    listes_factures.append(Facture.number)
            
            for Facture in Factures:
                if Facture.reference in listes_factures:
                    listes_factures.remove(Facture.reference)
                    listes_factures.remove(Facture.number)

            dict_assurance = {}
            for facture_number in listes_factures:
                facture = Invoices.search([('number', '=', facture_number)], limit=1)
                if not facture:
                    continue
                assurance = facture[0].party.sale_price_list
                if assurance.name in dict_assurance:
                    dict_assurance[assurance.id]['total_vente'] += facture[0].montant_assurance
                else:
                    dict_assurance[assurance.id] = {
                        'assurance_name': assurance.name,  # nom réel du champ Many2One
                        'total_vente': facture[0].montant_assurance
                    }

            return dict_assurance

Que j’utilise dans la vue déclarative comme ceci :

<record model="ir.ui.view" id="dashboard_ventes_assurance_view_list2">
            <field name="model">general.dashboard</field>
            <field name="type">board</field>
            <field name="name">dashboard_ventes</field>
        </record>

        <record model="ir.action.act_window" id="act_dashboard_syntheses_assurances_form2">
         <field name="name">Dashboard General</field>
         <field name="res_model">general.dashboard</field>
        </record>

        <record model="ir.action.act_window.view" id="act_dashboard_syntheses_assurances_form_view12">
            <field name="sequence" eval="10"/>
            <field name="view" ref="dashboard_ventes_assurance_view_list2"/>
            <field name="act_window" ref="act_dashboard_syntheses_assurances_form2"/>
        </record>
    
        <menuitem
            parent="menu_rapport"
            action="act_dashboard_syntheses_assurances_form2"
            sequence="10"
            id="menu_act_dashboard_syntheses_assurances_form"/>

A l’intérieur de ma vue dashboard_ventes donc j’ai ceci.

<?xml version="1.0"?>
<board>
    <action name="act_dashboard_syntheses_assurances_form2">
    <label name="date_debut"/>
    <label name="date_fin"/>
    <separator string="Paramètres Additionnels."
        colspan="4" id="parametres.additionnels"/>
    <label name="vente_assurance"/>
    <notebook colspan="6">
        <label name="assurance_name"/>
        <label name="total_vente"/>
    </notebook>
</board>

QUi est particulièrement inexact à cause des propriétés Separator, notebook.

Mais Lorsque j’enlève plus rien ne se passe.

Je veux comprendre comment afficher les éléments de ma classe si j’ai bien compris le dashboard me permettra de le faire.

Besoin d’aide s’il vous plait

@ced @pokoli any ideas of this please?

Les vues board ne sont pas liées à un modèle.
Ce sont des vues qui regroupe plusieurs action windows dans un seul onglet.
Elles sont assez complexes à mettre en œuvre et aucun module standard n’en utilise (à part le module dashboard mais c’est une utilisation encore plus complexe).

De ce que je comprend du code fournit, ce serait plus une sorte de rapport en utilisant un modèle de contexte et une action avec un domain contextuel.

Si vous le dites comme celà.

Je pensais pouvoir utiliser cette vue pour afficher un dashboard avec des vues GRAPH.

Mais vu que ce n’est pas possible, quelle méthode ou éléments je peux utiliser pour implémenter ce genre de dashboard sur Tryton?

Si vous avez des idées je suis preneur s’il vous plait.

Il faudrait définir précisément ce que vous voulez afficher afin qu’on puisse fournir un conseil.

Il y’a plusieurs trucs que je veux afficher mais qui tourne autour du traitement des factures prioritairement.
Par exemple :

  • Le nombre de facture par client sur une période donnée
  • Le nombre de facture par assurance sur une période donnée et la somme totale pour chaque assurance.
  • La catégorie de produit la plus utilisée / Le produit le plus rentable sur une période.
  • Les différentes factures crédit et leur équivalence sur une période

Bien évidemment j’ai d’autres éléments qui ne tourne pas autour des factures.

L’idée principale est d’avoir une seule interface capable d’afficher la majorité de ses éléments sous forme de tableau ou de Chart Pie cela dépends des possibilités.

A priori le plus simple est de créer les différentes ir.action.act_window qui correspond à chaque données.
Et ensuite utiliser le module dashboard pour ajouter ces actions sur le profile de l’utilisateur.

Chaque ir.action.act_window est relié à une classe ou un modèle.

Ca veut dire que je dois créer, par exemple pour chaque tiret de la liste plus haut, un modèle et pour chaque modèle un ir.action.act_window.

Si on va dans ce sens. Les éléments d’un modèle actuellement sont enregistrés et j’ai utilisé un ir.action.act_windows pour l’affichage

Maintenant j’aimerai savoir si c’est une bonne pratique d’utiliser un wizard afin de sauvegarder les éléments de ce modèle.

Je vous montre ma classe :

class Classement_Assurance_vente(ModelSQL, ModelView):
    "Classement des ventes Totale par Assurance"
    __name__ = "ventes.assurances"

    assurance_name = fields.Char("Assurance")
    total_vente = fields.Float("Total des ventes.")

Mon wizard

class Elements_Actualisations(ModelView):
    'Les Élements D\'actualisations du rapports'
    __name__ = 'elements.refresh.init'

    date_debut = fields.Date("Date de Début", required=True)
    date_fin = fields.Date("Date de Fin", required=True)

    vente_assurance = fields.Boolean("Ventes Par Assurances", help="Cocher si vous voulez faire une actualisation des ventes par assurance")

class GenerateResultsReports(Wizard):
    'Generation des Rapports En Totalité'
    __name__ = 'rapports.refresh.all'

    start = StateView('elements.refresh.init',
        'z_all_synthesis.view_element_actualisation', [
            Button('Cancel', 'end', 'tryton-cancel'),
            Button('Generate Validation', 'actualise_graph_reports', 'tryton-ok',
                True),
            ])
    
    BATCH_SIZE = 10
     
    def default_start(self, fields):
        today = date.today()
        default = {
            'date_debut': datetime.combine(today, time.min),
            'date_fin': datetime.combine(today, time.max),
            }
        return default
    
    actualise_graph_reports = StateTransition()

    def transition_actualise_graph_reports(self):
        if self.start.vente_assurance :
            print("toto")
            self.is_vente_assurance(self.start.date_debut,  self.start.date_fin)

            return 'end'
    

    
    def is_vente_assurance(self, start_date, end_date):

        list_of_save_elements = []
        listes_factures = []

        Ventes_Assurance = Pool().get("ventes.assurances")
        Ventes_ass = Ventes_Assurance.search([])
        Ventes_Assurance.delete(Ventes_ass)

        Invoices = Pool().get("account.invoice")
        Factures = Invoices.search([('invoice_date', '>=', start_date), ('invoice_date', '<=', end_date), ('state', 'in', ['paid', 'posted'])])

        for Facture in Factures:
            if Facture.number not in listes_factures:
                listes_factures.append(Facture.number)
        
        for Facture in Factures:
            if Facture.reference in listes_factures:
                listes_factures.remove(Facture.reference)
                listes_factures.remove(Facture.number)

        dict_assurance = {}
        for facture_number in listes_factures:
            facture = Invoices.search([('number', '=', facture_number)], limit=1)
            if not facture:
                continue
            assurance = facture[0].party.sale_price_list
            if assurance.name in dict_assurance:
                dict_assurance[assurance.id]['total_vente'] += facture[0].montant_assurance
            else:
                dict_assurance[assurance.id] = {
                    'assurance_name': assurance.name,  # nom réel du champ Many2One
                    'total_vente': facture[0].montant_assurance
                }

        list_of_save_elements = list(dict_assurance.values())
        Ventes_Assurance.create(list_of_save_elements)


Ça marche très bien mais est-ce une bonne méthode de le faire? si vous avez une autre plus optimale j’aimerai savoir s’il vous plait

Ce n’est pas la méthode recommandée de Tryton, nous préférons définir de ModelSQL avec table_query comme ça les données sont toujours à jour car recalculées par la DB à la lecture.

Je n’ai pas d’idée sur comment ça fonctionne, si vous avez des exemples qui m’aiderait j’en serai ravi s’il vous plait

En gros tous les modèles de type “reporting” définit dans les modules standards.

Les modèles de types reporting?
Je ne comprends pas, les modèles de type reporting, ce sont des modèles définis dans cette section?

Pool.register(
        shipment.DeliveryNote,
        shipment.PickingList,
        shipment.SupplierRestockingList,
        shipment.CustomerReturnRestockingList,
        shipment.InteralShipmentReport,
        module='stock', type_='report')

Parce qu’il y’a des modèles définies dans la section type_= model, qui comportent des classes contenant une def table_query().

Dans ce cas c’est la première ou la deuxième que je dois utiliser?

Non ce ne sont pas des modèles mais des rapport.

C’est ceux-là, ils ont souvent reporting dans leur nom.

D’accord Merci pour la solution.

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.