summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/qrbill/qrbill.dtx
diff options
context:
space:
mode:
Diffstat (limited to 'macros/latex/contrib/qrbill/qrbill.dtx')
-rw-r--r--macros/latex/contrib/qrbill/qrbill.dtx243
1 files changed, 217 insertions, 26 deletions
diff --git a/macros/latex/contrib/qrbill/qrbill.dtx b/macros/latex/contrib/qrbill/qrbill.dtx
index e2b228f2ae..aa632a6845 100644
--- a/macros/latex/contrib/qrbill/qrbill.dtx
+++ b/macros/latex/contrib/qrbill/qrbill.dtx
@@ -54,7 +54,7 @@
% \fi
% \iffalse
%<*driver>
-\ProvidesFile{qrbill.dtx}[2022/07/02 v1.04 \ create QR-bills based on the Swiss standard]
+\ProvidesFile{qrbill.dtx}[2022/09/15 v1.05 \ create QR-bills based on the Swiss standard]
\documentclass[english, parskip=half-]{scrartcl}
\usepackage{iftex}
\ifPDFTeX
@@ -180,6 +180,7 @@
% \publishers{A collaborative project of pei\TeX{} and foobar LLC}
% \date{\filedate}
% \maketitle
+% \tableofcontents
% \section{Introduction}
% qrbill.sty, the \LaTeX-package, is the Free Software and Open Source answer to the launch of the swiss payments conversion, introduced mid 2020, replacing the former payment order slip by a restructured, QR enhanced slip. The published source code is based on the payment standard guidelines issued for Switzerland and intentionally has a modular structure to enable further development and adaptation for international use.
%
@@ -247,6 +248,10 @@
% \item[creditorprefix\\debtorprefix (String) (CR-/UD-)]
% For custom setups the predefined prefixes for the debtor and creditoraddress can be changes. The initial configuration is a requirement of the Swiss standards.
%
+% \item[data-to-string (true/false) (false)]
+% Converts data to be used to setup the billing QRcode into a string. This option has to be updated if the data should not be treated as ordinary \LaTeX{} code.
+% You can use this to automatically escape special characters.\changes{v1.05}{2022/09/15}{add data-to-string option}
+%
% \item[font (Frutiger/Arial/Helvetica/Liberation Sans/custom) (Liberation Sans)]
% \label{opt:font}
% The official guideline for the Swiss qrbill limits the choice of the font to the first four values of this option. The font selection and sizes currently hardcoded to fit to the size. Custom setups might be provided in the future.
@@ -258,8 +263,9 @@
% \renewcommand*{\qrbillfont}{\fontspec{Laconic}}
% \end{doccode}
%
-% \item[frame (true/false/top/bottom) (true)]
+% \item[frame (true/false/top/bottom/none) (true)]
% Switch to disable the frame around the created QRbill. The top/bottom options should be prefered when the bill is embedded into a document of a4 papersize.
+% The option none also disables the vertical line inside the bill as this may be included on preprinted paper.
%
% \changes{v1.02}{2020/08/25}{add ibanseparator option}
% \item[ibanseparator (tokenlist) (\textbackslash,)]
@@ -271,7 +277,11 @@
%
% \item[iconwidth (length) (7mm)]
% This option allows custom scaling for custom icons.
-
+%
+% \item[qrmode (package/lua) (package)] Selects the mechanism for QRcode generation.
+% With Version 2.0 the package supports usage of the the luaqrcode library \cite{luaqrcode}. This can be enabled by using the \latexinline{qmode=lua} option.
+% In that case the luaqrcode libary has to be installed within the \verb+$LUAINPUTS+.
+%
% \item[qrscheme (Name of a custom QRbill scheme) (swiss)]
% Loads the definitions for the QRcode and the BillingInformation. Currently only the
% swiss qrbill scheme is available, but one can define own variants based on this file.
@@ -299,8 +309,19 @@
% \changes{v1.02}{2020/08/25}{Fix placement issue with separate option}
% \item[separate (false/text/symbol) (text)]
% Setup the separation rule between the document and the qrbill. If the value is text or symbol the Info \enquote{\qrbillseparatename} or the corresponding translation will be printed on top of the frame. This option will be ignored it the frame has no top rule.
-% \end{optionlist}
+%
+% \item[replace-tilde\\replace-umlauts (true/false) (false)]
+% Add automatic string replacements for \latexinline{~} and Umlauts.
+% In general the Data has either to be parsed as string or be expandable.
+% There are some specials about active characters like \latexinline{~}.
+% The option \latexinline{replace-tilde=true} will replace this by an ordinary space within the data string for the QRcode.
+%
+% Similarly the replace-umlauts options is mapping Umlauts to the two character representation. This can be used if UTF-8 is not supported.
+% Custom replacements can be set up using \latexinline{\QRbillAddCustomReplacement} as described in section \ref{sec:custom-replacement}.
+% \changes{v1.05}{2022/09/15}{Add replace-tilde/replace-umlauts options}
%
+% \end{optionlist}
+%
% \section{Data setup}
% \label{sec:data-setup}
% \changes{v1.04}{2022/07/02}{Add starrred variant of qrbillsetdata}
@@ -323,6 +344,16 @@
% \end{doccode}
% By default this setting will return the ISO date (YYYY-MM-DD) but the swiss scheme is already changing this to the desired (YYMMDD) structure.
%
+% \section{String replacements}\label{sec:custom-replacement}
+% \changes{v1.05}{2022/09/15}{Add support for custom string replacements}
+% Following a feature request qrbill received support for custom replacements.
+% Those allow the use of special characters within the data fields.
+% The corresponding options \latexinline{replace-tilde} and \latexinline{replace-umlauts} provide preset variants for the most common replacements.
+% In case you want to add another you can use the following structure:
+% \begin{doccode}
+% \AddQRbillCustomReplacement{Ä}{Ae}
+% \end{doccode}
+%
% \section{Setup for the preconfigured Swiss QR-bill}
% \subsection{Preconfigured data}
% \changes{v1.03}{2021/05/07}{Update to swiss qrbill standard version 2.2}
@@ -353,7 +384,7 @@
% \begin{center}
% \begin{tabular}{@{}>{\ttfamily}l>{\centering}p{.25\linewidth}>{\centering\arraybackslash}p{.25\linewidth}@{}}
% \toprule
-% AddressType&K&S\\\cmidrule(r){1-1}\cmidrule(l){2-3}
+% AddressType&S&K\\\cmidrule(r){1-1}\cmidrule(l){2-3}
% Name& \multicolumn{2}{c}{Name}\\\cmidrule(r){1-1}\cmidrule(l){2-3}
% Address1&Street&Street with number\\\cmidrule(r){1-1}\cmidrule(l){2-3}
% Address2&Number&Postal code with City\\\cmidrule(r){1-1}\cmidrule(l){2-3}
@@ -474,7 +505,7 @@
% \section{Implementation}
% \begin{macrocode}
\RequirePackage{expl3}
-\ProvidesExplPackage{qrbill}{2022/07/02}{1.04}{
+\ProvidesExplPackage{qrbill}{2022/09/15}{1.05}{
Template for QR-bills based on the Swiss Payment Standards
}
\RequirePackage{iftex}
@@ -485,11 +516,19 @@
\bool_new:N \g__qrbill_bottom_frame_bool
\bool_new:N \g__qrbill_left_frame_bool
\bool_new:N \g__qrbill_right_frame_bool
+\bool_new:N \g__qrbill_vrule_bool
\bool_new:N \g__qrbill_separateinfo_bool
+\prop_new:N \g__qrbill_replacement_prop
+
+\msg_new:nnn {qrbill} {typo-in-option} {
+ A~typo~within~the~option~#1~was~removed.\\
+ The~correct~name~for~the~option~is~#2.\\
+ Please~use~#2~instead~of~#1,~which~only\\
+ exists~for~backwards~compatibility~and~will~be~removed.
+}
\keys_define:nn {qrbill} {
font .choices:nn = {Frutiger, Arial, Helvetica, Liberation Sans} {
- \bool_gset_true:N \g__qrbill_fontsetup_bool
\tl_gset_eq:NN \g__qrbill_font_tl \l_keys_choice_tl
},
font .initial:n = Liberation Sans,
@@ -506,29 +545,41 @@
qrmode .initial:n = package,
frame .choice:,
frame / false .code:n = {
- \bool_gset_false:N \__g__qrbill_top_frame_bool
+ \bool_gset_false:N \g__qrbill_top_frame_bool
\bool_gset_false:N \g__qrbill_bottom_frame_bool
\bool_gset_false:N \g__qrbill_left_frame_bool
\bool_gset_false:N \g__qrbill_right_frame_bool
+ \bool_gset_true:N \g__qrbill_vrule_bool
},
frame / true .code:n = {
\bool_gset_true:N \g__qrbill_top_frame_bool
\bool_gset_true:N \g__qrbill_bottom_frame_bool
\bool_gset_true:N \g__qrbill_left_frame_bool
\bool_gset_true:N \g__qrbill_right_frame_bool
+ \bool_gset_true:N \g__qrbill_vrule_bool
},
frame / top .code:n = {
\bool_gset_true:N \g__qrbill_top_frame_bool
\bool_gset_false:N \g__qrbill_bottom_frame_bool
\bool_gset_false:N \g__qrbill_left_frame_bool
\bool_gset_false:N \g__qrbill_right_frame_bool
+ \bool_gset_true:N \g__qrbill_vrule_bool
},
frame / bottom .code:n = {
\bool_gset_false:N \g__qrbill_top_frame_bool
\bool_gset_true:N \g__qrbill_bottom_frame_bool
\bool_gset_false:N \g__qrbill_left_frame_bool
\bool_gset_false:N \g__qrbill_right_frame_bool
+ \bool_gset_true:N \g__qrbill_vrule_bool
+ },
+ frame / none .code:n = {
+ \bool_gset_false:N \g__qrbill_top_frame_bool
+ \bool_gset_false:N \g__qrbill_bottom_frame_bool
+ \bool_gset_false:N \g__qrbill_left_frame_bool
+ \bool_gset_false:N \g__qrbill_right_frame_bool
+ \bool_gset_false:N \g__qrbill_vrule_bool
},
+
frame .initial:n = true,
billinginfo .bool_gset:N = \g__grbill_billinginfo_auto_bool,
billinginfo .default:n = true,
@@ -570,22 +621,40 @@
separate .initial:n = text,
sep-iban .int_gset:N = \g__qrbill_ibansep_int,
sep-iban .initial:n = 0,
- ibanseperator .tl_gset:N = \g__qrbill_ibansep_tl,
- ibanseperator .initial:n = {\,},
+ ibanseparator .tl_gset:N = \g__qrbill_ibansep_tl,
+ ibanseparator .initial:n = {\,},
+ ibanseperator .code:n = \keys_set:nn {qrbill} {ibanseparator=#1}\msg_warning:nnnn {qrbill} {typo-in-option} {ibanseperator} {ibanseparator},
sep-reference .int_gset:N = \g__qrbill_referencesep_int,
sep-reference .initial:n = 0,
- referenceseperator .tl_gset:N = \g__qrbill_referencesep_tl,
- referenceseperator .initial:n = {\,}
+ referenceseparator .tl_gset:N = \g__qrbill_referencesep_tl,
+ referenceseparator .initial:n = {\,},
+ referenceseperator .code:n = \keys_set:nn {qrbill} {referenceseparator=#1}\msg_warning:nnnn {qrbill} {typo-in-option} {referenceseperator} {referenceseparator},
+ replace-tilde .choice:,
+ replace-tilde / true .code:n = \prop_gput:Nxx \g__qrbill_replacement_prop {\char_generate:nn {126} {12}} {\ },
+ replace-tilde / false .code:n = \exp_args:NNx \prop_gremove:Nn \g__qrbill_replacement_prop {\char_generate:nn {126} {12}},
+ replace-umlauts .choice:,
+ replace-umlauts / true .code:n = \prop_gput_from_keyval:Nn \g__qrbill_replacement_prop {ä=ae,Ä=AE,ü=ue,Ü=UE,ö=oe,Ö=OE,ß=ss,ẞ=SS},
+ replace-umlauts / false .code:n = \clist_map_inline:nn {ä,Ä,ü,Ü,ö,Ö,ß,ẞ} {\prop_gremove:Nn \g__qrbill_replacement_prop {##1}},
+ data-to-string .bool_gset:N = \g__qrbill_to_string_bool,
}
\ProcessKeysOptions{qrbill}
\newcommand*{\qrbillsetup}[1]{\keys_set:nn {qrbill}{#1}}
\NewDocumentCommand{\qrbillsetdata}{sm}{
+ \bool_if:NTF \g__qrbill_to_string_bool {
+ \IfBooleanTF {#1} {
+ \tl_set:Nx \l_tmpa_tl {#2}
+ \exp_args:Nnx \keys_set:nn {qrbill/data} {\tl_to_str:V \l_tmpa_tl}
+ }{
+ \exp_args:Nnx \keys_set:nn {qrbill/data} {\tl_to_str:n {#2}}
+ }
+ } {
\IfBooleanT {#1}
\exp_args:Nnx
\keys_set:nn
{qrbill/data}{#2}
+ }
}
\tl_if_empty:NTF \g__qrbill_font_tl {
@@ -593,16 +662,99 @@
}{
\RequirePackage{fontspec}
\newfontfamily{\qrbillfont}{\g__qrbill_font_tl}
+ \RequirePackage{anyfontsize}
}
\dim_new:N \g_qrbill_QRcode_dim
\dim_gset:Nn \g_qrbill_QRcode_dim {46mm}
+\bool_if:NT \g__qrbill_luamode_bool {
+ \file_if_exist:nTF {qrencode.lua} {
+ \lua_load_module:n {qrbill-latexluaqrcode}
+ } {
+ \msg_new:nnn {qrbill} {luaqrcode-not-found} {
+ Could~not~find~the~required~library~for~qrmode=lua.\\
+ I~will~switch~to~qrmode=package.
+ }
+ \msg_warning:nn {qrbill} {luaqrcode-not-found}
+ \bool_gset_false:N \g__qrbill_luamode_bool
+ }
+
+ % qrcode setup
+ \dim_new:N \l__qrbill_QRblocksize_dim
+ \cs_set_protected:Npn \qrbill_qrcode_black: {\rule{\l__qrbill_QRblocksize_dim}{\l__qrbill_QRblocksize_dim}}
+ \cs_set_protected:Npn \qrbill_qrcode_white: {\rule{\l__qrbill_QRblocksize_dim}{0pt}\rule{0pt}{\l__qrbill_QRblocksize_dim}}
+ \cs_new:Nn \qrbill_parse_QRcode:n {
+ \lua_now:e {
+ num, string = printQRcode("\lua_escape:n {#1}")
+ }
+ \dim_set:Nn \l__qrbill_QRblocksize_dim {\g_qrbill_QRcode_dim/\lua_now:n {tex.print(num)}}
+ \let\qrblack\qrbill_qrcode_black:
+ \let\qrwhite\qrbill_qrcode_white:
+ \def\qrnewline{\\[\dimexpr-\baselineskip+\l__qrbill_QRblocksize_dim]}
+ \noindent\parbox{\g_qrbill_QRcode_dim}{
+ \lua_now:n {tex.sprint(string)}
+ }
+ }
+}
+
\bool_if:NF \g__qrbill_luamode_bool {
\usepackage{qrcode}
- \cs_new:Nn \qrbill_parse_QRcode:n {
- \raisebox{\depth}{\qrcode[height= \g_qrbill_QRcode_dim]{#1}}
+ % modified version of \qr@encode@binary to allow utf8 qrcodes required by swiss qrbill scheme
+ % Copyright (C) 2015 by Anders Hendrickson <ahendric@cord.edu>
+ \cs_set:Nn \__qrbill_encode_unicode_binary:n {
+ % #1 = string of ascii characters, to be converted into bitstream
+ %
+ % We do this one entirely in hex, rather than binary, because we can.
+ \edef\qr@plaintext{#1}%
+ %
+ %First, the mode indicator.
+ \def\qr@codetext{4}% %This means `binary'
+ %
+ %Next, the character count.
+ \xdef\qr@stringlength{\tl_count:o {\qr@plaintext}}%
+ %Set \qr@charactercountlengthinhex to \qr@charactercountbits@byte/4%
+ \edef\qr@charactercountlengthinhex{\int_eval:n {\qr@charactercountbits@byte / 4}}%
+ \qr@decimaltohex[\qr@charactercountlengthinhex]{\qr@charactercount}{\qr@stringlength}%
+ \xa\g@addto@macro\xa\qr@codetext\xa{\qr@charactercount}%
+ %
+ %Now comes the actual data.
+ \exp_args:NNx \str_set_convert:Nnnn \l_tmpa_str { \qr@plaintext } {iso88591} {utf8}
+ \exp_args:NNV \str_set_convert:Nnnn \l_tmpa_str \l_tmpa_str {} {latin1/hex}
+ \str_gput_right:NV \qr@codetext \l_tmpa_str
+ \xdef\qr@codetext{\exp_args:No \str_lowercase:n {\qr@codetext}}
+ %Now the terminator.
+ \g@addto@macro\qr@codetext{0}% %This is '0000' in binary.
+ %
+ %There is no need to pad bits to make a multiple of 8,
+ %because the data length is already 4 + 8 + 8n + 4.
+ %
+ %Now add padding codewords if needed.
+ \setcounter{qr@hexchars}{\tl_count:o {\qr@codetext}}%
+ %Set \qr@numpaddingcodewords equal to \qr@totaldatacodewords - qr@hexchars/2.
+ \edef\qr@numpaddingcodewords{\int_eval:n {(-\c@qr@hexchars / 2)+\qr@totaldatacodewords}}
+ %
+ \int_compare:nNnT {\qr@numpaddingcodewords} < {0} {
+ \edef\ds{ERROR:~Too~much~data!~Over~by~\qr@numpaddingcodewords~bytes.}
+ }
+ \int_compare:nNnT {\qr@numpaddingcodewords} > {0} {
+ \int_step_inline:nnnn {2} {2} {\qr@numpaddingcodewords} {
+ \g@addto@macro{\qr@codetext}{ec11}%
+ }
+ \int_if_odd:nT {\qr@numpaddingcodewords} {
+ \g@addto@macro{\qr@codetext}{ec}%
+ }
+ }
+ }
+ \cs_set:Nn \qrbill_parse_QRcode:n {
+ \cs_set_eq:NN \qr@encode@binary \__qrbill_encode_unicode_binary:n
+ \raisebox{\depth}{\cs_set_eq:NN \qr@encode@binary \__qrbill_encode_unicode_binary:n\qrcode[height= \g_qrbill_QRcode_dim]{#1}}
}
- \cs_generate_variant:Nn \qrbill_parse_QRcode:n {V}
+}
+
+\cs_generate_variant:Nn \qrbill_parse_QRcode:n {V}
+
+\newcommand*{\QRbillAddCustomReplacement}[2]{
+ \prop_gput:Nxx \g__qrbill_replacement_prop {#1} {#2},
}
\RequirePackage{scrbase}
@@ -818,7 +970,9 @@
{\rule{\g__qrbill_rule_dim}{\c_qrbill_height_dim}}
{\rule{\g__qrbill_rule_dim}{\c_zero_dim}}
\hspace{\dimexpr62mm-1.5\g__qrbill_rule_dim}
- \rule{\g__qrbill_rule_dim}{\c_qrbill_height_dim}
+ \bool_if:NTF \g__qrbill_vrule_bool
+ {\rule{\g__qrbill_rule_dim}{\c_qrbill_height_dim}}
+ {\rule{\g__qrbill_rule_dim}{\c_zero_dim}}
\hspace{\dimexpr148mm-1.5\g__qrbill_rule_dim}
\bool_if:NTF \g__qrbill_right_frame_bool
{\rule{\g__qrbill_rule_dim}{\c_qrbill_height_dim}}
@@ -864,7 +1018,13 @@
\seq_new:N \l_qrbill_tmp_seq
\cs_new:Nn \qrbill_set_address_combined:nn {
- \seq_set_split:Nnn \l_qrbill_tmp_seq {\\} {#2}
+ \bool_if:NTF \g__qrbill_to_string_bool {
+ \exp_args:NNxx \seq_set_split:Nnn \l_qrbill_tmp_seq
+ {\tl_to_str:n {\\}}
+ { \str_range:nnn { #2 } { 2 } { -2 } }
+ } {
+ \seq_set_split:Nnn \l_qrbill_tmp_seq {\\} {#2}
+ }
\exp_args:Nnx \keys_set:nn {qrbill/data} {
#1AddressType=K,
#1Name=\seq_item:Nn \l_qrbill_tmp_seq {1},
@@ -877,7 +1037,13 @@
}
\cs_new:Nn \qrbill_set_address_structured:nn {
- \seq_set_split:Nnn \l_qrbill_tmp_seq {\\} {#2}
+ \bool_if:NTF \g__qrbill_to_string_bool {
+ \exp_args:NNxx \seq_set_split:Nnn \l_qrbill_tmp_seq
+ {\tl_to_str:n {\\}}
+ { \str_range:nnn { #2 } { 2 } { -2 } }
+ } {
+ \seq_set_split:Nnn \l_qrbill_tmp_seq {\\} {#2}
+ }
\exp_args:Nnx \keys_set:nn {qrbill/data} {
#1AddressType=S,
#1Name=\seq_item:Nn \l_qrbill_tmp_seq {1},
@@ -926,7 +1092,7 @@
\int_set:Nn \l_tmpb_int {\int_abs:n {\int_use:c {g__qrbill_#1sep_int}}}
\int_set:Nn \l_tmpa_int {1}
\tl_clear:N \l_tmpa_tl
- \int_while_do:nn {\l_tmpa_int < \str_count:N \l_tmpa_str} {
+ \int_while_do:nNnn {\l_tmpa_int} < {\str_count:N \l_tmpa_str - \l_tmpb_int +1 } {
\tl_put_right:Nx \l_tmpa_tl {
\str_range:Nnn \l_tmpa_str {\l_tmpa_int} {\l_tmpa_int + \l_tmpb_int-1}
}
@@ -960,7 +1126,7 @@
\keys_define:nn {qrbill/data} {
#1 .code:n = {
\tl_if_empty:nF {##1}{
- \keys_set:nx {qrbill/data} {
+ \exp_args:Nnx \keys_set:nn {qrbill/data} {
#1-Parameters={\qrbill_av_prefix:n {#1}##1}
}
}
@@ -971,7 +1137,11 @@
}
\newcommand*{\SetupQrBill}[1]{
- \keys_set:nn {qrbill/data} {#1}
+ \bool_if:NTF \g__qrbill_to_string_bool {
+ \exp_args:Nnx \keys_set:nn {qrbill/data} {\tl_to_str:n {#1}}
+ } {
+ \keys_set:nn {qrbill/data} {#1}
+ }
}
\str_new:N \l_qrbill_data_str
@@ -985,7 +1155,10 @@
\exp_args:NNv \str_put_right:Nn \l_qrbill_data_str {l_qrbill_data_##1_tl}
}
%necessary to preserve spaces!
- \str_replace_all:Nnn \l_qrbill_data_str {~ } {\ }
+ \str_replace_all:Nnn \l_qrbill_data_str {~ } {\ }
+ \prop_map_inline:Nn \g__qrbill_replacement_prop {
+ \str_replace_all:Nnn \l_qrbill_data_str {##1} {##2}
+ }
\tl_set_rescan:Nno \l_qrbill_data_str {\ExplSyntaxOff} {\l_qrbill_data_str}
}
@@ -1004,18 +1177,31 @@
\prop_new:N \g__qrbill_billing_info_prop
\seq_new:N \g__qrbill_billing_info_seq
+
+\clist_new:N \g__qrbill_billing_info_static_clist
+\newcommand*{\SetStaticData}[1]{\clist_gset:Nx \g__qrbill_billing_info_static_clist {\tl_to_str:n {#1}}}
+
\newcommand*{\SetBillingInfoScheme}[1]{
\prop_gset_from_keyval:Nn \g__qrbill_billing_info_prop {#1}
\seq_gclear:N \g__qrbill_billing_info_seq
\prop_map_inline:Nn \g__qrbill_billing_info_prop {
- \exp_args:Nx \clist_if_in:nnF {\tl_to_str:n {prefix , postfix}} {##1} {
- \seq_push:Nn \g__qrbill_billing_info_seq {##1}
+ \clist_if_in:NnF \g__qrbill_billing_info_static_clist {##1} {
+ \seq_push:Nn \g__qrbill_billing_info_seq {##1}
}
\keys_define:nn {qrbill/data} {
##2 .tl_set:c = l_qrbill_##2_tl,
##2 .initial:n =,
}
}
+ \seq_if_empty:NF \g__qrbill_billing_info_seq {
+ \prop_map_inline:Nn \g__qrbill_billing_info_prop {
+ \clist_if_in:NnT \g__qrbill_billing_info_static_clist {##1} {
+ \exp_args:Nx \clist_if_in:nnF {\tl_to_str:n {prefix , postfix}} {##1} {
+ \seq_push:Nn \g__qrbill_billing_info_seq {##1}
+ }
+ }
+ }
+ }
\seq_sort:Nn \g__qrbill_billing_info_seq {
\int_compare:nNnTF { ##1 } > { ##2 }
{ \sort_return_swapped: }
@@ -1111,6 +1297,8 @@
AV2-Parameters
}
+\SetStaticData{prefix,11,31}
+
\SetBillingInfoScheme{
prefix=//S1,
10=invoicenum,
@@ -1183,8 +1371,10 @@
%
% \PrintChanges
% \begin{thebibliography}{99}
-% \bibitem{qrbill-spec} Swiss Implementation Guidelines QR-bill: Technical and professional specifications of the payment part with Swiss QR Code and of the receipt. Version 2.2, with effect from 22 February 2021. \url{https://www.paymentstandards.ch/dam/downloads/ig-qr-bill-en.pdf}. Last checked 2021-05-07
+% \bibitem{qrbill-spec} Swiss Implementation Guidelines QR-bill: Technical and professional specifications of the payment part with Swiss QR Code and of the receipt. Version 2.2, with effect from 22 February 2021. \url{https://www.paymentstandards.ch/dam/downloads/ig-qr-bill-en.pdf}. Last checked 2022-08-28
% \bibitem{qrbill-design} Style Guide QR-billStyle Guide QR-bill: The right layout pays off. Layout rules and recommendations for the payment part with Swiss QR Code and for the receipt. \url{https://www.paymentstandards.ch/dam/downloads/style-guide-en.pdf}
+% \bibitem{luaqrcode} Luaqrcode – Pure Lua QR Code library. By Patrick Gundlach (SPEEDATA GMBH) and contributors.
+% \url{http://speedata.github.io/luaqrcode/}. Last checked 2022-08-28
% \end{thebibliography}
% \appendix
% \section{Example of standalone qrbill}
@@ -1252,7 +1442,8 @@
sep-reference=-5,
]{qrbill}
-% Setup layer
+% Setup layer:
+% This requires the scrlayer package which is already loaded by scrletter
\DeclareNewLayer[
align=bl,
voffset=\paperheight,