blob: a433fa84799abaa710bf1a270474b8b6e4ba975b [file] [log] [blame]
Sergiusz Bazanskifb18c992019-05-01 12:27:03 +02001package main
2
3import (
4 "bytes"
5 "fmt"
6 "html/template"
7 "time"
8
9 wkhtml "github.com/sebastiaanklippert/go-wkhtmltopdf"
10
11 "code.hackerspace.pl/hscloud/go/svc/invoice/templates"
12 pb "code.hackerspace.pl/hscloud/proto/invoice"
13)
14
15var (
16 invTmpl *template.Template
17)
18
19func init() {
20 a, err := templates.Asset("invoice.html")
21 if err != nil {
22 panic(err)
23 }
24 invTmpl = template.Must(template.New("invoice.html").Parse(string(a)))
25}
26
27func renderInvoicePDF(i *pb.Invoice, number string, proforma bool) ([]byte, error) {
28 now := time.Now()
29
30 type item struct {
31 Title string
32 UnitPrice string
33 Qty string
34 VATRate string
35 TotalNet string
36 Total string
37 }
38
39 data := struct {
40 InvoiceNumber string
41 InvoicerBilling []string
42 InvoicerVAT string
43 InvoicerCompanyNumber string
44 InvoiceeBilling []string
45 InvoiceeVAT string
46 Date time.Time
47 DueDate time.Time
48 IBAN string
49 SWIFT string
50 Proforma bool
51 ReverseVAT bool
52 USCustomer bool
53 Items []item
54 TotalNet string
55 VATTotal string
56 Total string
57 DeliveryCharge string
58 }{
59 InvoiceNumber: number,
60 Date: now,
61 DueDate: now.AddDate(0, 0, int(i.DaysDue)),
62 IBAN: i.Iban,
63 SWIFT: i.Swift,
64 InvoicerVAT: i.InvoicerVatId,
65 InvoicerCompanyNumber: i.InvoicerCompanyNumber,
66 InvoiceeVAT: i.CustomerVatId,
67 Proforma: proforma,
68 ReverseVAT: i.ReverseVat,
69 USCustomer: i.UsCustomer,
70
71 InvoicerBilling: make([]string, len(i.InvoicerBilling)),
72 InvoiceeBilling: make([]string, len(i.CustomerBilling)),
73 }
74
Sergiusz Bazanskic2d322c2019-05-01 13:14:32 +020075 unit := i.Unit
76 if unit == "" {
77 unit = "€"
78 }
Sergiusz Bazanskifb18c992019-05-01 12:27:03 +020079
80 for d, s := range i.InvoicerBilling {
81 data.InvoicerBilling[d] = s
82 }
83 for d, s := range i.CustomerBilling {
84 data.InvoiceeBilling[d] = s
85 }
86
87 totalNet := 0
88 total := 0
89 for _, i := range i.Item {
90 rowTotalNet := int(i.UnitPrice * i.Count)
91 rowTotal := int(float64(rowTotalNet) * (float64(1) + float64(i.Vat)/100000))
92
93 totalNet += rowTotalNet
94 total += rowTotal
95 data.Items = append(data.Items, item{
96 Title: i.Title,
97 Qty: fmt.Sprintf("%d", i.Count),
98 UnitPrice: fmt.Sprintf(unit+"%.2f", float64(i.UnitPrice)/100),
99 VATRate: fmt.Sprintf("%.2f%%", float64(i.Vat)/1000),
100 TotalNet: fmt.Sprintf(unit+"%.2f", float64(rowTotalNet)/100),
101 Total: fmt.Sprintf(unit+"%.2f", float64(rowTotal)/100),
102 })
103 }
104
105 data.TotalNet = fmt.Sprintf(unit+"%.2f", float64(totalNet)/100)
106 data.VATTotal = fmt.Sprintf(unit+"%.2f", float64(total-totalNet)/100)
107 data.Total = fmt.Sprintf(unit+"%.2f", float64(total)/100)
108 data.DeliveryCharge = fmt.Sprintf(unit+"%.2f", float64(0))
109
110 var b bytes.Buffer
111 err := invTmpl.Execute(&b, &data)
112 if err != nil {
113 return []byte{}, err
114 }
115
116 pdfg, err := wkhtml.NewPDFGenerator()
117 if err != nil {
118 return []byte{}, err
119 }
120 pdfg.Dpi.Set(600)
121 pdfg.NoCollate.Set(false)
122 pdfg.PageSize.Set(wkhtml.PageSizeA4)
123
124 pdfg.AddPage(wkhtml.NewPageReader(&b))
125
126 if err := pdfg.Create(); err != nil {
127 return []byte{}, err
128 }
129 return pdfg.Bytes(), nil
130}