| package main |
| |
| import ( |
| "bytes" |
| "fmt" |
| "html/template" |
| "time" |
| |
| wkhtml "github.com/sebastiaanklippert/go-wkhtmltopdf" |
| |
| "code.hackerspace.pl/hscloud/go/svc/invoice/templates" |
| pb "code.hackerspace.pl/hscloud/proto/invoice" |
| ) |
| |
| var ( |
| invTmpl *template.Template |
| ) |
| |
| func init() { |
| a, err := templates.Asset("invoice.html") |
| if err != nil { |
| panic(err) |
| } |
| invTmpl = template.Must(template.New("invoice.html").Parse(string(a))) |
| } |
| |
| func renderInvoicePDF(i *pb.Invoice, number string, proforma bool) ([]byte, error) { |
| now := time.Now() |
| |
| type item struct { |
| Title string |
| UnitPrice string |
| Qty string |
| VATRate string |
| TotalNet string |
| Total string |
| } |
| |
| data := struct { |
| InvoiceNumber string |
| InvoicerBilling []string |
| InvoicerVAT string |
| InvoicerCompanyNumber string |
| InvoiceeBilling []string |
| InvoiceeVAT string |
| Date time.Time |
| DueDate time.Time |
| IBAN string |
| SWIFT string |
| Proforma bool |
| ReverseVAT bool |
| USCustomer bool |
| Items []item |
| TotalNet string |
| VATTotal string |
| Total string |
| DeliveryCharge string |
| }{ |
| InvoiceNumber: number, |
| Date: now, |
| DueDate: now.AddDate(0, 0, int(i.DaysDue)), |
| IBAN: i.Iban, |
| SWIFT: i.Swift, |
| InvoicerVAT: i.InvoicerVatId, |
| InvoicerCompanyNumber: i.InvoicerCompanyNumber, |
| InvoiceeVAT: i.CustomerVatId, |
| Proforma: proforma, |
| ReverseVAT: i.ReverseVat, |
| USCustomer: i.UsCustomer, |
| |
| InvoicerBilling: make([]string, len(i.InvoicerBilling)), |
| InvoiceeBilling: make([]string, len(i.CustomerBilling)), |
| } |
| |
| unit := "€" |
| |
| for d, s := range i.InvoicerBilling { |
| data.InvoicerBilling[d] = s |
| } |
| for d, s := range i.CustomerBilling { |
| data.InvoiceeBilling[d] = s |
| } |
| |
| totalNet := 0 |
| total := 0 |
| for _, i := range i.Item { |
| rowTotalNet := int(i.UnitPrice * i.Count) |
| rowTotal := int(float64(rowTotalNet) * (float64(1) + float64(i.Vat)/100000)) |
| |
| totalNet += rowTotalNet |
| total += rowTotal |
| data.Items = append(data.Items, item{ |
| Title: i.Title, |
| Qty: fmt.Sprintf("%d", i.Count), |
| UnitPrice: fmt.Sprintf(unit+"%.2f", float64(i.UnitPrice)/100), |
| VATRate: fmt.Sprintf("%.2f%%", float64(i.Vat)/1000), |
| TotalNet: fmt.Sprintf(unit+"%.2f", float64(rowTotalNet)/100), |
| Total: fmt.Sprintf(unit+"%.2f", float64(rowTotal)/100), |
| }) |
| } |
| |
| data.TotalNet = fmt.Sprintf(unit+"%.2f", float64(totalNet)/100) |
| data.VATTotal = fmt.Sprintf(unit+"%.2f", float64(total-totalNet)/100) |
| data.Total = fmt.Sprintf(unit+"%.2f", float64(total)/100) |
| data.DeliveryCharge = fmt.Sprintf(unit+"%.2f", float64(0)) |
| |
| var b bytes.Buffer |
| err := invTmpl.Execute(&b, &data) |
| if err != nil { |
| return []byte{}, err |
| } |
| |
| pdfg, err := wkhtml.NewPDFGenerator() |
| if err != nil { |
| return []byte{}, err |
| } |
| pdfg.Dpi.Set(600) |
| pdfg.NoCollate.Set(false) |
| pdfg.PageSize.Set(wkhtml.PageSizeA4) |
| |
| pdfg.AddPage(wkhtml.NewPageReader(&b)) |
| |
| if err := pdfg.Create(); err != nil { |
| return []byte{}, err |
| } |
| return pdfg.Bytes(), nil |
| } |