Vertec Python functions

Description of Vertec Python functions

Operating mode

Cloud Suite

|

ON-PREMISES

Modules

Services & CRM

Budget & Phases

Purchases

Resource Planning

Business Intelligence

Created: 04.03.2013
Machine translated
Updated: 28.04.2025 | As of version 6.8: The module “vtcauth,” vtcapp.extractplaintext() and vtcapp functions for full-text search.

Overview

The module “vtcapp”

The Vertec installation includes a Vertec Python library (module), which is automatically available in the Python scripts after installation and is called vtcapp.

The module has the following methods/features:

Method / feature description Sample code
__doc__
Documentation of a feature.
>>> print vtcapp.__doc__ 
Interface module to host application.
argobject

Current Vertec object. This variable is always available, so the call can be made without vtcapp..
See also the description in the article Python Scripts.

projekt = argobject
checkcreate(class:string): int

Checks whether there are user rights to create objects of the specified class.

Returns 0 or 1 (False, True)

>>> print vtcapp.checkcreate('Projekt')
1
checkfeature(featurecode: string): boolean

Checks whether a particular feature is licensed.

The feature codes are according to Vertec feature matrix (e.g. fcPhasen for phases).

Returns False or True

>>> vtcapp.checkfeature('fcPhasen')
True
convertwordtopdf(wordDoc: string): string

Converts a Word document of type .docx to a PDF.

The corresponding Word document must be created and read:

in_file = open("C:\<yourPath>\BeispielWordFürEmail.docx", "rb")
wordDoc = in_file.read()

Conversion:

pdfDoc = vtcapp.convertwordtopdf(wordDoc)
createoutlookmail(to, subject, body=”“, cc=”“, bcc=”“, attachments=[], show=True, onBehalfOf=”“)

Python method from version 6.4.0.4, which creates to create an email message on the client via Outlook.

Works with the Desktop App and the Cloud App. If you are working with the Web App, the sendmail() method can be used.

  • to: String. Recipient addresses, separated by ;, if more than one.
  • subject: String. Subject of the email.
  • body:
    • String. The actual email text. Can be HTML or plaintext. HTML is recognized as such and then created in the form of an Outlook HTML mail.
    • Starting with version 6.5.0.21, a Word document can also be used (see example below).

Optional:

  • body: Optional as of version 6.7. If body not specified, an empty string or None, nothing is set in the created email.
  • cc: String, Optional, Keyword*. Cc addresses, separated by ;, if more than one.
  • bcc: String, Optional, Keyword*. Bcc addresses, separated by ;, if more than one.
  • attachments: List of tuples, Optional, Keyword. List of attachments as a tuple of two strings[(file name, content)], see example below.
  • show: Boolean, Optional, Keyword*. For True, the email is created and shown, for False, the email is saved in the drafts folder and not shown. Default value is True.
  • onBehalfOf: String, Optional. Send the email with a different sender. Example: vtcapp.createoutlookmail("dokumentation@vertec.com", "Betreff XYZ", onBehalfOf="noreply@vertec.com") opens an email with the sender noreply@vertec.com.

*Keyword means that you can specify the optional values with the parameter as a keyword, e.g. CC="abc@vertec.com". This way you do not need a specific quantity of commas as placeholders for unspecified optional values.

Examples:

  • Simplest case, body as string:
    vtcapp.createoutlookmail("dokumentation@vertec.com", "Dokumentation", "Dies ist der einfachste Fall")
  • Using Word documents as a body:

Note: Use tables in your Word documents and avoid tab stops, as they cannot be processed in the email.

  1. The corresponding Word document must be created and read:
    in_file = open("C:\<yourPath>\BeispielWordFuerEmail.docx", "rb") 
    fileData = in_file.read()
  2. Generate the email using the method:
    vtcapp.createoutlookmail('dokumentation@vertec.com', 'Test E-Mail from Word', fileData)
  • Keywords (show is given per keyword):
    vtcapp.createoutlookmail("dokumentation@vertec.com", "Dokumentation", "jetzt benutzen wir show per keyword", show=False)
  • Attachments:
    akt = argobject
    attachments=[('File1.txt', 'This is the content of file 1'),('Anhang.pdf', akt.content)] 
    vtcapp.createoutlookmail("dokumentation@vertec.com", "Dokumentation", "Eine E-Mail mit attachments", attachments=attachments, show=False)
    The attachment name must not be empty.
  • Body in HTML
    html="<html><body><p>Hallo</p><p>Dies ist eine Outlook Nachricht in HTML.</p><p>Es ist ziemlich einfach, verwenden Sie HTML BODY und P (Paragraph) wie hier dargestellt, und schon entsteht eine strukturierte E-Mail.</p><p>Möchten Sie <b>fettgedruckten</b>, <i>kursiven</i>, <u>unterstrichenen</u> Text, verwenden Sie die entsprechenden Tags.<span style=\"color: red\">Sie können auch eine andere Farbe verwenden.</span></p><p>Freundliche Grüsse</p><p>Ihr Vertec Team</p></body></html>" vtcapp.createoutlookmail("dokumentation@vertec.com", "Dokumentation", html)
createlist(classname, [list]): list
As of version 6.1.0.14. With this, a Vertec list can be created, on which OCL can be evaluated.
  • classname: the class name of the objects that the list will contain. The class name is necessary so that the list itself contains static type information and can serve as a basis for evaluating OCL expressions.
  • list (optional): the optional List argument allows constructing a list directly from another list. If the argument is not set, the generated list is empty and can be populated via append() or extend() method (see list of available methods on Vertec lists).

Starting with version 6.2.0.7 the python methods evalocl(), getwithsql() and getmemberwithsql() automatically return Vertec lists, see Vertec lists.

mylist = vtcapp.createlist('Projekt')
mylist.append(argobject)

or

liste = vtcapp.createlist("Projekt", vtcapp.evalocl("projekt->select(code.sqllike('A%'))"))
liste2 = liste.evalocl("self->select(aktiv)")
createobject(class: string)
Creates new object of the specified class.
leistung = vtcapp.createobject("OffeneLeistung")
currentlogin(): User
Current logged in user
>>> bearbeiter = vtcapp.currentlogin()
>>> bearbeiter.name
Christoph Keller
currentobject
See the description in the article Python Scripts.
projekt = currentobject
disableevents()

As of Vertec 6.7.0.7 always use Disabledevents() instead.

With disableevents(), event scripting can be turned off. This will affect the entire Vertec session (other Vertec sessions or Desktop App are not affected).
This feature is used, for example, if you want to customize a certain attribute that would otherwise execute an event.

Can be used with enableevents() re-enabled. Require extended user rights. Not allowed

in the Python editor for security reasons.    

# Ganzes Script
try:
    vtcapp.disableevents()
    main()
finally:
    vtcapp.enableevents()

# Teil eines Scripts
vtcapp.disableevents()
rechnung.datum = vtcapp.currentdate()
vtcapp.enableevents()
DisabledEvents()

As of version 6.7.0.7. Must include with can be called:

with vtcapp.DisabledEvents():

Within this method, event scripting is turned off, affecting the entire Vertec session (other Vertec sessions or Desktop App are not affected).

Used, for example, to modify a certain attribute that would otherwise execute an event.

Require extended user rights. Not allowed in the Python editor for security reasons.

with vtcapp.DisabledEvents():
    rechnung.datum = vtcapp.currentdate()
evalocl(expression: string): expressiontype
Evaluate global OCL expression.
projektListe = vtcapp.evalocl("Projekt.allinstances->orderby(code)")
evaloclstring(obj: object, expStr: string): string
Evaluate OCL expression within a string. Return Value: Fully evaluated string.
>>> vtcapp.evaloclstring(argobject,"Bearbeiter: %name% ist %stufe.asstring%")
Bearbeiter: Christoph Keller ist Senior Consultant
evaltovariable(obj: object, ocl: string, varname: string)
Evaluates an OCL and saves the value in an OCL variable. The variable can then be queried globally with evalocl().

Starting with version 6.1.0.14 you can no longer use “self” as the variable name, because this is a keyword. An error message appears.

>>> projekt = vtcapp.evalocl("projekt->select(code='TRASTA')->first")
>>> vtcapp.evaltovariable(projekt, "rechnungen->first", "varRechnung")
>>> vtcapp.evalocl("varRechnung")
15070005, TRASTA
>>> projekt.evalocl("varRechnung")
15070005, TRASTA
executefile(command: string, [argumentString: string])

Before 6.4.0.10: executefile(path: string)

Opens a file on the client (without Web App). The file path must be accessible from the client.

Starting with version 6.4.0.10 Command Line Parameters are also supported. You can optionally pass arguments for this. The previous simple case still works.

Parameter parsing is as follows:

  • No parsing occurs in command. Spaces are interpreted as part of the path.
  • Parsing occurs in argumentString, where spaces separate arguments unless they are enclosed in double quotation marks ““.

As of Vertec 6.5.0.11 only files of the type .doc, .docx, .xls, .xlsx, .pdf, .csv, .txt, .zip, .png, .jpg, .jpeg, .bmp, .gif, .eml and from Vertec 6.5.0.15 .ics be executed directly (same Whitelist as with sendfile()). For all others, there is a dialog asking if Vertec is allowed to open the file:

  • If Yes, the path and name of the file will be remembered, and the dialog will not appear when the file is called again.
    This is done by an entry in the registry in the key: HKEY_CURRENT_USER\Software\Vertec\ExecuteFileWhiteList. The whitelisting applies only to the executable file and path, not to any arguments.
  • If No, there is no write access to this part of the registry and the file cannot be remembered. A warning is written to the Logfile (Vertec.Cloud.log or Vertec.Desktop.log).

Examples:

pfad = r'S:\Dokumente\Kontakte\Bistro Cooper\Brief.docx'
vtcapp.executefile(pfad)

The r in front of the path causes control characters to be ignored. Since the backslash is a control character in some combinations for Python, otherwise the path may be misinterpreted or fragmented, resulting in an error.

vtcapp.executefile("calc.exe")

opens the Windows computer.

From 6.4.0.10 also:

vtcapp.executefile('notepad++.exe', r'-lpython "C:\Dokumente\Mein Script.py"')
executefolder(path: string)

Opens the specified folder on the client (without Web App), e.g. in Windows Explorer. The path must be accessible from the client.

If the folder does not exist yet, a message appears whether it should be created:

In a script this has to be queried and the folder has to be created in the code if no message should appear on the interface. This can be done e.g. via the Python module os (does not work with Restricted Scripting).

import os
pfad = r'S:\Dokumente\Kontakte\Bistro Cooper'
if os.path.isdir(pfad):
  vtcapp.executefolder(pfad)

The r in front of the path causes control characters to be ignored. Since the backslash is a control character in some combinations for Python, otherwise the path may be misinterpreted or fragmented, resulting in an error.

executereport(rootObj, optarg, reportObj, [saveAs, showDialog, doPrint, showApp]): report

Allows you to call and run Reports based on a report object. For
a table of availability with different systems, see the section further down.

  • rootObj: The object on which the report will be run. Only a single object can be specified, not a list.
  • optarg: Matches the optional address on the print dialog. Optional argument. If not used, specify parameters with None.
  • reportObj: A Vertec report definition (class report). The report is executed based on this definition.
    • If the report is a Legacy Word Report, you can also specify a path for the Office template instead of the report object.
    • The settings of the report object for Save As and Show Dialog can still be overridden via the corresponding arguments of this method.
  • saveAs: Optional. Path to save the report (if Office report). This string can also contain OCL expressions (separated by %).
    • If an empty string is specified, no file is saved.
    • If None is passed, the Saveas settings from the report object (reportObj) are applied.
  • showDialog: Display of dialog with stores under etc. (if Office report). Optional. Possible Values: True or False. Start
    with version 6.1.0.14, this setting also controls the display of messages such as “overwrite existing file” and “create new path”. If the parameter is not set, the corresponding setting from the report object (reportObj) is applied over.
  • doPrint: Optional. Possible Values: True or False. This value is only used for legacy Office-generated reports prior to version 6.6.0.8. If True, the report is printed directly without opening the corresponding Office application.        
  • showApp: Specifies whether to show the report open. Optional. Possible Values: True or False.

Examples:

Show a Word report for invoice without dialog and without saving a filesave

vtcapp.executereport(rech, None, rechTempl, "", showDialog=False)

The rechTempl variable must contain the object report for an invoice, the rech variable must contain the invoice object.

Starting with version 6.4.0.8 the method returns the report output as a byte string (only if berichObj is a Vertec report definition, not if a path is specified). This can be further processed and, for example, attached as an attachment to an email via vtcapp.createoutlookmail().

rechTempl = vtcapp.evalocl("bericht->select(eintragid='BerichtScriptInvoiceWithList')->first")
pdf = vtcapp.executereport(argobject, None, rechTempl, "", showDialog=False)
vtcapp.createoutlookmail("mail@adresse.com", "Betreffend", "Inhalt", attachments=[('rechnung.pdf', pdf)])
executereport2(rootObj, optarg, reportObj, [saveAs, showDialog, doPrint, showApp]): (report, activity)

Starting with version 6.4.0.22. Allow calling and executing Reports based on a report object.

The method returns a tuple consisting of the report output as a byte string and the corresponding activity.

For the description of the parameters see executereport() above. Only a Vertec report definition (class report) can be passed as reportObj, no file paths.

For a table of availability with the different systems, see the section further down.

rechTempl = vtcapp.evalocl("bericht->select(eintragid='BerichtScriptInvoiceWithList')->first")

reportdoc, activity = vtcapp.executereport2(argobject, None, rechTempl)

The method returns a tuple:

  • Content of the resulting report document is (byte string).
  • The created activity object or None

An activity is only created when a report is saved.

execututeurl(url)

Opens the specified URL on the client (all full-featured apps).

The URL must be accessible from the client. The Web App must be a publicly accessible path, access to the local client is not possible.

For example, to open a website in the browser:

vtcapp.executeurl("https://www.vertec.com")

Or a Vertec Breadcrumb URL:

vtcapp.executeurl("vertec://CK-676/eigene+Projekte-49/COMINSTALL-2880/")

the same also works as a short version, in which only the IDs are specified:

vtcapp.executeurl("vertec://676/49/2880/")
extractplaintext(file): string

Used to extract plain text from files.

The method checks whether the passed file (bytearray) is one of the following files:

  • PDF
  • DOC(X)
  • EML/MIME

If so, it extracts the text from these files and returns it as plaintext (string).

If the byte array does not represent any of the specified file types, or if reading the content fails, for example because the file is invalid or it is a password-protected PDF, a blank string is output.

Document Storage Internal:

file = argobject.content
text = vtcapp.extractplaintext(file)

Document Storage File system/DMS:

filename, file = vtcapp.requestfilefromclient("File auswählen", r"C:\Dokumente", "PDF|*.pdf|DOCX|*.docx|EML|*.eml|MIME|*.msg")
text = vtcapp.extractplaintext(file)
fetchlinkmembers(objectlist, membername): objectlist
As of version 6.4. Load the sublist (membername) for a list of objects (objectlist) into memory, and at the same time makes the multilink current, which means that when the link is accessed, the list is not reloaded. Therefore, the call should fetchlinkmembers() immediately prior to the re-use of the list.
# Loop durch die Phasen von Projekten, welche mindestens eine Phase "erteilt" haben
projekte = vtcapp.getwithsql("Projekt", "bold_id IN (SELECT projekt FROM projektphase WHERE status=1)", "")
vtcapp.fetchlinkmembers(projekte, "phasen")
for projekt in projekte:
    x = projekt.evalocl("phasen->select(status=1)")
generateinvoicenumber()

Generates the next Vertec invoice number according to system settings invoice / invoice.

rech = argobject
rech.nummer = vtcapp.generateinvoicenumber()
getcurrentobject()

Returns the selected object in the tree and can be called from Ocl call operators using OCL call operators.

 
getmailattachment(content, idx): bytestring

From version 6.5. Allow you to download an email attachment of an activity.

Returns the contents of the attachment as a byte string.

Since the names of the attachments are not necessarily unique, it must be identified by Idx.

filecontent = vtcapp.getmailattachment(activity.content, 0)
outfile.write(filecontent)
outfile.close()
getmailattachments(content): list(string)

As of version 6.5. Return a list of attachment names of an activity.

filename = vtcapp.getmailattachments(activity.content)[0]
outfile = open('C:/data/' + filename, 'wb')
getmemberwithsql(obj: object, membername: string, where: string, order: string): list of objects

Allows querying members of an object via SQL.
The executing user must have administrator rights or the SQL Query right.
For granting temporary administrator rights, the variant of extended user rights is available.

projekt = argobject
li=vtcapp.getmemberwithsql(projekt, "offeneleistungen", "xwertext>200", "") 
print len(li)
>>> 3
getobjectbyentryid(classname: string, entryid: string): object

As of version 6.6.0.2. Get the object with the specified class and Entry Id

Both parameters must always be specified.

If the class classname does not exist or does not inherit Eintrag, an error is thrown.

If no or more objects are found, an error is thrown.

Note: The objects are loaded internally via SQL. Thus, only objects already stored in the database are found. For newly created objects, a vtcapp.updatedatabase() so that the object is found with this method.

obj = vtcapp.getobjectbyentryid("Ordner", "FolderPublicProjectBySectors")
getobjectbyid(id: int, string or long*): object

Gets the object with the specified Internal Id.

If the id does not exist, an error is thrown.

Note: The objects are loaded internally via SQL. Thus, only objects already stored in the database are found. For newly created objects, a vtcapp.updatedatabase() so that the object is found with this method.

* As of Vertec 6.7.0.4.

obj = vtcapp.getobjectbyid(62162)

or

obj = vtcapp.getobjectbyid("62162")
getpropertyvalue(propname: string): value

Returns the value of the system setting (property) with the specified name.

The return value depends on the type of property.

>>> print vtcapp.getpropertyvalue("firma")
LKT Engineering GmbH, Hamburg
getvertecserveraddress(): string

Returns the address where the Vertec Cloud Server is available from the Internet.

vtcapp.executeurl(vtcapp.getvertecserveraddress())
getwithsql(class: string, where: string, order: string, [idfilterfeld: string, objectlist: list]): list of objects

Before version 6.3.0.8:
getwithsql(class: string, where: string, order: string): list of objects

 

This global SQL statement is used to filter lists to be filtered directly on the database in a performance-optimized manner (see the article Performance-optimized access to vertec objects).

A call via getwithsql() is only useful if a where clause is required. For unfiltered lists, use evalocl()() instead of getwithsql().

The executing user must have administrator rights or the SQL Query right. For granting temporary administrator rights, the variant of extended user rights is available.

  • class: class name as string.
  • where: SQL WHERE clause. This can also be done using the methods sqlwhere() and sqlwherebetweendate() can be created.
  • order: SQL sort expression, usually a field name of the specified class.
    Can only be used if no idfilterfield/objectlist is specified.
As of version 6.3.0.8 the following filter criteria can be optionally specified:
  • idfilterfeld: Name of the member by which the list should be filtered.
  • objectlist: List of objects to be searched for in the field specified under idfilterfield.

In Vertec versions before 6.7.0.9 (before Firebird 5) lists (not the result list, but the filter criteria list, in the example on the right the projekte) of more than 1500 entries have to be worked with these filter criteria, otherwise an error message will appear.

Without optional filter criteria:

projektlist = vtcapp.getwithsql("Projekt", "bold_id IN (SELECT projekt FROM projektphase WHERE status=1)", "code")

With optional filter criteria:

projekte = argobject.evalocl("eigProjekte")
leistungen = vtcapp.getwithsql("OffeneLeistung","", "datum", "projekt", projekte) 

 

getwithsqlbymember(class: string, member: string, expression: string, order [optional]: string): list of objects
Allows searching of objects of a class based on a single member comparison for users without SQL privilege (the generic SQL search methods getwithsql and getmemberwithsql are subject to SQL privilege restrictions because they can be called with any SQL WHERE clause.
  • class: class name as string.
  • member: Membername as string
  • expression: comparison string (without delimiter). It can contain % wildcards, any string delimiter within
    the string will be escaped. The comparison is case-insensitive.
  • order: SQL sort expression, usually a field name of the specified class.

When the feature is called, the user rights of the current user are checked on the member used for the selection. The user must have class-wide read permission on the member for the search to work. Otherwise, an error occurs.

projektlist = vtcapp.getwithsqlbymember("Projekt", "Code", "COM%")
importconfigset(xmltext: string/file)

As of Vertec 6.7.0.7:

importconfigset(xmltext: string/file): string

Import a config set into Vertec and apply it.

Valid XML text is passed as a string or file as a config set.

Note the encoding: Until 6.3.0.12 the passed XML text must be in ANSI format, from 6.3.0.13 it must be in UTF-8.

As of Vertec 6.7.0.7 the feature returns a string containing possible errors during the import.

vtcapp.importconfigset("""<?xml version="1.0" encoding="utf-8"?>
<configset name="test" author="test"> <requirements /> <references/> 
<objects/> <settings> <system-setting name="GlobalDokPfad">C:\Dokumente</system-setting>
</settings></configset>""")

From 6.3.0.13:

xml="""<?xml version="1.0" encoding="utf-8"?>
<configset name="test" author="test"> <requirements /> <references/> 
<objects/> <settings> <system-setting name="GlobalDokPfad">C:\Dokumente</system-setting>
</settings></configset>""".encode('utf-8')
vtcapp.importconfigset(xml)

Or as a file:

f = open(r"C:\Projekte\Vertec\ConfigSet\ConfigSet.xml")
vtcapp.importconfigset(f.read())
indexall([clean:boolean])

As of Vertec 6.8. Re-indexes all objects for Full Text Search.    

If clean is specified, the existing index is discarded and created.

vtcapp.indexall()

keeps the current index and supplements it with the changed objects.

vtcapp.indexall(True)

discards the existing index and creates it from scratch.    

indexclass(classname: string)

As of Vertec 6.8. Re-indexes objects of the specified class for Full Text Search.

If index configurations have been defined for the class passed with classname or if the System Settings for indexing documents or emails have been set for the class activity, all objects of this class are re-indexed with this feature.

If these conditions are not met, then nothing is done.

vtcapp.indexclass("Project")
indexlist(objectlist)

As of Vertec 6.8. The method takes a list of objects and re-indexes them for the Full Text Search.    

Objects for which no index should be written are automatically sorted out.

It is also possible to pass a single object as a list.

Indexing a single object:

vtcapp.indexlist([argobject])

Index list:

liste = argobject.eintraege
vtcapp.indexlist(liste)

As of Vertec 6.8. This method can be used to re-index activities of a specific type for Full Text Search.    

One of the following values is passed as type:

  • 0: Activities are re-indexed without document or email
  • 1: All documents (Word and PDF) are re-indexed
  • 2: All emails are re-indexed
vtcapp.indexactivities(1)

re-indexes all documents (Word and PDF).

indexstatus(): dict

As of Vertec 6.8. Outputs indexing status information for Full Text Search-text search as a dictionary with the following information:

  • IsAvailable: Boolean. True, if the server has been reached, otherwise False.
  • OperationRunning: Boolean. True: A “complex” operation is current running. Only available if there is a connection to the index server.
  • ProcessedObjectCount: Integer. Quantity of objects already processed. Only present if a “complex” operation is running.
  • TotalObjectCount: Integer. Total number of objects to process. Only present if a “complex” operation is running.
  • StatusMessage: String. Current status of the indexer.
  • PercentCompletion: Double. Completed in percent (from 0 to 1). Only present when a “complex” operation is running.

This information is also output to the System Info in the new Indexing area.

Complex operations are indexall(), indexclass() and indexactivities()). Only one complex operation can be started at a time. If an attempt is made to start another, the Vertec Cloud Server acknowledges this with an error. indexlist() can be started at the same time, but when it is running, no additional complex operation can be started.    

print vtcapp.indexstatus()
{u'OperationRunning': False, u'IsAvailable': True, u'StatusMessage': u'idle'}
indexabort()

As of Vertec 6.8. Abort a current running indexing for Full Text Search.    

The queuing of the objects is canceled, already queued objects are indexed.

vtcapp.indexabort()
inputbox(caption: string, prompt: string[, default: string]): string
Show simple input field.
  • caption: Title of the form
  • prompt: introductory text
  • default: Optional. Default value

The structure of the buttons and the return values works according to article msgbox/inputbox: description of the parameters.

print vtcapp.inputbox("Titel", "Geben Sie einen Text ein:")
>>> test
log(category: string, level: int, msg: string)

Log Message in Vertec Logging System. Levels available:

  • 10: Debug log
  • 20: Info log
  • 30: Warning Log
  • 40: Error log
  • 50: Fatal Log
projekt = argobject
leistung = projekt.evalocl("offeneleistungen->first")
if leistung:
    try:
        leistung.xwertext = 0
    except:
        vtcapp.log("Leistungen anpassen", 30, "Keine Berechtigung")
msgbox(msg: string)
Show Message Box (versions before 6.0)

Information is used as the title and always Info is used as the dialog type (button / symbol combination).

vtcapp.msgbox("Das ist ein Test")
msgbox(text: string [, buttons: int, title: string]): int

Show Message Box (versions 6.0 and above)

The feature supports (optional) arguments for buttons and titles.

The structure of the buttons and the return values works according to article msgbox/inputbox: description of the parameters.

 

vtcapp.msgbox("Dies ist mein Text", 1, "Vertec")
msgtomime(msgcontent): mimecontent

From version 6.5.0.11 up to and including version 6.6. Convert .msg Convert files to MIME format so that emails (activities) can be shown directly in Vertec.

.msg File and associates them with activities.

Existing emails as .msg Files, e.g. from the application with the Vertec Outlook add-in, can be converted by means of the script beside. The script works only without Restricted Scripting, i.e. not in the Cloud Suite, and not with Sharepoint paths. It runs on a list of activities (current container) and converts all .msg Files to (the emails are migrated from the drive paths to Vertec).

import os 

for act in argobject.eintraege: 
    if act.effpfad and os.path.exists(act.effpfad): 
        try: 
            f = open(act.effpfad, 'rb')
            act.content = vtcapp.msgtomime(f.read()) 
        except Exception as e: 
            print('error on activity %s: %s' % (act, e)) 
        else: 
            print('path is empty or doesn\'t exist on activity %s' % act)
pdfcombine(doc1:string, doc2:string): string

As of version 6.5.0.7. This method merges 2 PDF documents. The PDF documents are passed as a byte string.

newpdf = vtcapp.pdfcombine(pdf1, pdf2)
pdfextract(doc:string, pagefrom:int, pagetill:int): string
As of version 6.5.0.7. This method extracts one or more pages. The pagefrom and pagetill parameters correspond to the first and last page, respectively, and must be specified.
newpdf = vtcapp.pdfextract(pdf1, pagefrom, pagetill)
pdfpagecount(doc:string): int
As of version 6.5.0.7. This method specifies the number of pages in the document.
pages = vtcapp.pdfpagecount(pdf1)
processbi(from: String, to: String, generator: String)

Method for calculating Bi data for the Business Intelligence module.

Corresponds to the calculation of the BI data on a Measure and triggers the calculation of the generator given as parameter.

From and To dates are specified as a string in the format “Year-Month”.

The generator must be specified the same as for the measures, i.e. “<Modulname>.<Generatorname>,” see example.

Requires administrator rights.

This method can also be automated, for example, via a planned task.

To calculate all generators of all active metrics, see the method vtcapp.standardprocessbi() below.

Example: From January 2018 to February 2020:

vtcapp.processbi("2018-01", "2020-02", "OffersGenerator.OffersGenerator")
querycallback(state): dict
Queries a callback previously registered via registercallback.

As soon as the callback has been performed, the feature returns a dictionary with all supplied parameters (including state). As long as the callback has not yet been performed, the function returns a dictionary with all supplied parameters (including state). None Callbacks that have already been successfully queried cannot be queried again, because the registration is then no longer available.
When querying via querycallback in a loop (polling), it is important to install a delay using time.sleep calls so that the session is not blocked.

Example code:

state=vtcapp.registercallback()
# nur zur Demonstration: der Aufruf sollte natürlich über einen OAuth Authentifizierungs Server gehen
vtcapp.executeurl("https://myserver.vertec-mobile.com/callback?State=%s&message=ASecretMessage" % state)
time.sleep(3.0) # kurz warten bis browser offen
values=vtcapp.querycallback(state)
print(values["message"])
readinvoicedocument(binaryData)

From version 6.5.0.7. The Python feature readinvoicedocument accepts the PDF, JPG and PNG formats of accounts payable documents and processes the QR code contained therein, which it returns as a data object. As of version 6.5.0.11 EPC QR code is also supported.

Property description
Name Name of payee
Address Payee’s address information
Zip Postal code of the payee
City City of the payee
Country Country of payee
Amount Gross amount
Currency currency
Account Account
Reference Reference number
*DocumentNumber Number external
*DocumentDate Date
*DueDate Expiry date

*Optional data: will only be output if the QR code contains additional information.

The data object can finally be print() can be output.

In addition, the feature can also be used in a planned task.

Example script:

kreditorbeleg = open("C:\Users\Name\Desktop\QrCodeBeleg.pdf",'rb').read()
belegdaten = vtcapp.readinvoicedocument(kreditorbeleg)
lieferanten = vtcapp.getwithsqlbymember("Adresseintrag", "name", belegdaten.Name)
lieferant = lieferanten[0]
currency = vtcapp.getwithsqlbymember("Waehrung", "bezeichnung", belegdaten.Currency)[0]

kreditor=vtcapp.createobject("Kreditor")
kreditor.lieferant = lieferant
kreditor.belegbild = kreditorbeleg

kreditor.esrteilnehmer = belegdaten.Account
kreditor.esrcode = belegdaten.Reference
kreditor.waehrung = currency
kreditor.betragbrutto = belegdaten.Amount

if hasattr(belegdaten, 'DocumentNumber'):
    kreditor.nummer = belegdaten.DocumentNumber

if hasattr(belegdaten, 'DocumentDate'):
    kreditor.datum = belegdaten.DocumentDate

if hasattr(belegdaten, 'DueDate'):
    kreditor.xfaelligdatum = belegdaten.DueDate

if len(kreditor.auslagen) == 1:
    outlay = kreditor.auslagen[0]
    outlay.anzahl = None
    outlay.xwertintfwbrutto = belegdaten['Amount']
registercallback(): string

Registers a callback on the Cloud Server to transmit an authentication code. This is needed, for example, for authentication via OAuth. The return value is a randomly generated state string, which must be passed in the callback in order for it to be accepted. The callback is executed as an http get request to the Cloud Server, as an example https://mein.vertec-cloud.com/callback?state=<statestring>&code=<authentisierungscode>. The parameters transmitted with the callback can then be queried via vtcapp.querycallback.

Example code:

state=vtcapp.registercallback()
# nur zur Demonstration: der Aufruf sollte natürlich über einen OAuth Authentifizierungs Server gehen
vtcapp.executeurl("https://myserver.vertec-mobile.com/callback?State=%s&message=ASecretMessage" % state)
time.sleep(3.0) # kurz warten bis browser offen
values=vtcapp.querycallback(state)
print(values["message"])
rendertemplate(templateString, data): unicode string
As of version 6.3.0.9 there is a generic template engine in Python. It is based on the Jinja2 template engine (http://jinja.pocoo.org).

For ease of use in Vertec there is this method. It is also available in Restricted Scripting mode (cloud Cloud Suite) and returns a Unicode string.

The templateString argument can be a string or Unicode string and can contain Jinja2 specific markups.

To pass the data, the following options are available as further arguments to the feature:

  • Python Dictionary with string values as keys. Defines the variables available in the template.
  • Any quantity of keyword arguments that define the variables available in the template.
  • No further argument, the template will be processed without any data.
Alternatively, it is also possible to use the template engine directly by importing the jinja2 package. However, this application is not Cloud Suite compatible and is not recommended.

The main structures are as follows:

  • A block is enclosed with {% ... %}. It contains a control statement or a variable assignment.
    • {% if proj.code == "ABC" %} ... {% endif %}. An If statement in a block is used to conditionally output a range of the template. A if must be completed by a endif. Optionally, a {% else %} in between is allowed.
    • {% for proj in projects %} ... {% endfor %}. A for statement allows iteration of a template range. Must be completed by endfor.
  • An expression is separated with {{ ... }}. An expression is evaluated in the context of the template and merged into the output of the template as a string.
Full documentation of the possibilities in templates can be found at http://jinja.pocoo.org/docs/2.10/templates/.
# Beispiel Code für Ausgabe einer Projektliste

templateText = """
My own projects
===============
{% for proj in projects %}
Project: {{ proj.code }}, {{ proj.beschrieb }}
{% endfor %}
===============
"""

projects = vtcapp.evalocl("timSession->first.login.eigProjekte")
rendered_text = vtcapp.rendertemplate(templateText, projects = projects)

print rendered_text
requestfilefromclient(dialogTitle: string, directory: string, filter: string [, fileName: string]): (filename, file)

Before version 6.4.0.22:
requestfilefromclient(title: string, path: string, filter: string [, abspath: string]): (filepath, file)

Adjust the filter expression with Vertec version: The format can also contain several file types per filter. The changes are not backward compatiblebackward compatible with the new version the expression versions need to be adjusted.

Starting with version 6.3.0.4. The user can select a local file in the client application, which is then transferred to the server and is available as a binary stream for further processing by the Python method.
  • dialogTitle: Title of the dialog
  • directory: Path of the directory to open in the dialog. If the path does not exist, the desktop is shown.
  • filter: Filter expression to restrict the selection of files in the dialog. The filter expression changes with version 6.3.0.12, please see examples on the right.
  • fileName: Absolute path of the file to be uploaded. This parameter is optional. If it is specified, no dialog will be shown in versions prior to 6.5.0.11.
    As of Vertec 6.5.0.11 a dialog will appear informing the user that Vertec wants to read this file, which he can acknowledge with Yes or No. If No, the process will be aborted and an exception will be thrown.

The method returns a tuple consisting of file names and file contents (before version 6.4.0.22 the method returns a tuple consisting of absolute file path including file names and file contents).

The maximum size of the file to be uploaded is 50 MB.
There is a blacklist of directories from which files may not be requested, e.g. the Windows environment variable SYSTEMROOT (typically C:\Windows).

If the user clicks on Cancel in the dialog, the error message appears in Python: RuntimeError: The file upload was canceled by the user.

Web App

If a client-side path is specified (parameter abspath), an error message appears in the Web App.

The start directory (parameters path) is ignored.

In versions prior to 6.4.0.8 the file dialog cannot show a custom dialog title. The parameter title is not considered until version 6.4.0.8.

For the filter, the designation is not shown, it only says “All support types (...)” and then the suffixes individually.

vtcapp.requestfilefromclient("Hallo Welt", r"C:\MyDirectory", "Python|*.py|Text|*.txt|XML|*.xml")

  1. Wildcard must be specified (*.py instead of .py)
  2. Filter expression consists of filter pairs, where each filter pair requires a name and an expression.
  3. Pipes must be used as separators both between couples and within a couple between name and expression.
  4. In case of multiple file extensions, they must be separated by semicolons instead of commas:

    vtcapp.requestfilefromclient("Hallo Welt", r"C:\MyDirectory", "Office Documents|*.docx;*.xlsx|Text|*.txt|XML|*.xml")
    Open a dialog with the title “Hello World” in the directory C:\MyDirectory that allows you to upload Office, TXT or XML files.

A simple syntax is also supported:

vtcapp.requestfilefromclient("Hallo Welt", r"C:\MyDirectory", "*.txt")
Open a dialog with the title “Hello World” in the directory C:\MyDirectory, which allows the upload of TXT files.

vtcapp.requestfilefromclient("Hallo Welt", r"C:\MyDirectory", "*.txt;*.xml")
Open a dialog with the title “Hello World” in the directory C:\MyDirectory, which allows the upload of TXT or XML files.

vtcapp.requestfilefromclient("", "", "", r"C:\MyDirectory\MyFile.txt")
Upload the file.

vtcapp.requestfilefromclient("Hallo Welt", r"C:\Windows\System32", "*.dll")
Throw an error message because this directory cannot be accessed

vtcapp.requestfilefromclient("", "", "", r"C:\Windows\System32\cmd.exe")
Throw an error message because this directory cannot be accessed

Version before Vertec 6.3.0.12:

vtcapp.requestfilefromclient("Hallo Welt", r"C:\MyDirectory", "Python|.py,Text|.txt,XML|.xml")
Open a dialog with the title “Hello World” in the directory C:\MyDirectory, which allows the uploading of PY, TXT or XML files.

roundcurrency(amount, currency=None): float

Rounds the specified amount, taking into account the Project > Use Use rounding rules setting.

If a Currency is optionally entered, the value entered on it is also Runden auf taken into account.

Without currency indication:

amount = argobject.total
vtcapp.roundcurrency(amount)
5105.89

With currency indication:

amount = argobject.total
curr = argobject.waehrung
vtcapp.roundcurrency(amount, curr)
5105.9
search(term:string, [language:string, similarsearch:boolean, datetimefrom: date, datetimeto:date]): SearchResult

Performs a Full Text Search in the indexed objects.

  • term: The actual search term.
  • language: Optional. Here you can specify a country abbreviation for the search. The language is only taken into account if it is also indexed (see System Settings Full Text Search). If a different value or None passed, the search is performed in the default language.    
  • similarsearch: Optional. True or False. Here you can specify whether similar terms should be taken into account. Default is False.
  • datetimefrom, datetimeto: Optional. If from and/or to date is specified here, the results are filtered according to these dates.

Returns a Python object of type SearchResult. It contains the following properties:

  • objects: All business objects found with the search (as BoldObjectListAdapter).
  • totalhitsapprox: Quantity of results found.
  • items: List of SearchResultItems with the following properties:
    • object: The individual business object
    • score: Relevance value
    • fields: Location (in English)
    • date: date from index
    • fragments: List of text fragments.

A search returns a maximum of 500 business objects (SearchResultItems). These are sorted in descending order of relevance (score).

results = vtcapp.search("keller", "EN", False, datetimeto=vtcapp.currentdate())
for item in results.items:
    print item, item.fragments

With .objects you get a list of Vertec objects.    

results = vtcapp.search("consulting")
projects = results.objects.evalocl("self->select(oclIsTypeOf(Project))")

 

scriptexecute(scripttext, argobject=None)

Allows calling a Vertec script.

  • scripttext: The actual code is passed as scripttext. This can be the text of a script registered in Vertec or a code text itself.
  • argobject: This parameter allows you to specify the object on which the script should be executed. If this parameter is omitted, the script will be called on the current Vertec object.
proj = vtcapp.getobjectbyentryid("Projekt", "TemplateProject")
scripttext = vtcapp.evalocl("scripteintrag->select(bezeichnung='Projekt kopieren')->first.scripttext")
vtcapp.scriptexecute(scripttext, proj)
selectaddress()
selectphase()
selectproject()
selectobjectintree()

From version 6.4.0.21. Allow calling the different search and selection dialogs for addresses, projects, phases and the tree directly from Python.

The methods support the following optional keyword arguments:

  • selectaddress(string title, string classname, string filter)
    • title: Dialog title (Default: select Address)
    • classname: Address class in which to search, e.g. Firma. (Default: address)
    • filter: Additional SQL Filter condition (default: empty), e.g. only on active objects
    The address search dialog uses the default search definition according to system settings.
  • selectphase(string title, string filter)
    • title: Dialog title (Default: select phases)
    • filter: Additional SQL Filter condition (default: empty), e.g. only on active objects
  • selectproject(string title, string filter)
    • title: Dialog title (Default: select projects)
    • filter: Additional SQL Filter condition (default: empty), e.g. only on active objects
  • selectobjectintree(string title, list entrylist, string browsefilter, string selectfilter)
    • title: Dialog title (Default: select Object)
    • entrylist: List of Vertec objects, which are displayed in the dialog as root elements.
    • browsefilter: Comma-delimited Filter for object types (e.g. Ordner, Expressionordner)
    • selectfilter: The selectfilter determines on which entries (classes and their subclasses) you can confirm the dialog and thus “selected,” also comma-delimited.

Return value is the selected object.

adresse= vtcapp.selectaddress(title="Adressauswahl", classname="Kontakt", filter="vorname like '%S%'")

projekt = vtcapp.selectproject(title="Projektauswahl", filter="code like '%S%'")

phase= vtcapp.selectphase(title="Phasenauswahl", filter="code like '%S%'")

Kontakte = argobject.subordner
Kontaktordner = list(Kontakte)
Kontaktordner.append(argobject)
selected=vtcapp.selectobjectintree("Objekt wählen",Kontaktordner, "Ordner, Kontakt", selectfilter="Kontakt")
selectfromlist (caption: string, text: string, col1caption: string, col2caption: string, default: string, list: list of tuple): string
Creates a selection dialog according to the specifications.
  • caption: Title of the form
  • text: Introductory text
  • col1caption: Column title 1
  • col2caption: Column title 2
  • default: Default return value or pre-selected row *)
  • list: List of values to be shown for selection
The feature returns a string with the selected value. Only one value can be selected from the list.

*) To pre-select a row, the tuples of the list rows must consist of 3 elements. The third element is then the return value when the row is selected (this third column is invisible).

Only in this case does the default parameter have an effect: it then preselects the row whose third column corresponds to the specified default.
$








vtc__000__999_77 îîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîî
sendfile(file: string, filename: string, [showsavedialog: boolean], [openfile: boolean]): boolean

As of version 6.2. Send a file or a string (as a file) to a client.

The method also works in Restrict Scripting mode.

  • file: Here you can pass a string as file content or a Python file object.
  • filename: Name of the file, if saved.
  • showsavedialog: Optional. Default = False. Desktop and Cloud App The transferred file should be saved on the client saved or executed immediately depending on the client’s requirements and capabilities.
    A showsavedialog argument causes a save dialog to show displayed. By default, the desktop is shown as the locationshow
    If showsavedialog=false, the file is saved in the temp folder of the client’s having overwritten an existing file. This makes sense in connection with openfile=true, then the file is saved in Temp and opened immediately.
As of Vertec 6.5.0.11 the suppression of a dialog is only possible for the following file types (extensions). Whitelist:

.doc, .docx, .xls, .xlsx, .pdf, .csv, .txt, .zip, .png, .jpg, .jpeg, .bmp, .gif, .eml and from Vertec 6.5.0.15 .ics.
For all file types that are not on this whitelist, an error message appears.

  • openfile: Optional. Desktop and Cloud App. If true, the file will be opened after saving. Default is true.

The combination showsavedialog=false and openfile=false does not make sense, as this saves the file in the temp directory and nothing else happens.

With the Web App as client, the file always appears as a download in the web browser. The arguments showsavedialog and openfile are irrelevant.

As of version 6.3.0.8 the method has a return value and returns True or False:

  • True, if the file was saved,
  • False if the file was not saved,
  • The Web App always returns True because it cannot check if the file has been saved. When using the Web Web App we recommend that you turn on automatic download in your browser.

Example of a simple project export:

projekte = argobject.evalocl("eintraege.list")
projektstr = ""
for projekt in projekte:
    projektstr += projekt.code + "\r\n"
vtcapp.sendfile(projektstr, 'projekte.txt', True, True)

Example of how to send a locally available image:

filename = r"C:\Arbeitsverzeichnis\python_editor.png"
# opening for [r]eading as [b]inary
with open(filename, 'rb') as afile:
    vtcapp.sendfile(afile, 'aFilenameHere.jpg', True, True)

Files should be explicitly closed after use. Otherwise, they will only be closed by the garbage collector or, in case of failure, on the next exception. It is recommended to use open with with as in the example above.

sendmail(to, subject, body, [cc, bcc, fromSender, attachments])

Allows sending emails from Vertec with the requirements described in System Settings Email. This method can be used with all apps.

  • to: String. Recipient addresses.
    • Using a semicolon ; several addresses can also be specified, without a distance between the addresses and the semicolon.
  • subject: String. Subject of the email.
  • body:
    • String: The actual email text. Can be HTML or plaintext. HTML is recognized as such and then created in the form of an Outlook HTML mail.
    • Starting with version 6.5.0.21, a Word document can also be used (see example below).

Optional:

  • fromSender: String. if null or empty, the sender is removed from the system settings. User rights etc. are not checked, it must be ensured that the user is authorized to send emails under this sender, otherwise it will not work on the client side.
  • cc: String. If populated as CC recipient.
  • bcc: String. If filled as BCC receiver.
  • attachment: [(file name, content)]: If filled in, the attachment will be attached to the email.

Examples:

  • Simplest case, body as string:    
vtcapp.sendmail("dokumentation@vertec.com", "Dokumentation", "Dies ist der einfachste Fall")
  • Use Word documents as a body:
    Note: Use tables in your Word documents and avoid tab stops, as they cannot be processed in the email.

1. The corresponding Word document must be created and read:

in_file = open("C:\<yourPath>\BeispielWordFürEmail.docx", "rb")
dataFileData = in_file.read()

2. Use the method to generate the email:    

vtcapp.sendmail('dokumentation@vertec.com', 'Test E-Mail from Word', dataFileData)
setpropertyvalue(name, value)

Sets a system setting. The corresponding name is specified for each system setting.

vtcapp.setpropertyvalue('Sperrdatum', vtcapp.incmonth(vtcapp.currentdate(), -1))
setresourceplanvalue
(user, project, phase, date, intervalType, value)

Only Vertec versions before 6.6. From Vertec version 6.6 onward, use the setresourceplanvalue Methods on Users, Projects or Phases.

Sets a resource plan value.

  • intervalType: 0 = day, 1 = week, 2 = month
  • value: Value in minutes.
  • date: The period is filled with the value in which the date is. It is best to take the date at the beginning of the period, then there are no ambiguities.
bearbeiter = vtcapp.currentlogin()
projekt = argobject

vtcapp.setresourceplanvalue(bearbeiter, projekt, None, vtcapp.firstdayofmonth(vtcapp.currentdate()), 0, 240)
showcustomdialog(dialog definition, initial values)

Dialog function with which dialogs can be defined in Python scripts and shown by the script. Available from version 6.1.

a detailed description can be found in the article about the Python dialogs.
showdetailform(obj: object)
Displays the detail view of the object in a new tab.
leistung = vtcapp.createobject("Offeneleistung")
vtcapp.showdetailform(leistung)
standardprocessbi()

Method for calculating Bi data for the Business Intelligence module.

Corresponds to the execution of the planned task supplied by default and triggers the calculation of all generators on all active measures.

Requires administrator rights.

To calculate individual generators, see the method vtcapp.processbi() above.

vtcapp.standardprocessbi()
strtominutes(string): integer
Translates a string to a minute value (integer), taking into account the current set system setting setting.

Display minutes is hours:minutes:

print vtcapp.strtominutes('1:30')
>>> 90
print vtcapp.strtominutes('1.50')
>>> 110

Display minutes is hours.Decimal:

print vtcapp.strtominutes('1.50')
>>> 90
sqldateliteral(date: date): string
This method returns the correct date format for SQL queries, depending on the database server used, which is then converted into a    getwithsql statement can be built in.
aktivitaeten = vtcapp.getwithsql('Aktivitaet', 'datum = %s' % vtcapp.sqldateliteral(vtcapp.currentdate()), '')
for akt in aktivitaeten:
    print akt

>>>
Support, 30.05.2017, Support Frau Müller
Verkauf, 30.05.2017, Rechnung mit Leistungsliste (Word)
Verkauf, 30.05.2017, Rechnung mit Leistungsliste (Word)
Verkauf, 30.05.2017, Offerte (Word)
Verkauf, 30.05.2017, Offerte (Word)
Marketing, 30.05.2017, Informationen bezüglich KZU
>>>
sqlwhere(where: string): string
Creates a SQL WHERE clause matching the current used database server, which is then placed in a    getwithsql Statement can be incorporated.
whereclause = vtcapp.sqlwhere("standardadresse like 'Dachsweg%'")
leistungen = vtcapp.sqlwherebetweendate('datum', vtcapp.firstdayofmonth(heute), heute)
print leistungen, whereclause

adressen = vtcapp.getwithsql("Adresseintrag", whereclause, "bold_id")
for adresse in adressen:
    print adresse

>>>
upper(standardadresse) starting with 'DACHSWEG'
Comtelsat AG
Comtelsat AG, Lanz André
Comtelsat AG, Huber Thomas
>>> 
query:string, from: date, to: date): string

Creates a SQL between clause with a date interval corresponding to the database server current in use, which is then getwithsql Statement can be incorporated.

heute = vtcapp.currentdate()
whereclause = vtcapp.sqlwherebetweendate('datum', vtcapp.firstdayofmonth(heute), heute)
print whereclause

leistungen = vtcapp.getwithsql("Leistung", whereclause, "datum")
for leistung in leistungen:
    print leistung

>>>
datum between '01.05.2017' and '30.05.2017'
COMINSTALL, 09.05.2017, BER Besprechung mit Hr. Müller
COMINSTALL, 16.05.2017, TM Telefon mit Hr. Müller
>>> 
syncpayments()

Starting with version 6.4.0.22. Perform a global payment import.

If no customer interface with payment import is installed, the method reports an error.

vtcapp.syncpayments()

For example, the method can be registered as a planned task.

SystemContext()

As of version 6.6.

Activates Extended user rights within the script.

  • Must be with the with-Statement can be called.
  • Not allowed in the Python editor for security reasons.
with vtcapp.SystemContext():
    ...Code der vom Systemcontext profitiert.
translate(txt: string[, language:string]): string

Translates a GUI text into the current Vertec language.

As of version 6.5.0.20, an optional parameter for the target language of the translation can be used.

The current Vertec language is English:

>>> vtcapp.translate("Leistung")
Service

From version 6.5.0.20:

>>> vtcapp.translate('Offer', 'DD')
Angebot
updatedatabase()
Saves changes to the database.
vtcapp.updatedatabase()
validateobjects()

Validates rebuild objects. If they do not violate any rules, they are no longer invalid afterwards.

vtcapp.validateobjects()
versiontointeger(versionstring): int
Converts a Vertec version string to a number suitable for comparing different versions.
Bsp: "5.5.0.67" wird in 550067 umgesetzt, 
"5.5" in 550000, 
"5" in 500000

Date Functions

The following date functions are available. They are all located in the vtcapp module.

feature Explanation Example From version
currentdate(): date
Returns the current date.
>>> vtcapp.currentdate()
2017-01-23
6.1.0.10
currentdatetime(): datetime
Returns the current date and time.
>>> vtcapp.currentdatetime()
2017-01-23 15:01:12.880000
6.1.0.10
datetostr(date): string
Converts a date to a string and returns it according to the country settings.

For example, in Australian English:

>>> print vtcapp.strtodate('13/06/17')
2017-06-13
>>> print vtcapp.datetostr(datum)
13/06/2017
6.1.0.14
datetostrgerman(date): string
Converts a date to a string and returns it in German date format.

It sometimes needs German date values in some locations in scripts, regardless of current region settings (see e.g. from/to arguments in groupperformance operators).
>>> vtcapp.datetostrgerman(argobject.evalocl('creationdatetime'))
13.10.2016
6.2
firstdayofmonth(date): date
Returns the date of the first day of the same month
>>> vtcapp.firstdayofmonth(vtcapp.currentdate())
2018-03-01
5.7
firstdayofyear(date): date
Returns the date of the first day of the same year
>>> vtcapp.firstdayofyear(vtcapp.currentdate())
2018-01-01
5.7
formatminutes(integer): string
Returns hour-minute display as settings in Vertec
>>> vtcapp.formatminutes(argobject.minutenext)
1:00
5.7
incday(date, integer): date
Increments the day (+ or -) and returns the new date
>>> vtcapp.incday(vtcapp.currentdate(), 1)
2018-03-17
5.7
incminute(datetime, integer): datetime
Increments minutes (+ or -) and returns a new date.

The date that is passed must be in datetime format, i.e. have a time fraction.

Adds 4 hours to the current time:
>>> vtcapp.incminute(vtcapp.currentdatetime(), 240)
2018-03-16 18:43:44.958000

5.7

incmonth(date, integer): date

Increments month (+ or -) and returns the new date

Note: If the date is at the end of the month and the respective months have a different quantity of days, the last day of the month is used.

Example: incmonth(-1) executed on 31.03.2021 results in 28.02.2021.

>>> vtcapp.incmonth(vtcapp.currentdate(), -1)
2018-02-16 
5.7
incyear(date, integer): date
Increments the year (+ or -) and returns the new date
>>> vtcapp.incyear(vtcapp.currentdate(), -1)
2017-03-16
5.7
lastdayofmonth(date): date
Returns the date of the last day of the same month
>>> vtcapp.lastdayofmonth(vtcapp.currentdate())
2018-03-31
5.7
lastdayofyear(date): date
Returns the date of the last day in the same year
>>> vtcapp.lastdayofyear(vtcapp.currentdate())
2018-12-31
5.7
ocldate(date): string
Returns OCL encodedate string based on a date value
>>> import datetime
>>> vtcapp.ocldate(datetime.date(2018,01,31))
encodedate(2018,1,31)
5.7
strtodate(string): datetime
Interprets a date string according to Windows locale settings (see notes on using strtodate below).
print vtcapp.strtodate('1.10.17')
>>> 2017-10-01 00:00:00
5.7
thismonday(date): date
Returns the date of Monday in the same week
>>> vtcapp.thismonday(vtcapp.currentdate())
2018-03-12
5.7

Note on the use of strtodate

The use of strtodate is tricky because the string is interpreted according to the Windows locale. For example, the expression vtcapp.strtodate('31.01.2017') returns an error if it is not a German locale.

The Python date function datetime.date(year, month, day) should always be used in the code (see the example above). However, if you want to query the user for a specific date via an input box, you can do this by presenting the user with a suggested date in the correct format, which the user can modify accordingly.

For this, the date is formatted according to local country settings (vtcapp.datetostr..):

# Frage den Benutzer nach dem Datum. Das Datum wird gemäss Windows-locale dargestellt.
res = vtcapp.inputbox('Vertec', 'Datum für die Berechnung', vtcapp.datetostr(vtcapp.currentdate()))
print vtcapp.strtodate(res)

The datetostr() method was introduced in Vertec version 6.1.0.14. In earlier Vertec versions, the date can be formatted with strftime according to local country settings:

import datetime

# Frage den Benutzer nach dem Datum. Datum gemäss Windows-locale dargestellt.
res = vtcapp.inputbox('Vertec', 'Datum für die Berechnung', datetime.date.today().strftime('%x'))
print vtcapp.strtodate(res).date()

Availability of executereport() with different systems

executereport(rootObj, optarg, reportObj, [saveAs, showDialog, doPrint, showApp])
Reporting system ReportObj saveAs showDialog doPrint showApp Desktop Cloud Web
Office-generated legacy reports (Word, Excel) Report object in Vertec

 

or

Path to the Office template on the file system.

  • None uses path from reportObj. If no path is specified, the document is not saved.
  • Path, also with OCL variables
  • File name (uses rootObj doc DocPath)

If an empty string is specified or the argument is omitted, no file is saved.

True or False

Default=False

True or False

Default=False

No longer considered in versions 6.6.0.8 or later.

True or False

 

In versions before 6.6.0.8 disregarded if doPrint = True. In this case, the report is always shown.

disregarded if report is not saved. In this case, the report is always shown.

x x  
Vertec-generated legacy word reports Report object in Vertec Dito Dito Not included Not included x x x
Office reports (Word, Excel, PDF) Report object in Vertec Dito Dito Not included True or False

 

Disregarded if report is not saved. In this case, the report is always shown.

x x x
executereport2(rootObj, optarg, reportObj, [saveAs, showDialog, doPrint, showApp])
Reporting system ReportObj saveAs showDialog doPrint showApp Desktop Cloud Web
Office-generated legacy reports (Word, Excel)

Report object in Vertec

No paths.

  • None uses path from reportObj. If no path is specified, the document is not saved.
  • Path, also with OCL variables
  • File name (uses rootObj doc DocPath)

If an empty string is specified or the argument is omitted, no file is saved.

If no file is saved, no activity is created.

True or False

 

Default=False

True or False

Default=False

No longer considered in versions 6.6.0.8 or later.

True or False

 

In versions before 6.6.0.8 disregarded if doPrint = True. In this case, the report is always shown.

disregarded if report is not saved. In this case, the report is always shown.

x x  
Vertec-generated legacy word reports Report object in Vertec Dito Dito Not included Not included x x x
Office reports (Word, Excel, PDF) Report object in Vertec Dito Dito Not included True or False

 

Disregarded if report is not saved. In this case, the report is always shown.

x x x

italics: optional parameter

The module “vtcextensions”

There is a Vertec module called vtcextensions for handling extensions.

It is also available in Restricted Scripting mode starting with version 6.3 and includes the following methods:

Method / feature description Example code
GetExtension(art:string) or
getextension(art:string): extension
Returns a reference to the extension of the specified type.
import vtcextensions

# Aufruf der DEBI-Extension
ext = vtcextensions.getextension("DEBI")
CreateVtcExtensionHost(extension:string): host

With this method, the host used for the extensions (example: __init__(self, host)) can be simulated in the code for testing purposes.

When using the extensions via Vertec, this happens automatically.

import vtcextensions
host = vtcextensions.CreateVtcExtensionHost('FibuAbacus.AbacusDebiExtension')
ext = FibuAbacus.AbacusDebiExtension(host)

Example using an extension

# Buchungen
# Wir fragen den Benutzer, ob er in die Buchhaltung buchen will. Vielleicht will er auch einfach nur die Buchungen anschauen.
if vtcapp.msgbox("Die Buchungen wurden erstellt und als .txt Datei am üblichen Ort dokumentiert. Möchten Sie die Buchungen jetzt übertragen?",3, "Vertec") == 6:
   # Buchungen werden übertragen.
   ext = vtcextensions.getextension("DEBI")
   ext.StartLohnBuchung()
   for rec in reclist:
       ext.LohnBuchungsZeile(rec.Mandant, rec.Personalnummer, rec.Lohnartnummer, rec.Text, rec.GueltigVon, rec.GueltigBis, rec.Anzahl)
       # Buchungen werden hier abgesetzt. Vor der Buchung wird überprüft,
       # ob diese Zeile bereits vorhanden ist, wenn ja, überspringen.
   ext.EndLohnBuchung()

The module “ziputils”

As of version 6.3.0.2 there is a Vertec module called ziputils, which allows you to compress files by generating ZIP files in Python.

It is also available in Resctict Scripting mode and includes the following methods:

Method / feature description Sample code
createzip(contentlist: tuples): bytestream As of version 6.3.0.2. Compress a list of tuples (filename,content) into a ZIP file and return it as a bytestream. This can easily be saved/downloaded with Filename.zip.
import ziputils

zip = ziputils.createzip([('file.txt', 'Hallo das ist ein Text')])
vtcapp.sendfile(zip, 'ziptest.zip', True)

Starting with version 6.5.0.14 the following 3 features are available:

  • readnames(zipcontent) returns a list of the file names contained in the ZIP file. If the ZIP file has a folder structure, the names contain the paths separated by slashes (/).
  • readbyname(zipcontent, name) reads a file from the ZIP file based on its name.
  • readbyidx(zipcontent, idx) reads a file based on its index in the name list.

The module “vtcplanningcore”

As of version 6.6, the Python module vtcplanningcore is available for Resource Planning with the following methods:

Method / feature description
increment_interval_date(date, increment): date Feature for incrementing and decrementing period start data. Increment the specified date by the increment specified quantity of intervals. A negative quantity of intervals can be specified for decrementing.
get_planning_level(): string Returns the planning layer as a string.
Possible results: 'Projekt' or 'ProjektPhase'.
get_planning_interval_type(): string Returns the planning interval as a string.
Possible results: 'day', 'week' or 'month'.
show_bulk_planning_dialog(left_obj, right_obj)

Displays a dialog for efficiently setting multiple planning values for the specified objects.

The order in which the objects are provided does not play Role, but the caller must ensure that one of them is an object of type AbstractWorker is, so either a project user or a Planning Officer, and the other either a Projekt or a Projektphase, depending on the Planning Level set.

The ResourcePlanningProvider helper object

For the implementation of the Resource Planning lists, this module also includes a ResourcePlanningProvider Class available which allows reading and setting of plan data and which can be used in a List Controller.

A ResourcePlanningProvider Object is created for a list of entries (users, projects or phases) and a time period. The provider then loads all planning data for these source objects and for the specified period. Subsequently, the planned values can be retrieved or set.

A budgeted value in ResourcePlanningProvider always applies to 2 entries and a date, e.g. for the user “Christoph Keller,” the project “AZZ2” and the month starting with 01.08.2022.

The one entry (the source entry, sourceEntry) must come from the list of entries specified at the time of initialization. The other entry is called “opposite” (othersideEntry).

The following methods are available on a ResourcePlanningProvider object:

ResourcePlanningProvider(sourceEntries, start, end) Constructor, creates a planning provider and loads the planning data for the specified objects and period.
add_entry(obj) Adds a new object to the provider’s sourceEntries list.
add_otherside_entry(obj) Adds a new object temporarily to the list of otherside entries. This allows this object to be set_planned_minutes() Budgeted values can be entered.
get_planned_minutes(date, sourceEntry, othersideEntry, subscriber): int Returns the planned time in minutes for the planning cell with interval date date and the two entries indicated. If no plan data is available, None returned.
set_planned_minutes(date, sourceEntry, othersideEntry, value) Sets the planned time in minutes for the planning cell with interval date date and the specified entries.
Setting a None Value as value removes the plan data for this cell.
has_write_access(sourceEntry, othersideEntry, subscriber): boolean Checks whether the two objects and the date interval have write permissions.
get_planned_minutes_aggregated (source_entry, otherside_entry, dateFrom, dateTo=None, subscriber=None): int Returns the aggregated scheduled time for the two specified records in the specified period.
  • Both source_entry and otherside_entry can None be; in this case, all entries known to the current Resourceplanningprovider are taken into account.
  • dateFrom is required, dateTo is optional. If no dateTo is specified, only the interval that matches dateFrom is considered.
Gives None return if no budgeted values with the specified criteria are found.
get_net_capacity_minutes(self, worker, dateFrom, dateTo=None, subscriber=None): int Net capacity in minutes per user.
  • worker: AbstractWorker, PlanningWorker or user
  • dateFrom: start date
  • dateTo: Optional, end date. If None, the end date of the interval of the dateFrom is used.
For example, on a project, the users who are already overloaded can be highlighted in color in the list.
get_custom_net_capacity_minutes(self, worker, dateFrom, dateTo=None, subscriber=None): int

As of Vertec 6.7.0.5. Net Capacity in minutes per user based on the system setting Adjusted Net Capacity (Percentage).

Gives None if the system setting is empty or contains an invalid value.

get_gross_capacity_minutes(self, worker, dateFrom, dateTo=None, subscriber=None): int Gross capacity in minutes per user.
  • worker: AbstractWorker, PlanningWorker or user
  • dateFrom: start date
  • dateTo: Optional, end date. If None, the end date of the interval of the dateFrom is used.
For example, on a project, the users who are already overloaded can be highlighted in color in the list.
get_remaining_capacity_minutes(worker, dateFrom, dateTo=None, subscriber=None): int Remaining free capacity in minutes for a given user and a given date range (net_capacity – planned_minutes).
  • worker: AbstractWorker, PlanningWorker or project user (see 2.4)
  • dateFrom: start date
  • dateTo: Optional, end date. If None, the end date of the interval of the dateFrom is used.
get_custom_remaining_capacity_minutes(self,worker, dateFrom, dateTo=None, subscriber=None): int

As of Vertec 6.7.0.5. Remain free capacity in minutes for a specific user and a specific date range, taking into account the system setting Adjusted Net Capacity (Percentage).

Gives None if the system setting is empty or contains an invalid value.

get_otherside_entries(subscriber): list of entries Returns the list of entries for which plan data already exists, based on the sourceEntries objects specified in the constructor.
generate_date_range(start, end) Returns a list of date values for scheduling intervals of start to end. Depend on the system-wide setting of the planning interval (months, weeks, days).
get_start_preceding_interval(): date Returns the date of the interval preceding the start interval.
get_column_title_by_date(date): string Returns the appropriate column title if the date value for a specific planning interval is specified.

ResourcePlanningProviders are commonly used in list controllers and custom renderers for planning lists. The list controller instantiates a planning provider, which is then used to show and set the values in plan cells.    

vtcplanningcore as Stub File

The vtcplanningcore module is also available as a Python Stub File. It says vtcplanningcore.py and is stored like the other Stub Files in the PythonStubs subfolder in the Vertec installation directory.

The module “vtcplanning”

From version 6.6. there is the Python module vtcplanning, which provides standard implementations of list controllers for Resource Planning. List Controllers

These all have one initialize_with_period(start, end, interval) Method which is called by the Vertec core and specifies the planning period and the planning interval to be displayed.

To ensure that a planning list that starts on a new interval (e.g. current month) is not completely empty, the list controllers also load planning data for an interval before the specified start date.

This means that if August – October is specified as the planning period (planning interval “month”) then row objects are also displayed which have planning data in July, but not in August-October.

Timetables

The Timetables are based on a single object and show one row for each planned opposite object. The columns correspond to the scheduled time intervals.

Time tables can also be shown as read-only sum tables based on a list.

We provide the following list controller classes in the Python module vtcplanning:

list controller description
vtcplanning.SingleObjectTimeTableController

Used to plan on individual objects (check Für einzelne Objekte anzeigen? is set).

The controller can handle the different classes (project, project phase, AbstractWorker, project user or PlanningWorker), the same controller can always be specified.

vtcplanning.ReadonlySingleObjectTimeTableController Based on a single object, but read-only, not for scheduling. Used for timesheets on single objects that cannot be scheduled.
vtcplanning.ReadonlyProjectsSingleObjectTimeTableController For read-only project timesheets on individual objects. Use to show project totals if the planning level is phases.
vtcplanning.ReadonlyPhasesSingleObjectTimeTableController For read-only phase time tables on individual objects. Use to show phase totals if the planning type is Processor Phase Assignment.
vtcplanning.ReadonlyContainerTimeTableController For read-only timesheets on lists (check Für Listen anzeigen? is set).
Used for Total Timesheets.
vtcplanning.ReadonlyOtherSideContainerTimeTableController For read-only timesheets on lists (check Für Listen anzeigen? is set).
Use for Total Timesheets to show the totals of the opposite side on a list of objects (e.g. editor totals on a project list).
vtcplanning.ReadonlyPhasesContainerTimeTableController For read-only timesheets on lists (check Für Listen anzeigen? is set) to show sums of phases on a list of projects or users if the planning level is project (in this case, the normal list controllers on projects would not be shown).

Pivot tables

Starting from a list of entries (AbstractWorker, project or phases), a Resource Planning Pivot Table can be displayed. The pivot table shows the entries as columns and the planned opposing entries as rows. This makes it possible to enter planning data for new opposing entries via star-row.

The following list controller classes are available to implement pivot table views:

list controller description
vtcplanning.RegularPivotTableController

For pivot tables with the entries in the list as rows and the opposite side as columns. Use to plan on a list (check Für Listen anzeigen? is set).

The controller can handle the different classes (project, project phase, AbstractWorker, project user or PlanningWorker), the same controller can always be specified.

vtcplanning.MirroredPivotTableController

For pivot tables with the entries in the list as columns and the opposite side as rows. Use to plan on a list (check Für Listen anzeigen? is set).

a star line can be shown in this list to add new objects to be planned. More detailed information can be found here.

The controller can handle the different classes (project, project phase, AbstractWorker, project user or PlanningWorker), the same controller can always be specified.

vtcplanning.ReadonlyRegularPivotTableController Used to show project user PivotTables when the planning level Phasen is, with the entries of the list as rows and the opposite side as columns.
vtcplanning.ReadonlyMirroredPivotTableController Used to show project user pivot tables when the planning level Phasen is, with the entries of the list as columns and the opposite side as rows.
vtcplanning.RegularSingleObjectPivotTableController Used to also plan on a single project in pivot tables. Display a pivot table with the single entry as a row and the opposite side as columns.
vtcplanning.MirroredSingleObjectPivotTableController Used to also plan on a single project in pivot tables. Show a pivot table with the single entry as a column and the opposite side as rows.

Available renderers

To match this, the following Custom Renderer are available for use in the resource planning tables. All of these renderers can be used in the list settings in two ways:

Dynamic
  • Expression: %col%
  • Checkbox : Ja

Displays the value in the cell that matches the row/column combination.

Static
  • Expression: empty
  • Checkbox Dynamic: Nein

Displays the summed value across all columns per row.

Custom renderer description
vtcplanning.PlannedMinutesRenderer

Renderer for the planning times. Allows you to enter the planned values in the individual cells.

vtcplanning.NetCapacityRenderer

Renderer to show the net availability of users.

vtcplanning.CustomNetCapacityRenderer

As of Vertec 6.7.0.5. Show the net availability of users taking into account the system setting setting.

vtcplanning.GrossCapacityRenderer

Renderer to show the gross availability of users.

vtcplanning.RemainingCapacityRenderer

Renderer to show the remaining availability of users.

vtcplanning.CustomRemainingCapacityRenderer

As of Vertec 6.7.0.5. Show the remaining availability of users taking into account the system setting Adjusted Net Capacity (Percentage).

vtcplanning as Stub File

The vtcplanning module is also available as a Python Stub File. It says vtcplanning.py and is stored like the other Stub Files in the PythonStubs subfolder in the Vertec installation directory.

The module “vtccom”

As of Vertec 6.7.0.7 there is the Python module vtccom, which implements the possibilities of COM forwarding.

This includes the feature vtccom.createobject(identifier), which provides a forwarding proxy for the COM server on the client.

For more information, see the article on Com forwarding.

The module “vtcauth”

From version 6.8 there is the Python module vtcauth to be able to use OAuth authentication in arbitrary extensions and Python scripts in Vertec.

This contains a decorator authenticate to which a config dictionary is passed as argument. The parameters that can be passed in the config dictionary are the following in vtcauth existing instance variables:

prefix
a prefix can be used to automatically read and save the following values from Vertec Property:
  • AccessToken
  • RefreshToken
  • ApplicationID
  • ApplicationSecret

The properties, including prefix, must be named exactly as follows: {prefix}Name. For the prefix “Outlook” OutlookAccessToken, OutlookRefreshToken etc.

If a prefix is specified in the config, these values are automatically read from or saved in the Vertec properties.

If no prefix is specified, these configurations must be specified individually in the config.

logging

Default value is False, but can be overridden with True in the given config. Returns authentication information as output to the Python console.

client_id

Corresponds to the Application ID. Must be specified only if not covered via prefix.

client_secret

Corresponds to the Application Secret. Only to be specified if not covered via prefix.

individual_login

Default value is True. Can be overridden with False if you want to log in as an application.

scope

Defines the amount of access the application requires to a user’s resources. Standard (MS Graph):

"https://graph.microsoft.com/.default offline_access"

Requires only if OAuth is to be used for another endpoint.

response_mode

Default value is query.

redirect_uri

Corresponds to the Vertec callback address and cannot be overridden with the config.

tenant_id

Required when using MS Graph and must be specified with the config accordingly.

auth_base_url

Authorization endpoint. Standard (MS Graph):

"https://login.microsoftonline.com/{tenant_id}/oauth2/v2.0/authorize"

Requires only if OAuth is to be used for another endpoint.

token_endpoint

Endpoint for the tokens. Designed for MS Graph by default:

"https://login.microsoftonline.com/{tenant_id}/oauth2/v2.0/token"

Requires only if OAuth is to be used for another endpoint.

access_token

AccessToken. Must be specified only if not covered via prefix.

refresh_token

RefreshToken. Only to be specified if not covered via prefix.

The minimum call (for MS Graph) in a script looks like this:

from vtcauth import authenticate
# config example using vertec properties with prefix
config_prefix = {
    "tenant_id":"xxxxxxxxxxxxxxxxxxx.onmicrosoft.com",
    "prefix":"DmsSharePoint",
    "logging":True,}
# using decorator from vtcauth with config_prefix dict
@authenticate(config_prefix)

The entire OAuth authentication takes place via the decorator @authenticate(config_prefix) instead.

If the user is not already logged in to the targeted application, he has one minute to authenticate. If he does not log in to the open login dialog of the targeted product within one minute, there is a timeout.

If the token is expired or invalid, a TokenExpiredException This triggers the OAuth mechanism to fetch new tokens. If a RefreshToken is present and valid, the AccessToken is fetched with the RefreshToken. The exception can be executed a maximum of three times in the same call (by default), after which an error is thrown.

Example

In this example, the first 10 sites of a SharePoint are displayed (MS Graph with OAuth authentication):

import requests
from vtcauth import authenticate, TokenExpiredException

# config example using vertec properties with prefix
config_prefix = {
    "tenant_id":"xxxxxxxxxxxxxxxxxxx.onmicrosoft.com",
    "prefix":"DmsSharePoint",
    "logging":True,}

class SharePointSiteQuery:
    # using decorator from vtcauth with config_prefix dict
    @authenticate(config_prefix)
    def get_sites_with_prefix_config(self):
        return self.get_sites()

    def get_sites(self):
        headers = {
            "Authorization": "Bearer {}".format(self.access_token),
            "Content-Type": "application/json",}
        response = requests.get("https://graph.microsoft.com/v1.0/sites?search=*&$top=10", headers=headers)
        if response.ok:
            content = response.json()
        elif: response.status_code == requests.codes.unauthorized:
            raise TokenExpiredException
        else:
            print(response.json().get("error").get("code") + ' - ' + response.json().get("error").get("message"))

query = SharePointSiteQuery()
query.get_sites_with_prefix_config()

The Vertec SharePoint Extension now also uses the module vtcauth internally. This does not change the operation of the extension.

Stub File

The module vtcauth is also supplied as a Stub File.

The single vertec data object

For individual objects, the following methods are available:

Method/Feature description Sample code
addtag(tagname)

As of version 6.1.0.10. Set a tag on the object. For more information, see the article Tag on user records.

argobject.addtag('mytag')
checkright(right: string, membername: string): boolean

Checks whether the logged-in user has the specified right on the specified member name.

Possible rights are: 'read’, 'write’, 'create’, 'delete’, 'execute

Return value: 1 = True, 0 = False

obj = argobject
if obj.checkright('read', 'offeneleistung'):
  ...
delete()

Deletes the object in Vertec

obj.delete()
evalocl(OCL:string)

Evaluates an OCL expression on the object.

Before 6.1.0.10 this was called eval() on the individual object. Then the method was aligned to the global method so that it has the same name everywhere. In 6.1.0.10 and later you should always use evalocl().

projektcode = argobject.evalocl("code")
getattr(object, name[, default])

Returns the value of a member.

getattr(obj, “first name”)

is equivalent to obj.vorname. Sometimes you need getattr because you get a member as a parameter in a method, for example, and then query it like this.

If there is no member of this name on the object, the method returns the default if one is specified. Otherwise, there is an AttributeError.

getattr(obj, "vorname", "")
projekt = argobject
if hasattr(projekt, "offeneleistungen"):
    liste = getattr(projekt, "offeneleistungen")
    for leistung in liste:
        print leistung.text
getkeystring(key): string
getkeybool(key): boolean
getkeycurr(key): currency
getkeyint(key): integer
getkeydate(key): datetime

As of version 6.1.0.10. These methods are used to access the values stored as key values.

Details can be found in the article Key values on user entries.

>>> argobject.getkeydate('datum')
2017-02-03 00:00:00
getmemfootprint(): integer

As of version 5.8. Return the quantity of bytes that the object occupies in memory (Memory Footprint).

The value is determined as follows:

Instance of the object

+ Sum of instances of all members

+ Size of the value of each member (for strings the length)

+ MemFootPrint of all owned linked objects (e.g. phases of the project).

It should be noted that this is an approximation, since the boundary of what must be counted for an object cannot be drawn exactly.

The following script displays the memory requirements of all projects in the system:

r = vtcapp.evalocl("projekt")
for projekt in r:
    print projekt.code+' '+str(projekt.getmemfootprint())
getmlvalue(membername:string, language:string): value

The so-called multilanguage attributes (MLStrings) can be queried via this method.

  • Member name: Member name
  • Language is the respective language code (DE, FR, IT, EN).

Multilanguage attributes are:

  • Servicetype.Text
  • Expense type.Text
  • Outlay type.Text
  • Custom field class.Designation (designation of custom field items)
  • GridColDef.Title (column title in list settings)

To set such an attribute, the method setmlvalue() can be used.

taetigkeit = argobject
print taetigkeit.getmlvalue("text", "FR")
>>>
Vacances
>>>

If the member is queried normally, the return value always corresponds to the current Vertec language:

print taetigkeit.text
>>>
Ferien/Urlaub
>>>
hasattr(object, name): boolean

Checks whether an object has a corresponding member.

obj = adresse
if hasattr(obj, "vorname"):
    print obj.vorname
hastag(tagname): boolean

As of version 6.1.0.10. Check whether an object has set a corresponding tag.

For more information, see the article Tags on user entries.

obj = argobject
if obj.hastag('mytag'):
  ...
istypeof(Classname:string)

or

IsTypeOf(Classname:string): boolean

Checks whether the object is of type Classname.

True or False.

obj = argobject # das aktuelle Objekt ist eine Firma in Vertec
obj.IsTypeOf("Projekt")
>>> 0 # false

obj.istypeof("Firma")
>>> 1 # true
linkto(target, Role)

Makes a link type from the object to the passed object (target) with the specified Role.

For detailed information on this topic, see the article Operators and methods for links.

objid

Returns the internal ID of the object.

>>> argobject.objid
3011
removetag(tagname)

As of version 6.1.0.10. Delete the corresponding tag from this object.

For more information, see the article Tags on user entries.

argobject.removetag('mytag')
setattr(object, name, value)

Describes the name attribute of the object object with the value value.

For example, you can loop through the custom field items of an object and use the found attribute names to describe the attributes.

This code creates a new object of the same type as the argobject and copies the contents of all additional fields to the new object.

source = argobject
target = vtcapp.createobject(source.evalocl('ocltype.asstring'))
zusatzfelder = source.zusatzfelder
for z in zusatzfelder:
    zName = z.metazusatzfeld.fieldname

Now you know the name of the additional field, but if you address it with target.zName, you would get an error message “target has no attribute zName”. So you use setattr:

setattr(target, zName, getattr(source, zName))
vtcapp.showdetailform(target)
setkeyvalue(key, value)

As of version 6.1.0.10. With this method, customer-specific values are stored as key values on user entries.

These values can be accessed later via the getkey methods and lists can thus be filtered efficiently.

argobject.setkeyvalue("datum", "2017-02-03")
setmemberoutofdate(membername:string)

If a value is to be read freshly from database, the field out of date must be set.

This method does the same as the Notif for a Modified message.

proj = argobject
proj.setmemberoutofdate('code')

ensures that the next time you access Projekt.code, this value is loaded freshly from the database.

setmlvalue(membername:string, value:string, language:string)

The so-called multilanguage attributes (MLStrings, multilingual attributes) can be set via this method.

  • Member name: Member name
  • Value: The value for the specified language
  • Language is the respective language code (DE, FR, IT, EN).

Multilanguage attributes are:

  • Servicetype.Text
  • Expense type.Text
  • Outlay type.Text
  • Custom field class.Designation (designation of custom field items)
  • GridColDef.Title (column title in list settings)

To retrieve such an attribute, the method getmlvalue() can be used.

taetigkeit = argobject
taetigkeit.setmlvalue("text", "Vacanze", "IT")
unlink(target, Role)

Removes the link from the object to the passed object (target) with the specified link role.

For detailed information on this topic, see the article Operators and methods for links.

unload(): None

Removes the object from the Vertec object store.

This method was introduced solely to control memory usage during data migrations. It should be used with caution, as subsequent accesses to the unloaded object can result in errors.

 

Class name of an object

Access to the classname works in Python only via OCL:

obj.evalocl('ocltype.asstring')

Methods on individual objects of type “project”

Method/Feature description Sample code
entrytypeslookup(typidx, phase=None): List of project entry types

Returns a list of project entry types for the project (and optionally a phase)

typeidx: 0: service types, 1: types of expenses, 2: types of expenses.

proj = argobject
taetigkeitenliste = proj.entrytypeslookup(0, None)
phaseslookup(user, entrytype=None): List of project phases

Returns a list of project phases for the specified user (and optionally a project entry type).

proj = argobject
bearbeiter= vtcapp.currentlogin()
phasenliste = proj.phaseslookup(bearbeiter, None)
project managerisassigned(user): boolean

Specifies whether the specified user is authorized to create services etc. on this project.

proj = argobject
bearbeiter= vtcapp.currentlogin()
if proj.projektbearbeiterisassigned(bearbeiter):
   ...

setresourceplanvalue(worker, date, value)

As of Vertec 6.6. Allow the setting of resource plan values when the is set to project.

  • a or a project user is passed as worker.
  • date: The period in which the date is located is filled with the value.
  • value: Value in minutes.
bearb = vtcapp.currentlogin()
projekt = argobject
projekt.setresourceplanvalue(bearb, vtcapp.strtodate('15.05.2023'), 180)

Methods on individual objects of type “AbstractWorker”

The following methods are available on Abstractworker, project users and Planningworker:

Method/Feature description Example code

setresourceplanvalue(project_or_phase, date, value)

Vertec 6.6 and later. Allows the setting of resource plan values.

  • project or phase: Depend on the Planning Level, a project or a project phase is specified here.
  • date: The period in which the date is located is filled with the value.
  • value: Value in minutes.
bearb = vtcapp.currentlogin()
projekt = argobject
bearb.setresourceplanvalue(projekt, vtcapp.strtodate('15.05.2023'), 180)

Methods on individual objects of type “user”

 On users, the following methods are available:

Method/Feature description Example code

setnotification(category, text, link)

As of Vertec 6.6. Add a Notification (Notification) to the user with specified category, text and optionally linked User Entry.

If a notification with the same category and the same linked object already exists on the user, the text is updated.

  • category is a string that indicates the category (type) of the notification. This is freely selectable.
  • text is any text describing the notification and usually containing information about the linked object.
  • link (optional): is a Vertec object (User Entry). If specified, the notification will be displayed with the corresponding icon and the String Representation of the object.
aktivitaet = argobject
zustaendig = aktivitaet.zustaendig
if zustaendig and not aktivitaet.erledigt:
    zustaendig.setnotification('pending_activity', aktivitaet.titel, aktivitaet)
deletenotification(category, link) As of Vertec 6.6. Delete the Notification (Notification) on the user with the corresponding category and linked object. If no corresponding notification is found, nothing happens. No error message appears.
aktivitaet = argobject
zustaendig = aktivitaet.zustaendig 
if zustaendig and aktivitaet.erledigt: 
    zustaendig.deletenotification('pending_activity', aktivitaet)

Methods on individual objects of type “Project Phase”

At phases, the following methods are available:

Method/Feature description Sample code

setresourceplanvalue(worker, date, value)

As of Vertec 6.6. Allow the setting of resource plan values when the Planning Level is set to phase.

  • worker: A Planning Officer or a project user is passed as worker.
  • date: The period in which the date is located is filled with the value.
  • value: Value in minutes.
bearb = vtcapp.currentlogin()
phase = argobject
phase.setresourceplanvalue(bearb, vtcapp.strtodate('15.05.2023'), 180)

Methods on individual objects of type “invoice”

Method/Feature description Sample code
book([raiseException])

From version 48th Post an invoice into accounting.

The raiseException argument is a Boolean (True/False) that indicates whether errors should be reported when posting or cancelling.

raiseException is optional, default is True.

If raiseException is False, then errors during posting are ignored, the invoice is simply not posted.

rechnung = argobject
rechnung.buchen()
import payments()

From version 5.8. Import the payments to the current invoice. Work only if the customer interface supports payment import.

argobject.importzahlungen()
makeoffen([raiseException])

As of version 5.8. Set a settled invoice back to open (reverse charge).

The raiseException argument is a Boolean (True/False) that specifies whether errors should be reported during charging or undone during charging.

raiseException is optional, default is True.

If raiseException is False, then errors are reversed and the invoice simply remains charged.

rechnung = argobject
rechnung.makeoffen(False)
makeverrechnet([raiseException])

From version 5.8. Charges an open invoice.

The raiseException argument is a Boolean (True/False) that specifies whether errors should be reported during charging or undone during charging.

raiseException is optional, default is True.

If raiseException is False, then errors will be ignored, leaving the invoice open.

rechnung = argobject
rechnung.makeverrechnet(False)
cancel([raiseException])

As of version 5.8. Cancels a posted invoice.

The raiseException argument is a Boolean (True/False) that indicates whether errors should be reported when posting or cancelling.

raiseException is optional, default is True.

If raiseException is False, then errors in the post are ignored, the invoice is simply not cancelled.
rechnung = argobject
rechnung.stornieren()

Methods on individual objects of type “project entry”

The term project entry is used to summarize services, expenses and outlays.

Method/Feature description Example code
makeoffen()

From version 5.8. Set a billed service, expense or outlay to open.

This only works if the service, expense or outlay is not on an invoice, otherwise an error will be thrown.

argobject.makeoffen()
makecompute()

As of version 5.8. Set an open service, expense or outlay to charged.

This only works if the service, expense or outlay is not on an invoice, otherwise an error will be thrown.

argobject.makeverrechnet()

Methods on individual objects of type “service”

Method/Feature description Example code
update set()
From version 6.1.0.14. Hourly rate is recalculated (from rate system).

Requires user rights Projekt-Administrator or Super.

argobject.updatesatz()

Methods on individual objects of type “activity”

Method/function description Example code
setpath(path: string)

As of version 6.1.0.14. Set the document path to the activity when the Document Storage is set to Dateisystem oder DMS is set.

argobject.setpfad('C:\\Dokumente\\text.txt')
setdocumentcontent(filename, documentcontent)

As of Vertec 6.7.0.15. Add a document to the activity if the Document Storage is Intern is set.

  • filename: Name under which the file should be saved.
  • documentcontent: Document content as bytestream.

The activity will do the following:

  • DocumentFullName is set
  • DocumentData object is created and described with the content
  • DocumentSize is set to length of the content array

After successful execution, the Document page is shown.

If a document is already saved on the activity, an error is output.

Note: The method can also be used if the document storage is not set to Internal, but the document is in any case saved internally.

(name, file) = vtcapp.requestfilefromclient("Dokument auswählen", r"C:", "Word|*.docx")
activity = vtcapp.createobject("Aktivitaet")
activity.setdocumentcontent(name, file)
vtcapp.showdetailform(activity)
setemailcontent(mimecontent)

As of Vertec 6.7.0.15. Add an email to the activity.

  • mimecontent: Here is the .eml File specified. If the email is a .msg If a file acts, it must be converted to MIME using vtcapp.msgtomime() first.

The activity will do the following:

  • EmailSender is extracted and set
  • EmailRecipients is extracted and set
  • DocumentData object is created and described with the content
  • DocumentSize is set to length of the content array
  • EmailAttachmentNames is set
  • Text is described with body (plain text)
  • Title is described with subject

Upon successful completion, the email page will be shown.

If a document is already saved on the activity, an error is output.

(name, file) = vtcapp.requestfilefromclient("Email auswählen", r"C:", "Email|*.msg")
mimecontent = vtcapp.msgtomime(file) 
activity = vtcapp.createobject("Aktivitaet")
activity.setemailcontent(mimecontent)
vtcapp.showdetailform(activity)

Methods on individual objects of type “currency”

Method/Feature description Sample code
getkursto(currency: object, date: date): currency
As of version 6.1.0.14. Return the conversion rate at the corresponding date.
chf.getkursto(eur, vtcapp.currentdate())

Vertec Lists

Starting with version 6.2.0.7 all Python methods that return lists of business objects directly return a Vertec list and no longer a Python list. The methods from the methods

  • evalocl()
  • getwithsql()
  • getmemberwithsql()

Resulting lists are directly Vertec lists and no longer need to be created with vtcapp.createlist().

Example

Versions before 6.2.0.7: liste = vtcapp.createlist("Projekt", vtcapp.evalocl("projekt->select(code.sqllike('A%'))"))

Versions from 6.2.0.7: liste = vtcapp.evalocl("projekt->select(code.sqllike('A%'))")

Methods on vertec lists

Method/Feature description Sample code
append(object)
A list can be populated using the append() method. Only individual objects can be passed, not entire lists with append().
mylist = vtcapp.createlist('Projekt')
mylist.append(argobject)
evalocl(OCL:string)
An OCL expression can be dropped from the Vertec list.
projektIds = argobject.evalocl("eintraege").idstring()
leistungen = vtcapp.createlist("OffeneLeistung", vtcapp.getwithsql("OffeneLeistung", "projekt IN (%s)" % projektIds, ""))
print leistungen.evalocl("wertext->sum")
extend(list: list)
As of version 6.2. With the extend() method, another list can be appended to a Vertec list.

This checks whether the vertec list is a derived list (e.g. Container.eintraege). Access is denied in this case.

projektIds = argobject.evalocl("eintraege").idstring()
leistungen = vtcapp.createlist("OffeneLeistung", vtcapp.getwithsql("OffeneLeistung", "projekt IN (%s)" % projektIds, ""))
leistungen.extend(vtcapp.createlist("VerrechneteLeistung", vtcapp.getwithsql("VerrechneteLeistung", "projekt IN (%s)" % projektIds, "")))
print leistungen.evalocl("wertext->sum")
idstring()

a common requirement in Python scripts is to formulate a SQL query with bold_id in (...) based on a list of Vertec objects.

To do this, the IDs of a list of objects must be converted to a comma-delimited string.

  • List.idstring() returns the IDs of the Vertec objects as a comma-delimited string.
  • If the list contains non-persistent objects, the method returns an error message.
>>> vtcapp.evalocl('Projektbearbeiter->allinstances').idstring()
300,676,7613,682,688,694
index(object)
As of version 6.2.0.7. Return the index of the object in the list.
If the object occurs more than once, the lowest index is returned. Introduce
for compatibility with Python lists (see below).
>>> liste = vtcapp.evalocl("projekt.code")
>>> print liste.index('COMINSTALL')
25
insert(index, object)
As of version 6.2.0.7. Insert an object into the list at index. Introduce
for compatibility with Python lists (see below).
>>> liste = [123, 'xyz', 'miau', 'abc']
>>> liste.insert(3, 2009)
>>> print liste
[123, 'xyz', 'miau', 2009, 'abc']
remove(object)
Removes the specified object from the list
projektIds = argobject.evalocl("eintraege").idstring()
leistungen = vtcapp.createlist("OffeneLeistung", vtcapp.getwithsql("OffeneLeistung", "projekt IN (%s)" % projektIds, ""))
fl = leistungen.evalocl("self->select(bearbeiter.asstring = 'Judith Feller')")
for leistung in fl:
    leistungen.remove(leistung)

The example above serves to show the remove() method. This use case would be solved via reject:

projektIds = argobject.evalocl("eintraege").idstring()
leistungen = vtcapp.createlist("OffeneLeistung", vtcapp.getwithsql("OffeneLeistung", "projekt IN (%s)" % projektIds, ""))
leistungen = leistungen.evalocl("self->reject(bearbeiter.asstring = 'Judith Feller')")

Differences vertec and python lists

Vertec and Python lists differ in the following ways:

The + operator is not applicable to vertec lists. Code of the type
projektIds = argobject.evalocl("eintraege").idstring()
leistungen = vtcapp.getwithsql("OffeneLeistung", "projekt IN (%s)" % projektIds, "") \
             + vtcapp.getwithsql("VerrechneteLeistung", "projekt IN (%s)" % projektIds, "")

does not work. An error appears: TypeError: can only concatenate list (not "BoldListAdapter") to list.

Instead, use extend() or +=:

leistungen = vtcapp.getwithsql("OffeneLeistung", "projekt IN (%s)" % projektIds, "")
leistungen.extend(vtcapp.getwithsql("VerrechneteLeistung", "projekt IN (%s)" % projektIds, ""))
or
leistungen = vtcapp.getwithsql("OffeneLeistung", "projekt IN (%s)" % projektIds, "")
leistungen += vtcapp.getwithsql("VerrechneteLeistung", "projekt IN (%s)" % projektIds, "")

Python lists can be created from Vertec lists by using list(vertecliste).

It is important to note that Vertec lists are “live”. This means that actions related to the logic of the list calculation can change, as shown in the following examples:

With remove() and delete(), the list is shorter after each iteration. At the end, only half of the list is deleted. To delete all objects in a list, it is best to convert it to a Python list:

for l in list(argobject.offeneleistungen):
    l.delete()

The following is a list of open services:

leistungen = phase.evalocl("offeneleistungen")
for l in leistungen:
    l.makeverrechnet()

If they are charged in turn, they will automatically disappear from the list. The effect is the same as above: Only half of the services are charged. Instead, convert to a Python list:

for l in list(phase.evalocl("offeneleistungen")):
    l.makeverrechnet()

'count’, 'pop’, 'reverse’ and 'sort’ are only available on Python lists. If you use these methods, you would have to rewrite them or make the Vertec list back into a Python list with list(vertecliste).

Netherlands

United Kingdom