Programmatie rond de ontvangstfunctionaliteiten van Peppol via de PeppolBoxHelper

0000003284     -      25-10-2025

Mercator bevat de klasse MercatorUi.Forms.Other.OtherClasses.PeppolBoxHelper, die een reeks tools biedt voor het ontvangen van berichten via het Peppol-netwerk.

Deze klasse is IDisposable. Ze implementeert de volgende drie interfaces:

  • MercatorUi.ICustomizers.IPeppolBoxHelperCreated : methode void PeppolBoxHelperCreated(Forms.Other.OtherClasses.PeppolBoxHelper peppolBoxHelper) die wordt aangeroepen bij de initialisatie van een object van dit type
  • MercatorUi.ICustomizers.IPeppolBoxHelperClosed : methode void PeppolBoxHelperClosed(Forms.Other.OtherClasses.PeppolBoxHelper peppolBoxHelper) die wordt aangeroepen wanneer dit object wordt verwijderd.
  • MercatorUi.ICustomizers.IStringUpdater : om eventueel de selectie van berichten uit de tabel PEPPPOL_RECEIVED_MESSSAGES aan te passen

Om he gedrag van dit object aan te passen, moet een PeppolBox-customizer worden aangemaakt:

Zoom
using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Linq;
using MercatorApi;
using MercatorExtensions;
using MercatorUi;
using MercatorDatabase;
using System.Xml;

// <CompileWithRoslyn />

namespace PeppolBox
{
    public class Customizer : MercatorUi.ICustomizers.IPeppolBoxHelperCreated, MercatorUi.ICustomizers.IPeppolBoxHelperClosed
    {
        public void PeppolBoxHelperCreated(MercatorUi.Forms.Other.OtherClasses.PeppolBoxHelper peppolBoxHelper)
        {
            ...
        }

        public void PeppolBoxHelperClosed(MercatorUi.Forms.Other.OtherClasses.PeppolBoxHelper peppolBoxHelper)
        {
            ...
        }
    }
}

 

Deze klasse bevat de volgende publieke eigenschappen:

  • DataTable DataTable : de gegevens achter het raster van de PeppoBox
  • PeppolMessagesCollection Messages : dezelfde gegevens, voorgesteld als objecten van het type PeppolMessage
  • PeppolBoxForm PeppolBoxForm : het venster van de PeppolBox. Null indien de helper autonoom is geïnstantieerd (cf. infra).

De eerste twee eigenschappen zijn twee verschillende representaties van dezelfde gegevens. Een wijziging of verwijdering van een DataRow in de DataTable leidt automatisch tot een wijziging of verwijdering van het overeenkomstige bericht in de collectie. En omgekeerd. Om de aangepaste code te vereenvoudigen, wordt aanbevolen om de collectie te gebruiken.

Ze bevat de volgende publieke methoden:

  • Voor het downloaden van nieuwe berichten
    • bool Download() 
    • Task<(bool result, string error)> DownloadAsync()
  • Voor het verwijderen van de berichten die zich in Datatable / Messages bevinden (dus zichtbaar zijn in de PeppolBox) én in de tabel PEPPPOL_RECEIVED_MESSSAGES van de database
    • bool RemoveAllFromListAndDb()
    • Task<(bool result, string error)> RemoveAllFromListAndDbAsync()

 

De collectie Messages, die IEnumerable is, bevat instanties van de klasse MercatorUi.Forms.Other.OtherClasses.PeppolMessage. Deze laatste bevat de volgende eigenschappen:

  • Guid Id : identificatie van het bericht. Komt overeen met de primaire sleutel van de tabel PEPPPOL_RECEIVED_MESSSAGES
  • DateTime Moment : datum en tijdstip van doorgang in het Peppol-netwerk
  • string Message : het Peppol-bericht in Json-formaat (bruikbaar via ReceivedDoc)
  • string MsgType : het type bericht
  • bool IsNew : true als het bericht net is ontvangen, false anders
  • bool IsInvoiceOrCreditNote : true als het bericht een factuur of creditnota is, false anders
  • MercatorPeppol.ReceivedDoc ReceivedDoc : objectrepresentatie van de inhoud van het bericht (cf. infra). Null als het bericht geen factuur of creditnota is.
  • PeppolBoxHelper ParentPeppolBoxHelper : de bijhorende helper van dit bericht
  • DataRow DataRow : de  overeenkomende DataRow correspondante in  de DataTable

En deze methoden om dit bericht te verwijderen uit de Datatable / collectie én uit de tabel PEPPPOL_RECEIVED_MESSSAGES van de database:

  • bool RemoveFromListAndDb()
  • Task<(bool result, string error)> RemoveFromListAndDbAsync()

En deze andere methoden:

  • StartImportIntoAccounting() : het importeren in de boekhouding starten.
  • ImportIntoAccounting() : de import in de boekhouding uitvoeren. Zie dit voorbeeld.
  • StartImportIntoBilling() : het importeren in de commerciële beheer starten.
  • StartInvoiceResponse() : het verzenden van een invoice response starten.
  • ShowInvoiceOrCreditNote() : de factuur / creditnota weergeven (de PDF indien aanwezig, anders de XML-inhoud).
  • ShowXml() : de XML-inhoud weergeven.
  • void ExportToXml(string xmlFileName = null) : exporteren van het document (factuur / creditnota) naar XML-bestand. Indien  xmlFileName niet is opgegeven, verschijnt er een opslaan-als-dialoog.
  • void ExportToXmlraw(string xmlFileName = null) : exporteren van het ruwe bericht van het Peppol-netwerk naar XML-bestand. Indien  xmlFileName niet is opgegeven, verschijnt er een opslaan-als-dialoog.

  

De klasse MercatorPeppol.ReceivedDoc beat onder meer de methode ParseContent, die een type MercatorPeppol.ReceivedDoc.ParseContentRet retourneert. Deze accepteert een parameter waarmee, naast de gewenste taal, ook kan worden bepaald wat men naast de XML-inhoud als XmlDocument in het resultaat wenst te ontvangen: MercatorPeppol.ReceivedDoc.ParseContentEnum.WithSupplierName | MercatorPeppol.ReceivedDoc.ParseContentEnum.WithPdf | MercatorPeppol.ReceivedDoc.ParseContentEnum.WithRawContent

Als men de XML-inhoud wil parseren, is het aanbevolen om ParseContentRet.XmlDoc te gebruiken in plaats van ParseContentRet.RawContent. Na het parseren moet altijd worden gecontroleerd of ParseContentRet.Error null is, want het is mogelijk dat een door een derde verzonden bericht syntactisch geen geldige XML is.

Het is eenvoudig om knooppunten in het XmlDoc te lokaliseren via de methode XmlSelectNodes.

XmlNode nodeNumTva = parsedContent.XmlSelectNodes("cac:AccountingSupplierParty/cac:Party/cac:PartyTaxScheme/cbc:CompanyID").FirstOrDefault();

Voorbeelden:

 


Gebruik van de PeppolBoxHelper in autonome modus

De PeppolBoxHelper kan worden geïnstantieerd buiten de PeppolBoxForm. Zo kunnen via code alle handelingen worden uitgevoerd die beschikbaar zijn in de PeppolBoxForm.

bijvoorbeeld, deze eenvoudige code geplaatst in een Main-customizer kan berichten downloaden vanuit een taak in consolemodus.

Zoom
public void DownloadPeppolMessages()
{
    MercatorUi.Globals.MercatorTasksToMain.Log("Instantiering van de PeppolBoxHelper");
    using (MercatorUi.Forms.Other.OtherClasses.PeppolBoxHelper peppolBoxHelper = new MercatorUi.Forms.Other.OtherClasses.PeppolBoxHelper())
    {
        if (peppolBoxHelper.DataTable == null)
            MercatorUi.Globals.MercatorTasksToMain.Log("Fout bij de initialisatie van de PeppolBoxHelper: " + Api.LastError, isError: true);
        else if (!peppolBoxHelper.Download())
            MercatorUi.Globals.MercatorTasksToMain.Log("Fout bij het downloaden van de berichten: " + Api.LastError, isError: true);
        else
            MercatorUi.Globals.MercatorTasksToMain.Log("Bericht(en) gedownload: " + peppolBoxHelper.Messages.Count(m => m.IsNew));
    }
}

 Het is niet nodig om een uitvoeringsinterval van minder dan 15 minuten in te stellen. Het Peppol-netwerk heeft namelijk een latentie van ongeveer 15 minuten.

In de laatste else van deze code kan eender welke code worden geplaatst die peppolBoxHelper.Messages gebruikt om een voorverwerking van deze berichten uit te voeren.

 

Een ander voorbeeld: het automatisch importeren van een eFactuur in de boekhouding

 

De PeppolBoxHelper bevat ook de volgende statische methoden, die bijzonder nuttig zijn buiten de PeppolBoxForm :

  • PeppolMessage PeppolMessageFromId(Guid id) : retourneert een PeppolMessage op basis van het id in de tabel PEPPPOL_RECEIVED_MESSSAGES
  • PeppolMessage PeppolMessageFromAction(Engine.Crm.ActionEngine actionEngine) : retourneert een PeppolMessage op basis van hetzelfde id opgeslagen in actionEngine.ActionsRecord.ENTRYID

Een volledig voorbeeld van een implementatie van een geautomatiseerde distributie van ontvangen facturen / creditnota’s via Peppol is beschikbaar op deze pagina.

In het algemeen is bij gebruik van de PeppolBoxHelper in autonome modus de code in de PeppolBox-customizer niet langer nodig. De code van deze customizer kan rechtstreeks worden overgenomen in de maatwerkcode die de PeppolBoxHelper instantieert. In de PeppolBox-customizer is het eenvoudig te bepalen of de code wordt aangeroepen door een PeppolBoxHelper in autonome modus: PeppolBoxHelper.PeppolBoxForm is dan null



Functionele cookies: Cookies die nodig zijn voor het gebruik van de website en voorkeurscookies. Ze bevatten geen persoonsgegevens. (Meer informatie)

Analytische cookies: Verzamelen van statistieken met betrekking tot het gedrag van internetgebruikers. (Meer informatie)

Marketingcookies: Om bezoekers op verschillende websites te volgen voor advertentiedoeleinden. (Meer informatie)