Vous consultez une page technique concernant le logiciel de gestion Mercator. Celle-ci contient des informations spécifiques destinées aux professionnels de Mercator. Souhaitez-vous être redirigés vers des informations plus générales ?


   Ne plus poser cette question

Dans le signalétique articles, calculer une somme provenant du tableau des articles liés

0000002039     -      10/10/2018

L'objet de cette programmation est de calculer, dans l'interface de Mercator, la somme des S_PRIX_HT * Q pour les articles liés présents dans la grille de liaisons de l'article en cours. Ce calcul sera fait de façon interactive : cela signifie que toute modification apportée dans la grille ArtLiens sera automatiquement répercutée dans le champ contenant ce total calculé. Dans notre exemple, ce total sera sauvegardé dans le champ S_PRIX_HT de l'article (parent) en cours. Le code pourra être facilement adapté pour déroger à cela.

Une même problématique pourrait être résolue par un traitement SQL, soit par trigger, soit à la validation de la fiche, mais dans ce cas, il n'y aurait aucune interactivité puisque le calcul de ce total ne serait effectué que lors de la validation. Cette programmation a été conçue pour que, lors de l'arrivée dans une fiche, le total soit recalculé. Il est possible que si le prix d'un article a changé par exemple, ce total doivent être modifié. Il est donc normal qu'à la sortie de cette fiche, même si l'utilisateur n'y a rien modifié, Mercator propose de sauvegarder les modifications. Par contre, si le prix d'un article enfant a été modifié et que l'utilisateur ne repasse pas par la fiche de l'article parent, alors ce total ne sera pas recalculé. (Ceci pourrait être effectué par un trigger SQL, mais cela sort du cadre de la présente information)

La programmation illustrée ici est réalisée sur base d'un customizer SigStock qui implémente les interfaces suivantes :

et elle exploite l'évènement TotalUpdated de ArtLiens qui permet de lancer un code quand Mercator recalcule le total affiché sous la grille des articles liés. Par ailleurs, comme notre programmation n'effectue le total que pour les lignes pour lesquelles la case "V" est cochée, nous exploitons l'évènement CheckBoxValueChanged de cette même grille, pour détecter les modifications dans cette colonne.

Dans Mercator, par défaut, le contenu d'une grille n'est calculé que si cette grille est visible. (Ceci pour des raisons de performance afin d'éviter que, par exemple, lors du passage de fiche en fiche, Mercator ne passe un temps important à rafraîchir des grilles invisibles.) Dans notre cas, par contre, il est essentiel que les données de la grille soient toujours présentes, que la grille soit visible ou non. Ceci est est assuré par la méthode FillWithData de la grille, appelé dans l'évènement AfterRead.

Le code de ce customizer s'établit comme suit :

Zoom
using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Windows.Forms;
using MercatorApi;
using MercatorUi;

namespace SigStock
{
    public class Customizer : MercatorUi.ICustomizers.IFormLoadCustomizer, MercatorUi.ICustomizers.IFormClosedCustomizer
    {

        public void FormLoadCustomize(Form form)
        {
            MercatorUi.Forms.Sig.SigForm sigForm = (MercatorUi.Forms.Sig.SigForm)form;
            List<Control> l = sigForm.FindMovableControlsByType(typeof(MercatorUi.Forms.Sig.SigGrids.ArtLiens));
            if (l.Count == 0)
                return;
            MercatorUi.Forms.Sig.SigGrids.ArtLiens artLiens = (MercatorUi.Forms.Sig.SigGrids.ArtLiens)l[0];
            artLiens.AfterRead += new MercatorUi.MovableControls.MovableGrid.AfterReadHandler(artLiens_AfterRead);
            artLiens.TotalUpdated += new EventHandler(artLiens_TotalUpdated);
            artLiens.CheckBoxValueChanged += new MercatorUi.Forms.Sig.SigGrids.ArtLiens.CheckBoxValueChangedEventHandler(artLiens_CheckBoxValueChanged);
        }

        public void FormClosedCustomize(Form form)
        {
            MercatorUi.Forms.Sig.SigForm sigForm = (MercatorUi.Forms.Sig.SigForm)form;
            List<Control> l = sigForm.FindMovableControlsByType(typeof(MercatorUi.Forms.Sig.SigGrids.ArtLiens));
            if (l.Count == 0)
                return;
            MercatorUi.Forms.Sig.SigGrids.ArtLiens artLiens = (MercatorUi.Forms.Sig.SigGrids.ArtLiens)l[0];
            artLiens.AfterRead -= new MercatorUi.MovableControls.MovableGrid.AfterReadHandler(artLiens_AfterRead);
            artLiens.TotalUpdated -= new EventHandler(artLiens_TotalUpdated);
            artLiens.CheckBoxValueChanged -= new MercatorUi.Forms.Sig.SigGrids.ArtLiens.CheckBoxValueChangedEventHandler(artLiens_CheckBoxValueChanged);
        }

        void artLiens_AfterRead(object sender, EventArgs e)
        {
            MercatorUi.Forms.Sig.SigGrids.ArtLiens artLiens = (MercatorUi.Forms.Sig.SigGrids.ArtLiens)sender;
            MercatorUi.Forms.Sig.SigForm sigForm = (MercatorUi.Forms.Sig.SigForm)artLiens.Form;
            string currentId = sigForm.DataSourceRow["S_ID"].ToString();
            if (artLiens.LastIdFilled != currentId)
                artLiens.FillWithData();
        }

        void artLiens_TotalUpdated(object sender, EventArgs e)
        {
            MercatorUi.Forms.Sig.SigGrids.ArtLiens artLiens = (MercatorUi.Forms.Sig.SigGrids.ArtLiens)sender;
            MercatorUi.Forms.Sig.SigForm sigForm = (MercatorUi.Forms.Sig.SigForm)artLiens.Form;
            if (sigForm.IsFiltring || (artLiens.Grid == null) || (artLiens.Grid.DataSource == null) || (artLiens.Grid.Rows.Count == 0))
                return;

            StringBuilder sbReqSql = new StringBuilder(); // on va construire une requête SQL unique pour l'ensemble des articles de la grille ArtLiens
            foreach (DataGridViewRow dgr in artLiens.Grid.Rows)
            {
                string id_lien = dgr.Cells["id_lien"].Value.ToString();
                if ((id_lien != "") && Convert.ToBoolean(dgr.Cells["ven"].Value))
                {
                    if (sbReqSql.Length == 0)
                        sbReqSql.AppendFormat("(s_id='{0}')", Api.UnquoteSql(id_lien));
                    else
                        sbReqSql.AppendFormat(" or (s_id='{0}')", Api.UnquoteSql(id_lien));
                }
            }
            if (sbReqSql.Length == 0) // la grille ne contient aucun article pour lequel on a coché "V"
                return;
            DataSet ds = Api.Zselect(Globals.RepData, "select s_id,s_prix_ht from stock where " + sbReqSql.ToString());
            if (ds == null)
                return;
            double d = 0;
            foreach (DataGridViewRow dgr in artLiens.Grid.Rows)
            {
                string id_lien = dgr.Cells["id_lien"].Value.ToString();
                if ((id_lien != "") && Convert.ToBoolean(dgr.Cells["ven"].Value))
                {
                    DataRow[] rowsStock = ds.Tables[0].Select(string.Format("s_id='{0}'", Api.UnquoteSql(dgr.Cells["id_lien"].Value.ToString())));
                    if (rowsStock.Length > 0)
                        d += Convert.ToDouble(dgr.Cells["q"].Value) * Convert.ToDouble(rowsStock[0]["s_prix_ht"]);
                }
            }
            Api.SmartReplace(sigForm.DataSourceRow, "S_PRIX_HT", Math.Round(d, MercatorUi.Globals.DEC_DEV_B)); // SmartReplace ne fait réellement le remplacement qui si la valeur est différente
        }

        void artLiens_CheckBoxValueChanged(object sender, MercatorUi.Forms.Sig.SigGrids.ArtLiens.CheckBoxValueChangedEventArgs e)
        {
            if (e.ColumnName == "ven") // on a coché / déc
                artLiens_TotalUpdated(sender, null);
        }

    }
}

Remarque : en version Legacy, cette fonctionnalité était partiellement rencontrée via la fonction xSumLiens. (Cette fonction existe aussi en Aruba, dans MercatorController.xFunctions, mais ne renvoie que des données provenant de la base de données SQL. Elle ne peut donc être utilisée pour prendre en compte des données de la grille ArtLiens)