Template for cloud-ready debtor interfaces

Template for cloud-ready debtor interfaces

Product line

Standard

|

Expert

Operating mode

CLOUD ABO

|

ON-PREMISES

Modules

Services & CRM

Budget & Phases

Purchases

Resource Planning

Business Intelligence

Created: 05.11.2019
Machine translated
Updated: 21.03.2024 | Added code examples.

There is a sample accounts receivable interface that shows what needs to be implemented to create a runable cloud-ready F&A interface. It can be used as a basis for new extensions.

To implement the sample interface or view the code, create a new extension in Vertec in the Extensions folder.

For the extension ID, specify one of the following references:

  • Online interface: FibuExampleExtension.ExampleOnlineDebiExtension. This is an example of an extension that works online and with requests. An example of this is the Run my Accounts receivables extension.
  • Offline interface: FibuExampleExtension.ExampleOfflineDebiExtension. This is an example of an extension that creates a text file each time posting or cancelling and delivers it for download. These text files are then read into the accounting systems. Examples are the Datev receivable extension and the BMD receivable extension.

Once you have entered the extension ID, you can open the code using the button with the three dots:

The code for both interfaces is in the same file, but only one or the other can be registered per extension.

Online interface

The class for online debtor interfaces is called ExampleOnlineDebiExtension and contains the following entry points:

TryPostInvoiceBookings(self, invoiceList)

This method is called directly by Vertec and is used to post the invoices in the accounting system. During this process, the debtor address is also written.

Its argument is a list of Vertec invoice objects. The list contains only valid invoices. The consistency check is performed before calling this method.

def TryPostInvoiceBookings(self, invoiceList):
    response = [""] * len(invoiceList)
    for i in range(len(invoiceList)):
        try:
            self.CreateOrUpdateDebitor(invoiceList[i])
            self.BookInvoice(invoiceList[i])
        except Exception as e :
            errortext = translate('The invoice with the number %s reports:') % str(invoiceList[i].nummer)
            errortext += '\n'
            errortext += str(e)
            response[i] = errortext.replace('\n', "\n \t")
    return response

It must return a list of strings with the same length as the list of invoices.

  • Each string is linked to the invoice on the same index.
  • If the string is empty, Vertec considers the invoice to be posted.
  • In any other case, the error message must be written to the string.

Example

        invoicelist[0] - response[0] = ""
        invoicelist[1] - response[1] = ""
        invoicelist[2] - response[2] = "Ein erster Fehler ist aufgetreten"
        invoicelist[3] - response[3] = "Es ist ein zweiter Fehler aufgetreten"
        invoicelist[4] - response[4] = ""

The invoices with index 0, 1 and 4 are posted in Vertec. The other invoices are not posted.

In addition, the first error is shown to the user as an error message: “A first error has occurred”. Only the first error is shown at a time.

TryCancelInvoiceBookings(self, invoiceList)

This method is called directly by Vertec and is used to cancel invoices in accounting.

Its argument is a list of Vertec invoice objects. The list contains only valid invoices. The consistency check is performed before calling this method.

def TryCancelInvoiceBookings(self, invoiceList):
    response = [""] * len(invoiceList)
    for i in range(len(invoiceList)):
        try:
            self.CancelInvoice(invoiceList[i])
        except Exception as e :
            errortext = translate('The invoice with the number %s reports:') % str(invoiceList[i].nummer)
            errortext += '\n'
            errortext += str(e)
            response[i] = errortext.replace('\n', "\n \t")
    return response

It must return a list of strings with the same length as the list of invoices.

  • Each string is linked to the invoice on the same index.
  • If the string is empty, Vertec considers the invoice to be posted.
  • In any other case, the error message must be written to the string.

 Example

        invoicelist[0] - response[0] = ""
        invoicelist[1] - response[1] = ""
        invoicelist[2] - response[2] = "Ein erster Fehler ist aufgetreten"
        invoicelist[3] - response[3] = "Es ist ein zweiter Fehler aufgetreten"
        invoicelist[4] - response[4] = ""

Invoices with index 0.1 and 4 are canceled in Vertec. The other invoices are not canceled.

In addition, the first error is shown to the user as an error message: “A first error has occurred”. Only the first error is shown at a time.

ImportPayments(self, invoiceList)

This method is called directly by Vertec and is used to import payments from accounting into Vertec.

Its argument is a list of Vertec invoice objects. The list contains only valid invoices. The consistency check is performed before calling this method.

def ImportPayments(self, invoiceList):
    for invoice in invoiceList:

        # get payments from fibu
        amount = 9.95
        date = datetime.date.today()

        # get paymenttyp from vertec
        zahltyp = vtcapp.evalocl("zahlungstyp->select(code='AUTO')->first")
        if not zahltyp:
            self.Log('No Paymenttyp with code "AUTO" found, will be created.')
            zahltyp = vtcapp.createobject('Zahlungstyp')
            zahltyp.Code = "AUTO"
            zahltyp.Bezeichnung = translate("automatically created through synchronization of payment")
            zahltyp.Aktiv = True

        # create vertec payment
        zahlobj = vtcapp.createobject('Zahlung')
        zahlobj.rechnung    = invoice
        zahlobj.typ         = zahltyp
        zahlobj.betrag      = amount
        zahlobj.datum       = date
        zahlobj.text        = "This payment was done by the example fibu extension"
        # Mark invoice as payed, if no open fees left.
        if invoice.betragoffen == 0:
            invoice.bezahlt = True

        print("Imported payments for invoice with number "+str(invoice.nummer))

There are three cases:

  1. Payment import performed on a single invoice: The list contains only one invoice.
  2. Payment import performed on a list of invoices: The list contains all invoices in the list.
  3. Payment import accessed globally: The list contains all invoices that have not been paid.

Payments must be created in Vertec and assigned to the invoice.    

If there is no Payment Type with the code in Vertec AUTO exists, one is created.

In addition, the invoice must:    bezahlt marked when it has been paid in full.

In the example extension, a payment of 9.95 is added to the invoice. In addition, when posting the personal account number on addresses on    1 set. This number must come from the FAR, please note comment in the code.

Offline Interface

The class for offline debtor interfaces is called ExampleOnlineDebiExtension and includes the following entry points:

PostInvoiceBookings(self, invoiceList)

The method is called directly by Vertec and is used to post invoices to accounting. The argument is a list of invoices. The list contains only valid invoices, since the consistency check is performed before calling this method.

The debtor address is also written or updated in the accounting.

 def PostInvoiceBookings(self, invoiceList):

    zipContentList = []
    for invoice in invoiceList:
        content_address = self.CreateOrUpdateDebitor(invoice)
        content_invoice = self.BookInvoice(invoice)
        zipContentList.append(content_address)
        zipContentList.append(content_invoice)
    
    zipFileAsBytes = ziputils.createzip(zipContentList)

    return ("FileNameForBookedInvoices.zip", zipFileAsBytes)

The return value is a tuple (filname, fileAsByteArray) saved by Vertec.

What happens if the booking process fails

If the extension throws an exception, the entire posting process is considered to have failed in Vertec. In this case, none of the invoices in the list are set to posted. This implies that all invoices in the list must be posted to the FARU at the same time, otherwise deviations between Vertec and the FARU can arise.

CancelInvoiceBookings(self, invoiceList)

The method is called directly by Vertec and is used to cancel invoices in accounting. The argument is a list of invoices. The list contains only valid invoices, since the consistency check is performed before calling this method.

def CancelInvoiceBookings(self, invoiceList):

    zipContentList = []
    for invoice in invoiceList:
        content = self.CancelInvoice(invoice)
        zipContentList.append(content)
    
    zipFileAsBytes = ziputils.createzip(zipContentList)

    return ("FileNameForCanceledInvoices.zip", zipFileAsBytes)

The return value is a tuple (filname, fileAsByteArray) saved by Vertec.

ImportPayments(self, invoiceList)

This method is called directly by Vertec and is used to import payments from accounting into Vertec.

Its argument is a list of Vertec invoice objects. The list contains only valid invoices. The consistency check is performed before calling this method.

The implementation should allow the user to select a payment file to import and process.

 def ImportPayments(self, invoiceList):

    # show file selection dialog
    filename, content = vtcapp.requestfilefromclient("Import payments file", '', '*.txt')

    # here we would process the payments file content....

    # as an example, we just add a payment to all the invoices
    for invoice in invoiceList:

        # get payments from fibu
        amount = 9.95
        date = datetime.date.today()

        # get paymenttyp from vertec
        zahltyp = vtcapp.evalocl("zahlungstyp->select(code='AUTO')->first")
        if not zahltyp:
            self.Log('No Paymenttyp with code "AUTO" found, will be created.')
            zahltyp = vtcapp.createobject('Zahlungstyp')
            zahltyp.Code = "AUTO"
            zahltyp.Bezeichnung = translate("automatically created through synchronization of payment")
            zahltyp.Aktiv = True

        # create vertec payment
        zahlobj = vtcapp.createobject('Zahlung')
        zahlobj.rechnung    = invoice
        zahlobj.typ         = zahltyp
        zahlobj.betrag      = amount
        zahlobj.datum       = date
        zahlobj.text        = "This payment was done by the example fibu extension"
        # Mark invoice as payed, if no open fees left.
        if invoice.betragoffen == 0:
            invoice.bezahlt = True

        print("Imported payments for invoice with number "+str(invoice.nummer))

There are three cases:

  1. Payment import performed on a single invoice: The list contains only one invoice.
  2. Payment import performed on a list of invoices: The list contains all invoices in the list.
  3. Payment import accessed globally: The list contains all invoices that have not been paid.

Payments must be created in Vertec and assigned to the invoice.  

If there is no Payment Type with the code in Vertec AUTO exists, one is created.

In addition, the invoice must be marked as bezahlt if it has been paid in full.

In the example extension, a payment of 9.95 is added to the invoice. In addition, when posting, the personal account number is set to addresses that do not yet have such a number. The corresponding numbers come from the system setting Next Next Debtor Number .

Implementation Details

The following notes should be observed when implementing a new extension:

The following may NOT be written by the extension:

  • The state gebucht on the invoice is set by the Vertec business logic and must not be set separately from the extension.
  • The same applies to the persistent accounting attributes on the invoice (the values with bhXX), which are also automatically described by Vertec.

The following MUST be written by the extension:

  • The posting number (rechnung.belegnr) must be set by the extension, because without a posting number cannot be canceled. For accounting systems that work without posting numbers, 0 can be simply entered.

Issue

Prints are written to the Python Console when posting and cancelling.