Mercator 10.10 permet de gérer les promotions x + y gratuits sur une ligne d'un document. Dans l'exemple ci-dessous, nous montrons comment permettre d'avoir l'article gratuit différent de l'article facturé.
Si ce n'est fait, il faut ajouter les champs de la page promotions x + y gratuits.
Il faut également ajouter dans la table BAREMES la colonne ID_ART_GR.
alter table BAREMES add ID_ART_GR char(10) not null default ''
Une fois cette colonne ajoutée, Mercator affichera 3 colonnes supplémentaires dans la grille des remises. Celles-ci permettent de sélectionner l'article gratuit.
Il est possible d'ajouter autant de colonnes ID_ART_GR que souhaité en mettant un indice à la fin (ID_ART_GR1, ID_ART_GR2, ...).
Une fois la colonne disponible dans l'écran des remises et si celle-ci est complétée avec un article, le seuil pour voir si la remise est éligible est calculé uniquement avec la quantité facturée. Si plusieurs articles gratuits ont été ajoutés (ID_ART_GR, ID_ART_GR1, ID_ART_GR2, ...), il faut, au minimum que la colonne ID_ART_GR soit complétée pour calculer le seuil.
Il faut aussi ajouter dans LIGNES_V la colonne DL_ID_PARENT
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 ''
Ensuite, nous utilisons l'évènement GettingBareme pour sommer les lignes d'un même article et BeforeQYGratuit qui permet depuis l'eventArgs d'annuler la gestion des articles gratuits "standard".
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();
}
}
}
Notes :
Informations complémentaires :
Fonctionnalités de "Outils > Remises"