camper/pkg/invoice/pdf.go

76 lines
1.6 KiB
Go

package invoice
import (
"archive/zip"
"bytes"
"errors"
"fmt"
"io"
"log"
"net/http"
"os"
"os/exec"
"dev.tandem.ws/tandem/camper/pkg/auth"
"dev.tandem.ws/tandem/camper/pkg/database"
"dev.tandem.ws/tandem/camper/pkg/template"
)
func mustWriteInvoicesPdf(r *http.Request, user *auth.User, company *auth.Company, conn *database.Conn, slugs []string) []byte {
buf := new(bytes.Buffer)
w := zip.NewWriter(buf)
for _, slug := range slugs {
inv := mustGetInvoice(r.Context(), conn, company, slug)
if inv == nil {
continue
}
f, err := w.Create(fmt.Sprintf("%s-%s.pdf", inv.Number, template.Slugify(inv.Invoicee.Name)))
if err != nil {
panic(err)
}
mustWriteInvoicePdf(f, r, user, company, inv)
}
mustClose(w)
return buf.Bytes()
}
func mustWriteInvoicePdf(w io.Writer, r *http.Request, user *auth.User, company *auth.Company, inv *invoice) {
cmd := exec.Command("weasyprint", "--stylesheet", "web/static/invoice.css", "-", "-")
var stderr bytes.Buffer
cmd.Stderr = &stderr
stdin, err := cmd.StdinPipe()
if err != nil {
panic(err)
}
stdout, err := cmd.StdoutPipe()
if err != nil {
panic(err)
}
defer func() {
err := stdout.Close()
if !errors.Is(err, os.ErrClosed) {
panic(err)
}
}()
if err = cmd.Start(); err != nil {
panic(err)
}
go func() {
defer mustClose(stdin)
template.MustRenderAdmin(stdin, r, user, company, "invoice/view.gohtml", inv)
}()
if _, err = io.Copy(w, stdout); err != nil {
panic(err)
}
if err := cmd.Wait(); err != nil {
log.Printf("ERR - %v\n", stderr.String())
panic(err)
}
}
func mustClose(closer io.Closer) {
if err := closer.Close(); err != nil {
panic(err)
}
}