diff options
Diffstat (limited to 'macros/latex/contrib/zugferd/zugferd-invoice.sty')
-rw-r--r-- | macros/latex/contrib/zugferd/zugferd-invoice.sty | 197 |
1 files changed, 197 insertions, 0 deletions
diff --git a/macros/latex/contrib/zugferd/zugferd-invoice.sty b/macros/latex/contrib/zugferd/zugferd-invoice.sty new file mode 100644 index 0000000000..04fab68283 --- /dev/null +++ b/macros/latex/contrib/zugferd/zugferd-invoice.sty @@ -0,0 +1,197 @@ +% +% Copyright (C) 2024 Marei Peischl <marei@peitex.de> +% --------------------------------------------------------- +% +% This file may be distributed and/or modified under the +% conditions of the LaTeX Project Public License, either version 1.3c +% of this license or (at your option) any later version. +% The latest version of this license is in: +% +% http://www.latex-project.org/lppl.txt +% +% and version 1.3c or later is part of all distributions of LaTeX +% version 2008-05-04 or later. +% +\ProvidesExplPackage{zugferd-invoice}{2024-11-07}{0.9a}{Invoice wrapper example package for the factur-x to create ZUGFerD invoices} + +\keys_define:nn {zugferd/invoice}{ + default-vat .tl_set:N = \defaultVAT, + default-vat .initial:n = 19, + format .code:n = \PassOptionsToPackage{format=#1}{zugferd}, + format .initial:n = xrechnung3.0, +} + +\ProcessKeyOptions[zugferd/invoice] + +\msg_new:nnnn {ptxcd/zugferd} {not-for-production} { + This~package~is~intented~to~be~an~example~for~a~possible~implementation~to~use~the~zugferd~package~for~invoicing.\\ + As~this~integrates~a~lot~with~the~visual~structure~of~your~invoice~this~should~not~be~used~directly~but~may~be~an~example~for~your~own~package. +}{See~zugferd~documentation~for~instructions~concerning~the~interfaces~used~in~this~file.} +\msg_warning:nn {ptxcd/zugferd} {not-for-production} + +\RequirePackage{scrletter} +\RequirePackage{ragged2e} +\RequirePackage{zugferd} +\RequirePackage{babel} + +% e.g. use comma as output decimal marker if german +\addto\extrasgerman{\sisetup{locale=DE}} +\addto\extrasngerman{\sisetup{locale=DE}}% for backwards compatibility + +\RequirePackage{xltabular} +\RequirePackage{booktabs} + +\newcounter{invoiceitem} +\seq_new:N \g__ptxcd_VAT_rates_seq + +% InitVAT accepts 2 Arguments +% Percentage + Tax Type Code the latter one is set to S as a default +\NewDocumentCommand{\InitVAT}{mO{S}}{ + \seq_gput_right:Nn \g__ptxcd_VAT_rates_seq {#1} + \fp_new:c {g__ptxcd_invoice_sum_vat#1_fp} + \fp_new:c {g__ptxcd_invoice_base_vat#1_fp} + \cs_new:cn {__ptxcd_invoice_type_code#1:} {#2} +} + +%Initialize VAT rates for (5),7,(16) and 19 % VAT +%\InitVAT{16} +\InitVAT{19} +%\InitVAT{5} +\InitVAT{7} + +% Tax initialisation with a different Code than S in this example Syntax would be +% \InitVAT{0}[AE] + + +\newcommand*{\SetDefaultVAT}[1]{\def\defaultVAT{#1}} + + +\seq_new:N \l__ptxcd_invoice_items_seq + +% Auxiliary macro to allow setting the Invoice items at a different position as they are printed later +\NewDocumentCommand{\AddInvoiceItem}{D<>{}O{\defaultVAT}mmm}{ + \seq_put_right:Nn \l__ptxcd_invoice_items_seq { + {#2}{#3}{#4}{#5}{#1} + } +} + +\newcolumntype{P}{r<{\PrintTableCurrency}} + +\fp_new:N \g__ptxcd_invoice_sum_fp +\fp_new:N \g__ptxcd_invoice_total_fp +\fp_new:N \g__ptxcd_tax_total_fp +\fp_new:N \g__ptxcd_invoice_item_fp +\fp_new:N \g__ptxcd_invoice_item_vat_fp +\fp_new:N \g__ptxcd_invoice_sum_vat_fp + +\newcommand*{\PrintInvoiceTabular}{ +\bool_gset_true:N \g_ptxcd_first_run_bool + \begin{ZUGFeRD} + \sisetup{round-precision=2,round-mode=places,round-pad=false,table-number-alignment=right,minimum-decimal-digits=2,mode=text} + \begin{xltabular}{\linewidth}{@{}rS[round-precision=1,table-format=2.1]>{\RaggedRight}XPP@{}} + \toprule[\lightrulewidth] + \noalign{\global\let\PrintTableCurrency\relax}% + \small\emph{Pos.}&\small\emph{Std.}&\small\emph{Beschreibung}&\small\emph{Einzelpreis}&\small\emph{Gesamtpreis}\\\midrule[\heavyrulewidth] + \noalign{\global\let\PrintTableCurrency\TableCurrency}% + \endhead + \bottomrule[\lightrulewidth]\multicolumn{5}{@{}p{\textwidth}@{}}{\strut\hspace*{\fill}\footnotesize Fortsetzung auf der nächsten Seite}\endfoot + \bottomrule\endlastfoot +% Only write xml for the first run of the tabular. + \fp_compare:nNnF {\g__ptxcd_invoice_sum_fp} = {\c_zero_dim} { + \fp_gzero:N \g__ptxcd_invoice_sum_fp + \zugferd_disable_XML_interfaces: + } + \seq_map_inline:Nn \g__ptxcd_VAT_rates_seq { + \fp_gzero:c {g__ptxcd_invoice_sum_vat##1_fp} + \fp_gzero:c {g__ptxcd_invoice_base_vat##1_fp} + } + \fp_gzero:N \g__ptxcd_invoice_sum_fp + \seq_map_inline:Nn \l__ptxcd_invoice_items_seq { + \PrintInvoiceItem##1 + } + \tabularnewline + \noalign{\skip_vertical:n {-\ht\strutbox-\dp\strutbox}}%offset for extra empty row of mapping + \midrule[\heavyrulewidth] + \PrintInvoiceTotal + \end{xltabular} + \end{ZUGFeRD} +} + +\newcommand*{\PrintInvoiceTotal}{ + \zugferd_startInvoiceSums: + \fp_gset:Nn \g__ptxcd_invoice_total_fp { \g__ptxcd_invoice_sum_fp} + \fp_gzero:N \g__ptxcd_tax_total_fp + \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}} + \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}} + } + } + \PrintInvoiceSum{brutto}{\fp_eval:n {\g__ptxcd_tax_total_fp + \g__ptxcd_invoice_total_fp }} + % TODO add support for allowance, chargeTotal, and prepaid + \zugferd_write_Summation:nnnnnnnn + {\fp_use:N \g__ptxcd_invoice_sum_fp}% LineTotalAmount + {0} %ChargeTotalAmount + {0} %AllowanceTotalAmount + {\fp_use:N \g__ptxcd_invoice_sum_fp} %TaxBasisTotalAmount + {\fp_use:N \g__ptxcd_tax_total_fp} %TaxTotalAmount + {\fp_eval:n {\g__ptxcd_tax_total_fp + \g__ptxcd_invoice_total_fp }} %GrandTotalAmount + {0} % TotalPrepaidAmount + {\fp_eval:n {\g__ptxcd_tax_total_fp + \g__ptxcd_invoice_total_fp }} %DuePayableAmount = GrandTotalAmount - TotalPrepaidAmount + \zugferd_stopInvoiceSums: +} + +%Ausgabe der einzelnen Rechnungspositionen +\newcommand*{\PrintInvoiceItem}[5]{% + \stepcounter{invoiceitem}% + \theinvoiceitem%Positionsnummer + \zugferd_fp_gset_rounded:Nn \g__ptxcd_invoice_item_vat_fp {#2 * (#1/100) * #4} + \zugferd_fp_gset_rounded:Nn \g__ptxcd_invoice_item_fp {#2 * #4} + \fp_gadd:cn {g__ptxcd_invoice_base_vat#1_fp} {\g__ptxcd_invoice_item_fp} + \fp_gadd:cn {g__ptxcd_invoice_sum_vat#1_fp} {\g__ptxcd_invoice_item_vat_fp} + \fp_gadd:Nn \g__ptxcd_invoice_sum_fp {\g__ptxcd_invoice_item_fp} + + % optionen position nummer name einzel-preis anzahl gesamtpreis + \zugferd_write_Item:ennnnnn {tax/rate=#1, tax/category=\use:c {__ptxcd_invoice_type_code#1:},#5} {\theinvoiceitem} {} {#3} {#4} {#2} {\fp_use:N \g__ptxcd_invoice_item_fp} + + % Anzahl + \space(\printVAT{#1}~MwSt.)% Beschreibung mit Angabe der MwSt, in Klammern + &\num{#4}%\num[round-mode=places,output-decimal-marker={,},round-pad = false]{#4}\tl_show:n {#4}%Einzelpreis + &\exp_args:Nx \num{\fp_use:N \g__ptxcd_invoice_item_fp} + \tabularnewline +} + + + +\newcommand*{\PrintInvoiceSum}[2]{ + \PrintSum{\csname invoicesum#1name\endcsname}{#2} +} + +\newcommand*{\PrintVatSum}[3][]{ + \PrintSum{\invoicesumvatname[#1]{#2}}{#3} +} + +\newcommand*{\invoicesumvatname}[2][]{MwSt.~\printVAT{#2}\tl_if_empty:nF {#1} {\space(\num[round-precision=2]{#1}\TableCurrency)}} +\renewcommand*{\theinvoiceitem}{\int_compare:nNnT {\value{invoiceitem}}<{10}{0}\arabic{invoiceitem}} + +\newcommand*{\PrintSum}[2]{ + &&\multicolumn{1}{r}{#1\invoicesumseparator}&\multicolumn{1}{l}{}&\exp_args:Nx \num {#2}\tabularnewline +} + +\ExplSyntaxOff + +\newcommand*{\invoicesumnettoname}{Summe (Netto)} +\newcommand*{\invoicesumbruttoname}{Summe (Brutto)} +\newcommand*{\invoicesumseparator}{:\space} + +\newcommand*{\TableCurrency}{\,€} +\newcommand*{\printVAT}[1]{\num[round-mode=none]{#1}\,\%} + +\newcommand*{\PrintPositionenVAT}[5]{% + \stepcounter{invoiceitem}% + \theinvoiceitem\space(\printVAT{#3})\tabularnewline +} + +\endinput |