506 lines
17 KiB
Go
506 lines
17 KiB
Go
package main
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"github.com/jung-kurt/gofpdf"
|
|
"golang.org/x/text/language"
|
|
"golang.org/x/text/message"
|
|
"gopkg.in/yaml.v2"
|
|
"image/png"
|
|
"io/ioutil"
|
|
"log"
|
|
"math"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"github.com/stapelberg/qrbill"
|
|
)
|
|
|
|
// Metadata type
|
|
type Metadata struct {
|
|
InvoiceNr string `yaml:"invoice_nr"`
|
|
InvoiceDate string `yaml:"invoice_date"`
|
|
Vat float64 `yaml:"vat"`
|
|
Account string `yaml:"account"`
|
|
VatNumber string `yaml:"vat_number"`
|
|
}
|
|
|
|
// Address type
|
|
type Address struct {
|
|
Name string `yaml:"name"`
|
|
Street string `yaml:"street"`
|
|
StreetNumber string `yaml:"streetnumber"`
|
|
Zip string `yaml:"zip"`
|
|
City string `yaml:"city"`
|
|
TelNo string `yaml:"tel_no"`
|
|
Email string `yaml:"email"`
|
|
}
|
|
|
|
// InvoiceItem type
|
|
type InvoiceItem struct {
|
|
Text string `yaml:"text"`
|
|
Quantity float64 `yaml:"quantity"`
|
|
PricePerUnit float64 `yaml:"price_per_unit"`
|
|
}
|
|
|
|
// InvoiceData type
|
|
type InvoiceData struct {
|
|
Metadata Metadata `yaml:"metadata"`
|
|
SenderAddress Address `yaml:"sender_address"`
|
|
BillingAddress Address `yaml:"billing_address"`
|
|
InvoiceItems []InvoiceItem `yaml:"invoice_items"`
|
|
}
|
|
|
|
/* global variable declaration */
|
|
var pdf *gofpdf.Fpdf
|
|
var yPos float64
|
|
var invoiceData InvoiceData
|
|
var progDir string
|
|
var currentPage int
|
|
var totalPages int
|
|
var totalItemLines int
|
|
var totalNetAmount float64
|
|
var totalInvoiceAmount float64
|
|
|
|
const defaultFontSize = 9
|
|
const smallFontSize = 7
|
|
const paymentSlipTitleFontSize = 11
|
|
const paymentSlipHeadingFontSize = 6
|
|
const paymentSlipValuesFontSize = 8
|
|
const marginTop = 7
|
|
const logoTop = 6
|
|
const logoHeight = 20
|
|
const lineSpacing = 5
|
|
const lineSpacingSmall = 4.5
|
|
const lineSpacingPaymentSlipBig = 6
|
|
const lineSpacingPaymentSlipBelowHeading = 2.8
|
|
const lineSpacingPaymentSlipSmall = 3.175
|
|
const addressTop = 50
|
|
const metadataTopFirstPage = 70
|
|
const metadataTopNotFirstPage = 30
|
|
const tabstopLeft = 20
|
|
const tabstopLeftAlt = 40
|
|
const tabstopMetadata = 60
|
|
const tabstopAddress = 120
|
|
const tabstopLogo = 155
|
|
const tabstopRight = 200
|
|
const widthItemText = 96
|
|
const widthQuantity = 28
|
|
const widthPricePerUnit = 28
|
|
const widthPrice = 28
|
|
const tabstopQuantity = tabstopRight - widthPrice - widthPricePerUnit - widthQuantity
|
|
const tabstopPricePerUnit = tabstopRight - widthPrice - widthPricePerUnit
|
|
const tabstopPrice = tabstopRight - widthPrice
|
|
const itemsTopFirstPage = 105
|
|
const itemsTopNotFirstPage = 50
|
|
const totalsTop = 158
|
|
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 {
|
|
return (math.Round(f*20) / 20)
|
|
}
|
|
|
|
func floatToString(f float64, sep string) string {
|
|
p := message.NewPrinter(language.English)
|
|
s := strings.ReplaceAll(p.Sprintf("%.2f", f), ",", sep)
|
|
//fmt.Printf("--- s: @%s@\n", s)
|
|
return s
|
|
}
|
|
|
|
func readInvoiceData(filename string) {
|
|
data, err := ioutil.ReadFile(filename)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
//fmt.Printf("File contents: %s", data)
|
|
|
|
err = yaml.Unmarshal([]byte(data), &invoiceData)
|
|
if err != nil {
|
|
log.Fatalf("error: %v", err)
|
|
}
|
|
|
|
//fmt.Printf("--- t:\n%v\n\n", invoiceData)
|
|
}
|
|
|
|
func writeText(x float64, y float64, w float64, text string, alignStr ...string) {
|
|
tr := pdf.UnicodeTranslatorFromDescriptor("")
|
|
align := "LT"
|
|
if len(alignStr) > 0 {
|
|
align = alignStr[0]
|
|
}
|
|
pdf.SetXY(x, y)
|
|
pdf.CellFormat(w, 11, tr(text), "", 0, align, false, 0, "")
|
|
}
|
|
|
|
func setupInvoice() {
|
|
pdf = gofpdf.New("P", "mm", "A4", "")
|
|
pdf.SetMargins(0, 0, 0)
|
|
pdf.SetAutoPageBreak(false, 0)
|
|
pdf.SetFontLocation("fonts")
|
|
pdf.AddFont("Dejavusans", "", "DejaVuSans.json")
|
|
pdf.AddFont("Dejavusans-Bold", "", "DejaVuSans-Bold.json")
|
|
pdf.SetFont("Dejavusans", "", defaultFontSize)
|
|
currentPage = 0
|
|
}
|
|
|
|
func printPageHeader(firstPage bool) {
|
|
var opt gofpdf.ImageOptions
|
|
|
|
currentPage = currentPage + 1
|
|
pdf.AddPage()
|
|
yPos = marginTop
|
|
pdf.SetFont("Dejavusans-Bold", "", defaultFontSize)
|
|
writeText(tabstopLeft, yPos, 0, invoiceData.SenderAddress.Name)
|
|
pdf.SetFont("Dejavusans", "", defaultFontSize)
|
|
yPos = yPos + lineSpacing
|
|
writeText(tabstopLeft, yPos, 0, invoiceData.SenderAddress.Street+" "+invoiceData.SenderAddress.StreetNumber)
|
|
yPos = yPos + lineSpacing
|
|
writeText(tabstopLeft, yPos, 0, invoiceData.SenderAddress.Zip+" "+invoiceData.SenderAddress.City)
|
|
if firstPage {
|
|
yPos = yPos + lineSpacing
|
|
yPos = yPos + lineSpacing
|
|
writeText(tabstopLeft, yPos, 0, "Telefon")
|
|
writeText(tabstopLeftAlt, yPos, 0, invoiceData.SenderAddress.TelNo)
|
|
yPos = yPos + lineSpacing
|
|
writeText(tabstopLeft, yPos, 0, "E-Mail")
|
|
writeText(tabstopLeftAlt, yPos, 0, invoiceData.SenderAddress.Email)
|
|
yPos = yPos + lineSpacing
|
|
writeText(tabstopLeft, yPos, 0, "MwSt. Nr.")
|
|
writeText(tabstopLeftAlt, yPos, 0, invoiceData.Metadata.VatNumber)
|
|
}
|
|
|
|
opt.ImageType = "png"
|
|
opt.ReadDpi = true
|
|
pdf.ImageOptions("logos/nbit-logo-40x20mm-400dpi.png", tabstopLogo, logoTop, 0, logoHeight, false, opt, 0, "")
|
|
pdf.SetFont("Dejavusans", "", defaultFontSize)
|
|
}
|
|
|
|
func printAddress() {
|
|
yPos = addressTop
|
|
writeText(tabstopAddress, yPos, 0, invoiceData.BillingAddress.Name)
|
|
yPos = yPos + lineSpacing
|
|
writeText(tabstopAddress, yPos, 0, invoiceData.BillingAddress.Street+" "+invoiceData.BillingAddress.StreetNumber)
|
|
yPos = yPos + lineSpacing
|
|
writeText(tabstopAddress, yPos, 0, invoiceData.BillingAddress.Zip+" "+invoiceData.BillingAddress.City)
|
|
}
|
|
|
|
func printMetadata(firstPage bool) {
|
|
yPos = metadataTopNotFirstPage
|
|
if firstPage {
|
|
yPos = metadataTopFirstPage
|
|
pdf.SetFont("Dejavusans-Bold", "", 16)
|
|
writeText(tabstopLeft, yPos, 0, "Rechnung")
|
|
yPos = yPos + lineSpacing
|
|
yPos = yPos + lineSpacing
|
|
}
|
|
pdf.SetFont("Dejavusans-Bold", "", defaultFontSize)
|
|
writeText(tabstopLeft, yPos, 0, "Rechnungsnummer:")
|
|
pdf.SetFont("Dejavusans", "", defaultFontSize)
|
|
writeText(tabstopMetadata, yPos, 0, invoiceData.Metadata.InvoiceNr)
|
|
yPos = yPos + lineSpacing
|
|
if firstPage {
|
|
pdf.SetFont("Dejavusans-Bold", "", defaultFontSize)
|
|
writeText(tabstopLeft, yPos, 0, "Rechnungsdatum:")
|
|
pdf.SetFont("Dejavusans", "", defaultFontSize)
|
|
writeText(tabstopMetadata, yPos, 0, invoiceData.Metadata.InvoiceDate)
|
|
yPos = yPos + lineSpacing
|
|
}
|
|
pdf.SetFont("Dejavusans-Bold", "", defaultFontSize)
|
|
writeText(tabstopLeft, yPos, 0, "Seite:")
|
|
pdf.SetFont("Dejavusans", "", defaultFontSize)
|
|
writeText(tabstopMetadata, yPos, 0, fmt.Sprintf("%d von %d", currentPage, totalPages))
|
|
}
|
|
|
|
func printItemsHeader() {
|
|
if currentPage == 1 {
|
|
yPos = itemsTopFirstPage
|
|
} else {
|
|
yPos = itemsTopNotFirstPage
|
|
}
|
|
pdf.SetFont("Dejavusans-Bold", "", defaultFontSize)
|
|
writeText(tabstopLeft, yPos, 0, "Bezeichnung")
|
|
writeText(tabstopQuantity, yPos, widthQuantity, "Menge", "TR")
|
|
writeText(tabstopPricePerUnit, yPos, widthPricePerUnit, "Einheitspreis", "TR")
|
|
writeText(tabstopPrice, yPos, widthPrice, "Preis", "TR")
|
|
pdf.SetFont("Dejavusans", "", defaultFontSize)
|
|
yPos = yPos + lineSpacing
|
|
pdf.Line(tabstopLeft, yPos, tabstopRight, yPos)
|
|
yPos = yPos + lineSpacing
|
|
}
|
|
|
|
func maybeNewPage() {
|
|
if yPos > maxYPos {
|
|
printPageHeader(false)
|
|
printMetadata(false)
|
|
printItemsHeader()
|
|
}
|
|
}
|
|
|
|
func printItems() {
|
|
for _, i := range invoiceData.InvoiceItems {
|
|
if i.Quantity != 0 {
|
|
writeText(tabstopQuantity, yPos, widthQuantity, fmt.Sprintf("%g", i.Quantity), "TR")
|
|
writeText(tabstopPricePerUnit, yPos, widthPricePerUnit, fmt.Sprintf("%.2f", i.PricePerUnit), "TR")
|
|
itemNetAmount := round5rappen(i.Quantity * i.PricePerUnit)
|
|
totalNetAmount = totalNetAmount + itemNetAmount
|
|
writeText(tabstopPrice, yPos, widthPrice, floatToString(itemNetAmount, "'"), "TR")
|
|
}
|
|
if i.Text != "" {
|
|
lines := pdf.SplitText(i.Text, widthItemText)
|
|
for _, il := range lines {
|
|
totalItemLines = totalItemLines + 1
|
|
writeText(tabstopLeft, yPos, 0, strings.ReplaceAll(il, "_", " "))
|
|
yPos = yPos + lineSpacing
|
|
maybeNewPage()
|
|
}
|
|
} else {
|
|
totalItemLines = totalItemLines + 1
|
|
yPos = yPos + lineSpacing
|
|
maybeNewPage()
|
|
}
|
|
}
|
|
}
|
|
|
|
func printTotals() {
|
|
yPos = totalsTop
|
|
pdf.Line(tabstopRight-widthPrice, yPos+(lineSpacing/2), tabstopRight, yPos+(lineSpacing/2))
|
|
pdf.SetFont("Dejavusans-Bold", "", defaultFontSize)
|
|
yPos = yPos + lineSpacing
|
|
writeText(tabstopLeft, yPos, 0, "Summe")
|
|
pdf.SetFont("Dejavusans", "", defaultFontSize)
|
|
writeText(tabstopPrice, yPos, widthPrice, floatToString(totalNetAmount, "'"), "TR")
|
|
yPos = yPos + lineSpacing
|
|
pdf.SetFont("Dejavusans-Bold", "", defaultFontSize)
|
|
writeText(tabstopLeft, yPos, 0, fmt.Sprintf("MwSt. %.1f%%", invoiceData.Metadata.Vat))
|
|
mwstAmount := round5rappen(totalNetAmount * invoiceData.Metadata.Vat / 100)
|
|
pdf.SetFont("Dejavusans", "", defaultFontSize)
|
|
writeText(tabstopPrice, yPos, widthPrice, floatToString(mwstAmount, "'"), "TR")
|
|
yPos = yPos + lineSpacing
|
|
yPos = yPos + lineSpacing
|
|
pdf.SetFont("Dejavusans-Bold", "", defaultFontSize)
|
|
writeText(tabstopLeft, yPos, 0, "Rechnungbetrag in CHF")
|
|
totalInvoiceAmount = totalNetAmount + mwstAmount
|
|
writeText(tabstopPrice, yPos, widthPrice, floatToString(totalNetAmount+mwstAmount, "'"), "TR")
|
|
yPos = yPos + lineSpacingSmall
|
|
pdf.SetFont("Dejavusans", "", smallFontSize)
|
|
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() {
|
|
var opt gofpdf.ImageOptions
|
|
|
|
var b []byte
|
|
var err error
|
|
qrch := qrchFromInvoiceData(invoiceData)
|
|
bill, err := qrch.Encode()
|
|
|
|
code, err := bill.EncodeToImage()
|
|
if err != nil {
|
|
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.ReadDpi = false
|
|
|
|
pdf.ImageOptions("qr-images/"+invoiceData.Metadata.InvoiceNr+".png", tabstopPaymentSlipMiddle-2, paymentSlipTop+13, 56, 56, false, opt, 0, "")
|
|
}
|
|
|
|
func CreateInvoice() {
|
|
totalNetAmount = 0
|
|
totalItemLines = 0
|
|
readInvoiceData(os.Args[1])
|
|
setupInvoice()
|
|
printPageHeader(true)
|
|
printAddress()
|
|
printMetadata(true)
|
|
printItemsHeader()
|
|
printItems()
|
|
printTotals()
|
|
printPaymentSlip()
|
|
printQR()
|
|
}
|
|
|
|
func main() {
|
|
dir, err := filepath.Abs(filepath.Dir(os.Args[0]))
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
progDir = dir
|
|
|
|
if len(os.Args) != 2 {
|
|
fmt.Printf("usage: mkinvoice <yaml-file>\n")
|
|
os.Exit(1)
|
|
}
|
|
|
|
// First Run to get total number of pages
|
|
CreateInvoice()
|
|
totalPages = pdf.PageNo()
|
|
fmt.Printf("Total Pages is: %d\n", totalPages)
|
|
fmt.Printf("Total Item Lines is: %d\n", totalItemLines)
|
|
|
|
// Second Run
|
|
CreateInvoice()
|
|
|
|
err = pdf.OutputFileAndClose(filepath.Join(progDir, "output", invoiceData.Metadata.InvoiceNr+".pdf"))
|
|
if err == nil {
|
|
fmt.Printf("Successfully created invoice\n")
|
|
} else {
|
|
fmt.Printf("Error: %v\n", err)
|
|
}
|
|
}
|