Kortingen en promoties : x + y gratis met het gratis artikel verschillend van het gefactureerde artikel

0000003038     -      21-12-2021

Met Mercator 10.10 kan u x + y promoties beheren in de lijnen van een document. In het onderstaande voorbeeld laten we zien hoe u gratis y kunt toestaan voor een ander artikel dan het huidige artikel.

Als dit niet gebeurt, moeten de velden van de x + y promoties pagina toegevoegd worden.
De kolom ID_ART_GR moet toegevoegd worden aan de BAREMES-tabel.

alter table BAREMES add ID_ART_GR char(10) not null default ''

Zodra deze kolom is toegevoegd, toont Mercator 3 extra kolommen in het kortingenscherm. Deze maken het mogelijk om het gratis artikel te selecteren. Het is mogelijk om zoveel ID_ART_GR kolommen toe te voegen als gewenst door een index aan het einde te plaatsen (ID_ART_GR1, ID_ART_GR2, ...).

Wanneer deze kolom beschikbaar is in het kortingenscherm en wordt aangevuld met een artikel, wordt de drempel berekend met alleen de gefactureerde hoeveelheid om te zien of men in aanmerking komt voor de korting.

Het is ook nodig om in LIGNES_V de kolom DL_ID_PARENT toe te voegen 

alter table LIGNES_V add DL_ID_PARENT char(10) not null default ''
alter table LIGNES_V add ID_ART_GR char(10) not null default ''

Vervolgens gebruiken we event GettingBareme voor de regels van hetzelfde artikel en BeforeQYGratuit toe te voegen. Dit maakt het mogelijk om vanuit eventArgs het beheer van de gratis artikels te annuleren.

Zoom
using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Linq;
using System.Windows.Forms;
using MercatorApi;
using MercatorUi;
using MercatorUi.Engine.Gescom;
using MercatorExtensions;
using MercatorDatabase;
using MercatorUi.ICustomizers;

// <CompileWithRoslyn />

namespace Billing
{
    public class Customizer :
        IBillingEngineCreated,
        IBillingEngineClosed
    {
        public void BillingEngineCreated(BillingEngine billingEngine)
        {
            billingEngine.AfterInsertItem += BillingEngine_AfterInsertItem;
            billingEngine.BeforeDeleteLine += BillingEngine_BeforeDeleteLine;
            billingEngine.AfterDeleteLine += BillingEngine_AfterDeleteLine;
            billingEngine.GettingBareme += BillingEngine_GettingBareme;
            billingEngine.BeforeBeforePaymentOrSave += BillingEngine_BeforeBeforePaymentOrSave;
        }

        public void BillingEngineClosed(BillingEngine billingEngine)
        {
            billingEngine.AfterInsertItem -= BillingEngine_AfterInsertItem;
            billingEngine.BeforeDeleteLine -= BillingEngine_BeforeDeleteLine;
            billingEngine.AfterDeleteLine -= BillingEngine_AfterDeleteLine;
            billingEngine.GettingBareme -= BillingEngine_GettingBareme;
            billingEngine.BeforeBeforePaymentOrSave -= BillingEngine_BeforeBeforePaymentOrSave;
        }

        private void BillingEngine_AfterInsertItem(object sender, BillingEngine.AfterInsertItemEventArgs e)
        {
            BillingEngine billingEngine = (BillingEngine) sender;
            if (billingEngine.LignesVRecords.Where(l => l.ID_ART_GR == e.LignesVRecord.ID_ARTICLE).Any())
                billingEngine.ChangeAllPrices($"ID_ART_GR='{e.LignesVRecord.ID_ARTICLE}'");
        }

        private void BillingEngine_BeforeDeleteLine(object sender, BillingEngine.AfterDeleteLineEventArgs e)
        {
            BillingEngine billingEngine = (BillingEngine) sender;
            if (!string.IsNullOrWhiteSpace(e.LignesVRecord.ID_ART_GR))
            {
                var ligneASupprimer = billingEngine.LignesVRecords.Where(l => (billingEngine.LignesVRecords.Any(l2 => l.DL_ID_GRATUIT == l2.DL_ID)));

                if (ligneASupprimer?.Any() ?? false)
                {
                    foreach (var ligne in ligneASupprimer.ToList())
                    {
                        billingEngine.LignesVRecords.Where(l2 => l2.DL_ID == ligne.DL_ID_PARENT).ToList().ForEach(l => l.Q += ligne.Q);
                        billingEngine.LignesVRecords.Remove(ligne);
                    }
                }
            }
        }
        private void BillingEngine_AfterDeleteLine(object sender, BillingEngine.AfterDeleteLineEventArgs e)
        {
            BillingEngine billingEngine = (BillingEngine) sender;
            billingEngine.ChangeAllPrices();
        }
        private void BillingEngine_GettingBareme(object sender, BillingEngine.GettingBaremeEventArgs e)
        {
            BillingEngine billingEngine = (BillingEngine) sender;
            double totQ = billingEngine.LignesVRecords.Where(l => l.ID_ARTICLE == e.LigneVRecord.ID_ARTICLE).Sum(l => l.Q);
            double totQRayon = billingEngine.LignesVRecords.Where(l => !string.IsNullOrWhiteSpace(l.ID_ARTICLE) && billingEngine.StockRecords[l.ID_ARTICLE].S_ID_RAYON == billingEngine.StockRecords[e.LigneVRecord.ID_ARTICLE].S_ID_RAYON).Sum(l => l.Q);
            double totQFamille = billingEngine.LignesVRecords.Where(l => !string.IsNullOrWhiteSpace(l.ID_ARTICLE) && billingEngine.StockRecords[l.ID_ARTICLE].S_ID_FAMIL == billingEngine.StockRecords[e.LigneVRecord.ID_ARTICLE].S_ID_FAMIL).Sum(l => l.Q);
            double totQSsFam = billingEngine.LignesVRecords.Where(l => !string.IsNullOrWhiteSpace(l.ID_ARTICLE) && billingEngine.StockRecords[l.ID_ARTICLE].S_ID_SSFAM == billingEngine.StockRecords[e.LigneVRecord.ID_ARTICLE].S_ID_SSFAM).Sum(l => l.Q);
            double totQCat1 = billingEngine.LignesVRecords.Where(l => !string.IsNullOrWhiteSpace(l.ID_ARTICLE) && billingEngine.StockRecords[l.ID_ARTICLE].S_CAT1 == billingEngine.StockRecords[e.LigneVRecord.ID_ARTICLE].S_CAT1).Sum(l => l.Q);
            double totQCat2 = billingEngine.LignesVRecords.Where(l => !string.IsNullOrWhiteSpace(l.ID_ARTICLE) && billingEngine.StockRecords[l.ID_ARTICLE].S_CAT2 == billingEngine.StockRecords[e.LigneVRecord.ID_ARTICLE].S_CAT2).Sum(l => l.Q);
            double totQCat3 = billingEngine.LignesVRecords.Where(l => !string.IsNullOrWhiteSpace(l.ID_ARTICLE) && billingEngine.StockRecords[l.ID_ARTICLE].S_CAT3 == billingEngine.StockRecords[e.LigneVRecord.ID_ARTICLE].S_CAT3).Sum(l => l.Q);
            double totQOther = billingEngine.LignesVRecords.Where(l => !string.IsNullOrEmpty(l.ID_ARTICLE)).Sum(l => l.Q);

            if ((totQ.CompareTo(e.Qart, Globals.N_DEC_Q) != 0) || (totQRayon.CompareTo(e.Qrayon, Globals.N_DEC_Q) != 0) || (totQFamille.CompareTo(e.Qfamille, Globals.N_DEC_Q) != 0) || (totQSsFam.CompareTo(e.Qssfam, Globals.N_DEC_Q) != 0) || (totQCat1.CompareTo(e.Qcat1, Globals.N_DEC_Q) != 0)
                || (totQCat2.CompareTo(e.Qcat2, Globals.N_DEC_Q) != 0) || (totQCat3.CompareTo(e.Qcat3, Globals.N_DEC_Q) != 0) || (totQOther.CompareTo(e.Qother, Globals.N_DEC_Q) != 0))
            {
                e.Qart = totQ;
                e.Qcat1 = totQCat1;
                e.Qcat2 = totQCat2;
                e.Qcat3 = totQCat3;
                e.Qrayon = totQRayon;
                e.Qfamille = totQFamille;
                e.Qssfam = totQSsFam;
                e.Qother = totQOther;
            }

            BillingEngine.BeforeQYGratuitEventHandler beforeQYGratuitEventHandler = null;
            beforeQYGratuitEventHandler = (s, e2) =>
                {
                billingEngine.BeforeQYGratuit -= beforeQYGratuitEventHandler;
                if ((e.DataRowLignes == e2.DataRowLignes) && (!string.IsNullOrWhiteSpace(e2.LignesVRecord.ID_ART_GR) || ((e2.DataRowBaremes != null) && !string.IsNullOrWhiteSpace(e2.DataRowBaremes["ID_ART_GR"].ToString()))))
                {
                    var ligneASupprimer = billingEngine.LignesVRecords.Where(l => (billingEngine.LignesVRecords.Any(l2 => l.DL_ID_GRATUIT == l2.DL_ID && l2.ID_ART_GR == (string.IsNullOrWhiteSpace(e2.LignesVRecord.ID_ART_GR) ? e2.DataRowBaremes["ID_ART_GR"].ToString() : e2.LignesVRecord.ID_ART_GR))) && billingEngine.LignesVRecords.Any(l2 => (l2.DL_ID == l.DL_ID_PARENT)));

                    if (ligneASupprimer?.Any() ?? false)
                    {
                        foreach (var ligne in ligneASupprimer.ToList())
                        {
                            billingEngine.LignesVRecords.Where(l2 => l2.DL_ID == ligne.DL_ID_PARENT).ToList().ForEach(l => l.Q += ligne.Q);
                            billingEngine.LignesVRecords.Remove(ligne);
                        }
                    }
                }
                
                if ((e2.DataRowBaremes != null) && (!string.IsNullOrWhiteSpace(e2.DataRowBaremes["ID_ART_GR"].ToString())))
                {
                    e2.Cancel = true;
                    var lignesArticleGratuit = billingEngine.LignesVRecords.Where(l => l.ID_ARTICLE == e2.DataRowBaremes["ID_ART_GR"].ToString() && string.IsNullOrWhiteSpace(l.DL_ID_GRATUIT) && (l.Q.CompareTo(0, Globals.N_DEC_Q) > 0));
                    IEnumerable<LIGNES_V> lignesParent = null;
                    if (!string.IsNullOrWhiteSpace(e2.DataRowBaremes["ar_ref"].ToString()))
                    {
                        lignesParent = billingEngine.LignesVRecords.Where(l => (l.ID_ARTICLE == e.LigneVRecord.ID_ARTICLE));
                    }
                    else if (!string.IsNullOrWhiteSpace(e2.DataRowBaremes["id_fam"].ToString()))
                    {
                        MercatorDatabase.STOCK stockRecord = (e2.StockRecord ?? billingEngine.StockRecords[e2.LignesVRecord.ID_ARTICLE]);
                        switch (e2.DataRowBaremes["tag"].ToString())
                        {
                            case "4":
                            case "12":
                            case "20":
                                lignesParent = billingEngine.LignesVRecords.Where(l => !string.IsNullOrWhiteSpace(l.ID_ARTICLE) && billingEngine.StockRecords[l.ID_ARTICLE].S_ID_RAYON == stockRecord.S_ID_RAYON);
                                break;
                            case "3":
                            case "11":
                            case "19":
                                lignesParent = billingEngine.LignesVRecords.Where(l => !string.IsNullOrWhiteSpace(l.ID_ARTICLE) && billingEngine.StockRecords[l.ID_ARTICLE].S_ID_FAMIL == stockRecord.S_ID_FAMIL);
                                break;
                            case "2":
                            case "10":
                            case "18":
                                lignesParent = billingEngine.LignesVRecords.Where(l => !string.IsNullOrWhiteSpace(l.ID_ARTICLE) && billingEngine.StockRecords[l.ID_ARTICLE].S_ID_SSFAM == stockRecord.S_ID_SSFAM);
                                break;
                            case "5":
                            case "13":
                            case "21":
                                lignesParent = billingEngine.LignesVRecords.Where(l => !string.IsNullOrWhiteSpace(l.ID_ARTICLE) && billingEngine.StockRecords[l.ID_ARTICLE].S_CAT1 == stockRecord.S_CAT1);
                                break;
                            case "6":
                            case "14":
                            case "22":
                                lignesParent = billingEngine.LignesVRecords.Where(l => !string.IsNullOrWhiteSpace(l.ID_ARTICLE) && billingEngine.StockRecords[l.ID_ARTICLE].S_CAT2 == stockRecord.S_CAT2);
                                break;
                            case "7":
                            case "15":
                            case "23":
                                lignesParent = billingEngine.LignesVRecords.Where(l => !string.IsNullOrWhiteSpace(l.ID_ARTICLE) && billingEngine.StockRecords[l.ID_ARTICLE].S_CAT3 == stockRecord.S_CAT3);
                                break;
                        }
                    }
                    else
                    {
                        lignesParent = billingEngine.LignesVRecords.Where(l => !string.IsNullOrWhiteSpace(l.ID_ARTICLE));
                    }
                    double totQForGratuit = lignesParent.Sum(l => l.Q);
                    double nbGratis = Math.Truncate(totQForGratuit / (Convert.ToDouble(e2.DataRowBaremes["q_fact"]))) * Convert.ToDouble(e2.DataRowBaremes["q_gratuit"]);
                    lignesParent.ToList().ForEach(l => l.ID_ART_GR = e2.DataRowBaremes["ID_ART_GR"].ToString());
                    if (lignesArticleGratuit.Any() && (nbGratis.CompareTo(0, Globals.N_DEC_Q) > 0))
                    {
                        foreach (var ligne in lignesArticleGratuit.ToList().OrderByDescending(l => l.RECNO))
                        {
                            int new_row_index = billingEngine.AppendLine(ligne.DataRow);
                            DataRow drLigneGratuit = billingEngine.LIGNES.Rows[new_row_index];
                            billingEngine.RowIndexOfLastLine = billingEngine.LIGNES.Rows.Count - 1;
                            Api.DataRowMerge(drLigneGratuit, ligne.DataRow, false, new string[] { "DL_ID" }, false);
                            if ((ligne.Q).CompareTo(nbGratis, Globals.N_DEC_Q) > 0)
                            {
                                drLigneGratuit["Q"] = nbGratis;
                                nbGratis = 0;
                            }
                            else
                            {
                                nbGratis = nbGratis - (ligne.Q);
                                drLigneGratuit["Q"] = ligne.Q;
                            }
                            ligne.Q -= Convert.ToDouble(drLigneGratuit["Q"]);
                            drLigneGratuit["dl_id_gratuit"] = e.DataRowLignes["dl_id"];
                            drLigneGratuit["dl_id_parent"] = ligne.DL_ID;
                            drLigneGratuit["not_pr"] = true;
                            drLigneGratuit["pu"] = 0;
                            drLigneGratuit["remise"] = 0;
                            if (Globals.EngineBillingV.FieldListLignes.ContainsKey("REMISE2"))
                                drLigneGratuit["remise2"] = 0;
                            if (Globals.EngineBillingV.FieldListLignes.ContainsKey("REMISE3"))
                                drLigneGratuit["remise3"] = 0;
                            if (Globals.EngineBillingV.FieldListLignes.ContainsKey("REMISE4"))
                                drLigneGratuit["remise4"] = 0;

                            if (nbGratis.CompareTo(0, Globals.N_DEC_Q) <= 0)
                                break;
                        }
                    }
                }
                else
                {
                    Api.SmartReplace(e.DataRowLignes, "ID_ART_GR", "");
                }
                };
            billingEngine.BeforeQYGratuit += beforeQYGratuitEventHandler;
        }

        private void BillingEngine_BeforeBeforePaymentOrSave(object sender, BillingEngine.BeforeBeforePaymentOrSaveEventArgs e)
        {
            BillingEngine billingEngine = (BillingEngine) sender;
            billingEngine.ChangeAllPrices();
        }
    }
}

 

Opmerkingen :
Aanvullende informatie : Functionaliteiten in "Tools > Kortingen"