From: Paul Hänsch Date: Thu, 10 Apr 2025 01:55:11 +0000 (+0200) Subject: Bugfix: tax rate sections and validation X-Git-Url: https://git.plutz.net/?a=commitdiff_plain;h=b473451ce0b9d6757fb1de635fc68e341fb800ab;p=invoices Bugfix: tax rate sections and validation --- diff --git a/factur-x.sh b/factur-x.sh new file mode 100644 index 0000000..43aa2ed --- /dev/null +++ b/factur-x.sh @@ -0,0 +1,250 @@ +#!/bin/sh + +yield_xml() { + local date iban bic + + date="$(isdate "$(DB3 get date)")" + tnfc="$(DB3 get sender 6 |grep -xE '[0-9]{3}/[0-9]{3}/[0-9]{5}')" + tnva="$(DB3 get sender 7 |grep -xE '[A-Z]{2}[0-9]{9}')" + iban="$(DB3 get sender 8)" + bic="$(DB3 get sender 9)" + duedate="$(DB3 get duedate)" + + DB3 check invnum || return 1 + [ -n "$date" ] || return 1 + DB3 check sender 2 || return 1 + DB3 check rcpt 2 || return 1 + [ -n "$tnfc" -o -n "$tnva" ] || return 1 + + # date_due="$(date -d "$date" +%s)" + # date_due="$((date_due + 28 * 86400))" + # date_due="$(date -d @${date_due} +%Y%m%d)" + date="$(date -d "$date" +%Y%m%d)" + + cat <<-ZUGFERD + + + + urn:cen.eu:en16931:2017#compliant#urn:factur-x.eu:1p0:basic + + + + $(DB3 get invnum |HTML) + 380 + + ${date} + + + + $(DB3 get freeformtop |HTML) + + + $(DB3 get freeformbottom |HTML) + + + + + $(n=0 seq=0 skip=0 pcs= ppp= desc= uc= vat= vatrate= + [ $n -lt "$(DB3 count tb_pcs )" ] && n="$(DB3 count tb_pcs)" + [ $n -lt "$(DB3 count tb_ppp )" ] && n="$(DB3 count tb_ppp)" + [ $n -lt "$(DB3 count tb_desc)" ] && n="$(DB3 count tb_desc)" + + while [ $seq -le $n ]; do + seq=$((seq + 1)) + pcs="$(DB3 get tb_pcs $seq |grep -m1 -xE '[0-9]+(\.00?|\.25|\.50?|\.75)?' || printf 1)" + ppp="$(DB3 get tb_ppp $seq |grep -m1 -xEe '-?(\.[0-9]+|[0-9]+\.?[0-9]*)' || printf 0)" + desc="$(DB3 get tb_desc $seq)" + uc="$(DB3 get tb_uc $seq |grep -m1 -xE 'HUR|DAY|KMT|NAR|LS' || printf LS)" + vat="$(DB3 get tb_vat $seq |grep -m1 -xE 'S|Z|E|AE|K|G|O|L|M' || printf O)" + + if [ "$pcs" = 1 -a "$ppp" = 0 -a -z "$desc" ]; then + skip=$((skip + 1)) + continue + fi + [ "$vat" = S ] && vatrate="$(DB3 get tb_vatrate)" || vatrate=0 + + cat <<-ROW + + + $((seq - skip)) + + + $(HTML "$desc") + + + ${ppp} + + + ${pcs} + + + + + VAT + ${vat} + $(printf %.2f "${vatrate}") + + + $(awk "BEGIN { printf \"%.2f\", ${pcs} * ${ppp}; }") + + + + ROW + done) + + + + + $(DB3 get sender 1 |HTML) + + $(DB3 get sender 3 |HTML) + $(DB3 get rcpt 2 \ + | sed -E '/^\r?$/d;' \ + | for n in One Two Three; do + read -r l || break + printf '%s' "$n" "$(HTML "$l")" "$n" + done) + $(DB3 get sender 4 |HTML) + $(DB3 get sender 5 |HTML) + + + $([ -n "$tnfc" ] && cat cat <<-TNFC + + $(HTML "$tnfc") + + TNFC + ) + $([ -n "$tnva" ] && cat <<-TNVA + + $(HTML "$tnva") + + TNVA + ) + + + + $(DB3 get rcpt 1 |HTML) + + $(DB3 get rcpt 3 |HTML) + $(DB3 get rcpt 2 \ + | sed -E '/^\r?$/d;' \ + | for n in One Two Three; do + read -r l || break + printf '%s' "$n" "$(HTML "$l")" "$n" + done) + $(DB3 get rcpt 4 |HTML) + $(DB3 get rcpt 5 |HTML) + + + + + + + + ${date} + + + + + + EUR + + $( [ -n "$iban" ] && cat <<- IBANBICIBAN + + 58 + + $(HTML "$iban") + + + $( [ -n "$bic" -a ] && cat <<- IBANBICBIC + + IBANBICBIC + ) + + IBANBICIBAN + ) + + $(vat= net= tax= gross= vatrate= + for vat in $(DB3 iterate tb_vat |sort -u); do + case "$vat" in + (S) for vatrate in $(vatrates); do + read -r net tax gross <<-EOF + $(sumtotal "${vatrate}%") + EOF + cat <<-TAXBLOCK + + ${tax} + VAT + ${net} + ${vat} + $(printf '%.2f' "$vatrate") + + TAXBLOCK + done + ;; + (Z) read -r net tax gross <<-EOF + $(sumtotal "$vat") + EOF + cat <<-TAXBLOCK + + ${tax} + VAT + ${net} + ${vat} + 0.00 + + TAXBLOCK + ;; + (E|AE|K|G|O|L|M) + read -r net tax gross <<-EOF + $(sumtotal "$vat") + EOF + cat <<-TAXBLOCK + + ${tax} + VAT + $(DB3 get taxfreetext |HTML) + ${net} + ${vat} + 0.00 + + TAXBLOCK + ;; + esac + done + ) + + $(duedatet="$(isdate "$duedate")" + if [ -n "$duedatet" ] ; then + cat <<-DUEDATE + + + $(date -d "$duedatet" +%Y%m%d) + + + DUEDATE + else + cat <<-DUEDATE + + ${duedate} + + DUEDATE + fi) + + + ${net} + 0.00 + 0.00 + ${net} + ${tax} + ${gross} + ${gross} + + + + + + ZUGFERD +}