main.go

  1package main
  2
  3import (
  4	_ "embed"
  5	"flag"
  6	"fmt"
  7	"log"
  8	"strings"
  9	"time"
 10
 11	"github.com/signintech/gopdf"
 12	"github.com/spf13/cobra"
 13)
 14
 15//go:embed Inter.ttf
 16var interFont []byte
 17
 18//go:embed Inter-Bold.ttf
 19var interBoldFont []byte
 20
 21var (
 22	id    string
 23	title string
 24
 25	logo string
 26	from string
 27	to   string
 28	date string
 29	due  string
 30
 31	items      []string
 32	quantities []int
 33	rates      []float64
 34
 35	tax      float64
 36	discount float64
 37	currency string
 38
 39	note   string
 40	output string
 41)
 42
 43func init() {
 44	generateCmd.Flags().StringVar(&id, "id", time.Now().Format("20060102"), "ID")
 45	generateCmd.Flags().StringVar(&title, "title", "INVOICE", "Title")
 46
 47	generateCmd.Flags().Float64SliceVarP(&rates, "rate", "r", []float64{25}, "Rates")
 48	generateCmd.Flags().IntSliceVarP(&quantities, "quantity", "q", []int{2}, "Quantities")
 49	generateCmd.Flags().StringSliceVarP(&items, "item", "i", []string{"Paper Cranes"}, "Items")
 50
 51	generateCmd.Flags().StringVarP(&logo, "logo", "l", "", "Company logo")
 52	generateCmd.Flags().StringVarP(&from, "from", "f", "Project Folded, Inc.", "Issuing company")
 53	generateCmd.Flags().StringVarP(&to, "to", "t", "Untitled Corporation, Inc.", "Recipient company")
 54	generateCmd.Flags().StringVar(&date, "date", time.Now().Format("Jan 02, 2006"), "Date")
 55	generateCmd.Flags().StringVar(&due, "due", time.Now().AddDate(0, 0, 14).Format("Jan 02, 2006"), "Payment due date")
 56
 57	generateCmd.Flags().Float64Var(&tax, "tax", 0.13, "Tax")
 58	generateCmd.Flags().Float64VarP(&discount, "discount", "d", 0.0, "Discount")
 59	generateCmd.Flags().StringVarP(&currency, "currency", "c", "USD", "Currency")
 60
 61	generateCmd.Flags().StringVarP(&note, "note", "n", "For debugging purposes.", "Note")
 62	generateCmd.Flags().StringVarP(&output, "output", "o", "invoice.pdf", "Output file (.pdf)")
 63
 64	flag.Parse()
 65}
 66
 67var rootCmd = &cobra.Command{
 68	Use:   "invoice",
 69	Short: "Invoice generates invoices from the command line.",
 70	Long:  `Invoice generates invoices from the command line.`,
 71}
 72
 73var generateCmd = &cobra.Command{
 74	Use:   "generate",
 75	Short: "Generate an invoice",
 76	Long:  `Generate an invoice`,
 77	RunE: func(cmd *cobra.Command, args []string) error {
 78		pdf := gopdf.GoPdf{}
 79		pdf.Start(gopdf.Config{
 80			PageSize: *gopdf.PageSizeA4,
 81		})
 82		pdf.SetMargins(40, 40, 40, 40)
 83		pdf.AddPage()
 84		err := pdf.AddTTFFontData("Inter", interFont)
 85		if err != nil {
 86			return err
 87		}
 88
 89		err = pdf.AddTTFFontData("Inter-Bold", interBoldFont)
 90		if err != nil {
 91			return err
 92		}
 93
 94		writeLogo(&pdf, logo, from)
 95		writeTitle(&pdf, title, id)
 96		writeBillTo(&pdf, to)
 97		writeHeaderRow(&pdf)
 98		subtotal := 0.0
 99		for i := range items {
100			q := 1
101			if len(quantities) > i {
102				q = quantities[i]
103			}
104
105			r := 0.0
106			if len(rates) > i {
107				r = rates[i]
108			}
109
110			writeRow(&pdf, items[i], q, r)
111			subtotal += float64(q) * r
112		}
113		writeNotes(&pdf, note)
114		writeTotals(&pdf, subtotal, subtotal*tax, subtotal*discount)
115		writeFooter(&pdf, id)
116		output = strings.TrimSuffix(output, ".pdf") + ".pdf"
117		err = pdf.WritePdf(output)
118		if err != nil {
119			return err
120		}
121
122		fmt.Printf("Generated %s\n", output)
123
124		return nil
125
126	},
127}
128
129func main() {
130	rootCmd.AddCommand(generateCmd)
131	err := rootCmd.Execute()
132	if err != nil {
133		log.Fatal(err)
134	}
135}