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

Envoi de factures électroniques Peppol

0000002697     -      05/10/2022

Mercator 10.0 ou ultérieur permet l'envoi de factures de la gestion commerciale sous forme électronique au format

XML > UBL (Invoice/Credit Note) > EN16931 > BIS 3.0 Billing

Pour disposer de cette fonctionnalité, il faut ajouter une colonne C_EINVOICE1 char(30) dans la table CLI.

alter table CLI add C_EINVOICE1 char(30) not null default ''
Il convient ensuite de modifier la fiche client en y ajoutant un ComboBox qui utilise ce champ en tant que source. Mercator ajoute automatiquement cet élément dans le menu "Fichier" :

 

Ce menu permet d'envoyer une facture si les conditions suivantes sont remplies :

  • Le champ C_EINVOICE1 pour le client en cours contient  BIS3 via Peppol.
  • La facture / note de crédit est déjà sauvegardée, et donc numérotée définitivement.
  • Elle n'est pas en régime TVA comprise (le n° de TVA de la fiche client doit être complété).
  • Elle ne contient pas de remise en pied.
  • Sa référence est complétée.
  • Un modèle d'impression permet la production d'au moins un duplicata PDF qui sera inclus dans le fichier XML.
  • Le compte bancaire de l'émetteur est indiqué dans la zone "Banque" de "Outils > Identification" sous la forme IBAN:BIC.

 

Un fichier produit par Mercator est confié à Digiteal afin qu'il soit acheminé à son destinataire via le réseau Peppol. Pour rendre cette fonctionnalité disponible, il faut :

  • disposer de l'option PEPPOL dans le voucher de Mercator
  • mettre l'option "Fournisseur d'accès Peppol" à Digiteal (id=PEPPOL_PRV)
  • compléter les informations de "Outils > Paramètres > Identification Digiteal".
    • Dans cet écran, les zones "ID Peppol" se complètent automatiquement sur base du numéro de TVA et du pays. Elles ne sont pas modifiables.
    • Si, lors de l'inscription, un ou plusieurs ID Peppol produisent une erreur, il faut contacter le support Mercator qui procédera à une inscription manuelle.

Cette fonctionnalité permet une transmission des fichiers totalement transparente pour l'utilisateur.

En standard, Mercator produit un fichier conforme avec les normes reprises ci-dessus. Il offre, de base, ces possibilités :

  • Si le client de livraison est installé (ID_CLI_LIV) et s'il est différent du client de facturation, Mercator placera un bloc "cac:Delivery" avec cette adresse de livraison.
  • Pour une facture, le champ "Référence" est utilisé pour alimenter "cac:OrderReference" (purchase order no - n° de commande).
  • Pour une note de crédit, la référence est utilisée en tant que "cac:InvoiceDocumentReference", c'est-à-dire la référence de la facture sur laquelle porte la note de crédit.
  • Les régimes suivants sont reconnus : normal, exonéré, contractant et CEE et traités correctement en ce qui concerne l'information de TVA à transmettre.
  • Les différentes copies PDF mentionnées en tant que modèle dans la séquence sont incluses comme "cbc:EmbeddedDocumentBinaryObject". Il est obligatoire d'inclure au moins un fichier PDF.
  • Le VCS éventuellement associé à une facture est passé en tant que "cbc:InstructionID" et "cbc:PaymentID".
  • Les frais de port peuvent être mentionnés séparément en tant que "cac:AllowanceCharge" d'entête. Pour cela, il faut compléter l'option EINV_PORT avec le S_ID de l'article "Frais de port".
  • Un escompte déduit est aussi traité comme "cac:AllowanceCharge" d'entête.
  • Les remises à la ligne sont gérées en tant que "cac:AllowanceCharge" de ligne, en ce compris les remises optionnelles 2, 3 et 4.
  • Les numéros de série et les numéros de lots sont pris en compte dans un bloc "cac:ItemInstance".

Il est essentiel de bien comprendre que tout le travail de personnalisation du document, habituellement effectué dans le modèle d'impression de la facture, devra aussi être fait dans le modèle électronique. Comme pour une facture imprimée, cela se fera dans la couche "paramétrage" de Mercator. Pour cela, le BillingEngine met à disposition 3 événements :

  • EinvNodeAdding : lors de l'ajout de chaque nœud dans la structure XML. En mettant e.Cancel = true, on a la possibilité de ne pas ajouter le nœud
  • EinvNodeAdded : quand le noeud vient d'être ajouté à l’arborescence XML
  • EinvFileCreating : lorsque toute l’arborescence XML est prête, juste avant de produire le fichier XML. La propriété e.FileName permet de modifier le nom du fichier qui va être produit.

Les fichiers produits doivent satisfaire au standard édicté par Peppol : voir ce document descriptif pour les factures.

Nous reprenons sur cette page des exemples de paramétrage.


Le code ci-dessous peut être placé dans un bouton dans l'écran de factures / notes de crédit. Il permet d'obtenir le statut d'envoi du document en cours.

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

// <CompileWithRoslyn />

namespace MercatorUi.MovableControls.ButtonsCodes
{
    public static class Script
    {
        public static void Exec(MercatorUi.MovableControls.MovableButton clickedButton)
        {
            // enter your customized code here
            Forms.Billing.BillingForm billingForm = (Forms.Billing.BillingForm)clickedButton.Form;
            string peppol_response = Api.StrExtract(billingForm.BillingEngine.PiedsVRecord.PEPPOL_RESPONSE, "<Digiteal>", "</Digiteal>");
            if (peppol_response == "")
            {
                MercatorUi.Dialogs.Stop("Ce document n'a jamais été envoyé dans le réseau Peppol !");
                return;
            }
            MercatorTunnel.Digiteal.CreatePeppolInvoiceResponse createPeppolInvoiceResponse = Api.JsonConvertDeserializeObject<MercatorTunnel.Digiteal.CreatePeppolInvoiceResponse>(peppol_response);
            Dialogs.Stop("Id = " + createPeppolInvoiceResponse.Id
                       + "\r\n" + createPeppolInvoiceResponse.Moment.ToShortDateString() + " " + createPeppolInvoiceResponse.Moment.ToShortTimeString());
        }
    }
}

 

Le code ci-dessous reste valable pour les anciens envois effectués via Ibanity :

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

// <CompileWithRoslyn />

namespace MercatorUi.MovableControls.ButtonsCodes
{
    public static class Script
    {
        public static void Exec(MercatorUi.MovableControls.MovableButton clickedButton)
        {
            // enter your customized code here
            Forms.Billing.BillingForm billingForm = (Forms.Billing.BillingForm)clickedButton.Form;
            string peppol_response = Api.StrExtract(billingForm.BillingEngine.PiedsVRecord.PEPPOL_RESPONSE, "<Ibanity>", "</Ibanity>");
            if (peppol_response == "")
            {
                MercatorUi.Dialogs.Stop("Ce document n'a jamais été envoyé dans le réseau Peppol !");
                return;
            }
            MercatorUi.Ibanity.CreatePeppolInvoiceResponse createPeppolInvoiceResponse = Api.JsonConvertDeserializeObject<MercatorUi.Ibanity.CreatePeppolInvoiceResponse>(peppol_response);
            MercatorUi.Ibanity.GetPeppolInvoiceResponse r = MercatorUi.Ibanity.PeppolInvoiceUploadStatus(createPeppolInvoiceResponse.data.id, out string error);
            if (error != null)
                Dialogs.Stop(error);
            else
                Dialogs.Stop("Statut = " + (r.data.attributes.status == null ? "indéterminé" : r.data.attributes.status)
                    + (!string.IsNullOrEmpty(r.data.attributes.transmissionId) ? "\r\n" + r.data.attributes.transmissionId : "")
                    + ((r.data.attributes.errors != null) && (r.data.attributes.errors.Count > 0) ? "\r\nCode erreur = " + r.data.attributes.errors[0].code + "\r\n" + r.data.attributes.errors[0].detail : "")
                    );
        }
    }
}

 

Le code ci-dessous reste valable pour les anciens envois effectués via CodaBox :

Zoom
// enter your customized code here
Forms.Billing.BillingForm billingForm = (Forms.Billing.BillingForm)clickedButton.Form;
string peppol_response = Api.StrExtract(billingForm.BillingEngine.PiedsVRecord.PEPPOL_RESPONSE, "<CodaBox>", "</CodaBox>");
if (peppol_response == "")
{
    MercatorUi.Dialogs.Stop("Ce document n'a jamais été envoyé dans le réseau Peppol !");
    return;
}
Forms.Billing.BillingCodaBox.Classes.UploadStatus status = Api.JsonConvertDeserializeObject<Forms.Billing.BillingCodaBox.Classes.UploadStatus>(peppol_response);
Forms.Billing.BillingCodaBox.CodaBox codaBox = new Forms.Billing.BillingCodaBox.CodaBox();
status = codaBox.GetStatus(status.id);
if (status == null)
    Dialogs.Stop(codaBox.Errors.ToString());
else
    Dialogs.Stop("Statut = " + (status.sent_state == null ? "indéterminé" : status.sent_state) + (!string.IsNullOrEmpty(status.sent_reason_state) ? "\r\n" + status.sent_reason_state : ""));