Skip to content

Commit

Permalink
Add checks before build
Browse files Browse the repository at this point in the history
  • Loading branch information
angelodlfrtr committed Jun 24, 2022
1 parent c0c106a commit 836cb19
Show file tree
Hide file tree
Showing 8 changed files with 193 additions and 45 deletions.
13 changes: 4 additions & 9 deletions build.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@ import (
// Build pdf document from data provided
func (doc *Document) Build() (*fpdf.Fpdf, error) {
// Validate document data
err := doc.Validate()
if err != nil {
if err := doc.Validate(); err != nil {
return nil, err
}

Expand All @@ -28,18 +27,14 @@ func (doc *Document) Build() (*fpdf.Fpdf, error) {

// Set header
if doc.Header != nil {
err = doc.Header.applyHeader(doc)

if err != nil {
if err := doc.Header.applyHeader(doc); err != nil {
return nil, err
}
}

// Set footer
if doc.Footer != nil {
err = doc.Footer.applyFooter(doc)

if err != nil {
if err := doc.Footer.applyFooter(doc); err != nil {
return nil, err
}
}
Expand Down Expand Up @@ -369,7 +364,7 @@ func (doc *Document) appendTotal() {

var descString bytes.Buffer
discountType, discountAmount := doc.Discount.getDiscount()
if discountType == "percent" {
if discountType == DiscountTypePercent {
descString.WriteString("-")
descString.WriteString(discountAmount.String())
descString.WriteString(" % / -")
Expand Down
45 changes: 43 additions & 2 deletions discount.go
Original file line number Diff line number Diff line change
@@ -1,27 +1,68 @@
package generator

import (
"errors"

"github.com/shopspring/decimal"
)

// ErrInvalidDiscount when percent and amount are empty
var ErrInvalidDiscount = errors.New("invalid discount")

// Discount types
const (
DiscountTypeAmount string = "amount"
DiscountTypePercent string = "percent"
)

// Discount define discount as percent or fixed amount
type Discount struct {
Percent string `json:"percent,omitempty"` // Discount in percent ex 17
Amount string `json:"amount,omitempty"` // Discount in amount ex 123.40

_percent decimal.Decimal
_amount decimal.Decimal
}

// Prepare convert strings to decimal
func (d *Discount) Prepare() error {
if len(d.Percent) == 0 && len(d.Amount) == 0 {
return ErrInvalidDiscount
}

// Percent
if len(d.Percent) > 0 {
percent, err := decimal.NewFromString(d.Percent)
if err != nil {
return err
}
d._percent = percent
}

// Amount
if len(d.Amount) > 0 {
amount, err := decimal.NewFromString(d.Amount)
if err != nil {
return err
}
d._amount = amount
}

return nil
}

// getDiscount as return the discount type and value
func (t *Discount) getDiscount() (string, decimal.Decimal) {
tax := "0"
taxType := "percent"
taxType := DiscountTypePercent

if len(t.Percent) > 0 {
tax = t.Percent
}

if len(t.Amount) > 0 {
tax = t.Amount
taxType = "amount"
taxType = DiscountTypeAmount
}

decVal, _ := decimal.NewFromString(tax)
Expand Down
8 changes: 5 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ module github.com/angelodlfrtr/go-invoice-generator
go 1.17

require (
github.com/creasty/defaults v1.5.2
github.com/creasty/defaults v1.6.0
github.com/go-pdf/fpdf v0.6.0
github.com/go-playground/validator/v10 v10.11.0
github.com/leekchan/accounting v0.3.1
github.com/shopspring/decimal v1.3.1
gopkg.in/go-playground/validator.v9 v9.31.0
)

require (
Expand All @@ -16,5 +16,7 @@ require (
github.com/go-playground/universal-translator v0.18.0 // indirect
github.com/leodido/go-urn v1.2.1 // indirect
github.com/pkg/errors v0.9.1 // indirect
gopkg.in/go-playground/assert.v1 v1.2.1 // indirect
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 // indirect
golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069 // indirect
golang.org/x/text v0.3.7 // indirect
)
45 changes: 36 additions & 9 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,29 @@ github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl
github.com/boombuler/barcode v1.0.1/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I=
github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ=
github.com/creasty/defaults v1.5.2 h1:/VfB6uxpyp6h0fr7SPp7n8WJBoV8jfxQXPCnkVSjyls=
github.com/creasty/defaults v1.5.2/go.mod h1:FPZ+Y0WNrbqOVw+c6av63eyHUAl6pMHZwqLPvXUZGfY=
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/creasty/defaults v1.6.0 h1:ltuE9cfphUtlrBeomuu8PEyISTXnxqkBIoQfXgv7BSc=
github.com/creasty/defaults v1.6.0/go.mod h1:iGzKe6pbEHnpMPtfDXZEr0NVxWnPTjb1bbDy08fPzYM=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/go-pdf/fpdf v0.6.0 h1:MlgtGIfsdMEEQJr2le6b/HNr1ZlQwxyWr77r2aj2U/8=
github.com/go-pdf/fpdf v0.6.0/go.mod h1:HzcnA+A23uwogo0tp9yU+l3V+KXhiESpt1PMayhOh5M=
github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A=
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/locales v0.14.0 h1:u50s323jtVGugKlcYeyzC0etD1HifMjqmJqb8WugfUU=
github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs=
github.com/go-playground/universal-translator v0.18.0 h1:82dyy6p4OuJq4/CByFNOn/jYrnRPArHwAcmLoJZxyho=
github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA=
github.com/go-playground/validator/v10 v10.11.0 h1:0W+xRM511GY47Yy3bZUbJVitCNg2BOGlCyvTqsp/xIw=
github.com/go-playground/validator/v10 v10.11.0/go.mod h1:i+3WkQ1FvaUjjxh1kSvIA4dMGDBiPU55YFDl0WbKdWU=
github.com/jung-kurt/gofpdf v1.0.0/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/leekchan/accounting v0.3.1 h1:6cIBKG9QngR6tuVV+mWjzcxsJDnoegrc70Ntb3MFqYM=
github.com/leekchan/accounting v0.3.1/go.mod h1:3timm6YPhY3YDaGxl0q3eaflX0eoSx3FXn7ckHe4tO0=
github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w=
Expand All @@ -22,29 +34,44 @@ github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/phpdave11/gofpdf v1.4.2/go.mod h1:zpO6xFn9yxo3YLyMvW8HcKWVdbNqgIfOOp2dXMnm1mY=
github.com/phpdave11/gofpdi v1.0.12/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI=
github.com/phpdave11/gofpdi v1.0.13/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
github.com/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58/go.mod h1:6lfFZQK844Gfx8o5WFuvpxWRwnSoipWe/p622j1v06w=
github.com/ruudk/golang-pdf417 v0.0.0-20201230142125-a7e3863a1245/go.mod h1:pQAZKsJ8yyVxGRWYNEm9oFB8ieLgKFnamEyDmSA0BRk=
github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4=
github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8=
github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 h1:0es+/5331RGQPcXlMfP+WrnIIS6dNnNRe0WB02W0F4M=
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/image v0.0.0-20190910094157-69e4b8554b2a/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/image v0.0.0-20210607152325-775e3b0c77b9/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069 h1:siQdpVirKtzPhKl3lZWozZraCFObP8S1v6PRp0bLrtU=
golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/go-playground/assert.v1 v1.2.1 h1:xoYuJVE7KT85PYWrN730RguIQO0ePzVRfFMXadIrXTM=
gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE=
gopkg.in/go-playground/validator.v9 v9.31.0 h1:bmXmP2RSNtFES+bn4uYuHT7iJFJv7Vj+an+ZQdDaD1M=
gopkg.in/go-playground/validator.v9 v9.31.0/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
54 changes: 39 additions & 15 deletions item.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,42 @@ type Item struct {
Quantity string `json:"quantity,omitempty"`
Tax *Tax `json:"tax,omitempty"`
Discount *Discount `json:"discount,omitempty"`
}

// unitCost returns the item unit cost
func (i *Item) unitCost() decimal.Decimal {
unitCost, _ := decimal.NewFromString(i.UnitCost)
return unitCost
_unitCost decimal.Decimal
_quantity decimal.Decimal
}

// quantity returns the item quantity
func (i *Item) quantity() decimal.Decimal {
quantity, _ := decimal.NewFromString(i.Quantity)
return quantity
// Prepare convert strings to decimal
func (i *Item) Prepare() error {
// Unit cost
unitCost, err := decimal.NewFromString(i.UnitCost)
if err != nil {
return err
}
i._unitCost = unitCost

// Quantity
quantity, err := decimal.NewFromString(i.Quantity)
if err != nil {
return err
}
i._quantity = quantity

// Tax
if i.Tax != nil {
if err := i.Tax.Prepare(); err != nil {
return err
}
}

// Discount
if i.Discount != nil {
if err := i.Discount.Prepare(); err != nil {
return err
}
}

return nil
}

// TotalWithoutTaxAndWithoutDiscount returns the total without tax and without discount
Expand All @@ -45,7 +69,7 @@ func (i *Item) TotalWithoutTaxAndWithDiscount() decimal.Decimal {
if i.Discount != nil {
dType, dNum := i.Discount.getDiscount()

if dType == "amount" {
if dType == DiscountTypeAmount {
total = total.Sub(dNum)
} else {
// Percent
Expand Down Expand Up @@ -73,7 +97,7 @@ func (i *Item) TaxWithTotalDiscounted() decimal.Decimal {
totalHT := i.TotalWithoutTaxAndWithDiscount()
taxType, taxAmount := i.Tax.getTax()

if taxType == "amount" {
if taxType == TaxTypeAmount {
result = taxAmount
} else {
divider := decimal.NewFromFloat(100)
Expand Down Expand Up @@ -138,7 +162,7 @@ func (i *Item) appendColTo(options *Options, doc *Document) {
doc.pdf.CellFormat(
ItemColQuantityOffset-ItemColUnitPriceOffset,
colHeight,
doc.encodeString(doc.ac.FormatMoneyDecimal(i.unitCost())),
doc.encodeString(doc.ac.FormatMoneyDecimal(i._unitCost)),
"0",
0,
"",
Expand All @@ -152,7 +176,7 @@ func (i *Item) appendColTo(options *Options, doc *Document) {
doc.pdf.CellFormat(
ItemColTaxOffset-ItemColQuantityOffset,
colHeight,
doc.encodeString(i.quantity().String()),
doc.encodeString(i._quantity.String()),
"0",
0,
"",
Expand Down Expand Up @@ -196,7 +220,7 @@ func (i *Item) appendColTo(options *Options, doc *Document) {
var discountDesc string

dCost := i.TotalWithoutTaxAndWithoutDiscount()
if discountType == "percent" {
if discountType == DiscountTypePercent {
discountTitle = fmt.Sprintf("%s %s", discountAmount, doc.encodeString("%"))

// get amount from percent
Expand Down Expand Up @@ -277,7 +301,7 @@ func (i *Item) appendColTo(options *Options, doc *Document) {
var taxTitle string
var taxDesc string

if taxType == "percent" {
if taxType == TaxTypePercent {
taxTitle = fmt.Sprintf("%s %s", taxAmount, "%")
// get amount from percent
dCost := i.TotalWithoutTaxAndWithDiscount()
Expand Down
45 changes: 43 additions & 2 deletions tax.go
Original file line number Diff line number Diff line change
@@ -1,27 +1,68 @@
package generator

import (
"errors"

"github.com/shopspring/decimal"
)

// ErrInvalidTax when percent and amount are empty
var ErrInvalidTax = errors.New("invalid tax")

// Tax types
const (
TaxTypeAmount string = "amount"
TaxTypePercent string = "percent"
)

// Tax define tax as percent or fixed amount
type Tax struct {
Percent string `json:"percent,omitempty"` // Tax in percent ex 17
Amount string `json:"amount,omitempty"` // Tax in amount ex 123.40

_percent decimal.Decimal
_amount decimal.Decimal
}

// Prepare convert strings to decimal
func (t *Tax) Prepare() error {
if len(t.Percent) == 0 && len(t.Amount) == 0 {
return ErrInvalidTax
}

// Percent
if len(t.Percent) > 0 {
percent, err := decimal.NewFromString(t.Percent)
if err != nil {
return err
}
t._percent = percent
}

// Amount
if len(t.Amount) > 0 {
amount, err := decimal.NewFromString(t.Amount)
if err != nil {
return err
}
t._amount = amount
}

return nil
}

// getTax return the tax type and value
func (t *Tax) getTax() (string, decimal.Decimal) {
tax := "0"
taxType := "percent"
taxType := TaxTypePercent

if len(t.Percent) > 0 {
tax = t.Percent
}

if len(t.Amount) > 0 {
tax = t.Amount
taxType = "amount"
taxType = TaxTypeAmount
}

decVal, _ := decimal.NewFromString(tax)
Expand Down
Loading

0 comments on commit 836cb19

Please sign in to comment.