Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix amount inversion on credit notes #12

Merged
merged 6 commits into from
Mar 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/lint.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v1
with:
go-version: "1.18"
go-version: "1.21"
id: go

- name: Check out code
Expand All @@ -31,4 +31,4 @@ jobs:
- name: Lint
uses: golangci/golangci-lint-action@v3
with:
version: v1.51
version: v1.55
2 changes: 1 addition & 1 deletion .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v2
with:
go-version: 1.18
go-version: 1.21

- name: Run GoReleaser
uses: goreleaser/goreleaser-action@v2
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v1
with:
go-version: "1.18"
go-version: "1.21"
id: go

- name: Check out code
Expand Down
2 changes: 1 addition & 1 deletion cmd/gobl.ticketbai/cancel.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ func (c *cancelOpts) runE(cmd *cobra.Command, args []string) error {
panic(err)
}

err = tbai.Cancel(doc)
err = tbai.Cancel(cmd.Context(), doc)
if err != nil {
panic(err)
}
Expand Down
4 changes: 2 additions & 2 deletions cmd/gobl.ticketbai/fetch.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ func (c *fetchOpts) cmd() *cobra.Command {
return cmd
}

func (c *fetchOpts) runE(*cobra.Command, []string) error {
func (c *fetchOpts) runE(cmd *cobra.Command, _ []string) error {
soft := &ticketbai.Software{
NIF: c.swNIF,
Name: c.swName,
Expand Down Expand Up @@ -92,7 +92,7 @@ func (c *fetchOpts) runE(*cobra.Command, []string) error {
panic(err)
}

_, err = tbai.Fetch(l10n.Code(c.zone), c.nif, c.name, c.year, c.page)
_, err = tbai.Fetch(cmd.Context(), l10n.Code(c.zone), c.nif, c.name, c.year, c.page)
if err != nil {
panic(err)
}
Expand Down
6 changes: 4 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
module github.com/invopop/gobl.ticketbai

go 1.18
go 1.21

toolchain go1.22.1

require (
github.com/go-resty/resty/v2 v2.10.0
github.com/invopop/gobl v0.69.0
github.com/invopop/gobl v0.69.1
github.com/invopop/xmldsig v0.9.0
github.com/lestrrat-go/libxml2 v0.0.0-20231124114421-99c71026c2f5
github.com/magefile/mage v1.15.0
Expand Down
7 changes: 5 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,21 @@ github.com/go-resty/resty/v2 v2.10.0 h1:Qla4W/+TMmv0fOeeRqzEpXPLfTUnR5HZ1+lGs+Ck
github.com/go-resty/resty/v2 v2.10.0/go.mod h1:iiP/OpA0CkcL3IGt1O0+/SIItFUbkkyw5BGXiVdTu+A=
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4=
github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/invopop/gobl v0.69.0 h1:W0Nn5QzvTJUXhe3T+mLfrWR9yUKx/xdKpYEPMsrT1lI=
github.com/invopop/gobl v0.69.0/go.mod h1:Jau+ajdfUCBPVH9VMor6aeYq3S9o7HuSNm07QxxxomE=
github.com/invopop/gobl v0.69.1 h1:/Hgqx77E0npX0R1X46lRvmkbyXiFRZsi33Q3gG3vN/I=
github.com/invopop/gobl v0.69.1/go.mod h1:Jau+ajdfUCBPVH9VMor6aeYq3S9o7HuSNm07QxxxomE=
github.com/invopop/jsonschema v0.12.0 h1:6ovsNSuvn9wEQVOyc72aycBMVQFKz7cPdMJn10CvzRI=
github.com/invopop/jsonschema v0.12.0/go.mod h1:ffZ5Km5SWWRAIN6wbDXItl95euhFz2uON45H2qjYt+0=
github.com/invopop/validation v0.3.0 h1:o260kbjXzoBO/ypXDSSrCLL7SxEFUXBsX09YTE9AxZw=
github.com/invopop/validation v0.3.0/go.mod h1:qIBG6APYLp2Wu3/96p3idYjP8ffTKVmQBfKiZbw0Hts=
github.com/invopop/xmldsig v0.9.0 h1:fOmPSGzXgbZEJu2ZkqXYUPJ9w1SkVuMSslb8lB7VNog=
github.com/invopop/xmldsig v0.9.0/go.mod h1:dc3+2BYNw0vzauyZiOobTltp1t3BbvWSq7ae/F2gdk0=
github.com/invopop/yaml v0.1.0 h1:YW3WGUoJEXYfzWBjn00zIlrw7brGVD0fUKRYDPAPhrc=
github.com/invopop/yaml v0.1.0/go.mod h1:2XuRLgs/ouIrW3XNzuNj7J3Nvu/Dig5MXvbCEdiBN3Q=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/lestrrat-go/libxml2 v0.0.0-20231124114421-99c71026c2f5 h1:lR4DHv41vdkhNPNDlr56n8BuLINQeWNeQAaAzBEOcuw=
github.com/lestrrat-go/libxml2 v0.0.0-20231124114421-99c71026c2f5/go.mod h1:/0MMipmS+5SMXCSkulsvJwYmddKI4IL5tVy6AZMo9n0=
Expand Down Expand Up @@ -117,6 +119,7 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/xmlpath.v1 v1.0.0-20140413065638-a146725ea6e7 h1:zibSPXbkfB1Dwl76rJgLa68xcdHu42qmFTe6vAnU4wA=
gopkg.in/xmlpath.v1 v1.0.0-20140413065638-a146725ea6e7/go.mod h1:wo0SW5T6XqIKCCAge330Cd5sm+7VI6v85OrQHIk50KM=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
Expand Down
3 changes: 1 addition & 2 deletions internal/doc/doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,7 @@ func NewTicketBAI(inv *bill.Invoice, ts time.Time, role IssuerRole, zone l10n.Co
// become "facturas rectificativas por diferencias" and, when a correction is for a
// credit operation, the amounts must be negative to cancel out the ones in the
// original invoice. For that reason, we invert the credit note quantities here.
inv.Invert()
if err := inv.Calculate(); err != nil {
if err := inv.Invert(); err != nil {
return nil, err
}
}
Expand Down
18 changes: 18 additions & 0 deletions internal/doc/doc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ import (

"github.com/invopop/gobl.ticketbai/internal/doc"
"github.com/invopop/gobl.ticketbai/test"
"github.com/invopop/gobl/bill"
"github.com/invopop/gobl/l10n"
"github.com/invopop/gobl/num"
"github.com/invopop/gobl/regimes/es"
"github.com/invopop/gobl/tax"
"github.com/stretchr/testify/assert"
Expand Down Expand Up @@ -101,4 +103,20 @@ func TestInvoiceConversion(t *testing.T) {

assert.Nil(t, invoice.Sujetos.Destinatarios)
})

t.Run("fail when charges are present since they aren't supported", func(t *testing.T) {
inv, _ := test.LoadInvoice("sample-invoice.json")
inv.Lines[0].Charges = []*bill.LineCharge{{Amount: num.MakeAmount(100, 2)}}

_, err := doc.NewTicketBAI(inv, ts, role, doc.ZoneBI)
require.Error(t, err)
assert.Contains(t, err.Error(), "charges are not supported")

inv.Lines[0].Charges = nil
inv.Charges = []*bill.Charge{{Amount: num.MakeAmount(100, 2)}}

_, err = doc.NewTicketBAI(inv, ts, role, doc.ZoneBI)
require.Error(t, err)
assert.Contains(t, err.Error(), "charges are not supported")
})
}
10 changes: 10 additions & 0 deletions internal/doc/validations.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,5 +39,15 @@ func validate(inv *bill.Invoice, zone l10n.Code) error {
}
}

for _, l := range inv.Lines {
if len(l.Charges) > 0 {
return errors.New("charges are not supported")
}
}

if len(inv.Charges) > 0 {
return errors.New("charges are not supported")
}

return nil
}
16 changes: 9 additions & 7 deletions internal/gateways/ebizkaia.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package gateways

import (
"context"
"crypto/tls"
"errors"
"fmt"
Expand Down Expand Up @@ -60,7 +61,7 @@ func newEbizkaia(env Environment, tlsConfig *tls.Config) *EBizkaiaConn {

// Post sends the complete TicketBAI document to the remote end-point. We assume
// the document has been signed and prepared.
func (c *EBizkaiaConn) Post(inv *bill.Invoice, doc *doc.TicketBAI) error {
func (c *EBizkaiaConn) Post(ctx context.Context, inv *bill.Invoice, doc *doc.TicketBAI) error {
payload, err := doc.Bytes()
if err != nil {
return fmt.Errorf("generating payload: %w", err)
Expand All @@ -79,7 +80,7 @@ func (c *EBizkaiaConn) Post(inv *bill.Invoice, doc *doc.TicketBAI) error {

resp := ebizkaia.LROEPJ240FacturasEmitidasConSGAltaRespuesta{}

err = c.sendRequest(req, eBizkaiaExecutePath, &resp)
err = c.sendRequest(ctx, req, eBizkaiaExecutePath, &resp)
if errors.Is(err, ErrInvalidRequest) {
if resp.FirstErrorCode() == eBizkaiaN3RespCodeDuplicated {
return ErrDuplicatedRecord
Expand All @@ -95,7 +96,7 @@ func (c *EBizkaiaConn) Post(inv *bill.Invoice, doc *doc.TicketBAI) error {

// Fetch retrieves the TicketBAI from the remote end-point for the given
// taxpayer and year.
func (c *EBizkaiaConn) Fetch(nif string, name string, year int, page int, head *doc.CabeceraFactura) ([]*doc.TicketBAI, error) {
func (c *EBizkaiaConn) Fetch(ctx context.Context, nif string, name string, year int, page int, head *doc.CabeceraFactura) ([]*doc.TicketBAI, error) {
sup := &ebizkaia.Supplier{
Year: year,
NIF: nif,
Expand All @@ -108,7 +109,7 @@ func (c *EBizkaiaConn) Fetch(nif string, name string, year int, page int, head *
}

resp := ebizkaia.LROEPJ240FacturasEmitidasConSGConsultaRespuesta{}
if err := c.sendRequest(d, eBizkaiaQueryPath, &resp); err != nil {
if err := c.sendRequest(ctx, d, eBizkaiaQueryPath, &resp); err != nil {
return nil, fmt.Errorf("sending fetch request: %w", err)
}

Expand All @@ -122,7 +123,7 @@ func (c *EBizkaiaConn) Fetch(nif string, name string, year int, page int, head *

// Cancel sends the cancellation request for the TickeBAI invoice to the remote
// end-point.
func (c *EBizkaiaConn) Cancel(inv *bill.Invoice, doc *doc.AnulaTicketBAI) error {
func (c *EBizkaiaConn) Cancel(ctx context.Context, inv *bill.Invoice, doc *doc.AnulaTicketBAI) error {
payload, err := doc.Bytes()
if err != nil {
return fmt.Errorf("generating payload: %w", err)
Expand All @@ -139,11 +140,12 @@ func (c *EBizkaiaConn) Cancel(inv *bill.Invoice, doc *doc.AnulaTicketBAI) error
return fmt.Errorf("create request: %w", err)
}

return c.sendRequest(req, eBizkaiaExecutePath, nil)
return c.sendRequest(ctx, req, eBizkaiaExecutePath, nil)
}

func (c *EBizkaiaConn) sendRequest(doc *ebizkaia.Request, path string, resp interface{}) error {
func (c *EBizkaiaConn) sendRequest(ctx context.Context, doc *ebizkaia.Request, path string, resp interface{}) error {
r := c.client.R().
SetContext(ctx).
SetHeader("Content-Encoding", "gzip").
SetHeader("Content-Type", "application/octet-stream").
SetHeader("Accept-Encoding", "gzip").
Expand Down
7 changes: 4 additions & 3 deletions internal/gateways/gateways.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
package gateways

import (
"context"
"errors"
"fmt"

Expand Down Expand Up @@ -32,9 +33,9 @@ var (
type Connection interface {
// Post sends the complete TicketBAI document to the remote end-point. We assume
// the document has been fully prepared and signed.
Post(inv *bill.Invoice, doc *doc.TicketBAI) error
Fetch(nif string, name string, year int, page int, head *doc.CabeceraFactura) ([]*doc.TicketBAI, error)
Cancel(inv *bill.Invoice, doc *doc.AnulaTicketBAI) error
Post(ctx context.Context, inv *bill.Invoice, doc *doc.TicketBAI) error
Fetch(ctx context.Context, nif string, name string, year int, page int, head *doc.CabeceraFactura) ([]*doc.TicketBAI, error)
Cancel(ctx context.Context, inv *bill.Invoice, doc *doc.AnulaTicketBAI) error
}

// List keeps together the list of connections
Expand Down
22 changes: 14 additions & 8 deletions test/data/credit-note-es-es-tbai.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
{
"$schema": "https://gobl.org/draft-0/envelope",
"head": {
"uuid": "8a51fd30-2a27-11ee-be56-0242ac120002",
"uuid": "78f1695c-e5ce-11ee-9527-e6a7901137ed",
"dig": {
"alg": "sha256",
"val": "2349886e98f484bd81d81d4d07b16d686259e5e4e56ad218d81796b4ac8ae1ec"
"val": "0c28b4a60a0330ad4c2f419c9c3b8a3d43eb8cd51f24eef926710bea9cdb1134"
},
"draft": true
},
Expand Down Expand Up @@ -104,19 +104,25 @@
"price": "10.00"
},
"sum": "10.00",
"discounts": [
{
"amount": "5.00",
"reason": "5-euro coupon"
}
],
"taxes": [
{
"cat": "VAT",
"rate": "zero",
"percent": "0.0%"
}
],
"total": "10.00"
"total": "5.00"
}
],
"totals": {
"sum": "1630.00",
"total": "1630.00",
"sum": "1625.00",
"total": "1625.00",
"taxes": {
"categories": [
{
Expand All @@ -130,7 +136,7 @@
},
{
"key": "zero",
"base": "10.00",
"base": "5.00",
"percent": "0.0%",
"amount": "0.00"
}
Expand All @@ -141,8 +147,8 @@
"sum": "340.20"
},
"tax": "340.20",
"total_with_tax": "1970.20",
"payable": "1970.20"
"total_with_tax": "1965.20",
"payable": "1965.20"
},
"notes": [
{
Expand Down
3 changes: 3 additions & 0 deletions test/data/credit-note-es-es-tbai.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@ lines:
item:
name: "Financial service"
price: "10.00"
discounts:
- amount: "5.00"
reason: "5-euro coupon"
taxes:
- cat: VAT
rate: zero
Expand Down
Loading
Loading