76 lines
1.6 KiB
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)
|
|
}
|
|
}
|