diff --git a/currency.go b/currency.go index b16a0f3..22402e6 100644 --- a/currency.go +++ b/currency.go @@ -1,4 +1,4 @@ -package main +package invoiceservice var currencySymbols = map[string]string{ "USD": "$", diff --git a/main.go b/entry.go similarity index 66% rename from main.go rename to entry.go index 440f5ff..d5ecfdf 100644 --- a/main.go +++ b/entry.go @@ -1,10 +1,9 @@ -package main +package invoiceservice import ( _ "embed" "flag" "fmt" - "log" "strings" "time" @@ -33,9 +32,10 @@ type Invoice struct { Quantities []int `json:"quantities" yaml:"quantities"` Rates []float64 `json:"rates" yaml:"rates"` - Tax float64 `json:"tax" yaml:"tax"` - Discount float64 `json:"discount" yaml:"discount"` - Currency string `json:"currency" yaml:"currency"` + Tax float64 `json:"tax" yaml:"tax"` + IncludeTax bool `json:"include_tax" yaml:"include_tax"` + Discount float64 `json:"discount" yaml:"discount"` + Currency string `json:"currency" yaml:"currency"` Note string `json:"note" yaml:"note"` } @@ -52,6 +52,7 @@ func DefaultInvoice() Invoice { Date: time.Now().Format("Jan 02, 2006"), Due: time.Now().AddDate(0, 0, 14).Format("Jan 02, 2006"), Tax: 0, + IncludeTax: false, Discount: 0, Currency: "USD", } @@ -102,7 +103,7 @@ var generateCmd = &cobra.Command{ Short: "Generate an invoice", Long: `Generate an invoice`, RunE: func(cmd *cobra.Command, args []string) error { - + // Read CLI params / JSON config into 'file' if importPath != "" { err := importData(importPath, &file, cmd.Flags()) if err != nil { @@ -110,65 +111,80 @@ var generateCmd = &cobra.Command{ } } - pdf := gopdf.GoPdf{} - pdf.Start(gopdf.Config{ - PageSize: *gopdf.PageSizeA4, - }) - pdf.SetMargins(40, 40, 40, 40) - pdf.AddPage() - err := pdf.AddTTFFontData("Inter", interFont) + err := GenerateInvoice(file) if err != nil { return err } - err = pdf.AddTTFFontData("Inter-Bold", interBoldFont) - if err != nil { - return err - } + return nil + }, +} - writeLogo(&pdf, file.Logo, file.From) - writeTitle(&pdf, file.Title, file.Id, file.Date) - writeBillTo(&pdf, file.To) - writeHeaderRow(&pdf) - subtotal := 0.0 - for i := range file.Items { - q := 1 - if len(file.Quantities) > i { - q = file.Quantities[i] - } +func GenerateInvoice(file Invoice) (err error) { + pdf := gopdf.GoPdf{} + pdf.Start(gopdf.Config{ + PageSize: *gopdf.PageSizeA4, + }) + pdf.SetMargins(40, 40, 40, 40) + pdf.AddPage() + err = pdf.AddTTFFontData("Inter", interFont) + if err != nil { + return err + } - r := 0.0 - if len(file.Rates) > i { - r = file.Rates[i] - } + err = pdf.AddTTFFontData("Inter-Bold", interBoldFont) + if err != nil { + return err + } - writeRow(&pdf, file.Items[i], q, r) - subtotal += float64(q) * r - } - if file.Note != "" { - writeNotes(&pdf, file.Note) - } - writeTotals(&pdf, subtotal, subtotal*file.Tax, subtotal*file.Discount) - if file.Due != "" { - writeDueDate(&pdf, file.Due) + writeLogo(&pdf, file.Logo, file.From) + writeTitle(&pdf, file.Title, file.Id, file.Date) + writeBillTo(&pdf, file.To) + writeHeaderRow(&pdf) + subtotal := 0.0 + for i := range file.Items { + q := 1 + if len(file.Quantities) > i { + q = file.Quantities[i] } - writeFooter(&pdf, file.Id) - output = strings.TrimSuffix(output, ".pdf") + ".pdf" - err = pdf.WritePdf(output) - if err != nil { - return err - } - - fmt.Printf("Generated %s\n", output) - return nil - }, -} + r := 0.0 + if len(file.Rates) > i { + r = file.Rates[i] + } -func main() { - rootCmd.AddCommand(generateCmd) - err := rootCmd.Execute() + writeRow(&pdf, file.Items[i], q, r, file.Currency) + subtotal += float64(q) * r + } + if file.Note != "" { + writeNotes(&pdf, file.Note) + } + var tax float64 + if file.IncludeTax { + tax = subtotal * (1 - (1 / (1 + file.Tax))) + } else { + tax = subtotal * file.Tax + } + writeTotals(&pdf, subtotal, tax, file.IncludeTax, subtotal*file.Discount, file.Currency) + if file.Due != "" { + writeDueDate(&pdf, file.Due) + } + writeFooter(&pdf, file.Id) + output = strings.TrimSuffix(output, ".pdf") + ".pdf" + err = pdf.WritePdf(output) if err != nil { - log.Fatal(err) + return err } + + fmt.Printf("Generated %s\n", output) + + return nil } + +// func main() { +// rootCmd.AddCommand(generateCmd) +// err := rootCmd.Execute() +// if err != nil { +// log.Fatal(err) +// } +// } diff --git a/import.go b/import.go index 115f402..3ef4cbb 100644 --- a/import.go +++ b/import.go @@ -1,4 +1,4 @@ -package main +package invoiceservice import ( "encoding/json" diff --git a/pdf.go b/pdf.go index 5a1cd55..be72cc8 100644 --- a/pdf.go +++ b/pdf.go @@ -1,4 +1,4 @@ -package main +package invoiceservice import ( "fmt" @@ -123,7 +123,7 @@ func writeFooter(pdf *gopdf.GoPdf, id string) { pdf.Br(48) } -func writeRow(pdf *gopdf.GoPdf, item string, quantity int, rate float64) { +func writeRow(pdf *gopdf.GoPdf, item string, quantity int, rate float64, currency string) { _ = pdf.SetFont("Inter", "", 11) pdf.SetTextColor(0, 0, 0) @@ -134,26 +134,30 @@ func writeRow(pdf *gopdf.GoPdf, item string, quantity int, rate float64) { pdf.SetX(quantityColumnOffset) _ = pdf.Cell(nil, strconv.Itoa(quantity)) pdf.SetX(rateColumnOffset) - _ = pdf.Cell(nil, currencySymbols[file.Currency]+strconv.FormatFloat(rate, 'f', 2, 64)) + _ = pdf.Cell(nil, currencySymbols[currency]+strconv.FormatFloat(rate, 'f', 2, 64)) pdf.SetX(amountColumnOffset) - _ = pdf.Cell(nil, currencySymbols[file.Currency]+amount) + _ = pdf.Cell(nil, currencySymbols[currency]+amount) pdf.Br(24) } -func writeTotals(pdf *gopdf.GoPdf, subtotal float64, tax float64, discount float64) { +func writeTotals(pdf *gopdf.GoPdf, subtotal float64, tax float64, includeTax bool, discount float64, currency string) { pdf.SetY(650) - writeTotal(pdf, subtotalLabel, subtotal) + writeTotal(pdf, subtotalLabel, subtotal, currency) if tax > 0 { - writeTotal(pdf, taxLabel, tax) + writeTotal(pdf, taxLabel, tax, currency) } if discount > 0 { - writeTotal(pdf, discountLabel, discount) + writeTotal(pdf, discountLabel, discount, currency) } - writeTotal(pdf, totalLabel, subtotal+tax-discount) + var total float64 = subtotal - discount + if !includeTax { + total = total + tax + } + writeTotal(pdf, totalLabel, total, currency) } -func writeTotal(pdf *gopdf.GoPdf, label string, total float64) { +func writeTotal(pdf *gopdf.GoPdf, label string, total float64, currency string) { _ = pdf.SetFont("Inter", "", 9) pdf.SetTextColor(75, 75, 75) pdf.SetX(rateColumnOffset) @@ -164,7 +168,7 @@ func writeTotal(pdf *gopdf.GoPdf, label string, total float64) { if label == totalLabel { _ = pdf.SetFont("Inter-Bold", "", 11.5) } - _ = pdf.Cell(nil, currencySymbols[file.Currency]+strconv.FormatFloat(total, 'f', 2, 64)) + _ = pdf.Cell(nil, currencySymbols[currency]+strconv.FormatFloat(total, 'f', 2, 64)) pdf.Br(24) }