De hier beschreven processen automatiseren de distributie van berichten ui het Peppol-netwerk die een factuur of creditnota bevatten. Wanneer een bericht wordt ontvangen via de PeppolBoxHelper, wordt het gedecodeerd en gedistribueerd, afhankelijk van de inhoud, naar een bepaalde afdeling. Deze distributie gebeurt via een Mercator CRM actie. Deze actie bevat een knop waarmee de factuur / creditnota kan worden ingevoerd in het commercieel beheer of in de boehkouding. In de hier voorgestelde modellen is de actie ontworpen als een taak.
Er worden twee acties gemaakt:
- Peppol document om te importeren : voor het commercieel beheer (bijvoorbeeld goederenfacturen)
- Peppol-invoer om te importeren : voor de boekhouding (bijvoorbeeld kostenfacturen).
De actiesjablonen zijn beschikbaar in het onderstaande zip-bestand. Om deze acties te installeren:
Een taak in consolemodus downloadt regelmatig berichten. De PeppolBox wordt daarom niet meer gebruikt. De methode die moet worden geplaatst in de Main customizer wordt hieronder getoond. Elk correct geïdentificeerd bericht zal één van deze twee acties genereren.
using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Linq;
using MercatorApi;
using MercatorExtensions;
using MercatorUi;
using MercatorDatabase;
// <CompileWithRoslyn />
namespace Main
{
public class Customizer
{
public void DownloadAndDispatchPeppolMessages()
{
Globals.MercatorTasksToMain.Log("Instantiatie van de PeppolBoxHelper");
using (MercatorUi.Forms.Other.OtherClasses.PeppolBoxHelper peppolBoxHelper = new MercatorUi.Forms.Other.OtherClasses.PeppolBoxHelper())
{
if (peppolBoxHelper.DataTable == null)
Globals.MercatorTasksToMain.Log("Fout bij het initialiseren van de PeppolBoxHelper: " + Api.LastError, isError: true);
else if (!peppolBoxHelper.Download())
Globals.MercatorTasksToMain.Log("Fout bij het downloaden van berichten: " + Api.LastError, isError: true);
else
{
Globals.MercatorTasksToMain.Log("Bericht(en) gedownload: " + peppolBoxHelper.Messages.Count(m => m.IsNew));
int nActions = 0;
foreach (MercatorUi.Forms.Other.OtherClasses.PeppolBoxHelper.PeppolMessage message in peppolBoxHelper.Messages.Where(m => m.IsNew && m.IsInvoiceOrCreditNote))
{
MercatorPeppol.ReceivedDoc.ParseContentRet parsedContent = message.ReceivedDoc.ParseContent(Globals.Langue, MercatorPeppol.ReceivedDoc.ParseContentEnum.WithSupplierName | MercatorPeppol.ReceivedDoc.ParseContentEnum.WithPdf);
if (!string.IsNullOrWhiteSpace(parsedContent.Error))
{
Globals.MercatorTasksToMain.Log(string.Format("Bericht verwerken {0} : {1}", message.Id, parsedContent.Error), isError: true);
continue;
}
string id_actempl = null;
// hier worden de testen geplaatst om op basis van de inhoud van het bericht het juiste CRM-actietype te bepalen
if (...)
{
id_actempl = ".A-0RFCEXW"; // id_actempl gescom
}
else if (...)
{
id_actempl = ".A-KC6V639"; // id_actempl compta
}
if (id_actempl == null)
continue; // dit bericht wordt niet gedistribueerd
using (MercatorUi.Engine.Crm.ActionEngine actionEngine = MercatorUi.Engine.Crm.ActionEngine.InitNew(MercatorUi.Sig._SigEnum._none, null, id_actempl))
{
if (actionEngine == null)
{
Globals.MercatorTasksToMain.Log("ActionEngine.InitNew : " + actionEngine.LastError, isError: true);
continue;
}
if (actionEngine.ReadOnly)
{
Globals.MercatorTasksToMain.Log("ActionEngine.InitNew : engine is ReadOnly!");
continue;
}
actionEngine.ActionsRecord.OBJET = (message.ReceivedDoc.ChangeType == "INVOICE_RECEIVED" ? "Factuur" : "Creditnota") + " Peppol van " + parsedContent.SupplierName;
actionEngine.ActionsRecord.ENTRYID = message.Id.ToString();
actionEngine.ActionsRecord.MOMENT_2 = message.Moment;
actionEngine.ActionsRecord.MOMENT_1 = message.Moment.AddDays(5); // deadline voor de actie op 5 dagen
if (!actionEngine.Save())
{
Globals.MercatorTasksToMain.Log(string.Format("Bericht {0} : fout bij het bewaren van de actie: {1}", message.Id, actionEngine.LastError), isError: true);
continue;
}
else if (parsedContent.Pdf == null)
{
Globals.MercatorTasksToMain.Log(string.Format("Bericht {0} : geen PDF in het bericht", message.Id), isError: true);
}
else
{
if (!Api.BytesToSqlFile(parsedContent.Pdf, Api.AddBS(actionEngine.SqlFileViewDefaultDirectory) + "PeppolDoc.pdf"))
Globals.MercatorTasksToMain.Log(string.Format("Bericht {0} : kan PDF niet aan actie koppelen", message.Id), isError: true);
}
nActions++;
}
}
Globals.MercatorTasksToMain.Log("Aangemaakte actie(s): " + nActions);
}
}
}
}
}
In het ini-bestand zal deze lijn worden toegevoegd:
Task1= DownloadAndDispatchPeppolMessages
De testen die bepalen welke actie moet worden aangemaakt, moeten aangepast worden volgens eigen criteria. Deze code geeft bijvoorbeeld het btw-nummer van de leverancier, wat nuttig kan zijn voor identificatie voorafgaand aan de toewijzing van de actie:
XmlNode nodeNumTva = parsedContent.XmlSelectNodes("cac:AccountingSupplierParty/cac:Party/cac:PartyTaxScheme/cbc:CompanyID").FirstOrDefault();
string numTva = nodeNumTva?.InnerText;
De gegenereerde acties verschijnen in de takenlijst van de betrokken gebruikers. Indien nodig kan de lijst van ontvangers worden gewijzigd door de actierechten. Elke actie bevat een PDF voor het bekijken van de factuur / creditnota. Het bevat ook een knop om de daadwerkelijke import te starten.
Bijvoorbeeld, voor importeren in het commercieel beheer is de code voor deze knop:
public static void Exec(MercatorUi.MovableControls.MovableButton clickedButton)
{
// enter your customized code here
MercatorUi.Forms.Action.ActionForm actionForm = (MercatorUi.Forms.Action.ActionForm)clickedButton.Form;
MercatorUi.Forms.Other.OtherClasses.PeppolBoxHelper.PeppolMessage peppolMessage =
MercatorUi.Forms.Other.OtherClasses.PeppolBoxHelper.PeppolMessageFromAction(actionForm.ActionEngine);
actionForm.Close();
peppolMessage?.StartImportIntoBilling(new MercatorUi.Engine.Crm.Tools.ActionDescriptor(actionForm.ActionEngine));
}
Voor boekhoudkundige import moet de laatste regel gewoon worden aangepast: StartImportIntoAccounting
Zodra de invoer of het document voor het commercieel beheer is gegenereerd en opgeslagen, wordt de taak automatisch gemarkeerd als "gedaan".
Merk op dat deze instelling geen berichten verwijdert uit de PeppolBox. Berichten worden na het importeren en opslaan verwijderd als de gebruiker positief antwoordt op de vraag "Dit document verwijderen uit de PeppolBox?". Net zoals bij een normale import uit de PeppolBox.
De instellingen hieronder tonen hoe een gebruiker deze acties manueel kan aanmaken vanuit de PeppolBox. Hierdoor kan een beheerder bijvoorbeeld berichten verdelen die niet automatisch verwerkt konden worden door de hierboven geïllustreerde taak. Dit gebeurt codeless via de instelling van grids zonder code.
Ga naar "Tools / Setup / Rasters-Customizers" en selecteer in de keuzelijst PeppolBox.
- Vink AutoAddCustomColumns aan
- Plaats deze StringUpdater :
- links : as isnew
- rechts : as isnew,'CreateActionFromPeppolMessage' as UserDefinedButtonColumnCustom
- Voeg daarna een kolomregel toe in de eigenschap CustomRules:
- Name : UserDefinedButtonColumnCustom
- Width : 50
- ButtonText : Action
En plaats ten slotte deze code in de customizer PeppolBox:
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
{
public void CreateActionFromPeppolMessage(MercatorUi.GridPro.DataGridViewXPro grid, System.Windows.Forms.DataGridViewCellEventArgs e)
{
MercatorUi.Forms.Other.PeppolBoxForm peppolBoxForm = (MercatorUi.Forms.Other.PeppolBoxForm)grid.FindForm();
Guid guid = (Guid)grid.Rows[e.RowIndex].Cells["id"].Value;
List<bool> l = Api.Zselect<bool>(MercatorUi.Globals.RepData, "if exists(select * from ACTIONS where entryid=@id) select cast(1 as bit) as ret else select cast(0 as bit) as ret", new MercatorSqlParam("@id", guid.ToString(), SqlDbType.Char));
if (l == null)
return;
if (l[0])
{
MercatorUi.Dialogs.Stop("Dit bericht zit al in een CRM-actie!");
return;
}
MercatorUi.Forms.Other.OtherClasses.PeppolBoxHelper.PeppolMessage message = peppolBoxForm.PeppolBoxHelper.Messages.First(m => m.Id == guid);
if (!message.IsInvoiceOrCreditNote)
return;
MercatorPeppol.ReceivedDoc.ParseContentRet parsedContent = message.ReceivedDoc.ParseContent(Globals.Langue, MercatorPeppol.ReceivedDoc.ParseContentEnum.WithSupplierName | MercatorPeppol.ReceivedDoc.ParseContentEnum.WithPdf);
if (!string.IsNullOrWhiteSpace(parsedContent.Error))
{
MercatorUi.Dialogs.Stop(string.Format("Bericht verwerken {0} : {1}", message.Id, parsedContent.Error));
return;
}
int n = MercatorUi.Dialogs.Answer3Buttons("Een CRM-actie met dit bericht aanmaken?", "Gescom", "Compta", Api.Iif_langue(MercatorUi.Globals.Langue, IifLangueEnum.Cancel));
if (n == 3)
return; // Cancel
MercatorUi.Engine.Crm.Tools.ActionDescriptor actionCreated;
string id_actempl = n == 1 ? ".A-0RFCEXW" : ".A-KC6V639";
using (MercatorUi.Engine.Crm.ActionEngine actionEngine = MercatorUi.Engine.Crm.ActionEngine.InitNew(MercatorUi.Sig._SigEnum._none, null, id_actempl))
{
if (actionEngine == null)
{
MercatorUi.Dialogs.Stop("ActionEngine.InitNew : " + actionEngine.LastError);
return;
}
if (actionEngine.ReadOnly)
{
MercatorUi.Dialogs.Stop("ActionEngine.InitNew : engine is ReadOnly!");
return;
}
actionEngine.ActionsRecord.OBJET = (message.ReceivedDoc.ChangeType == "INVOICE_RECEIVED" ? "Factuur" : "Creditnota") + " Peppol van " + parsedContent.SupplierName;
actionEngine.ActionsRecord.ENTRYID = message.Id.ToString();
actionEngine.ActionsRecord.MOMENT_2 = message.Moment;
actionEngine.ActionsRecord.MOMENT_1 = message.Moment.AddDays(5);
if (!actionEngine.Save())
{
MercatorUi.Dialogs.Stop(string.Format("Fout bij het bewaren van de actie: {0}", actionEngine.LastError));
return;
}
else if (parsedContent.Pdf == null)
{
MercatorUi.Dialogs.Stop("Geen PDF in het bericht");
}
else
{
if (!Api.BytesToSqlFile(parsedContent.Pdf, Api.AddBS(actionEngine.SqlFileViewDefaultDirectory) + "PeppolDoc.pdf"))
MercatorUi.Dialogs.Stop("Kan PDF niet aan actie koppelen");
}
actionCreated = new MercatorUi.Engine.Crm.Tools.ActionDescriptor(actionEngine);
}
MercatorUi.Globals.Main.ShowActionExisting(actionCreated.Id, actionCreated.Module, actionCreated.IdSig);
}
}
}
Te laden :
0000003285.zip (13 Kb - 25-03-2025)