ZUGFeRD is a standard developed by FeRD (Forum for Electronic Invoicing in Germany) to standardize the process of creating and sharing electronic invoices. A XML format is used to enable the electronic invoice checks. This XML is generated via the ZUGFeRD API from PDFreactor. The integrator itself does not have to deal with the XML.
PDFreactor supports two out of the three profiles specified by FeRD which can be used
to generate the ZUGFeRD PDF in the profiles basic and comfort.
The profile extended is currently not supported. Profile determines which
ZUGFeRD-properties can be generated into the ZUGFeRD PDF and which cannot.
Without a profile the ZUGFeRD PDF cannot be created and the conversion will terminate
with an appropriate error message.
If for example the profile is basic, properties which require
the profile comfort, even if specified, will not be generated. However if the
profile would be comfort, properties which only require basic
will be generated, if specified. There are also properties which are always required
in order to create a ZUGFeRD PDF. These properties all require the profile basic,
and have to be specified in your JavaScript using the API. Furthermore with a higher
profile, there won't be any new required properties. Hence it is possible to generate a ZUGFeRD PDF with the
profile comfort while only specifying properties which are used in basic.
| Profile | Description |
|---|---|
basic |
The lowest ZUGFeRD profile. Allows to set all required information. Does not allow full support for electronic checks. |
comfort |
Higher level than basic.
Allows to set more specific information, especially in terms of positions.
Allows support for electronic checks to a certain degree. |
A ZUGFeRD PDF consists of two parts, the PDF and the XML.
Everything that is visible in the PDF can be generated into the XML.
Though it is not prevented programmatically, the ZUGFeRD specification states that
only information that is visible or can be derived from the PDF is allowed to be
generated into the XML. The last case could be the country, which is a 2-character
long code. This means, if a ZUGFeRD-property is required to generate the ZUGFeRD XML
and cannot be specified from the PDF, the PDF as well as the XML are invalid.
There are of course some exceptions where the required information may not be specified
in the PDF. This could be the zugferd-profile or the test-indicator.
To generate a ZUGFeRD PDF, there are some requirements that have to be met.
For ZUGFeRD, the PDF/A standard has to be used, which enables long term archivability. The PDF standard must also allow the attachment of the ZUGFeRD XML, which limits the options to PDF/A-3a, PDF/A-3b, PDF/A-3u and PDF/A-3a with the PDF/UA-1 specification.
To create the ZUGFeRD PDF from the PDF, the JavaScript has to be specified in either the document or the PDFreactor API. For PDFreactor to be able to process the JavaScript, the JavaScriptProcessing has to be enabled.
The following example specifies all requirements for PDFreactor to create a ZUGFeRD PDF with either the Java library or the Java wrapper:
PDFreactor does not validate prices and totals which have been specified via the
ZUGFeRD API. When using the API, PDFreactor assumes that all positions, taxes and
totals have been calculated correctly. If they were not, the document itself would
not be valid. However some properties are validated. For the most part this includes
properties which have to be specified as ZUGFeRD code like the document-type
or the country code. This also includes codes which have been set via the
options object. There are also special cases which have to
be validated to ensure that the resulting ZUGFeRD PDF is correct, like the
elements Gross- and NetPrice.
Before using the API the two types of elements have to be known. Unique and repeating elements, which follow a tree data structure.
Unique elements are leaf elements directly connected to the root.
This elements will only be set once via the API, but are the most important
elements. In fact it is possible to create a ZUGFeRD PDF without any repeating
elements. These are elements like currency to set the currency used in
the document or document-type which describes the type of the
document, like invoice, with ZUGFeRD codes.
While repeating elements are not required to create the ZUGFeRD PDF, they add more
information to it. Depending on your PDF these elements will be set once or multiple
times. Repeating elements itself are not directly
connected to the root, instead they branch off the root into leaves.
An example for repeating elements are positions. These branch off with the
path item and the leaves holding the information
of the position, like the product name (item.name) or the quantity
(item.billed-quantity) for the position.
It is also possible that a repeating element branches off from another repeating
element. These are called nested repeating elements.
When using a ZUGFeRD-property the structure will be self-explanatory.
There are also some restrictions on what leaves have to be specified. When specifying a position,
the most important information is the product name (item.name) and thus has to be
specified. Otherwise the element will not be generated. All other information should be specified if possible
but are not a requirement.
To specify which value has to be passed to which element, ZUGFeRD-properties have to be used. These ZUGFeRD-properties can be fragmented into paths and properties. While most documents will not require the use of fragments, they will be useful if they are used correctly.
A ZUGFeRD-property is made from fragments.
These fragments define the tree data structure, by splitting at the "."
of the ZUGFeRD-property.
If a ZUGFeRD-property, like "zugferd-profile", does not contain a "."
it is automatically a property.
Paths are all fragments except the last fragment. The path is used to specify one or multiple repeating elements. The reason for this is, that a repeating element itself cannot have a value. Only the leaf elements of a repeating element can hold values. So when using a path the tree data structure will be specified.
If a ZUGFeRD-property contains more than one "." it means that there
is a repeating element inside a repeating element. This also means that there are two
paths fragments. It is not possible to specify these as a single path.
Instead the first path retrieves a repeating element from the ro.zugferd
object, and the second path retrieves the repeating elements from the retrieved
element.
Because unique elements only occur once, they do not have a path.
The last fragment or the ZUGFeRD-property itself, if the ZUGFeRD-property does
not contain a ".", is the property.
This fragment defines the leaf element to which the specified or retrieved
value will be applied.
Most of the time the use of fragments is unnecessary.
A ZUGFeRD PDF can be generated from a complex document without ever having to fragment
a ZUGFeRD-property.
Fragments are only required if a value has to be passed to a specific repeating element.
Whenever the get method is called from the "ro.zugferd" object with the
first fragment, to retrieve a repeating element every other method which is called
on this repeating element has to be the next fragment of the ZUGFeRD-property.
Let's examine the following HTML snippet for example:
This table can be converted into a ZUGFeRD PDF by using fragments, but it can also be avoided:
As seen above, both ways are possible but using fragments adds an extra layer of complexity. Consequently, fragments should only be used if the case requires them.
While the API should be as easy to use as possible, some elements and properties require more attention than others. This is either due to the ZUGFeRD specification or how they were implemented in PDFreactor.
While the ZUGFeRD specification does allow an unlimited amount of tax registrations,
PDFreactor limits this information to two ZUGFeRD-properties per involved party.
To specify this information for the selling party for example, the properties
seller-vatid and seller-taxid are used.
Gross- and NetPrice are two elements, which are always generated if at least
one of them is specified with the ZUGFeRD-properties item.gross-price-amount or
item.net-price-amount. As long as the ZUGFeRD-property item.gross-price-allowance-charge.amount
has not been specified to define an allowance or charge, Gross and NetPrice are the
same and no special attention has to be given. If item.gross-price-allowance-charge.amount
has been specified however, the net price is not allowed to be equal to the gross price
and the ZUGFeRD PDF will not be generated. An appropriate exception will be thrown.
When referencing a document, like a previously sent invoice which now has to
be canceled, the options object is still required to specify
the current date format. However, the output format is fixed to yyyy-MM-dd'T'00:00:00
and thus has not to be specified via the options object property scheme.
To specify the document type by ZUGFeRD code, the property document-type has to be used.
While the document does not have to be a commercial invoice, with the ZUGFeRD profile basic
only the ZUGFeRD code 380 is allowed. Other document types may require
more information than it is possible to specify with a basic profile.
These two ZUGFeRD-properties are required per ZUGFeRD specification to generate the ZUGFeRD PDF.
While they are required, PDFreactor will set this properties automatically with the value 0.00.
This is because, these two properties may not be able to be set from the PDF. However if they are
specified in the PDF these two properties should be set to ensure that the ZUGFeRD PDF is valid.
When using the ZUGFeRD-property item.global-id, it is not possible
to specify the organization in which this product is registered via the options object
property scheme. This is due to the fact that different products can be registered
by different organizations and setting them via the API in bulk can lead to undesirable results.
To specify the organization by ZUGFeRD code, the ZUGFeRD-property item.global-id-type is used
instead.
When specifying the ZUGFeRD-property mandate-reference it is possible
to specify an id for this mandate. This mandate-reference-id is given by
the mandate itself and has to be used. The ZUGFeRD-property mandate-reference-id
is not required to generate the mandate-reference.
To interact with the ZUGFeRD API, the ro.zugferd object has to be used.
With this object it is possible to configure certain values, set default
values for repeating elements and to define the input and output formats, as
well as setting unique and repeating elements and retrieving repeating elements.
Mappings can be used to set the specified value instead of the value passed to a method. This is especially useful if a human readable value was retrieved from the document, but it has to be passed as a ZUGFeRD code. Please note that the key is case sensitive and does not ignore spaces. To disable the mapping use the options object property ignoreMapping when calling a method. An errorHandler can be appended via the options object.
Sets the specified value as content for the specified ZUGFeRD-property. The value can be modified using the options object.
Retrieves the text content of an element matching the given selector and sets it as value for the specified ZUGFeRD-property. The content of the ZUGFeRD-element can be modified using the options object.
Retrieves the text content of each element matching the given selector and sets it as value of the specified ZUGFeRD-property. If no matching elements are found, this process will create new elements. This method is not allowed for ZUGFeRD-properties with multiple paths fragments. Use the setFromSelectorAll method with the selector array for these ZUGFeRD-properties instead. The content of the ZUGFeRD-element can be modified using the options object.
When using this method it is possible to define each fragment with its own selector. If more selectors than fragments have been specified, the method call will be interrupted. If the selector defines a path fragment, new repeating elements with this path fragment will be created. The number of newly created repeating elements depends on how many elements have been found via the selector and how many elements already exist. It is possible to select direct child elements only, by using the ">" selector after the first selector in the array. The content of the ZUGFeRD-element can be modified using the options object.
Returns the repeating element with the specified path at the specified index. If no repeating element with the specified path exists, the element itself as well as all previous elements will be created. An errorHandler can be appended using the options object.
Returns an array containing all repeating elements matching the given path. If there are no repeating elements matching the specified path, an error of errorType 5000 will be passed to the errorHandler. An errorHandler can be appended using the options object. While the returned array is not live, values which have been set will still be applied.
Elements are the repeating elements retrieved via the ro.zugferd get methods.
Sets the given value as content of the specified ZUGFeRD-property. Because the repeating Element is known, only the last fragment of the ZUGFeRD-property has to be specified. The value can be modified using the options object.
Sets the text content of an element matching the given selector as value of the specified ZUGFeRD-property. Because the repeating element is known, only the property fragment has to be specified. The content of the ZUGFeRD-element can be modified using the options object.
When called on a repeating element, this method returns the repeating element within this element, matching the specified path fragment at the specified index. If no repeating element with the specified path fragment exists, the elements and all previous elements will be created. An errorHandler can be appended using the options object.
When called on a repeating element, this method returns an array containing all repeating elements within the element, with the specified path fragment. If there are no repeating elements with the specified path an error with the errorType 5000 will be logged from the errorHandler. An errorHandler can be appended using the options object. While the returned array is not live, values which have been set will still be applied.
The "options" object can be passed to a method to modify a text and to specify
required information. If the ZUGFeRD-property type is Date or
Number this object is required, unless the information has already been
specified via the default object properties
inputFormat and scheme. If information of the same property
has been specified in both the options and the default object,
only the options object's information will be considered.
The inputFormat has to be specified for ZUGFeRD-properties of the
type Date and Number. For ZUGFeRD-properties of the type
Date, the Date's source format has to be described as a Java pattern.
If the ZUGFeRD-property is of the type Number, the decimal mark has
to be specified. The inputFormat is used and processed in these two
cases only. The default value for ZUGFeRD-properties of the type Number is
","
To specify the output format of a ZUGFeRD-property of the type Date,
the property scheme is needed.
The format is specified by a ZUGFeRD code.
Attention: Referenced documents use the type Date, but do not need an output format.
Another use for scheme is for Global IDs.
All codes can be found in the property list under each type.
The property scheme is only used and processed in these two cases.
The default Value for ZUGFeRD-properties of the type Date is 102
The property startDelimiter allows to extract a text starting
from the first occurrence of the delimiter, to the end of the text.
If both startDelimiter and endDelimiter are specified,
the text between the two specified delimiters is extracted.
The property endDelimiter allows to extract a text from the start
to the last occurrence of the specified delimiter.
If both startDelimiter and endDelimiter are specified,
the text between the two specified delimiters is extracted.
With the property splitDelimiter a text can be split at the specified delimiter.
The property splitIndex can then be used to select the desired part.
After splitting the text with the property splitDelimiter, the desired
part can be selected with the property splitIndex.
If no splitDelimiter has been specified, nothing can be retrieved.
The first part has the index 0.
The property processor allows to pass your own function to a method.
This enables the use of conditions for further text manipulation.
It is also possible to redefine the properties inputFormat and scheme.
The following read-only properties can be called as parameter:
| Name | Type | Description |
|---|---|---|
| rawText | String | Returns the unprocessed text. |
| text | String | Returns the processed text. |
| propertyName | String | Returns the name of the property with which the method has been called. |
| element | Element | Returns the element retrieved by the selector. |
| content | String | Returns the text content of the element, including the generated before and after text. |
| contentBefore | String | Returns the generated before text content of the element. |
| contentAfter | String | Returns the generated after text content of the element. |
| contentText | String | Returns the text content of the element. |
If mapping should be disabled for a ZUGFeRD-property use the property
ignoreMapping.
With the property errorHandler it is possible to identify and
analyze possible error cases. It is also possible to retrieve information regarding
the current processing step. The following information can be retrieved:
| Name | Type | Description |
|---|---|---|
| methodName | String | Name of the method. |
| propertyName | String | The name of the ZUGFeRD-property or the key if the called method
was addMapping. |
| value | String | The value which was passed to the method set or
addMapping. |
| selectors | String or [String] | In case of setFromSelector, the specified selector
or the selector array in case of setFromSelectorAll. |
| options | Object | The options object that was passed to the method. |
| message | String | The message of the current log. |
| errorType | Number | The type of the warning or error.
There is no errorType for info.
More information about the types can be found here. |
| level | String | The log level. The following levels are possible:
|
| matchCount | [Number] | On level info the property matchCount
contains an array of numbers, indicating how often a selector did find an element. |
Note: If no errorHandler has been specifiedvia the options or
default object, it is not possible to retrieve any information regarding the ZUGFeRD processing.
Possible errors cannot be analyzed.
The default object is used to specify the properties inputFormat
and scheme on a global level.
Their values will be used if properties that are required by the current ZUGFeRD type,
have not been specified via the options
object. It is also possible to set default values for repeating elements.
With the property inputFormat it is possible to set default values
for the ZUGFeRD-properties Date and Number.
| Name | Description |
|---|---|
| dateFormat | Specifies a Java date format pattern. |
| decimalMark | Specifies a decimal mark to process ZUGFeRD-properties of the
type Number. The default value is ",". |
The property scheme allows to set default values for the ZUGFeRD-properties Date and Global ID.
| Name | Description |
|---|---|
| dateFormat | Specifies a ZUGFeRD Code as output format for a date. The code
list can be found in the property list for the type Date.
The default value is 102. |
| globalId | Defines the organization the Global ID is registered with.
An excerpt of possible codes can be found in the property list for
the type Global ID. Because different products can be
registered in different organizations, this property will not be processed
for the ZUGFeRD-property item.global-id. Use the property
item.global-id-type to specify the organization instead. |
To set default values for repeating elements, the property propertyValues is used.
The syntax is as follows:
The property errorHandler is used in the same way as the
options object.
If an errorHandler is specified as default, it will be called for
each method call, as long as no errorHandler
is defined as an argument when calling the method.
A possible use case would be:
In case of a warning or error the problem is summarized
by the following types. A more detailed description can be retrieved from the message
property of the errorHandler.
| Type | Description |
|---|---|
| 1000 | API usage error |
| 2000 | The value or text content of an element could not be processed with the specified options object. |
| 3000 | The value or text content of an element is invalid or invalid for the specified ZUGFeRD-property. |
| 4000 | The value or text content could not be parsed.
This only occurs if the ZUGFeRD-property is either of the type Date
or Number. |
| 5000 | Error while trying to access a repeating element via get or if no
element could be found with the specified selectors. |