--- /dev/null
+#!/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
+ <rsm:CrossIndustryInvoice xmlns:rsm="urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100" xmlns:qdt="urn:un:unece:uncefact:data:standard:QualifiedDataType:100" xmlns:ram="urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:100" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:udt="urn:un:unece:uncefact:data:standard:UnqualifiedDataType:100">
+ <rsm:ExchangedDocumentContext>
+ <ram:GuidelineSpecifiedDocumentContextParameter>
+ <ram:ID>urn:cen.eu:en16931:2017#compliant#urn:factur-x.eu:1p0:basic</ram:ID>
+ </ram:GuidelineSpecifiedDocumentContextParameter>
+ </rsm:ExchangedDocumentContext>
+ <rsm:ExchangedDocument>
+ <ram:ID>$(DB3 get invnum |HTML)</ram:ID><!-- BT-1 -->
+ <ram:TypeCode>380</ram:TypeCode><!-- BT-3 -->
+ <ram:IssueDateTime>
+ <udt:DateTimeString format="102">${date}</udt:DateTimeString><!-- BT-2 -->
+ </ram:IssueDateTime>
+
+ <ram:IncludedNote>
+ <ram:Content>$(DB3 get freeformtop |HTML)</ram:Content>
+ </ram:IncludedNote>
+ <ram:IncludedNote>
+ <ram:Content>$(DB3 get freeformbottom |HTML)</ram:Content>
+ </ram:IncludedNote>
+ </rsm:ExchangedDocument>
+
+ <rsm:SupplyChainTradeTransaction>
+ $(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
+ <ram:IncludedSupplyChainTradeLineItem>
+ <ram:AssociatedDocumentLineDocument>
+ <ram:LineID>$((seq - skip))</ram:LineID>
+ </ram:AssociatedDocumentLineDocument>
+ <ram:SpecifiedTradeProduct>
+ <ram:Name>$(HTML "$desc")</ram:Name>
+ </ram:SpecifiedTradeProduct>
+ <ram:SpecifiedLineTradeAgreement><ram:NetPriceProductTradePrice>
+ <ram:ChargeAmount>${ppp}</ram:ChargeAmount>
+ </ram:NetPriceProductTradePrice></ram:SpecifiedLineTradeAgreement>
+ <ram:SpecifiedLineTradeDelivery>
+ <ram:BilledQuantity unitCode="$uc">${pcs}</ram:BilledQuantity>
+ </ram:SpecifiedLineTradeDelivery>
+
+ <ram:SpecifiedLineTradeSettlement>
+ <ram:ApplicableTradeTax>
+ <ram:TypeCode>VAT</ram:TypeCode>
+ <ram:CategoryCode>${vat}</ram:CategoryCode>
+ <ram:RateApplicablePercent>$(printf %.2f "${vatrate}")</ram:RateApplicablePercent>
+ </ram:ApplicableTradeTax>
+ <ram:SpecifiedTradeSettlementLineMonetarySummation>
+ <ram:LineTotalAmount>$(awk "BEGIN { printf \"%.2f\", ${pcs} * ${ppp}; }")</ram:LineTotalAmount>
+ </ram:SpecifiedTradeSettlementLineMonetarySummation>
+ </ram:SpecifiedLineTradeSettlement>
+ </ram:IncludedSupplyChainTradeLineItem>
+ ROW
+ done)
+
+ <ram:ApplicableHeaderTradeAgreement>
+
+ <ram:SellerTradeParty>
+ <ram:Name>$(DB3 get sender 1 |HTML)</ram:Name>
+ <ram:PostalTradeAddress>
+ <ram:PostcodeCode>$(DB3 get sender 3 |HTML)</ram:PostcodeCode>
+ $(DB3 get rcpt 2 \
+ | sed -E '/^\r?$/d;' \
+ | for n in One Two Three; do
+ read -r l || break
+ printf '<ram:Line%s>%s</ram:Line%s>' "$n" "$(HTML "$l")" "$n"
+ done)
+ <ram:CityName>$(DB3 get sender 4 |HTML)</ram:CityName>
+ <ram:CountryID>$(DB3 get sender 5 |HTML)</ram:CountryID>
+ </ram:PostalTradeAddress>
+
+ $([ -n "$tnfc" ] && cat cat <<-TNFC
+ <ram:SpecifiedTaxRegistration>
+ <ram:ID schemeID="FC">$(HTML "$tnfc")</ram:ID>
+ </ram:SpecifiedTaxRegistration>
+ TNFC
+ )
+ $([ -n "$tnva" ] && cat <<-TNVA
+ <ram:SpecifiedTaxRegistration>
+ <ram:ID schemeID="VA">$(HTML "$tnva")</ram:ID>
+ </ram:SpecifiedTaxRegistration>
+ TNVA
+ )
+ </ram:SellerTradeParty>
+
+ <ram:BuyerTradeParty>
+ <ram:Name>$(DB3 get rcpt 1 |HTML)</ram:Name>
+ <ram:PostalTradeAddress>
+ <ram:PostcodeCode>$(DB3 get rcpt 3 |HTML)</ram:PostcodeCode>
+ $(DB3 get rcpt 2 \
+ | sed -E '/^\r?$/d;' \
+ | for n in One Two Three; do
+ read -r l || break
+ printf '<ram:Line%s>%s</ram:Line%s>' "$n" "$(HTML "$l")" "$n"
+ done)
+ <ram:CityName>$(DB3 get rcpt 4 |HTML)</ram:CityName>
+ <ram:CountryID>$(DB3 get rcpt 5 |HTML)</ram:CountryID>
+ </ram:PostalTradeAddress>
+ </ram:BuyerTradeParty>
+ </ram:ApplicableHeaderTradeAgreement>
+
+ <ram:ApplicableHeaderTradeDelivery>
+ <ram:ActualDeliverySupplyChainEvent>
+ <ram:OccurrenceDateTime>
+ <udt:DateTimeString format="102">${date}</udt:DateTimeString>
+ </ram:OccurrenceDateTime>
+ </ram:ActualDeliverySupplyChainEvent>
+ </ram:ApplicableHeaderTradeDelivery>
+
+ <ram:ApplicableHeaderTradeSettlement>
+ <ram:InvoiceCurrencyCode>EUR</ram:InvoiceCurrencyCode>
+
+ $( [ -n "$iban" ] && cat <<- IBANBICIBAN
+ <ram:SpecifiedTradeSettlementPaymentMeans>
+ <ram:TypeCode>58</ram:TypeCode>
+ <ram:PayeePartyCreditorFinancialAccount>
+ <ram:IBANID>$(HTML "$iban")</ram:IBANID>
+ <!-- ram:AccountName>$(DB3 get sender 1 |HTML)</ram:AccountName -->
+ </ram:PayeePartyCreditorFinancialAccount>
+ $( [ -n "$bic" -a ] && cat <<- IBANBICBIC
+ <!-- ram:PayeeSpecifiedCreditorFinancialInstitution>
+ <ram:BICID>$(HTML "$bic")</ram:BICID>
+ </ram:PayeeSpecifiedCreditorFinancialInstitution -->
+ IBANBICBIC
+ )
+ </ram:SpecifiedTradeSettlementPaymentMeans>
+ 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
+ <ram:ApplicableTradeTax>
+ <ram:CalculatedAmount>${tax}</ram:CalculatedAmount><!-- BT-117 -->
+ <ram:TypeCode>VAT</ram:TypeCode>
+ <ram:BasisAmount>${net}</ram:BasisAmount><!-- BT-116 -->
+ <ram:CategoryCode>${vat}</ram:CategoryCode><!-- BT-118 -->
+ <ram:RateApplicablePercent>$(printf '%.2f' "$vatrate")</ram:RateApplicablePercent>
+ </ram:ApplicableTradeTax>
+ TAXBLOCK
+ done
+ ;;
+ (Z) read -r net tax gross <<-EOF
+ $(sumtotal "$vat")
+ EOF
+ cat <<-TAXBLOCK
+ <ram:ApplicableTradeTax>
+ <ram:CalculatedAmount>${tax}</ram:CalculatedAmount><!-- BT-117 -->
+ <ram:TypeCode>VAT</ram:TypeCode>
+ <ram:BasisAmount>${net}</ram:BasisAmount><!-- BT-116 -->
+ <ram:CategoryCode>${vat}</ram:CategoryCode><!-- BT-118 -->
+ <ram:RateApplicablePercent>0.00</ram:RateApplicablePercent>
+ </ram:ApplicableTradeTax>
+ TAXBLOCK
+ ;;
+ (E|AE|K|G|O|L|M)
+ read -r net tax gross <<-EOF
+ $(sumtotal "$vat")
+ EOF
+ cat <<-TAXBLOCK
+ <ram:ApplicableTradeTax>
+ <ram:CalculatedAmount>${tax}</ram:CalculatedAmount><!-- BT-117 -->
+ <ram:TypeCode>VAT</ram:TypeCode>
+ <ram:ExemptionReason>$(DB3 get taxfreetext |HTML)</ram:ExemptionReason>
+ <ram:BasisAmount>${net}</ram:BasisAmount><!-- BT-116 -->
+ <ram:CategoryCode>${vat}</ram:CategoryCode><!-- BT-118 -->
+ <ram:RateApplicablePercent>0.00</ram:RateApplicablePercent>
+ </ram:ApplicableTradeTax>
+ TAXBLOCK
+ ;;
+ esac
+ done
+ )
+
+ $(duedatet="$(isdate "$duedate")"
+ if [ -n "$duedatet" ] ; then
+ cat <<-DUEDATE
+ <ram:SpecifiedTradePaymentTerms>
+ <ram:DueDateDateTime>
+ <udt:DateTimeString format="102">$(date -d "$duedatet" +%Y%m%d)</udt:DateTimeString>
+ </ram:DueDateDateTime>
+ </ram:SpecifiedTradePaymentTerms>
+ DUEDATE
+ else
+ cat <<-DUEDATE
+ <ram:SpecifiedTradePaymentTerms>
+ <ram:Description>${duedate}</ram:Description>
+ </ram:SpecifiedTradePaymentTerms>
+ DUEDATE
+ fi)
+
+ <ram:SpecifiedTradeSettlementHeaderMonetarySummation>
+ <ram:LineTotalAmount>${net}</ram:LineTotalAmount>
+ <ram:ChargeTotalAmount>0.00</ram:ChargeTotalAmount>
+ <ram:AllowanceTotalAmount>0.00</ram:AllowanceTotalAmount>
+ <ram:TaxBasisTotalAmount>${net}</ram:TaxBasisTotalAmount>
+ <ram:TaxTotalAmount currencyID="EUR">${tax}</ram:TaxTotalAmount>
+ <ram:GrandTotalAmount>${gross}</ram:GrandTotalAmount>
+ <ram:DuePayableAmount>${gross}</ram:DuePayableAmount>
+ </ram:SpecifiedTradeSettlementHeaderMonetarySummation>
+
+ </ram:ApplicableHeaderTradeSettlement>
+ </rsm:SupplyChainTradeTransaction>
+ </rsm:CrossIndustryInvoice>
+ ZUGFERD
+}