203 lines
4.8 KiB
Go
203 lines
4.8 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"io/ioutil"
|
|
"log"
|
|
"os"
|
|
"os/exec"
|
|
"path/filepath"
|
|
|
|
"github.com/jung-kurt/gofpdf"
|
|
"gopkg.in/yaml.v2"
|
|
)
|
|
|
|
// Metadata type
|
|
type Metadata struct {
|
|
InvoiceNr string
|
|
InvoiceInfo string
|
|
InvoiceDdate string
|
|
Vat float64
|
|
Account string
|
|
DueDate string
|
|
}
|
|
|
|
// Address type
|
|
type Address struct {
|
|
Name string
|
|
Street string
|
|
Zip string
|
|
City string
|
|
TelNo string
|
|
Email string
|
|
}
|
|
|
|
// InvoiceItem type
|
|
type InvoiceItem struct {
|
|
Text string
|
|
Quantity float64
|
|
PicePerUnit float64
|
|
}
|
|
|
|
// InvoiceData type
|
|
type InvoiceData struct {
|
|
Metadata Metadata
|
|
SenderAddress Address
|
|
BillingAddress Address
|
|
Item []InvoiceItem
|
|
}
|
|
|
|
/* global variable declaration */
|
|
var pdf *gofpdf.Fpdf
|
|
var yPos float64
|
|
var invoiceData InvoiceData
|
|
var progDir string
|
|
|
|
const marginTop = 7
|
|
const logoTop = 6
|
|
const logoHeight = 20
|
|
const lineSpacing = 5
|
|
const addressTop = 50
|
|
const line1Top = 100
|
|
const tabstopLeft = 20
|
|
const tabstopLeftAlt = 32
|
|
const tabstopAddress = 120
|
|
const tabstopCount = 10
|
|
const tabstopPrice = 10
|
|
const tabstopTotal = 170
|
|
const tabstopLogo = 155
|
|
const tabstopRight = 200
|
|
|
|
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)
|
|
fmt.Printf("%s\n", invoiceData.BillingAddress.Name)
|
|
}
|
|
|
|
func writeText(x float64, y float64, text string, alignStr ...string) {
|
|
tr := pdf.UnicodeTranslatorFromDescriptor("")
|
|
align := "LT"
|
|
if len(alignStr) > 0 {
|
|
align = alignStr[0]
|
|
}
|
|
pdf.SetXY(x, y)
|
|
pdf.CellFormat(0, 11, tr(text), "", 0, align, false, 0, "")
|
|
}
|
|
|
|
func setupInvoice() {
|
|
pdf = gofpdf.New("P", "mm", "A4", "")
|
|
pdf.SetMargins(0, 0, 0)
|
|
pdf.SetFontLocation("fonts")
|
|
pdf.AddFont("Dejavusans", "", "DejaVuSans.json")
|
|
pdf.AddFont("Dejavusans-Bold", "", "DejaVuSans-Bold.json")
|
|
pdf.SetFont("Dejavusans", "", 10)
|
|
}
|
|
|
|
func printPageHeader(firstPage bool) {
|
|
var opt gofpdf.ImageOptions
|
|
|
|
pdf.AddPage()
|
|
yPos = marginTop
|
|
pdf.SetFont("Dejavusans-Bold", "", 10)
|
|
writeText(tabstopLeft, yPos, "nbit Informatik GmbH")
|
|
pdf.SetFont("Dejavusans", "", 10)
|
|
yPos = yPos + lineSpacing
|
|
writeText(tabstopLeft, yPos, "Kirchweg 2")
|
|
yPos = yPos + lineSpacing
|
|
writeText(tabstopLeft, yPos, "3510 Konolfingen")
|
|
yPos = yPos + lineSpacing
|
|
yPos = yPos + lineSpacing
|
|
writeText(tabstopLeft, yPos, "Tel.")
|
|
writeText(tabstopLeftAlt, yPos, "+41 31 792 00 40")
|
|
yPos = yPos + lineSpacing
|
|
writeText(tabstopLeft, yPos, "EMail")
|
|
writeText(tabstopLeftAlt, yPos, "joerg.lehmann@nbit.ch")
|
|
yPos = yPos + lineSpacing
|
|
|
|
opt.ImageType = "png"
|
|
opt.ReadDpi = true
|
|
pdf.ImageOptions("logos/nbit-logo.png", tabstopLogo, logoTop, 0, logoHeight, false, opt, 0, "")
|
|
}
|
|
|
|
func printAddress() {
|
|
fmt.Printf("Blabla: %s\n", invoiceData.BillingAddress.Name)
|
|
yPos = addressTop
|
|
writeText(tabstopAddress, yPos, invoiceData.BillingAddress.Name)
|
|
yPos = yPos + lineSpacing
|
|
writeText(tabstopAddress, yPos, invoiceData.BillingAddress.Street)
|
|
yPos = yPos + lineSpacing
|
|
writeText(tabstopAddress, yPos, invoiceData.BillingAddress.Zip+" "+invoiceData.BillingAddress.City)
|
|
yPos = yPos + lineSpacing
|
|
|
|
pdf.Line(tabstopLeft, line1Top, tabstopRight, line1Top)
|
|
}
|
|
|
|
func printQR() {
|
|
var opt gofpdf.ImageOptions
|
|
|
|
cmd := exec.Command(filepath.Join(progDir, "qrbill.sh"),
|
|
"--account", invoiceData.Metadata.Account,
|
|
"--amount", "123.00",
|
|
"--creditor-name", invoiceData.SenderAddress.Name,
|
|
"--creditor-street", invoiceData.SenderAddress.Street,
|
|
"--creditor-postalcode", invoiceData.SenderAddress.Zip,
|
|
"--creditor-city", invoiceData.SenderAddress.City,
|
|
"--extra-infos", invoiceData.Metadata.InvoiceInfo,
|
|
"--debtor-name", invoiceData.BillingAddress.Name,
|
|
"--debtor-street", invoiceData.BillingAddress.Street,
|
|
"--debtor-postalcode", invoiceData.BillingAddress.Zip,
|
|
"--debtor-city", invoiceData.BillingAddress.City,
|
|
"--due-date", invoiceData.Metadata.DueDate,
|
|
"--language", "de")
|
|
cmd.Env = append(os.Environ(),
|
|
"INVNO="+invoiceData.Metadata.InvoiceNr,
|
|
)
|
|
stdoutStderr, err := cmd.CombinedOutput()
|
|
fmt.Printf("%s\n", stdoutStderr)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
fmt.Printf("%s\n", stdoutStderr)
|
|
|
|
opt.ImageType = "jpeg"
|
|
opt.ReadDpi = true
|
|
pdf.ImageOptions("qr-images/"+invoiceData.Metadata.InvoiceNr+".jpg", 0, 200, 0, 0, false, opt, 0, "")
|
|
}
|
|
|
|
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)
|
|
}
|
|
|
|
readInvoiceData(os.Args[1])
|
|
setupInvoice()
|
|
printPageHeader(true)
|
|
printAddress()
|
|
printQR()
|
|
|
|
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)
|
|
}
|
|
}
|