pure golang version

This commit is contained in:
Joerg Lehmann 2020-12-28 21:24:23 +01:00
parent 4ab3666a98
commit 0ce37e9aa9
8 changed files with 232 additions and 99 deletions

View File

@ -5,12 +5,10 @@ purpose to generate PDF-Invoices for nbit Informatik GmbH
Font File can be generated with makefont Font File can be generated with makefont
Payment Slip is generated using https://github.com/claudep/swiss-qr-bill To generate the QRCode, following library is used:
https://github.com/stapelberg/qrbill
Installation / Upgrade
$ pip install --user qrbill -U
Usage (Example): Usage (Example):
$ ./mkinvoice yaml/123456.yml $ ./mkinvoice yaml/123456.yml
Joerg Lehmann, April 2020 Joerg Lehmann, December 2020

View File

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
version="1.1"
width="100"
height="60"
id="svg2">
<defs
id="defs4">
<marker
refX="0"
refY="0"
orient="auto"
id="Scissors"
style="overflow:visible">
<path
d="M 9.0898857,-3.6061018 C 8.1198849,-4.7769976 6.3697607,-4.7358294 5.0623558,-4.2327734 l -8.2124046,3.0779029 c -2.3882933,-1.3067135 -4.7482873,-0.9325372 -4.7482873,-1.5687873 0,-0.4973164 0.4566662,-0.3883222 0.3883068,-1.6831941 -0.065635,-1.2432767 -1.3635771,-2.1630796 -2.5903987,-2.0816435 -1.227271,-0.00735 -2.499439,0.9331613 -2.510341,2.2300611 -0.09143,1.3063864 1.007209,2.5196896 2.306764,2.6052316 1.5223406,0.2266616 4.218258,-0.6955566 5.482945,1.57086006 -0.9422847,1.73825774 -2.6140244,1.74307674 -4.1255107,1.65607034 -1.2548743,-0.072235 -2.7620933,0.2873979 -3.3606483,1.5208605 -0.578367,1.1820862 -0.0112,2.8646022 1.316749,3.226412 1.3401912,0.4918277 3.1806689,-0.129711 3.4993722,-1.6707242 0.2456585,-1.187823 -0.5953659,-1.7459574 -0.2725074,-2.1771537 0.2436135,-0.32536 1.7907806,-0.1368452 4.5471053,-1.3748244 L 5.6763468,4.2330688 C 6.8000164,4.5467672 8.1730685,4.5362646 9.1684433,3.4313614 L -0.05164093,-0.05372222 9.0898857,-3.6061018 z m -18.3078016,-1.900504 c 1.294559,0.7227998 1.1888392,2.6835702 -0.1564272,3.0632889 -1.2165179,0.423661 -2.7710269,-0.7589694 -2.3831779,-2.0774648 0.227148,-1.0818519 1.653387,-1.480632 2.5396051,-0.9858241 z m 0.056264,8.0173649 c 1.3508301,0.4988648 1.1214429,2.7844356 -0.2522207,3.091609 -0.9110594,0.3163391 -2.2135494,-0.1387976 -2.3056964,-1.2121394 -0.177609,-1.305055 1.356085,-2.4841482 2.5579171,-1.8794696 z"
id="schere"
style="marker-start:none" />
</marker>
</defs>
<g
transform="translate(0,-992.36218)"
id="layer1">
<g
transform="matrix(4.2610846,-1.2351263,1.2351263,4.2610846,-1337.7659,-2994.9736)"
id="g4593">
<path
d="m 59.731665,956.40057 c -0.609784,-1.39286 -2.303491,-1.83556 -3.698902,-1.71226 l -8.742604,0.69566 c -1.935736,-1.91425 -4.307466,-2.2049 -4.132136,-2.81651 0.137044,-0.47806 0.545993,-0.24745 0.837105,-1.51102 0.279511,-1.21323 -0.714709,-2.45509 -1.916471,-2.71488 -1.177727,-0.34526 -2.659814,0.20827 -3.027677,1.45195 -0.447882,1.23061 0.273869,2.69969 1.499535,3.14003 1.400938,0.6374 4.246607,0.49379 4.837778,3.02096 -1.384807,1.41129 -2.993148,0.95525 -4.422137,0.4551 -1.186382,-0.41524 -2.734347,-0.48487 -3.649629,0.53589 -0.881717,0.97694 -0.800158,2.7506 0.376675,3.46434 1.15277,0.8421 3.093263,0.7518 3.824279,-0.64172 0.563472,-1.07414 -0.09119,-1.84242 0.337995,-2.16796 0.32384,-0.24563 1.759155,0.36194 4.749906,-0.0686 l 7.684693,5.46398 c 0.993719,0.61119 2.316503,0.97947 3.577814,0.19164 l -7.902726,-5.8909 9.766502,-0.89574 z m -17.075242,-6.87194 c 1.045256,1.05155 0.403306,2.90727 -0.994512,2.90157 -1.286163,0.072 -2.454591,-1.49318 -1.718425,-2.65375 0.516476,-0.97737 1.997384,-0.96769 2.712937,-0.24782 z m -2.155235,7.72245 c 1.161058,0.85179 0.310724,2.98566 -1.0944,2.9024 -0.962958,0.053 -2.089598,-0.7434 -1.882399,-1.80058 0.188897,-1.30347 1.988129,-2.01427 2.976799,-1.10182 z"
id="path4599"
style="marker-start:none" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

BIN
logos/scissors-rotated.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.8 KiB

BIN
logos/scissors.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

View File

@ -1,18 +1,21 @@
package main package main
import ( import (
"bytes"
"fmt" "fmt"
"github.com/jung-kurt/gofpdf" "github.com/jung-kurt/gofpdf"
"golang.org/x/text/language" "golang.org/x/text/language"
"golang.org/x/text/message" "golang.org/x/text/message"
"gopkg.in/yaml.v2" "gopkg.in/yaml.v2"
"image/png"
"io/ioutil" "io/ioutil"
"log" "log"
"math" "math"
"os" "os"
"os/exec"
"path/filepath" "path/filepath"
"strings" "strings"
"github.com/stapelberg/qrbill"
) )
// Metadata type // Metadata type
@ -28,6 +31,7 @@ type Metadata struct {
type Address struct { type Address struct {
Name string `yaml:"name"` Name string `yaml:"name"`
Street string `yaml:"street"` Street string `yaml:"street"`
StreetNumber string `yaml:"streetnumber"`
Zip string `yaml:"zip"` Zip string `yaml:"zip"`
City string `yaml:"city"` City string `yaml:"city"`
TelNo string `yaml:"tel_no"` TelNo string `yaml:"tel_no"`
@ -62,11 +66,17 @@ var totalInvoiceAmount float64
const defaultFontSize = 9 const defaultFontSize = 9
const smallFontSize = 7 const smallFontSize = 7
const paymentSlipTitleFontSize = 11
const paymentSlipHeadingFontSize = 6
const paymentSlipValuesFontSize = 8
const marginTop = 7 const marginTop = 7
const logoTop = 6 const logoTop = 6
const logoHeight = 20 const logoHeight = 20
const lineSpacing = 5 const lineSpacing = 5
const lineSpacingSmall = 4.5 const lineSpacingSmall = 4.5
const lineSpacingPaymentSlipBig = 6
const lineSpacingPaymentSlipBelowHeading = 2.8
const lineSpacingPaymentSlipSmall = 3.175
const addressTop = 50 const addressTop = 50
const metadataTopFirstPage = 70 const metadataTopFirstPage = 70
const metadataTopNotFirstPage = 30 const metadataTopNotFirstPage = 30
@ -87,14 +97,26 @@ const itemsTopFirstPage = 105
const itemsTopNotFirstPage = 50 const itemsTopNotFirstPage = 50
const totalsTop = 158 const totalsTop = 158
const maxYPos = 265 const maxYPos = 265
const paymentSlipTop = 190
const paymentSlipWaehrung = 270
const paymentSlipDashLeft = 63
const tabstopPaymentSlipLeft = 5
const tabstopPaymentSlipLeft2 = 17
const tabstopPaymentSlipLeft3 = 40
const tabstopPaymentSlipMiddle = 68
const tabstopPaymentSlipMiddle2 = 80
const tabstopPaymentSlipRight = 125
const scissorsTop = 200
const widthA4 = 210
const lengthA4 = 297
func round5rappen(f float64) float64 { func round5rappen(f float64) float64 {
return (math.Round(f*20) / 20) return (math.Round(f*20) / 20)
} }
func floatToString(f float64) string { func floatToString(f float64, sep string) string {
p := message.NewPrinter(language.English) p := message.NewPrinter(language.English)
s := strings.ReplaceAll(p.Sprintf("%.2f", f), ",", "'") s := strings.ReplaceAll(p.Sprintf("%.2f", f), ",", sep)
//fmt.Printf("--- s: @%s@\n", s) //fmt.Printf("--- s: @%s@\n", s)
return s return s
} }
@ -128,6 +150,7 @@ func writeText(x float64, y float64, w float64, text string, alignStr ...string)
func setupInvoice() { func setupInvoice() {
pdf = gofpdf.New("P", "mm", "A4", "") pdf = gofpdf.New("P", "mm", "A4", "")
pdf.SetMargins(0, 0, 0) pdf.SetMargins(0, 0, 0)
pdf.SetAutoPageBreak(false, 0)
pdf.SetFontLocation("fonts") pdf.SetFontLocation("fonts")
pdf.AddFont("Dejavusans", "", "DejaVuSans.json") pdf.AddFont("Dejavusans", "", "DejaVuSans.json")
pdf.AddFont("Dejavusans-Bold", "", "DejaVuSans-Bold.json") pdf.AddFont("Dejavusans-Bold", "", "DejaVuSans-Bold.json")
@ -145,7 +168,7 @@ func printPageHeader(firstPage bool) {
writeText(tabstopLeft, yPos, 0, invoiceData.SenderAddress.Name) writeText(tabstopLeft, yPos, 0, invoiceData.SenderAddress.Name)
pdf.SetFont("Dejavusans", "", defaultFontSize) pdf.SetFont("Dejavusans", "", defaultFontSize)
yPos = yPos + lineSpacing yPos = yPos + lineSpacing
writeText(tabstopLeft, yPos, 0, invoiceData.SenderAddress.Street) writeText(tabstopLeft, yPos, 0, invoiceData.SenderAddress.Street+" "+invoiceData.SenderAddress.StreetNumber)
yPos = yPos + lineSpacing yPos = yPos + lineSpacing
writeText(tabstopLeft, yPos, 0, invoiceData.SenderAddress.Zip+" "+invoiceData.SenderAddress.City) writeText(tabstopLeft, yPos, 0, invoiceData.SenderAddress.Zip+" "+invoiceData.SenderAddress.City)
if firstPage { if firstPage {
@ -171,7 +194,7 @@ func printAddress() {
yPos = addressTop yPos = addressTop
writeText(tabstopAddress, yPos, 0, invoiceData.BillingAddress.Name) writeText(tabstopAddress, yPos, 0, invoiceData.BillingAddress.Name)
yPos = yPos + lineSpacing yPos = yPos + lineSpacing
writeText(tabstopAddress, yPos, 0, invoiceData.BillingAddress.Street) writeText(tabstopAddress, yPos, 0, invoiceData.BillingAddress.Street+" "+invoiceData.BillingAddress.StreetNumber)
yPos = yPos + lineSpacing yPos = yPos + lineSpacing
writeText(tabstopAddress, yPos, 0, invoiceData.BillingAddress.Zip+" "+invoiceData.BillingAddress.City) writeText(tabstopAddress, yPos, 0, invoiceData.BillingAddress.Zip+" "+invoiceData.BillingAddress.City)
} }
@ -235,7 +258,7 @@ func printItems() {
writeText(tabstopPricePerUnit, yPos, widthPricePerUnit, fmt.Sprintf("%.2f", i.PricePerUnit), "TR") writeText(tabstopPricePerUnit, yPos, widthPricePerUnit, fmt.Sprintf("%.2f", i.PricePerUnit), "TR")
itemNetAmount := round5rappen(i.Quantity * i.PricePerUnit) itemNetAmount := round5rappen(i.Quantity * i.PricePerUnit)
totalNetAmount = totalNetAmount + itemNetAmount totalNetAmount = totalNetAmount + itemNetAmount
writeText(tabstopPrice, yPos, widthPrice, floatToString(itemNetAmount), "TR") writeText(tabstopPrice, yPos, widthPrice, floatToString(itemNetAmount, "'"), "TR")
} }
if i.Text != "" { if i.Text != "" {
lines := pdf.SplitText(i.Text, widthItemText) lines := pdf.SplitText(i.Text, widthItemText)
@ -260,52 +283,181 @@ func printTotals() {
yPos = yPos + lineSpacing yPos = yPos + lineSpacing
writeText(tabstopLeft, yPos, 0, "Summe") writeText(tabstopLeft, yPos, 0, "Summe")
pdf.SetFont("Dejavusans", "", defaultFontSize) pdf.SetFont("Dejavusans", "", defaultFontSize)
writeText(tabstopPrice, yPos, widthPrice, floatToString(totalNetAmount), "TR") writeText(tabstopPrice, yPos, widthPrice, floatToString(totalNetAmount, "'"), "TR")
yPos = yPos + lineSpacing yPos = yPos + lineSpacing
pdf.SetFont("Dejavusans-Bold", "", defaultFontSize) pdf.SetFont("Dejavusans-Bold", "", defaultFontSize)
writeText(tabstopLeft, yPos, 0, fmt.Sprintf("MwSt. %.1f%%", invoiceData.Metadata.Vat)) writeText(tabstopLeft, yPos, 0, fmt.Sprintf("MwSt. %.1f%%", invoiceData.Metadata.Vat))
mwstAmount := round5rappen(totalNetAmount * invoiceData.Metadata.Vat / 100) mwstAmount := round5rappen(totalNetAmount * invoiceData.Metadata.Vat / 100)
pdf.SetFont("Dejavusans", "", defaultFontSize) pdf.SetFont("Dejavusans", "", defaultFontSize)
writeText(tabstopPrice, yPos, widthPrice, floatToString(mwstAmount), "TR") writeText(tabstopPrice, yPos, widthPrice, floatToString(mwstAmount, "'"), "TR")
yPos = yPos + lineSpacing yPos = yPos + lineSpacing
yPos = yPos + lineSpacing yPos = yPos + lineSpacing
pdf.SetFont("Dejavusans-Bold", "", defaultFontSize) pdf.SetFont("Dejavusans-Bold", "", defaultFontSize)
writeText(tabstopLeft, yPos, 0, "Rechnungbetrag in CHF") writeText(tabstopLeft, yPos, 0, "Rechnungbetrag in CHF")
totalInvoiceAmount = totalNetAmount + mwstAmount totalInvoiceAmount = totalNetAmount + mwstAmount
writeText(tabstopPrice, yPos, widthPrice, floatToString(totalNetAmount+mwstAmount), "TR") writeText(tabstopPrice, yPos, widthPrice, floatToString(totalNetAmount+mwstAmount, "'"), "TR")
yPos = yPos + lineSpacingSmall yPos = yPos + lineSpacingSmall
pdf.SetFont("Dejavusans", "", smallFontSize) pdf.SetFont("Dejavusans", "", smallFontSize)
writeText(tabstopLeft, yPos, 0, "30 Tage netto") writeText(tabstopLeft, yPos, 0, "30 Tage netto")
} }
func qrchFromInvoiceData(id InvoiceData) *qrbill.QRCH {
return &qrbill.QRCH{
CdtrInf: qrbill.QRCHCdtrInf{
IBAN: id.Metadata.Account,
Cdtr: qrbill.Address{
AdrTp: qrbill.AddressType(string(qrbill.AddressTypeStructured)),
Name: id.SenderAddress.Name,
StrtNmOrAdrLine1: id.SenderAddress.Street,
BldgNbOrAdrLine2: id.SenderAddress.StreetNumber,
PstCd: id.SenderAddress.Zip,
TwnNm: id.SenderAddress.City,
Ctry: "CH",
},
},
CcyAmt: qrbill.QRCHCcyAmt{
Amt: fmt.Sprintf("%.2f", totalInvoiceAmount),
Ccy: "CHF",
},
UltmtDbtr: qrbill.Address{
AdrTp: qrbill.AddressType(string(qrbill.AddressTypeStructured)),
Name: id.BillingAddress.Name,
StrtNmOrAdrLine1: id.BillingAddress.Street,
BldgNbOrAdrLine2: id.BillingAddress.StreetNumber,
PstCd: id.BillingAddress.Zip,
TwnNm: id.BillingAddress.City,
Ctry: "CH",
},
RmtInf: qrbill.QRCHRmtInf{
Tp: "NON", // Reference type
Ref: "", // Reference
AddInf: qrbill.QRCHRmtInfAddInf{
Ustrd: "Rechnung Nummer " + id.Metadata.InvoiceNr,
},
},
}
}
func printPaymentSlip() {
var opt gofpdf.ImageOptions
pdf.SetDashPattern([]float64{0.8, 0.8}, 0)
pdf.Line(0, paymentSlipTop, widthA4, paymentSlipTop)
pdf.Line(paymentSlipDashLeft, paymentSlipTop, paymentSlipDashLeft, lengthA4)
opt.ImageType = "png"
pdf.ImageOptions("logos/scissors-rotated.png", paymentSlipDashLeft-1.5, paymentSlipTop+10, 3, 3, false, opt, 0, "")
pdf.SetFont("Helvetica", "B", paymentSlipTitleFontSize)
yPos = paymentSlipTop + 7
writeText(tabstopPaymentSlipLeft, yPos, 0, "Empfangsschein")
yPos = yPos + lineSpacingPaymentSlipBig
pdf.SetFont("Helvetica", "B", paymentSlipHeadingFontSize)
writeText(tabstopPaymentSlipLeft, yPos, 0, "Konto / Zahlbar an")
yPos = yPos + lineSpacingPaymentSlipBelowHeading
pdf.SetFont("Helvetica", "", paymentSlipValuesFontSize)
writeText(tabstopPaymentSlipLeft, yPos, 0, invoiceData.Metadata.Account)
yPos = yPos + lineSpacingPaymentSlipSmall
writeText(tabstopPaymentSlipLeft, yPos, 0, invoiceData.SenderAddress.Name)
yPos = yPos + lineSpacingPaymentSlipSmall
writeText(tabstopPaymentSlipLeft, yPos, 0, invoiceData.SenderAddress.Street+" "+invoiceData.SenderAddress.StreetNumber)
yPos = yPos + lineSpacingPaymentSlipSmall
writeText(tabstopPaymentSlipLeft, yPos, 0, invoiceData.SenderAddress.Zip+" "+invoiceData.SenderAddress.City)
yPos = yPos + lineSpacingPaymentSlipSmall
yPos = yPos + lineSpacingPaymentSlipSmall
pdf.SetFont("Helvetica", "B", paymentSlipHeadingFontSize)
writeText(tabstopPaymentSlipLeft, yPos, 0, "Zahlbar durch")
yPos = yPos + lineSpacingPaymentSlipBelowHeading
pdf.SetFont("Helvetica", "", paymentSlipValuesFontSize)
writeText(tabstopPaymentSlipLeft, yPos, 0, invoiceData.BillingAddress.Name)
yPos = yPos + lineSpacingPaymentSlipSmall
writeText(tabstopPaymentSlipLeft, yPos, 0, invoiceData.BillingAddress.Street+" "+invoiceData.BillingAddress.StreetNumber)
yPos = yPos + lineSpacingPaymentSlipSmall
writeText(tabstopPaymentSlipLeft, yPos, 0, invoiceData.BillingAddress.Zip+" "+invoiceData.BillingAddress.City)
yPos = paymentSlipWaehrung
pdf.SetFont("Helvetica", "B", paymentSlipHeadingFontSize)
writeText(tabstopPaymentSlipLeft, yPos, 0, "Währung")
writeText(tabstopPaymentSlipLeft2, yPos, 0, "Betrag")
yPos = yPos + lineSpacingPaymentSlipBelowHeading
pdf.SetFont("Helvetica", "", paymentSlipValuesFontSize)
writeText(tabstopPaymentSlipLeft, yPos, 0, "CHF")
writeText(tabstopPaymentSlipLeft2, yPos, 0, floatToString(totalInvoiceAmount, " "))
yPos = yPos + lineSpacingPaymentSlipSmall
yPos = yPos + lineSpacingPaymentSlipSmall
pdf.SetFont("Helvetica", "B", paymentSlipHeadingFontSize)
writeText(tabstopPaymentSlipLeft3, yPos, 0, "Annahmestelle")
pdf.SetFont("Helvetica", "B", paymentSlipTitleFontSize)
yPos = paymentSlipTop + 7
writeText(tabstopPaymentSlipMiddle, yPos, 0, "Zahlteil")
yPos = paymentSlipWaehrung
pdf.SetFont("Helvetica", "B", paymentSlipHeadingFontSize)
writeText(tabstopPaymentSlipMiddle, yPos, 0, "Währung")
writeText(tabstopPaymentSlipMiddle2, yPos, 0, "Betrag")
yPos = yPos + lineSpacingPaymentSlipBelowHeading
pdf.SetFont("Helvetica", "", paymentSlipValuesFontSize)
writeText(tabstopPaymentSlipMiddle, yPos, 0, "CHF")
writeText(tabstopPaymentSlipMiddle2, yPos, 0, floatToString(totalInvoiceAmount, " "))
yPos = paymentSlipTop + 7
pdf.SetFont("Helvetica", "B", paymentSlipHeadingFontSize)
writeText(tabstopPaymentSlipRight, yPos, 0, "Konto / Zahlbar an")
yPos = yPos + lineSpacingPaymentSlipBelowHeading
pdf.SetFont("Helvetica", "", paymentSlipValuesFontSize)
writeText(tabstopPaymentSlipRight, yPos, 0, invoiceData.Metadata.Account)
yPos = yPos + lineSpacingPaymentSlipSmall
writeText(tabstopPaymentSlipRight, yPos, 0, invoiceData.SenderAddress.Name)
yPos = yPos + lineSpacingPaymentSlipSmall
writeText(tabstopPaymentSlipRight, yPos, 0, invoiceData.SenderAddress.Street+" "+invoiceData.SenderAddress.StreetNumber)
yPos = yPos + lineSpacingPaymentSlipSmall
writeText(tabstopPaymentSlipRight, yPos, 0, invoiceData.SenderAddress.Zip+" "+invoiceData.SenderAddress.City)
yPos = yPos + (lineSpacingPaymentSlipSmall * 1.5)
pdf.SetFont("Helvetica", "B", paymentSlipHeadingFontSize)
writeText(tabstopPaymentSlipRight, yPos, 0, "Zusätzliche Informationen")
yPos = yPos + lineSpacingPaymentSlipBelowHeading
pdf.SetFont("Helvetica", "", paymentSlipValuesFontSize)
writeText(tabstopPaymentSlipRight, yPos, 0, "Rechnung Nummer "+invoiceData.Metadata.InvoiceNr)
yPos = yPos + (lineSpacingPaymentSlipSmall * 1.5)
pdf.SetFont("Helvetica", "B", paymentSlipHeadingFontSize)
writeText(tabstopPaymentSlipRight, yPos, 0, "Zahlbar durch")
yPos = yPos + lineSpacingPaymentSlipBelowHeading
pdf.SetFont("Helvetica", "", paymentSlipValuesFontSize)
writeText(tabstopPaymentSlipRight, yPos, 0, invoiceData.BillingAddress.Name)
yPos = yPos + lineSpacingPaymentSlipSmall
writeText(tabstopPaymentSlipRight, yPos, 0, invoiceData.BillingAddress.Street+" "+invoiceData.BillingAddress.StreetNumber)
yPos = yPos + lineSpacingPaymentSlipSmall
writeText(tabstopPaymentSlipRight, yPos, 0, invoiceData.BillingAddress.Zip+" "+invoiceData.BillingAddress.City)
}
func printQR() { func printQR() {
var opt gofpdf.ImageOptions var opt gofpdf.ImageOptions
cmd := exec.Command(filepath.Join(progDir, "qrbill.sh"), var b []byte
"--account", invoiceData.Metadata.Account, var err error
"--amount", floatToString(totalInvoiceAmount), qrch := qrchFromInvoiceData(invoiceData)
"--creditor-name", invoiceData.SenderAddress.Name, bill, err := qrch.Encode()
"--creditor-street", invoiceData.SenderAddress.Street,
"--creditor-postalcode", invoiceData.SenderAddress.Zip, code, err := bill.EncodeToImage()
"--creditor-city", invoiceData.SenderAddress.City,
"--extra-infos", "Rechnung Nummer " + invoiceData.Metadata.InvoiceNr,
"--debtor-name", invoiceData.BillingAddress.Name,
"--debtor-street", invoiceData.BillingAddress.Street,
"--debtor-postalcode", invoiceData.BillingAddress.Zip,
"--debtor-city", invoiceData.BillingAddress.City,
"--language", "de")
cmd.Env = append(os.Environ(),
"INVNO="+invoiceData.Metadata.InvoiceNr,
)
stdoutStderr, err := cmd.CombinedOutput()
fmt.Printf("%s\n", stdoutStderr)
if err != nil { if err != nil {
log.Fatal(err) log.Printf("%s", err)
return
}
var buf bytes.Buffer
if err := png.Encode(&buf, code); err != nil {
log.Printf("%s", err)
return
}
b = buf.Bytes()
err = ioutil.WriteFile("qr-images/"+invoiceData.Metadata.InvoiceNr+".png", b, 0644)
if err != nil {
// handle error
} }
opt.ImageType = "png" opt.ImageType = "png"
opt.ReadDpi = true opt.ReadDpi = false
pdf.ImageOptions("qr-images/"+invoiceData.Metadata.InvoiceNr+".png", 0, 193, -1, -1, false, opt, 0, "")
pdf.ImageOptions("qr-images/"+invoiceData.Metadata.InvoiceNr+".png", tabstopPaymentSlipMiddle-2, paymentSlipTop+13, 56, 56, false, opt, 0, "")
} }
func CreateInvoice() { func CreateInvoice() {
@ -319,6 +471,7 @@ func CreateInvoice() {
printItemsHeader() printItemsHeader()
printItems() printItems()
printTotals() printTotals()
printPaymentSlip()
printQR() printQR()
} }

View File

@ -1,39 +0,0 @@
#!/bin/bash
mydir="$(dirname $0)"
if [ -z "${INVNO}" ]; then
echo "ERROR: INVNO must be set as ENV variable"
exit 1
fi
echo "INVNO: ${INVNO}"
# should be called with following arguments (example)
# INVNO must be set as ENV variable
# --account "CH92 0023 5235 5662 3601 G"
# --amount 123.00
# --creditor-name "nbit Informatik GmbH"
# --creditor-street "Kirchweg 2"
# --creditor-postalcode "3510"
# --creditor-city "Konolfingen"
# --extra-infos "Rechnung Nummer ${INVNO}"
# --debtor-name "Wilhelm Tell"
# --debtor-street "Marktgasse 28"
# --debtor-postalcode "9400"
# --debtor-city "Rorschach"
# --due-date "2019-10-31"
# --language "de"
qrbill "$@" --output ${mydir}/temp/${INVNO}.svg
if [ $? -ne 0 ]; then
echo "ERROR: cannot create qrbill image"
exit 2
fi
#convert ${mydir}/temp/${INVNO}.svg ${mydir}/qr-images/${INVNO}.jpg
#inkscape ${mydir}/temp/${INVNO}.svg --export-width=794 --export-height=397 --export-filename ${mydir}/qr-images/${INVNO}.png
inkscape ${mydir}/temp/${INVNO}.svg --export-dpi=300 --export-filename ${mydir}/qr-images/${INVNO}.png
#cairosvg ${mydir}/temp/${INVNO}.svg -o ${mydir}/qr-images/${INVNO}.png
if [ $? -eq 0 ]; then
rm ${mydir}/temp/${INVNO}.svg
fi

View File

@ -1,16 +0,0 @@
#!/bin/bash
mydir="$(dirname $0)"
export INVNO=123456789
${mydir}/qrbill.sh --account "CH92 0023 5235 5662 3601 G" \
--amount 123.00 \
--creditor-name "nbit Informatik GmbH" \
--creditor-street "Kirchweg 2" \
--creditor-postalcode "3510" \
--creditor-city "Konolfingen" \
--extra-infos "Rechnung Nummer 123456789" \
--debtor-name "Wilhelm Tell" \
--debtor-street "Marktgasse 28" \
--debtor-postalcode "9400" \
--debtor-city "Rorschach" \
--due-date "2019-10-31" \
--language "de"