format invoice, multipage invoice

This commit is contained in:
Joerg Lehmann 2020-07-02 14:34:23 +02:00
parent b05854a20c
commit 7471882878
1 changed files with 66 additions and 30 deletions

View File

@ -23,6 +23,7 @@ type Metadata struct {
Vat float64 `yaml:"vat"` Vat float64 `yaml:"vat"`
Account string `yaml:"account"` Account string `yaml:"account"`
DueDate string `yaml:"due_date"` DueDate string `yaml:"due_date"`
VatNumber string `yaml:"vat_number"`
} }
// Address type // Address type
@ -57,20 +58,21 @@ var invoiceData InvoiceData
var progDir string var progDir string
var currentPage int var currentPage int
var totalPages int var totalPages int
var totalItemLines int
var totalNetAmount float64 var totalNetAmount float64
var totalInvoiceAmount float64 var totalInvoiceAmount float64
const defaultFontSize = 9 const defaultFontSize = 9
const fontSizeSmall = 7
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 = 3.5 const lineSpacingSmall = 3.5
const addressTop = 50 const addressTop = 50
const metadataTop = 70 const metadataTopFirstPage = 70
const metadataTopNotFirstPage = 30
const tabstopLeft = 20 const tabstopLeft = 20
const tabstopLeftAlt = 32 const tabstopLeftAlt = 40
const tabstopMetadata = 60 const tabstopMetadata = 60
const tabstopAddress = 120 const tabstopAddress = 120
const tabstopLogo = 155 const tabstopLogo = 155
@ -82,8 +84,10 @@ const widthPrice = 28
const tabstopQuantity = tabstopRight - widthPrice - widthPricePerUnit - widthQuantity const tabstopQuantity = tabstopRight - widthPrice - widthPricePerUnit - widthQuantity
const tabstopPricePerUnit = tabstopRight - widthPrice - widthPricePerUnit const tabstopPricePerUnit = tabstopRight - widthPrice - widthPricePerUnit
const tabstopPrice = tabstopRight - widthPrice const tabstopPrice = tabstopRight - widthPrice
const itemsTop = 105 const itemsTopFirstPage = 105
const totalsTop = 150 const itemsTopNotFirstPage = 50
const totalsTop = 165
const maxYPos = 265
func round5rappen(f float64) float64 { func round5rappen(f float64) float64 {
return (math.Round(f*20) / 20) return (math.Round(f*20) / 20)
@ -139,21 +143,25 @@ func printPageHeader(firstPage bool) {
currentPage = currentPage + 1 currentPage = currentPage + 1
pdf.AddPage() pdf.AddPage()
yPos = marginTop yPos = marginTop
pdf.SetFont("Dejavusans-Bold", "", fontSizeSmall) pdf.SetFont("Dejavusans-Bold", "", defaultFontSize)
writeText(tabstopLeft, yPos, 0, "nbit Informatik GmbH") writeText(tabstopLeft, yPos, 0, invoiceData.SenderAddress.Name)
pdf.SetFont("Dejavusans", "", fontSizeSmall) pdf.SetFont("Dejavusans", "", defaultFontSize)
yPos = yPos + lineSpacingSmall yPos = yPos + lineSpacing
writeText(tabstopLeft, yPos, 0, "Kirchweg 2") writeText(tabstopLeft, yPos, 0, invoiceData.SenderAddress.Street)
yPos = yPos + lineSpacingSmall yPos = yPos + lineSpacing
writeText(tabstopLeft, yPos, 0, "3510 Konolfingen") writeText(tabstopLeft, yPos, 0, invoiceData.SenderAddress.Zip+" "+invoiceData.SenderAddress.City)
yPos = yPos + lineSpacingSmall if firstPage {
yPos = yPos + lineSpacingSmall yPos = yPos + lineSpacing
writeText(tabstopLeft, yPos, 0, "Tel.") yPos = yPos + lineSpacing
writeText(tabstopLeftAlt, yPos, 0, "+41 31 792 00 40") writeText(tabstopLeft, yPos, 0, "Telefon")
yPos = yPos + lineSpacingSmall writeText(tabstopLeftAlt, yPos, 0, invoiceData.SenderAddress.TelNo)
writeText(tabstopLeft, yPos, 0, "EMail") yPos = yPos + lineSpacing
writeText(tabstopLeftAlt, yPos, 0, "joerg.lehmann@nbit.ch") writeText(tabstopLeft, yPos, 0, "E-Mail")
yPos = yPos + lineSpacingSmall 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.ImageType = "png"
opt.ReadDpi = true opt.ReadDpi = true
@ -170,25 +178,39 @@ func printAddress() {
writeText(tabstopAddress, yPos, 0, invoiceData.BillingAddress.Zip+" "+invoiceData.BillingAddress.City) writeText(tabstopAddress, yPos, 0, invoiceData.BillingAddress.Zip+" "+invoiceData.BillingAddress.City)
} }
func printMetadataFirstPage() { func printMetadata(firstPage bool) {
yPos = metadataTop yPos = metadataTopNotFirstPage
pdf.SetFont("Dejavusans-Bold", "", 16) if firstPage {
writeText(tabstopLeft, yPos, 0, "Rechnung") yPos = metadataTopFirstPage
yPos = yPos + lineSpacing pdf.SetFont("Dejavusans-Bold", "", 16)
yPos = yPos + lineSpacing writeText(tabstopLeft, yPos, 0, "Rechnung")
yPos = yPos + lineSpacing
yPos = yPos + lineSpacing
}
pdf.SetFont("Dejavusans-Bold", "", defaultFontSize) pdf.SetFont("Dejavusans-Bold", "", defaultFontSize)
writeText(tabstopLeft, yPos, 0, "Rechnungsnummer:") writeText(tabstopLeft, yPos, 0, "Rechnungsnummer:")
pdf.SetFont("Dejavusans", "", defaultFontSize) pdf.SetFont("Dejavusans", "", defaultFontSize)
writeText(tabstopMetadata, yPos, 0, invoiceData.Metadata.InvoiceNr) writeText(tabstopMetadata, yPos, 0, invoiceData.Metadata.InvoiceNr)
yPos = yPos + lineSpacing 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) pdf.SetFont("Dejavusans-Bold", "", defaultFontSize)
writeText(tabstopLeft, yPos, 0, "Rechnungsdatum:") writeText(tabstopLeft, yPos, 0, "Seite:")
pdf.SetFont("Dejavusans", "", defaultFontSize) pdf.SetFont("Dejavusans", "", defaultFontSize)
writeText(tabstopMetadata, yPos, 0, invoiceData.Metadata.InvoiceDate) writeText(tabstopMetadata, yPos, 0, fmt.Sprintf("%d von %d", currentPage, totalPages))
} }
func printItemsHeader() { func printItemsHeader() {
yPos = itemsTop if currentPage == 1 {
yPos = itemsTopFirstPage
} else {
yPos = itemsTopNotFirstPage
}
pdf.SetFont("Dejavusans-Bold", "", defaultFontSize) pdf.SetFont("Dejavusans-Bold", "", defaultFontSize)
writeText(tabstopLeft, yPos, 0, "Bezeichnung") writeText(tabstopLeft, yPos, 0, "Bezeichnung")
writeText(tabstopQuantity, yPos, widthQuantity, "Menge", "TR") writeText(tabstopQuantity, yPos, widthQuantity, "Menge", "TR")
@ -200,6 +222,14 @@ func printItemsHeader() {
yPos = yPos + lineSpacing yPos = yPos + lineSpacing
} }
func maybeNewPage() {
if yPos > maxYPos {
printPageHeader(false)
printMetadata(false)
printItemsHeader()
}
}
func printItems() { func printItems() {
for _, i := range invoiceData.InvoiceItems { for _, i := range invoiceData.InvoiceItems {
if i.Quantity != 0 { if i.Quantity != 0 {
@ -212,11 +242,15 @@ func printItems() {
if i.Text != "" { if i.Text != "" {
lines := pdf.SplitText(i.Text, widthItemText) lines := pdf.SplitText(i.Text, widthItemText)
for _, il := range lines { for _, il := range lines {
totalItemLines = totalItemLines + 1
writeText(tabstopLeft, yPos, 0, strings.ReplaceAll(il, "_", " ")) writeText(tabstopLeft, yPos, 0, strings.ReplaceAll(il, "_", " "))
yPos = yPos + lineSpacing yPos = yPos + lineSpacing
maybeNewPage()
} }
} else { } else {
totalItemLines = totalItemLines + 1
yPos = yPos + lineSpacing yPos = yPos + lineSpacing
maybeNewPage()
} }
} }
} }
@ -274,11 +308,12 @@ func printQR() {
func CreateInvoice() { func CreateInvoice() {
totalNetAmount = 0 totalNetAmount = 0
totalItemLines = 0
readInvoiceData(os.Args[1]) readInvoiceData(os.Args[1])
setupInvoice() setupInvoice()
printPageHeader(true) printPageHeader(true)
printAddress() printAddress()
printMetadataFirstPage() printMetadata(true)
printItemsHeader() printItemsHeader()
printItems() printItems()
printTotals() printTotals()
@ -301,6 +336,7 @@ func main() {
CreateInvoice() CreateInvoice()
totalPages = pdf.PageNo() totalPages = pdf.PageNo()
fmt.Printf("Total Pages is: %d\n", totalPages) fmt.Printf("Total Pages is: %d\n", totalPages)
fmt.Printf("Total Item Lines is: %d\n", totalItemLines)
// Second Run // Second Run
CreateInvoice() CreateInvoice()