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