texlive[73081] Master/texmf-dist: zugferd (9dec24)

commits+karl at tug.org commits+karl at tug.org
Mon Dec 9 22:13:34 CET 2024


Revision: 73081
          https://tug.org/svn/texlive?view=revision&revision=73081
Author:   karl
Date:     2024-12-09 22:13:34 +0100 (Mon, 09 Dec 2024)
Log Message:
-----------
zugferd (9dec24)

Modified Paths:
--------------
    trunk/Master/texmf-dist/doc/latex/zugferd/DEMO-rechnung-zugferd.pdf
    trunk/Master/texmf-dist/doc/latex/zugferd/DEMO-rechnung-zugferd.tex
    trunk/Master/texmf-dist/doc/latex/zugferd/README.md
    trunk/Master/texmf-dist/doc/latex/zugferd/zugferd.pdf
    trunk/Master/texmf-dist/source/latex/zugferd/zugferd.dtx
    trunk/Master/texmf-dist/tex/latex/zugferd/zugferd-invoice.sty
    trunk/Master/texmf-dist/tex/latex/zugferd/zugferd.sty

Modified: trunk/Master/texmf-dist/doc/latex/zugferd/DEMO-rechnung-zugferd.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/latex/zugferd/DEMO-rechnung-zugferd.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/zugferd/DEMO-rechnung-zugferd.tex	2024-12-09 21:13:19 UTC (rev 73080)
+++ trunk/Master/texmf-dist/doc/latex/zugferd/DEMO-rechnung-zugferd.tex	2024-12-09 21:13:34 UTC (rev 73081)
@@ -1,7 +1,7 @@
 % !TeX Program=lualatex
 %
 % Demo file for the LaTeX-ZUGFeRD project
-% This file corresponds to version 0.9b (2024-11-17)
+% This file corresponds to version 0.9c (2024-12-08)
 %
 % Copyright (C) 2024 Marei Peischl <marei at peitex.de>
 % ---------------------------------------------------------

Modified: trunk/Master/texmf-dist/doc/latex/zugferd/README.md
===================================================================
--- trunk/Master/texmf-dist/doc/latex/zugferd/README.md	2024-12-09 21:13:19 UTC (rev 73080)
+++ trunk/Master/texmf-dist/doc/latex/zugferd/README.md	2024-12-09 21:13:34 UTC (rev 73081)
@@ -2,7 +2,7 @@
 
 Copyright (C) 2023–2024 by Marei Peischl (peiTeX) <marei at peitex.de>
 
-zugferd version 0.9b (2024-11-17)
+zugferd version 0.9c (2024-12-08)
 
 ***************************************************************************
 
@@ -23,6 +23,10 @@
 
 ## Version History
 
+* 0.9c (2024-12-08)
+   - extend address interface
+   - add document reference fields
+   - fix bug adding the PDF attachment entry twice
 * 0.9b (2024-11-17)
    - Rename embedded xml-file if xrechnung is used
    - Fix bug leaving an unescaped `\n` in the output

Modified: trunk/Master/texmf-dist/doc/latex/zugferd/zugferd.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/source/latex/zugferd/zugferd.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/zugferd/zugferd.dtx	2024-12-09 21:13:19 UTC (rev 73080)
+++ trunk/Master/texmf-dist/source/latex/zugferd/zugferd.dtx	2024-12-09 21:13:34 UTC (rev 73081)
@@ -16,14 +16,14 @@
 % \fi
 % \iffalse
 %<*driver>
-\ProvidesFile{zugferd.dtx}[2024-11-17 v0.9b ZUGFerd Invoice and Faktur-X]
+\ProvidesFile{zugferd.dtx}[2024-12-08 v0.9c ZUGFerd Invoice and Faktur-X]
 %</driver>
 %<package>\NeedsTeXFormat{LaTeX2e}[2023-11-01]
-%<package>\ProvidesExplPackage{zugferd}{2024-11-17}{0.9b}{Create ZUGFerd invoices using LaTeX}
+%<package>\ProvidesExplPackage{zugferd}{2024-12-08}{0.9c}{Create ZUGFerd invoices using LaTeX}
 %<*driver>
 \DocumentMetadata{pdfstandard=a-3b,lang=en}
 \documentclass[lm-default=false,cs-break-nohyphen]{l3doc}
-\usepackage{zugferd}[2024-11-17]
+\usepackage{zugferd}[2024-12-08]
 \EnableCrossrefs
 %\CodelineIndex
 \RecordChanges
@@ -228,7 +228,7 @@
 \newcommand*{\XML}{XML\xspace}
 \newcommand*{\XMLfile}{\XML file}
 
-\newcommand*{\issue}[1]{%
+\DeclareRobustCommand{\issue}[1]{%
 	{\DeclareFieldFormat{citeurlpostfix}{\href{##1/issues/#1}{\##1}}\citefield{LaTeX-ZUGFeRD-GitHub}[citeurlpostfix]{url}}%
 }
 \newcommand*{\version}[1]{v#1}
@@ -487,8 +487,9 @@
 	}
 %    \end{macrocode}
 % \changes{v0.9a}{2024-11-07}{Add error message if pdfmanagement is outdated.}
+% \changes{v0.9c}{2024-12-08}{Compatbility to show the error message in older formats versions.}
 %    \begin{macrocode}
-	\IfPackageAtLeastF{pdfmanagement-testphase}{2024/09/13}{
+	\IfPackageAtLeastTF{pdfmanagement-testphase}{2024/09/13}{}{
 		\msg_new:nnn {zugferd} {PDFmanagement-too-old} {
 			Your~version~of~\LaTeX's~PDF~management~is~too~old.
 			You~need~to~update~your~LaTeX~distribution~to~be~able~to~use~the~zugferd~package~correctly.
@@ -753,20 +754,17 @@
 			\pdfdict_put:nnn {l_pdffile/Filespec} {Desc}{(Factur-X/ZUGFeRD-Rechnung)}
 			\exp_args:NnV \pdffile_embed_file:nnn {\g_@@_xml_file_tl} \g_@@_xml_embedded_file_tl
 				{zugferd/rechnung}
+		\group_end:
 %    \end{macrocode}
 % Since some tools require the Catalog entry to match the file name of the embedded file this this has to be set separately (\issue{26}).
 % \changes{v0.9b}{2024-11-17}{Fix file name of embedded file for the zugferd profile.}
+% \changes{v0.9c}{2024-12–08}{Remove second catalog entry linking to xml \issue{32}}
 %    \begin{macrocode}
-			\pdfmanagement_add:nee
-				  {Catalog/Names/EmbeddedFiles}
-				  {\g_@@_xml_embedded_file_tl}
-				  {\pdf_object_ref:n{zugferd/rechnung}}
-		\group_end:
-		\pdfmanagement_add:nnx
-			{Catalog/Names}
-			{EmbeddedFiles}
+		\pdfmanagement_add:nee
+			{Catalog/Names/EmbeddedFiles}
+			{\g_@@_xml_embedded_file_tl}
 			{\pdf_object_ref:n{zugferd/rechnung}}
-			% steht in der docu ist aber pdf 2.0 ....
+			% steht in der doku ist aber pdf 2.0 ....
 		\pdfmanagement_add:nnx{Catalog}{AF}{\pdf_object_ref:n{zugferd/rechnung}}
 	}
 }
@@ -844,6 +842,8 @@
 % And this will also print the \enquote{SpecifiedTradeSettlementPaymentMeans}, see \autoref{sec:PaymentMeans}.
 %
 % \DescribeMacro{\zugferd_write_TaxEntry:nnnn}
+% \DescribeMacro{\zugferd_write_TaxEntry:ennn}
+% \changes{v0.9c}{2024-12-08}{Added \cs{zugferd_write_TaxEntry:ennn} variant}
 % This command is writing the sum over a tax rate. This command has to be used once per rate applied to the items.
 % \begin{syntax}
 % \cs[no-index]{zugferd_write_TaxEntry:nnnn} \marg{tax category code} \marg{tax rate in \%} \marg{basis amount the tax applies to} \marg{tax amount}
@@ -933,7 +933,7 @@
 %    \end{macrocode}
 % \end{function}
 % \changes{v0.9}{2024-10-23}{Add interface using an argument for the keyval options locally per item}
-% \begin{function}{\_@@_write_Item:nnnnnnn}
+% \begin{function}{\zugferd_write_Item:nnnnnnn}
 %    \begin{macrocode}
 \cs_new:Nn \zugferd_write_Item:nnnnnnn {
 	\group_begin:
@@ -944,6 +944,11 @@
 \cs_generate_variant:Nn \zugferd_write_Item:nnnnnnn {ennnnnn}
 %    \end{macrocode}
 % \end{function}
+% \begin{function}{\zugferd_write_TaxEntry:ennn}
+%    \begin{macrocode}
+\cs_generate_variant:Nn \zugferd_write_TaxEntry:nnnn {ennn}
+%    \end{macrocode}
+% \end{function}
 % \begin{function}{\_@@_write_xml:n,\_@@_define_xml_writer:Nn,\_@@_define_xml_content:Nn}
 % These commands are used to toggle the writing of the \XMLfile. This corresponds to the option \option{write-xml}.
 %    \begin{macrocode}
@@ -1069,22 +1074,25 @@
 % \fi
 %    \begin{macrocode}
 \cs_new:Nn \zugferd_disable_macros: {
-	\let\{\textbraceleft
-	\let\}\textbraceright
-	\let\\\textbackslash
-	\let\#\textnumbersign
-	\let\$\textdollar
+	\let\{\c_left_brace_str
+	\let\textbraceleft\c_left_brace_str
+	\let\}\c_right_brace_str
+	\let\textbraceright\c_right_brace_str
+	\let\#\c_hash_str
 %    \end{macrocode}
 % This only is a part of the list.
 % There is no real use of printing the whole list, it's inside \file{zugferd.sty} anyway.
 % \comment
 %    \begin{macrocode}
-	\let\%\textpercent
-	\let\&\textampersand
-	\let\_\textunderscore
-	\let\P\textparagraph
-	\let\ldots\textellipsis
-	\let\dots\textellipsis
+	\let\textnumbersign\c_hash_str
+	\let\$\c_dollar_str
+	\let\textdollar\c_dollar_str
+	\let\%\c_percent_str
+	\let\&\c_ampersand_str
+	\let\_\c_underscore_str
+	\def\P{§}
+	\def\ldots{…}
+	\def\dots{…}
 	\def\\{\space}%
 	\def\newline{\space}%
 	\def\TeX{TeX}%
@@ -1188,6 +1196,55 @@
 % \end{function}
 % \end{implementation}
 % \begin{documentation}
+% \DescribeMacro{\zugferd_tl_set_escaped_xml:Nn}
+% \DescribeMacro{\zugferd_tl_gset_escaped_xml:Nn}
+% \changes{v0.9c}{2024-12-08}{Added mechanism to escape XML special characters.}
+% As described before and also in \issue{9} there are characters which are special in \XML but not within \LaTeX.
+% Additionally there also are characters which aren't special in \LaTeX{} but within \XML.
+% In version \version{0.9c} \pkg{zugferd} added some auxiliary commands to support users escaping those.
+% This mechanism involves turning the category codes of characters like |"<>'&| to active and might have side effects.
+% It is an experimental feature and should be handled with care!
+% \end{documentation}
+% \begin{implementation}
+%    \begin{macrocode}
+\tl_new:N \g_@@_tmp_tl
+\cs_new:Nn \zugferd_tl_gset_escaped_xml:Nn {
+	\group_begin:
+		\zugferd_disable_macros:
+		\_@@_escape_xml_aux:
+		\tl_gset_rescan:Nnn #1 {
+			\cctab_select:N \c_str_cctab
+			\_@@_escape_xml_activate:
+		 } {#2}
+		\tl_gset:Ne #1 {#1}
+	\group_end:
+}
+\cs_new:Nn \zugferd_tl_set_escaped_xml:Nn {
+	\zugferd_tl_gset_escaped_xml:Nn \g_@@_tmp_tl {#2}
+	\tl_set_eq:NN #1 \g_@@_tmp_tl
+}
+\cs_new:Nn \_@@_escape_xml_aux: {
+	\edef\&{\tl_to_str:n {&}}
+	\edef\textgreater{\tl_to_str:n {>}}
+	\edef\textless{\tl_to_str:n {<}}
+	\edef\textquotedbl{\tl_to_str:n {"}}
+	\edef\textquotesingle{\tl_to_str:n {'}}
+	\char_set_active_eq:NN > \textgreater
+	\char_set_active_eq:NN < \textless
+	\char_set_active_eq:NN " \textquotedbl
+	\char_set_active_eq:NN ' \textquotesingle
+	\char_set_active_eq:NN & \&
+}
+\cs_new:Nn \_@@_escape_xml_activate: {
+	\char_set_catcode_active:N >
+	\char_set_catcode_active:N <
+	\char_set_catcode_active:N "
+	\char_set_catcode_active:N '
+	\char_set_catcode_active:N &
+}
+%    \end{macrocode}
+% \end{implementation}
+% \begin{documentation}
 % \subsection{Rounding Interface}
 % \label{sec:rounding-interface}
 % \changes{v0.9a}{2024-11-07}{Add public interface for the rounding mechanism.}
@@ -1268,8 +1325,19 @@
 %    \end{macrocode}
 % \end{implementation}
 % \begin{documentation}
-% \DescribeKeyOption{document-type=commercial-invoice}{commercial-invoice}
-% Select the document type. The only supported value currently is |commercial-invoice|. This will select the corresponding type code, which is 380.
+% \DescribeKeyOption{document-type=\meta{type}}{commercial-invoice}
+% Select the document type. Since \version{0.9c} \pkg{zugferd} supports the following types:
+% \changes{v0.9c}{2024-12-08}{Add support for other invoice types.}
+% \begin{valuelist}
+% \item[commercial-invoice] 380
+% \item[partial-invoice] 326
+% \item[corrected-invoice] 384
+% \item[self-billed-invoice] 389
+% \item[credit-note] 381
+% \item[partial-construction-invoice] 875
+% \item[partial-final-construction-invoice] 876
+% \item[final-construction-invoice] 877
+% \end{valuelist}
 % \end{documentation}
 % \begin{implementation}
 % \begin{optionenv}{id, document-type}
@@ -1277,6 +1345,20 @@
 	document-type .choice:,
 	document-type / commercial-invoice .code:n =
 		\tl_gset:Nn \g_@@_DocumentTypeCode_tl {380},
+	document-type / partial-invoice .code:n =
+		\tl_gset:Nn \g_@@_DocumentTypeCode_tl {326},
+	document-type / corrected-invoice .code:n =
+		\tl_gset:Nn \g_@@_DocumentTypeCode_tl {384},
+	document-type / self-billed-invoice .code:n =
+		\tl_gset:Nn \g_@@_DocumentTypeCode_tl {389},
+	document-type / credit-note .code:n =
+		\tl_gset:Nn \g_@@_DocumentTypeCode_tl {381},
+	document-type / partial-construction-invoice .code:n =
+		\tl_gset:Nn \g_@@_DocumentTypeCode_tl {875},
+	document-type / partial-final-construction-invoice .code:n =
+		\tl_gset:Nn \g_@@_DocumentTypeCode_tl {876},
+	document-type / final-construction-invoice	.code:n =
+		\tl_gset:Nn \g_@@_DocumentTypeCode_tl {877},
 	document-type .initial:n = commercial-invoice,
 %    \end{macrocode}
 % \end{optionenv}
@@ -1443,13 +1525,18 @@
 % As this also depends on the selected scheme and version we will not list the details.
 % All fields for a trade party can be set using the \enquote{group} named by the party.
 % For example setting all the seller data is done in the following listing:
+% \changes{v0.9c}{2024-12-08}{Add support for extended Addresses including additionl legal data.}
 % \begin{examplecode}
 % \SetZUGFeRDData{
+%	seller/id = {ID – usually internal ID provided by buyer},
 %	seller/name = {peiTeX (Marei Peischl)},
+%	seller/legal-description = {Additional legal information},
+%	seller/legal-id = {legal registration ID},
+%	seller/trading-name = {trading name},
 %	seller/email = {invoicing at peitex.de},
 %	seller/vatid = {DE123456789},
 %	seller/contact= {Marei\\+4900000000\\marei at peitex.de},
-%	seller/address = {Address Line 1\\Address Line 2},
+%	seller/address = {Address Line 1\\Address Line 2\\Address Line 3},
 %	seller/postcode = {20253},
 %	seller/city ={Hamburg},
 %	seller/country = {DE},
@@ -1465,16 +1552,21 @@
 % \DescribeKeyOption*{\meta{party}/name=\meta{name}}{}*
 % \DescribeKeyOption*{\meta{party}/email=\meta{email address}}{}*
 % \DescribeKeyOption*{\meta{party}/vatid=\meta{VAT ID}}{}*
+% \DescribeKeyOption*{\meta{party}/taxid=\meta{VAT ID}}{}*
+% \changes{v0.9c}{2024-12-08}{Add support for taxid.}
 %
 % \DescribeKeyOption*{\meta{party}/address=\meta{address}}{}*
-% As shown in the example \option{address} can use two lines separted by |\\|.
+% \changes{v0.9c}{2024-12-08}{Add support for third address line.}
+% As shown in the example \option{address} can use three lines separted by |\\|.
 % It's possble to set all fields for all trade contacts, but e.\,g. for the |shipto|-party email and vatid will not be used in the \XML.
 %
-% Alternatively it's also possible to use \option{\meta{party}/lineone} and \option{\meta{party/linetwo}} separately.
+% Alternatively it's also possible to use \option{\meta{party}/lineone}, \option{\meta{party}/linetwo} and \option{\meta{party}/linethree} separately.
 % This may be helpful if you use a custom input format. In any way you should ensure that all macros used within the data either are expandable or disabled using \cs[no-index]{zugferd_disable_macros:}.
 %
 % \DescribeKeyOption*{\meta{party}/postcode=\meta{postal code}}{}*
 % \DescribeKeyOption*{\meta{party}/city=\meta{city}}{}*
+% \DescribeKeyOption*{\meta{party}/subdivision=\meta{subdivision}}{}*
+% \changes{v0.9c}{2024-12-08}{Add support for subdivision.}
 % \DescribeKeyOption*{\meta{party}/country=\meta{country code}}{}*
 % The two letter country codes allowed here can be found in \cite{country-codes}.
 %
@@ -1529,7 +1621,8 @@
 			%TODO error if more than 2 lines or only 1
 			\keys_set:nx {zugferd / #1} {
 				lineone=\seq_item:Nn \l_tmpa_seq {1},
-				linetwo=\seq_item:Nn \l_tmpa_seq {2}
+				linetwo=\seq_item:Nn \l_tmpa_seq {2},
+				linethree=\seq_item:Nn \l_tmpa_seq {3}
 			}
 		},
 		contact .code:n = {
@@ -1558,18 +1651,29 @@
 %    \end{macrocode}
 % \end{variable}
 % \end{optionenv}
-% \begin{function}{\_@@_PostalTradeAddress:N,\_@@_DefinedTradeContact:N}
+% \begin{function}{\_@@_TradePartyIdentity:N \_@@_PostalTradeAddress:N,\_@@_DefinedTradeContact:N}
 % Wrappers to map the property list items to the writing macro.
+% \changes{v0.9c}{2024-12-08}{Add TradePartyName to support additional legal information.}
 %    \begin{macrocode}
+\cs_new:Nn \_@@_TradePartyIdentity:N {
+	\_@@_TradePartyIdentity:eeeee
+			{\prop_item:Nn #1 {id}}
+			{\prop_item:Nn #1 {name}}
+			{\prop_item:Nn #1 {legal-description}}
+			{\prop_item:Nn #1 {legal-id}}
+			{\prop_item:Nn #1 {trading-name}}
+}
 \cs_new:Nn \_@@_PostalTradeAddress_short:N {
 	\exp_args:Ne \tl_if_blank:nF {\prop_item:Nn #1 {name}}
 	{<ram:Name>\prop_item:Nn #1 {name}</ram:Name>\iow_newline:\_@@_xml_auto_indent:}
-	\_@@_PostalTradeAddress:eeeee
+	\_@@_PostalTradeAddress:eeeeeee
 		{\prop_item:Nn #1 {postcode}}
 		{\prop_item:Nn #1 {lineone}}
 		{\prop_item:Nn #1 {linetwo}}
+		{\prop_item:Nn #1 {linethree}}
 		{\prop_item:Nn #1 {city}}
 		{\prop_item:Nn #1 {country}}
+		{\prop_item:Nn #1 {subdivision}}
 }
 \cs_new:Nn \_@@_PostalTradeAddress:N {%
 	\_@@_PostalTradeAddress:eeeeeee
@@ -1576,10 +1680,12 @@
 		{\prop_item:Nn #1 {postcode}}
 		{\prop_item:Nn #1 {lineone}}
 		{\prop_item:Nn #1 {linetwo}}
+		{\prop_item:Nn #1 {linethree}}
 		{\prop_item:Nn #1 {city}}
 		{\prop_item:Nn #1 {country}}
-		{\prop_item:Nn #1 {email}}
-		{\prop_item:Nn #1 {vatid}}
+		{\prop_item:Nn #1 {subdivision}}
+	\_@@_UniversalCommunication:n {\prop_item:Nn #1 {email}}
+	\_@@_TaxRegistration:nn {\prop_item:Nn #1 {vatid}} {\prop_item:Nn #1 {taxid}}
 }%
 \cs_new:Nn \_@@_DefinedTradeContact:N {%
 	\_@@_DefinedTradeContact:eeee
@@ -1594,10 +1700,31 @@
 \cctab_begin:N \g_@@_xml_cctab%
 %    \end{macrocode}
 % \iffalse
-% \_@@_PostalTradeAddress:nnnnnnn Name/Firma PLZ Zeile1 Zeile2 Ort Ländercode Email UID
+% \_@@_TradePartyIdentity:eeeee ID Name description legal-id trading-name
 % \fi
 %    \begin{macrocode}
-\_@@_define_xml_content:Nn \_@@_PostalTradeAddress:nnnnn {%
+\_@@_define_xml_content:Nn \_@@_TradePartyIdentity:nnnnn {%
+	%%<!-- BT-29 -->
+	\_@@_write_inline:nn {ram:ID} {#1}
+	%%<!-- BT-27 -->
+	\_@@_write_inline:nn {ram:Name} {#2}
+	%%<!-- BT-33 -->
+	\_@@_write_inline:nn {ram:Description} {#3}
+	\tl_if_blank:eF {#4#5} {%
+	<ram:SpecifiedLegalOrganization>
+	%%%<!-- BT-30 -->
+	\_@@_write_inline_i:nnn {ram:ID} {~schemeID="0088"} {#4}
+	%%<!-- BT-28 -->
+	\_@@_write_inline_i:nn {ram:TradingBusinessName} {#5}
+	</ram:SpecifiedLegalOrganization>
+	}%
+}%
+%    \end{macrocode}
+% \iffalse
+% \_@@_PostalTradeAddress:nnnnnnn Name/Firma PLZ Zeile1 Zeile2 Zeile3 Ort Ländercode Bundesland/Bezirk
+% \fi
+%    \begin{macrocode}
+\_@@_define_xml_content:Nn \_@@_PostalTradeAddress:nnnnnnn {%
 	<ram:PostalTradeAddress>
 	\bool_if:NF \g_@@_minimum_bool {%
 		\_@@_indent: <ram:PostcodeCode>#1</ram:PostcodeCode>
@@ -1607,27 +1734,43 @@
 		\tl_if_blank:nF {#3} {%
 			\_@@_indent: <ram:LineTwo>#3</ram:LineTwo>
 		}%
-		\_@@_indent: <ram:CityName>#4</ram:CityName>
+		\tl_if_blank:nF {#4} {%
+			\_@@_indent: <ram:LineThree>#4</ram:LineThree>
+		}%
+		\_@@_indent: <ram:CityName>#5</ram:CityName>
 	}%
-	\_@@_indent: <ram:CountryID>#5</ram:CountryID>
+	\_@@_indent: <ram:CountryID>#6</ram:CountryID>
+	\bool_if:NF \g_@@_minimum_bool {%
+		\tl_if_blank:nF {#7} {%
+			\_@@_indent: <ram:CountrySubDivisionName>#7</ram:CountrySubDivisionName>
+		}%
+	}%
 	</ram:PostalTradeAddress>%
-}
-\_@@_define_xml_content:Nn \_@@_PostalTradeAddress:nnnnnnn {%
-	\_@@_PostalTradeAddress:nnnnn {#1} {#2} {#3} {#4} {#5}%
-	\bool_lazy_or:nnF {\g_@@_minimum_bool}%
-			{\tl_if_blank_p:n {#6}}%
-		{%
-			\_@@_xml_newline_indent:%
+}%
+\bool_if:NTF \g_@@_minimum_bool {%
+	\cs_set_eq:NN \_@@_UniversalCommunication:n \use_none:n%
+} {%
+	\_@@_define_xml_content:Nn \_@@_UniversalCommunication:n {%
+		\tl_if_blank:eF {#1} {
 			<ram:URIUniversalCommunication>
-			\_@@_indent: <ram:URIID~schemeID="EM">#6</ram:URIID>
+			\_@@_indent: <ram:URIID~schemeID="EM">#1</ram:URIID>
 			</ram:URIUniversalCommunication>%
 		}%
-	% TODO add support local tax id: schemaID="FC"
-	\tl_if_empty:nF {#7} {
+	}%
+}%
+\_@@_define_xml_content:Nn \_@@_TaxRegistration:nn {%
+	%%%<!-- BT-34 -->
+	\tl_if_blank:eF {#1} {
 		<ram:SpecifiedTaxRegistration>
-		\_@@_indent: <ram:ID~schemeID="VA">#7</ram:ID>
+		\_@@_indent: <ram:ID~schemeID="VA">#1</ram:ID>
 		</ram:SpecifiedTaxRegistration>%
 	}%
+	%%%<!-- BT-32 -->
+	\tl_if_blank:eF {#2} {
+		<ram:SpecifiedTaxRegistration>
+		\_@@_indent: <ram:ID~schemeID="FC">#2</ram:ID>
+		</ram:SpecifiedTaxRegistration>%
+	}%
 }%
 %
 % Contact data phone/email to a specific contact person
@@ -1668,7 +1811,7 @@
 	\_@@_write_xml:n {<ram:SellerTradeParty>}%
 	\int_gincr:N \g_@@_indent_int%
 	\_@@_write_xml:e {%
-		<ram:Name>\prop_item:Nn \g_@@_seller_AddressData_prop {name}</ram:Name>
+		\_@@_TradePartyIdentity:N \g_@@_seller_AddressData_prop
 		\_@@_DefinedTradeContact:N \g_@@_seller_AddressData_prop%
 		\_@@_PostalTradeAddress:N \g_@@_seller_AddressData_prop%
 	}%
@@ -1679,7 +1822,7 @@
 	}%
 	\int_gincr:N \g_@@_indent_int%
 	\_@@_write_xml:e {%
-		<ram:Name>\prop_item:Nn \g_@@_buyer_AddressData_prop {name}</ram:Name>%
+		\_@@_TradePartyIdentity:N \g_@@_buyer_AddressData_prop
 		\bool_if:NF \g_@@_minimum_bool {
 			\_@@_DefinedTradeContact:N \g_@@_buyer_AddressData_prop%
 			\_@@_PostalTradeAddress:N \g_@@_buyer_AddressData_prop%
@@ -1687,6 +1830,9 @@
 	}%
 	\int_gdecr:N \g_@@_indent_int%
 	\_@@_write_xml:n {</ram:BuyerTradeParty>}%
+	\clist_map_inline:nn {SellerOrder,BuyerOrder,Contract} {%
+		\_@@_write_ReferencedDocument:n {##1}%
+	}%
 	\int_gdecr:N \g_@@_indent_int%
 	\_@@_write_xml:n {</ram:ApplicableHeaderTradeAgreement>}%
 	\bool_if:NTF \g_@@_minimum_bool%
@@ -1726,8 +1872,8 @@
 }%
 %
 \cctab_end:
+\cs_generate_variant:Nn \_@@_TradePartyIdentity:nnnnn {eeeee}
 \cs_generate_variant:Nn \_@@_DefinedTradeContact:nnnn {eeee}
-\cs_generate_variant:Nn \_@@_PostalTradeAddress:nnnnn {eeeee}%
 \cs_generate_variant:Nn \_@@_PostalTradeAddress:nnnnnnn {eeeeeee}
 \cs_generate_variant:Nn \_@@_ApplicableHeaderTradeDelivery:n {V}
 %    \end{macrocode}
@@ -1760,6 +1906,36 @@
 % \end{optionenv}
 % \end{implementation}
 % \begin{documentation}
+% \subsubsection{Document references}
+% Additionally to the general buyer reference there may be additional data used by the buyer a reference.
+% These fields are technically optional, but the buyer may enforce them to be used.
+% These were not supported before \version{0.9c}.
+% \end{documentation}
+% \begin{implementation}
+%    \begin{macrocode}
+\prop_new:N \g_@@_document_references_prop
+\clist_new:N \g_@@_buyer_document_references_clist
+\keys_define:nn {zugferd} {
+	contract-reference .prop_gput:N =  \g_@@_document_references_prop,
+	purchaseorder-reference .prop_gput:N =  \g_@@_document_references_prop,
+	purchase-order-reference .meta:n = {purchaseorder-reference=#1},
+	salesorder-reference .prop_gput:N =  \g_@@_document_references_prop,
+	sales-order-reference .meta:n = {salesorder-reference=#1},
+}
+\cctab_begin:N \g_@@_xml_cctab%
+\_@@_define_xml_writer:Nn \_@@_write_ReferencedDocument:n {%
+	\prop_if_in:NeT \g_@@_document_references_prop {\str_lowercase:n {#1}-reference} {%
+		\_@@_write_xml:e {%
+		<ram:#1ReferencedDocument>
+		\_@@_indent:<ram:IssuerAssignedID>\prop_item:Ne \g_@@_document_references_prop {\str_lowercase:n {#1}-reference}</ram:IssuerAssignedID>
+		</ram:#1ReferencedDocument>%
+		}%
+	}%
+}%
+\cctab_end:
+%    \end{macrocode}
+% \end{implementation}
+% \begin{documentation}
 % \subsubsection{Payment Means}
 % \label{sec:PaymentMeans}
 % The payment means are selected by numeric codes.
@@ -2095,15 +2271,21 @@
 %    \end{macrocode}
 % \endoptionenv
 %    \begin{macrocode}
-\_@@_define_xml_writer:Nn \_@@_write_inline:nn {
-	\tl_if_blank:nF {#2} {
-		<#1>#2</#1>
+\_@@_define_xml_content:Nn \_@@_write_inline:nn {
+	\_@@_write_inline:nnn {#1} {} {#2}
+}
+\_@@_define_xml_content:Nn \_@@_write_inline:nnn {
+	\tl_if_blank:nF {#3} {
+		<#1#2>#3</#1>
 	}
 }
 \cs_generate_variant:Nn \_@@_write_inline:nn {ne}
-\_@@_define_xml_writer:Nn  \_@@_write_inline_i:nn {
-	\_@@_indent: \_@@_write_inline:nn {#1} {#2}
+\_@@_define_xml_content:Nn  \_@@_write_inline_i:nnn {
+	\_@@_indent: \_@@_write_inline:nnn {#1} {#2} {#3}
 }
+\_@@_define_xml_content:Nn  \_@@_write_inline_i:nn {
+	\_@@_write_inline_i:nnn {#1} {} {#2}
+}
 \cctab_begin:N \g_@@_xml_cctab%
 %
 \bool_if:NTF \g_@@_minimum_bool {%
@@ -2211,10 +2393,13 @@
 %    \end{macrocode}
 % \end{function}
 % \begin{function}{\_@@_SpecifiedTradeProduct:nn}
+% \changes{v0.9c}{2024-12-08}{Don't use SellerAssignedID if format=basic, \issue{28}}
 %    \begin{macrocode}
-\_@@_define_xml_writer:Nn \_@@_SpecifiedTradeProduct:nn {%
+\_@@_define_xml_content:Nn \_@@_SpecifiedTradeProduct:nn {%
 	<ram:SpecifiedTradeProduct>
-	\tl_if_empty:nF {#1} {%
+	\bool_lazy_or:nnF%
+			{\tl_if_blank_p:n {#1}}%
+			{\str_if_eq_p:Vn \g_@@_conformance_level_str {BASIC}} {%
 		\_@@_indent: <ram:SellerAssignedID>#1</ram:SellerAssignedID>
 	}%
 	\_@@_indent: <ram:Name>#2</ram:Name>
@@ -2379,6 +2564,13 @@
 	\int_gincr:N \g_@@_indent_int%
 	\_@@_write_rounded:nnn {2} {CalculatedAmount} {#4}%BT117
 	\_@@_write_xml:n {<ram:TypeCode>VAT</ram:TypeCode>}%BT118
+%    \end{macrocode}
+% \changes{v0.9c}{2024-12-08}{Call exemption-reason-auto also locally inside ApplicableTradeTaxEntry}
+%    \begin{macrocode}%
+	\begingroup
+	\bool_if:NT \g_@@_auto_exemption_bool {%
+		\keys_set:nn  { zugferd / tax } {exemption-reason-auto=#1}
+	}%
 	\tl_if_blank:VF \l_@@_tax_exemption_reason_tl {%BT-120
 		\_@@_write_xml:e {<ram:ExemptionReason>
 			\l_@@_tax_exemption_reason_tl
@@ -2386,11 +2578,18 @@
 	}
 	{{\_@@_write_rounded:nnn {2} {BasisAmount} {#3}}}%BT-116
 	\_@@_write_xml:e {<ram:CategoryCode>#1</ram:CategoryCode>}%BT-118
-	\tl_if_blank:VF \l_@@_tax_exemption_code_tl {%BT121
-		\_@@_write_xml:e {<ram:ExemptionReasonCode>
-			\l_@@_tax_exemption_code_tl
-			</ram:ExemptionReasonCode>}
-	}
+%    \end{macrocode}
+% \changes{v0.9c}{2024-12-08}{Don't use exception-reason-code if format=BASIC \issue{28}}
+%    \begin{macrocode}
+	\bool_lazy_or:nnF%	BT121
+		{\tl_if_blank_p:V \l_@@_tax_exemption_code_tl}%
+		{\str_if_eq_p:Vn \g_@@_conformance_level_str {BASIC}}%
+	{%
+		\_@@_write_xml:e {%
+			<ram:ExemptionReasonCode>\l_@@_tax_exemption_code_tl</ram:ExemptionReasonCode>%
+		}%
+	}%
+	\endgroup
 	\_@@_write_xml:n {<ram:RateApplicablePercent>#2</ram:RateApplicablePercent>}%BT-119
 	\int_gdecr:N \g_@@_indent_int%
 	\_@@_write_xml:n {</ram:ApplicableTradeTax>}
@@ -2398,9 +2597,6 @@
 %
 \cctab_begin:N \g_@@_xml_cctab%
 % ApplicableHeaderTradeSettlement
-\_@@_define_xml_writer:Nn \_@@_ApplicableHeaderTradeSettlement:nnnnnnnn {%
-
-}%
 %    \end{macrocode}
 % ApplicableHeaderTradeSettlement needs to be splitted to be used in separate parts of the tabular.
 %    \begin{macrocode}

Modified: trunk/Master/texmf-dist/tex/latex/zugferd/zugferd-invoice.sty
===================================================================
--- trunk/Master/texmf-dist/tex/latex/zugferd/zugferd-invoice.sty	2024-12-09 21:13:19 UTC (rev 73080)
+++ trunk/Master/texmf-dist/tex/latex/zugferd/zugferd-invoice.sty	2024-12-09 21:13:34 UTC (rev 73081)
@@ -12,7 +12,7 @@
 % and version 1.3c or later is part of all distributions of LaTeX
 % version 2008-05-04 or later.
 %
-\ProvidesExplPackage{zugferd-invoice}{2024-11-17}{0.9b}{Invoice wrapper example package for the factur-x to create ZUGFerD invoices}
+\ProvidesExplPackage{zugferd-invoice}{2024-12-08}{0.9c}{Invoice wrapper example package for the factur-x to create ZUGFerD invoices}
 
 \keys_define:nn {zugferd/invoice}{
 	default-vat .tl_set:N =  \defaultVAT,
@@ -124,7 +124,7 @@
 	\PrintInvoiceSum{netto}{\fp_use:N  \g__ptxcd_invoice_sum_fp}
 	\seq_map_inline:Nn \g__ptxcd_VAT_rates_seq  {
 		\fp_compare:nNnF {\fp_use:c {g__ptxcd_invoice_sum_vat##1_fp}} = {0} {
-			\zugferd_write_TaxEntry:nnnn  {\use:c {__ptxcd_invoice_type_code##1:}} {##1} {\fp_use:c {g__ptxcd_invoice_base_vat##1_fp}} {\fp_use:c {g__ptxcd_invoice_sum_vat##1_fp}}
+			\zugferd_write_TaxEntry:ennn  {\use:c {__ptxcd_invoice_type_code##1:}} {##1} {\fp_use:c {g__ptxcd_invoice_base_vat##1_fp}} {\fp_use:c {g__ptxcd_invoice_sum_vat##1_fp}}
 			\fp_gadd:Nn \g__ptxcd_tax_total_fp {\fp_use:c {g__ptxcd_invoice_sum_vat##1_fp}}
 			\PrintVatSum[{\fp_use:c {g__ptxcd_invoice_base_vat##1_fp}}]{##1 }{\fp_use:c {g__ptxcd_invoice_sum_vat##1_fp}}
 		}

Modified: trunk/Master/texmf-dist/tex/latex/zugferd/zugferd.sty
===================================================================
--- trunk/Master/texmf-dist/tex/latex/zugferd/zugferd.sty	2024-12-09 21:13:19 UTC (rev 73080)
+++ trunk/Master/texmf-dist/tex/latex/zugferd/zugferd.sty	2024-12-09 21:13:34 UTC (rev 73081)
@@ -9,7 +9,7 @@
 %% Copyright (C) 2023--2024 by Marei Peischl (peiTeX) <marei at peitex.de>
 %% 
 \NeedsTeXFormat{LaTeX2e}[2023-11-01]
-\ProvidesExplPackage{zugferd}{2024-11-17}{0.9b}{Create ZUGFerd invoices using LaTeX}
+\ProvidesExplPackage{zugferd}{2024-12-08}{0.9c}{Create ZUGFerd invoices using LaTeX}
 \tl_new:N \l__zugferd_tmp_tl
 \str_new:N \g__zugferd_format_str
 \str_new:N \g__zugferd_businessProcessId_str
@@ -94,7 +94,7 @@
 }
 \msg_error:nn {zugferd} {PDFmanagement-not-active}
 }
-\IfPackageAtLeastF{pdfmanagement-testphase}{2024/09/13}{
+\IfPackageAtLeastTF{pdfmanagement-testphase}{2024/09/13}{}{
 \msg_new:nnn {zugferd} {PDFmanagement-too-old} {
 Your~version~of~\LaTeX's~PDF~management~is~too~old.
 You~need~to~update~your~LaTeX~distribution~to~be~able~to~use~the~zugferd~package~correctly.
@@ -237,14 +237,10 @@
 \pdfdict_put:nnn {l_pdffile/Filespec} {Desc}{(Factur-X/ZUGFeRD-Rechnung)}
 \exp_args:NnV \pdffile_embed_file:nnn {\g__zugferd_xml_file_tl} \g__zugferd_xml_embedded_file_tl
 {zugferd/rechnung}
+\group_end:
 \pdfmanagement_add:nee
-  {Catalog/Names/EmbeddedFiles}
-  {\g__zugferd_xml_embedded_file_tl}
-  {\pdf_object_ref:n{zugferd/rechnung}}
-\group_end:
-\pdfmanagement_add:nnx
-{Catalog/Names}
-{EmbeddedFiles}
+{Catalog/Names/EmbeddedFiles}
+{\g__zugferd_xml_embedded_file_tl}
 {\pdf_object_ref:n{zugferd/rechnung}}
 \pdfmanagement_add:nnx{Catalog}{AF}{\pdf_object_ref:n{zugferd/rechnung}}
 }
@@ -306,6 +302,7 @@
 \group_end:
 }
 \cs_generate_variant:Nn \zugferd_write_Item:nnnnnnn {ennnnnn}
+\cs_generate_variant:Nn \zugferd_write_TaxEntry:nnnn {ennn}
 \bool_if:NTF \g__zugferd_write_xml_bool {
 \cs_new:Nn \__zugferd_write_xml:n {
 \iow_now:Ne \__zugferd_xml_writer_iow {\__zugferd_xml_auto_indent: #1}
@@ -367,17 +364,20 @@
 %% 2019-2024 LaTeX Project
 %% modifications have been made to support the mechanism if hyperref is not loaded
 \cs_new:Nn \zugferd_disable_macros: {
-\let\{\textbraceleft
-\let\}\textbraceright
-\let\\\textbackslash
-\let\#\textnumbersign
-\let\$\textdollar
-\let\%\textpercent
-\let\&\textampersand
-\let\_\textunderscore
-\let\P\textparagraph
-\let\ldots\textellipsis
-\let\dots\textellipsis
+\let\{\c_left_brace_str
+\let\textbraceleft\c_left_brace_str
+\let\}\c_right_brace_str
+\let\textbraceright\c_right_brace_str
+\let\#\c_hash_str
+\let\textnumbersign\c_hash_str
+\let\$\c_dollar_str
+\let\textdollar\c_dollar_str
+\let\%\c_percent_str
+\let\&\c_ampersand_str
+\let\_\c_underscore_str
+\def\P{§}
+\def\ldots{…}
+\def\dots{…}
 \def\\{\space}%
 \def\newline{\space}%
 \def\TeX{TeX}%
@@ -471,6 +471,41 @@
 \hook_use:n {zugferd/disable-macros}
 }
 \hook_new:n {zugferd/disable-macros}
+\tl_new:N \g__zugferd_tmp_tl
+\cs_new:Nn \zugferd_tl_gset_escaped_xml:Nn {
+\group_begin:
+\zugferd_disable_macros:
+\__zugferd_escape_xml_aux:
+\tl_gset_rescan:Nnn #1 {
+\cctab_select:N \c_str_cctab
+\__zugferd_escape_xml_activate:
+ } {#2}
+\tl_gset:Ne #1 {#1}
+\group_end:
+}
+\cs_new:Nn \zugferd_tl_set_escaped_xml:Nn {
+\zugferd_tl_gset_escaped_xml:Nn \g__zugferd_tmp_tl {#2}
+\tl_set_eq:NN #1 \g__zugferd_tmp_tl
+}
+\cs_new:Nn \__zugferd_escape_xml_aux: {
+\edef\&{\tl_to_str:n {&}}
+\edef\textgreater{\tl_to_str:n {>}}
+\edef\textless{\tl_to_str:n {<}}
+\edef\textquotedbl{\tl_to_str:n {"}}
+\edef\textquotesingle{\tl_to_str:n {'}}
+\char_set_active_eq:NN > \textgreater
+\char_set_active_eq:NN < \textless
+\char_set_active_eq:NN " \textquotedbl
+\char_set_active_eq:NN ' \textquotesingle
+\char_set_active_eq:NN & \&
+}
+\cs_new:Nn \__zugferd_escape_xml_activate: {
+\char_set_catcode_active:N >
+\char_set_catcode_active:N <
+\char_set_catcode_active:N "
+\char_set_catcode_active:N '
+\char_set_catcode_active:N &
+}
 \cs_set:Nn \zugferd_fp_set_rounded:Nn {
 \__zugferd_number_format:nNn {2} \l__zugferd_tmp_tl {\fp_eval:n {#2}}
 \fp_set:Nn  #1 {\l__zugferd_tmp_tl }
@@ -491,6 +526,20 @@
 document-type .choice:,
 document-type / commercial-invoice .code:n =
 \tl_gset:Nn \g__zugferd_DocumentTypeCode_tl {380},
+document-type / partial-invoice .code:n =
+\tl_gset:Nn \g__zugferd_DocumentTypeCode_tl {326},
+document-type / corrected-invoice .code:n =
+\tl_gset:Nn \g__zugferd_DocumentTypeCode_tl {384},
+document-type / self-billed-invoice .code:n =
+\tl_gset:Nn \g__zugferd_DocumentTypeCode_tl {389},
+document-type / credit-note .code:n =
+\tl_gset:Nn \g__zugferd_DocumentTypeCode_tl {381},
+document-type / partial-construction-invoice .code:n =
+\tl_gset:Nn \g__zugferd_DocumentTypeCode_tl {875},
+document-type / partial-final-construction-invoice .code:n =
+\tl_gset:Nn \g__zugferd_DocumentTypeCode_tl {876},
+document-type / final-construction-invoice .code:n =
+\tl_gset:Nn \g__zugferd_DocumentTypeCode_tl {877},
 document-type .initial:n = commercial-invoice,
 id .choice:,
 id / komavar .code:n = \tl_gset:Nf \g__zugferd_id_tl {\scr at invoice@var},
@@ -562,7 +611,8 @@
 \seq_set_split:Nnn \l_tmpa_seq {\\} {##1}
 \keys_set:nx {zugferd / #1} {
 lineone=\seq_item:Nn \l_tmpa_seq {1},
-linetwo=\seq_item:Nn \l_tmpa_seq {2}
+linetwo=\seq_item:Nn \l_tmpa_seq {2},
+linethree=\seq_item:Nn \l_tmpa_seq {3}
 }
 },
 contact .code:n = {
@@ -588,15 +638,25 @@
 }
 }
 }
+\cs_new:Nn \__zugferd_TradePartyIdentity:N {
+\__zugferd_TradePartyIdentity:eeeee
+{\prop_item:Nn #1 {id}}
+{\prop_item:Nn #1 {name}}
+{\prop_item:Nn #1 {legal-description}}
+{\prop_item:Nn #1 {legal-id}}
+{\prop_item:Nn #1 {trading-name}}
+}
 \cs_new:Nn \__zugferd_PostalTradeAddress_short:N {
 \exp_args:Ne \tl_if_blank:nF {\prop_item:Nn #1 {name}}
 {<ram:Name>\prop_item:Nn #1 {name}</ram:Name>\iow_newline:\__zugferd_xml_auto_indent:}
-\__zugferd_PostalTradeAddress:eeeee
+\__zugferd_PostalTradeAddress:eeeeeee
 {\prop_item:Nn #1 {postcode}}
 {\prop_item:Nn #1 {lineone}}
 {\prop_item:Nn #1 {linetwo}}
+{\prop_item:Nn #1 {linethree}}
 {\prop_item:Nn #1 {city}}
 {\prop_item:Nn #1 {country}}
+{\prop_item:Nn #1 {subdivision}}
 }
 \cs_new:Nn \__zugferd_PostalTradeAddress:N {%
 \__zugferd_PostalTradeAddress:eeeeeee
@@ -603,10 +663,12 @@
 {\prop_item:Nn #1 {postcode}}
 {\prop_item:Nn #1 {lineone}}
 {\prop_item:Nn #1 {linetwo}}
+{\prop_item:Nn #1 {linethree}}
 {\prop_item:Nn #1 {city}}
 {\prop_item:Nn #1 {country}}
-{\prop_item:Nn #1 {email}}
-{\prop_item:Nn #1 {vatid}}
+{\prop_item:Nn #1 {subdivision}}
+\__zugferd_UniversalCommunication:n {\prop_item:Nn #1 {email}}
+\__zugferd_TaxRegistration:nn {\prop_item:Nn #1 {vatid}} {\prop_item:Nn #1 {taxid}}
 }%
 \cs_new:Nn \__zugferd_DefinedTradeContact:N {%
 \__zugferd_DefinedTradeContact:eeee
@@ -616,7 +678,23 @@
 {\prop_item:Nn #1 {contact-email}}
 }%
 \cctab_begin:N \g__zugferd_xml_cctab%
-\__zugferd_define_xml_content:Nn \__zugferd_PostalTradeAddress:nnnnn {%
+\__zugferd_define_xml_content:Nn \__zugferd_TradePartyIdentity:nnnnn {%
+%%<!-- BT-29 -->
+\__zugferd_write_inline:nn {ram:ID} {#1}
+%%<!-- BT-27 -->
+\__zugferd_write_inline:nn {ram:Name} {#2}
+%%<!-- BT-33 -->
+\__zugferd_write_inline:nn {ram:Description} {#3}
+\tl_if_blank:eF {#4#5} {%
+<ram:SpecifiedLegalOrganization>
+%%%<!-- BT-30 -->
+\__zugferd_write_inline_i:nnn {ram:ID} {~schemeID="0088"} {#4}
+%%<!-- BT-28 -->
+\__zugferd_write_inline_i:nn {ram:TradingBusinessName} {#5}
+</ram:SpecifiedLegalOrganization>
+}%
+}%
+\__zugferd_define_xml_content:Nn \__zugferd_PostalTradeAddress:nnnnnnn {%
 <ram:PostalTradeAddress>
 \bool_if:NF \g__zugferd_minimum_bool {%
 \__zugferd_indent: <ram:PostcodeCode>#1</ram:PostcodeCode>
@@ -626,27 +704,44 @@
 \tl_if_blank:nF {#3} {%
 \__zugferd_indent: <ram:LineTwo>#3</ram:LineTwo>
 }%
-\__zugferd_indent: <ram:CityName>#4</ram:CityName>
+\tl_if_blank:nF {#4} {%
+\__zugferd_indent: <ram:LineThree>#4</ram:LineThree>
 }%
-\__zugferd_indent: <ram:CountryID>#5</ram:CountryID>
+\__zugferd_indent: <ram:CityName>#5</ram:CityName>
+}%
+\__zugferd_indent: <ram:CountryID>#6</ram:CountryID>
+\bool_if:NF \g__zugferd_minimum_bool {%
+\tl_if_blank:nF {#7} {%
+\__zugferd_indent: <ram:CountrySubDivisionName>#7</ram:CountrySubDivisionName>
+}%
+}%
 </ram:PostalTradeAddress>%
-}
-\__zugferd_define_xml_content:Nn \__zugferd_PostalTradeAddress:nnnnnnn {%
-\__zugferd_PostalTradeAddress:nnnnn {#1} {#2} {#3} {#4} {#5}%
-\bool_lazy_or:nnF {\g__zugferd_minimum_bool}%
-{\tl_if_blank_p:n {#6}}%
-{%
-\__zugferd_xml_newline_indent:%
+}%
+\bool_if:NTF \g__zugferd_minimum_bool {%
+\cs_set_eq:NN \__zugferd_UniversalCommunication:n \use_none:n%
+} {%
+\__zugferd_define_xml_content:Nn \__zugferd_UniversalCommunication:n {%
+\tl_if_blank:eF {#1} {
 <ram:URIUniversalCommunication>
-\__zugferd_indent: <ram:URIID~schemeID="EM">#6</ram:URIID>
+\__zugferd_indent: <ram:URIID~schemeID="EM">#1</ram:URIID>
 </ram:URIUniversalCommunication>%
 }%
-\tl_if_empty:nF {#7} {
+}%
+}%
+\__zugferd_define_xml_content:Nn \__zugferd_TaxRegistration:nn {%
+%%%<!-- BT-34 -->
+\tl_if_blank:eF {#1} {
 <ram:SpecifiedTaxRegistration>
-\__zugferd_indent: <ram:ID~schemeID="VA">#7</ram:ID>
+\__zugferd_indent: <ram:ID~schemeID="VA">#1</ram:ID>
 </ram:SpecifiedTaxRegistration>%
 }%
+%%%<!-- BT-32 -->
+\tl_if_blank:eF {#2} {
+<ram:SpecifiedTaxRegistration>
+\__zugferd_indent: <ram:ID~schemeID="FC">#2</ram:ID>
+</ram:SpecifiedTaxRegistration>%
 }%
+}%
 \__zugferd_define_xml_content:Nn \__zugferd_DefinedTradeContact:nnnn {%
 \tl_if_blank:nT {#1} {\use_none:nnn} %
 \bool_if:NT \g__zugferd_writeTradeContact_bool {%
@@ -682,7 +777,7 @@
 \__zugferd_write_xml:n {<ram:SellerTradeParty>}%
 \int_gincr:N \g__zugferd_indent_int%
 \__zugferd_write_xml:e {%
-<ram:Name>\prop_item:Nn \g__zugferd_seller_AddressData_prop {name}</ram:Name>
+\__zugferd_TradePartyIdentity:N \g__zugferd_seller_AddressData_prop
 \__zugferd_DefinedTradeContact:N \g__zugferd_seller_AddressData_prop%
 \__zugferd_PostalTradeAddress:N \g__zugferd_seller_AddressData_prop%
 }%
@@ -693,7 +788,7 @@
 }%
 \int_gincr:N \g__zugferd_indent_int%
 \__zugferd_write_xml:e {%
-<ram:Name>\prop_item:Nn \g__zugferd_buyer_AddressData_prop {name}</ram:Name>%
+\__zugferd_TradePartyIdentity:N \g__zugferd_buyer_AddressData_prop
 \bool_if:NF \g__zugferd_minimum_bool {
 \__zugferd_DefinedTradeContact:N \g__zugferd_buyer_AddressData_prop%
 \__zugferd_PostalTradeAddress:N \g__zugferd_buyer_AddressData_prop%
@@ -701,6 +796,9 @@
 }%
 \int_gdecr:N \g__zugferd_indent_int%
 \__zugferd_write_xml:n {</ram:BuyerTradeParty>}%
+\clist_map_inline:nn {SellerOrder,BuyerOrder,Contract} {%
+\__zugferd_write_ReferencedDocument:n {##1}%
+}%
 \int_gdecr:N \g__zugferd_indent_int%
 \__zugferd_write_xml:n {</ram:ApplicableHeaderTradeAgreement>}%
 \bool_if:NTF \g__zugferd_minimum_bool%
@@ -736,8 +834,8 @@
 }%
 }%
 \cctab_end:
+\cs_generate_variant:Nn \__zugferd_TradePartyIdentity:nnnnn {eeeee}
 \cs_generate_variant:Nn \__zugferd_DefinedTradeContact:nnnn {eeee}
-\cs_generate_variant:Nn \__zugferd_PostalTradeAddress:nnnnn {eeeee}%
 \cs_generate_variant:Nn \__zugferd_PostalTradeAddress:nnnnnnn {eeeeeee}
 \cs_generate_variant:Nn \__zugferd_ApplicableHeaderTradeDelivery:n {V}
 \tl_new:N \g__zugferd_buyer_reference_tl
@@ -750,6 +848,26 @@
 \tl_gset:Nn \g__zugferd_buyer_reference_tl {#1}
 }
 }
+\prop_new:N \g__zugferd_document_references_prop
+\clist_new:N \g__zugferd_buyer_document_references_clist
+\keys_define:nn {zugferd} {
+contract-reference .prop_gput:N =  \g__zugferd_document_references_prop,
+purchaseorder-reference .prop_gput:N =  \g__zugferd_document_references_prop,
+purchase-order-reference .meta:n = {purchaseorder-reference=#1},
+salesorder-reference .prop_gput:N =  \g__zugferd_document_references_prop,
+sales-order-reference .meta:n = {salesorder-reference=#1},
+}
+\cctab_begin:N \g__zugferd_xml_cctab%
+\__zugferd_define_xml_writer:Nn \__zugferd_write_ReferencedDocument:n {%
+\prop_if_in:NeT \g__zugferd_document_references_prop {\str_lowercase:n {#1}-reference} {%
+\__zugferd_write_xml:e {%
+<ram:#1ReferencedDocument>
+\__zugferd_indent:<ram:IssuerAssignedID>\prop_item:Ne \g__zugferd_document_references_prop {\str_lowercase:n {#1}-reference}</ram:IssuerAssignedID>
+</ram:#1ReferencedDocument>%
+}%
+}%
+}%
+\cctab_end:
 \ExplSyntaxOff
 \providecommand*{\zugferd at paymentMeans@german}{
  1 = Keine Zahlungsart definiert,
@@ -937,15 +1055,21 @@
 end-date .tl_gset:N = \l__zugferd_end_date_tl,
 end-date .initial:n =,
 }%
-\__zugferd_define_xml_writer:Nn \__zugferd_write_inline:nn {
-\tl_if_blank:nF {#2} {
-<#1>#2</#1>
+\__zugferd_define_xml_content:Nn \__zugferd_write_inline:nn {
+\__zugferd_write_inline:nnn {#1} {} {#2}
 }
+\__zugferd_define_xml_content:Nn \__zugferd_write_inline:nnn {
+\tl_if_blank:nF {#3} {
+<#1#2>#3</#1>
 }
+}
 \cs_generate_variant:Nn \__zugferd_write_inline:nn {ne}
-\__zugferd_define_xml_writer:Nn  \__zugferd_write_inline_i:nn {
-\__zugferd_indent: \__zugferd_write_inline:nn {#1} {#2}
+\__zugferd_define_xml_content:Nn  \__zugferd_write_inline_i:nnn {
+\__zugferd_indent: \__zugferd_write_inline:nnn {#1} {#2} {#3}
 }
+\__zugferd_define_xml_content:Nn  \__zugferd_write_inline_i:nn {
+\__zugferd_write_inline_i:nnn {#1} {} {#2}
+}
 \cctab_begin:N \g__zugferd_xml_cctab%
 \bool_if:NTF \g__zugferd_minimum_bool {%
 \cs_set_eq:NN \__zugferd_write_note:n \use_none:n%
@@ -1028,9 +1152,11 @@
 \__zugferd_indent: <ram:LineID>#1</ram:LineID>
 </ram:AssociatedDocumentLineDocument>%
 }%
-\__zugferd_define_xml_writer:Nn \__zugferd_SpecifiedTradeProduct:nn {%
+\__zugferd_define_xml_content:Nn \__zugferd_SpecifiedTradeProduct:nn {%
 <ram:SpecifiedTradeProduct>
-\tl_if_empty:nF {#1} {%
+\bool_lazy_or:nnF%
+{\tl_if_blank_p:n {#1}}%
+{\str_if_eq_p:Vn \g__zugferd_conformance_level_str {BASIC}} {%
 \__zugferd_indent: <ram:SellerAssignedID>#1</ram:SellerAssignedID>
 }%
 \__zugferd_indent: <ram:Name>#2</ram:Name>
@@ -1150,6 +1276,10 @@
 \int_gincr:N \g__zugferd_indent_int%
 \__zugferd_write_rounded:nnn {2} {CalculatedAmount} {#4}%BT117
 \__zugferd_write_xml:n {<ram:TypeCode>VAT</ram:TypeCode>}%BT118
+\begingroup
+\bool_if:NT \g__zugferd_auto_exemption_bool {%
+\keys_set:nn  { zugferd / tax } {exemption-reason-auto=#1}
+}%
 \tl_if_blank:VF \l__zugferd_tax_exemption_reason_tl {%BT-120
 \__zugferd_write_xml:e {<ram:ExemptionReason>
 \l__zugferd_tax_exemption_reason_tl
@@ -1157,19 +1287,20 @@
 }
 {{\__zugferd_write_rounded:nnn {2} {BasisAmount} {#3}}}%BT-116
 \__zugferd_write_xml:e {<ram:CategoryCode>#1</ram:CategoryCode>}%BT-118
-\tl_if_blank:VF \l__zugferd_tax_exemption_code_tl {%BT121
-\__zugferd_write_xml:e {<ram:ExemptionReasonCode>
-\l__zugferd_tax_exemption_code_tl
-</ram:ExemptionReasonCode>}
-}
+\bool_lazy_or:nnF% BT121
+{\tl_if_blank_p:V \l__zugferd_tax_exemption_code_tl}%
+{\str_if_eq_p:Vn \g__zugferd_conformance_level_str {BASIC}}%
+{%
+\__zugferd_write_xml:e {%
+<ram:ExemptionReasonCode>\l__zugferd_tax_exemption_code_tl</ram:ExemptionReasonCode>%
+}%
+}%
+\endgroup
 \__zugferd_write_xml:n {<ram:RateApplicablePercent>#2</ram:RateApplicablePercent>}%BT-119
 \int_gdecr:N \g__zugferd_indent_int%
 \__zugferd_write_xml:n {</ram:ApplicableTradeTax>}
 }%
 \cctab_begin:N \g__zugferd_xml_cctab%
-\__zugferd_define_xml_writer:Nn \__zugferd_ApplicableHeaderTradeSettlement:nnnnnnnn {%
-
-}%
 \__zugferd_define_xml_writer:Nn \__zugferd_ApplicableHeaderTradeSettlement_start: {%
 \__zugferd_write_xml:n {<ram:ApplicableHeaderTradeSettlement>}%
 \int_gincr:N \g__zugferd_indent_int%



More information about the tex-live-commits mailing list.