From e0ffb56e6653d17cb5e022237c0121b7fb5592f4 Mon Sep 17 00:00:00 2001 From: Grzegorz Lisowski Date: Tue, 26 Mar 2024 18:31:11 +0100 Subject: [PATCH] Use credit-note instead of corrective invoices Poland doesn't have a distinction between credit notes and corrective invoices. Our implementation of invoice correction is closer to what we see in credit notes in other countries. For example we have differential values for line items. --- corrected.go | 3 +- invoice.go | 4 +- invoice_test.go | 2 +- ksef_test.go | 10 +- lines.go | 11 -- payments.go | 3 +- regime.go | 2 +- test/data/corrective-invoice.json | 120 ------------------ test/data/credit-note.json | 120 ++++++++++++++++++ ...corrective-invoice.xml => credit-note.xml} | 12 +- 10 files changed, 138 insertions(+), 149 deletions(-) delete mode 100644 test/data/corrective-invoice.json create mode 100644 test/data/credit-note.json rename test/data/out/{corrective-invoice.xml => credit-note.xml} (93%) diff --git a/corrected.go b/corrected.go index 4bacfdb..d4c2436 100644 --- a/corrected.go +++ b/corrected.go @@ -5,7 +5,7 @@ import ( "github.com/invopop/gobl/head" ) -// CorrectedInv defines the XML structure for KSeF correction invoiceÄ… +// CorrectedInv defines the XML structure for KSeF correction invoice type CorrectedInv struct { IssueDate string `xml:"DataWystFaKorygowanej,omitempty"` SequentialNumber string `xml:"NrFaKorygowanej,omitempty"` @@ -14,6 +14,7 @@ type CorrectedInv struct { KsefNumber string `xml:"NrKSeFFaKorygowanej,omitempty"` } +// NewCorrectedInv gets credit note data from GOBL invoice func NewCorrectedInv(prc *bill.Preceding) *CorrectedInv { inv := &CorrectedInv{ SequentialNumber: invoiceNumber(prc.Series, prc.Code), diff --git a/invoice.go b/invoice.go index 72f8c02..a77e254 100644 --- a/invoice.go +++ b/invoice.go @@ -95,8 +95,8 @@ func NewInv(inv *bill.Invoice) *Inv { for _, prc := range inv.Preceding { Inv.CorrectedInv = NewCorrectedInv(prc) Inv.CorrectionReason = prc.Reason - if prc.Ext.Has(pl.ExtKeyKSEFCorrection) { - Inv.CorrectionType = prc.Ext[pl.ExtKeyKSEFCorrection].Code().String() + if prc.Ext.Has(pl.ExtKeyKSeFEffectiveDate) { + Inv.CorrectionType = prc.Ext[pl.ExtKeyKSeFEffectiveDate].Code().String() } } } diff --git a/invoice_test.go b/invoice_test.go index c3c3cf9..d2e5aa1 100644 --- a/invoice_test.go +++ b/invoice_test.go @@ -70,7 +70,7 @@ func TestNewInv(t *testing.T) { Preceding: []*bill.Preceding{ { Ext: tax.Extensions{ - pl.ExtKeyKSEFCorrection: "1", + pl.ExtKeyKSeFEffectiveDate: "1", }, }, }, diff --git a/ksef_test.go b/ksef_test.go index bf1b7cf..0f2d576 100644 --- a/ksef_test.go +++ b/ksef_test.go @@ -37,14 +37,14 @@ func TestNewDocument(t *testing.T) { assert.Equal(t, output, data) }) - t.Run("should return bytes of the corrective invoice", func(t *testing.T) { - doc, err := test.NewDocumentFrom("corrective-invoice.json") + t.Run("should return bytes of the credit-note invoice", func(t *testing.T) { + doc, err := test.NewDocumentFrom("credit-note.json") require.NoError(t, err) data, err := doc.Bytes() require.NoError(t, err) - output, err := test.LoadOutputFile("corrective-invoice.xml") + output, err := test.LoadOutputFile("credit-note.xml") require.NoError(t, err) assert.Equal(t, output, data) @@ -72,7 +72,7 @@ func TestNewDocument(t *testing.T) { assert.Nil(t, validation) }) - t.Run("should generate valid correction invoice", func(t *testing.T) { + t.Run("should generate valid credit-note", func(t *testing.T) { err := xsdvalidate.Init() require.NoError(t, err) defer xsdvalidate.Cleanup() @@ -84,7 +84,7 @@ func TestNewDocument(t *testing.T) { require.NoError(t, err) defer xsdhandler.Free() - doc, err := test.NewDocumentFrom("corrective-invoice.json") + doc, err := test.NewDocumentFrom("credit-note.json") require.NoError(t, err) data, err := doc.Bytes() diff --git a/lines.go b/lines.go index 9d9297a..15fe160 100644 --- a/lines.go +++ b/lines.go @@ -27,7 +27,6 @@ func newLine(line *bill.Line) *Line { Measure: string(line.Item.Unit.UNECE()), NetUnitPrice: line.Item.Price.String(), Quantity: line.Quantity.String(), - UnitDiscount: unitDiscount(line), NetPriceTotal: line.Total.String(), TaxRate: line.Taxes[0].Percent.Rescale(2).StringWithoutSymbol(), } @@ -35,16 +34,6 @@ func newLine(line *bill.Line) *Line { return Line } -func unitDiscount(line *bill.Line) string { - if line.Total == line.Sum { - return "" - } - - discount := line.Total.Subtract(line.Sum).Divide(line.Quantity) // not sure if there should be some rescale or matchPrecision - - return discount.String() -} - // NewLines generates lines for the KSeF invoice func NewLines(lines []*bill.Line) []*Line { var Lines []*Line diff --git a/payments.go b/payments.go index 27ed020..325f6e7 100644 --- a/payments.go +++ b/payments.go @@ -6,7 +6,6 @@ import ( "github.com/invopop/gobl/bill" "github.com/invopop/gobl/cbc" "github.com/invopop/gobl/regimes/pl" - "github.com/invopop/gobl/tax" ) // AdvancePayment defines the XML structure for KSeF advance payments @@ -126,7 +125,7 @@ func findPaymentMeansCode(key cbc.Key) (string, error) { return code.String(), nil } -func findPaymentKeyDefinition(key cbc.Key) *tax.KeyDefinition { +func findPaymentKeyDefinition(key cbc.Key) *cbc.KeyDefinition { for _, keyDef := range regime.PaymentMeansKeys { if key == keyDef.Key { return keyDef diff --git a/regime.go b/regime.go index fcce211..069db0f 100644 --- a/regime.go +++ b/regime.go @@ -5,4 +5,4 @@ import ( "github.com/invopop/gobl/tax" ) -var regime = tax.RegimeFor(l10n.PL, l10n.CodeEmpty) +var regime = tax.RegimeFor(l10n.PL) diff --git a/test/data/corrective-invoice.json b/test/data/corrective-invoice.json deleted file mode 100644 index 70d00ed..0000000 --- a/test/data/corrective-invoice.json +++ /dev/null @@ -1,120 +0,0 @@ -{ - "$schema": "https://gobl.org/draft-0/envelope", - "head": { - "uuid": "d05c7988-e145-11ee-bef0-52f0b4d06139", - "dig": { - "alg": "sha256", - "val": "0630d41061873a3b8bf650cbfd204a57c6157210d8a6f49c4a4ee31338b43e1f" - }, - "draft": true - }, - "doc": { - "$schema": "https://gobl.org/draft-0/bill/invoice", - "type": "corrective", - "series": "COR", - "code": "002", - "issue_date": "2023-12-21", - "currency": "PLN", - "preceding": [ - { - "type": "standard", - "series": "SAMPLE", - "code": "001", - "issue_date": "2023-12-20", - "reason": "Special Discount", - "stamps": [ - { - "prv": "ksef-id", - "val": "9876543210-20231220-107FDF72DB53-F7" - } - ], - "ext": { - "pl-ksef-correction": "2" - } - } - ], - "supplier": { - "name": "Provide One S.L.", - "tax_id": { - "country": "PL", - "code": "9876543210" - }, - "addresses": [ - { - "num": "42", - "street": "Calle Pradillo", - "locality": "Madrid", - "region": "Madrid", - "code": "00-015", - "country": "PL" - } - ], - "emails": [ - { - "addr": "billing@example.com" - } - ] - }, - "customer": { - "name": "Sample Consumer", - "tax_id": { - "country": "PL", - "code": "1234567788" - }, - "addresses": [ - { - "num": "43", - "street": "Calle Pradillo", - "locality": "Madrid", - "region": "Madrid", - "code": "00-015", - "country": "PL" - } - ] - }, - "lines": [ - { - "i": 1, - "quantity": "20", - "item": { - "name": "Development services", - "price": "-10.00", - "unit": "h" - }, - "sum": "-200.00", - "taxes": [ - { - "cat": "VAT", - "rate": "standard", - "percent": "23.0%" - } - ], - "total": "-200.00" - } - ], - "totals": { - "sum": "-200.00", - "total": "-200.00", - "taxes": { - "categories": [ - { - "code": "VAT", - "rates": [ - { - "key": "standard", - "base": "-200.00", - "percent": "23.0%", - "amount": "-46.00" - } - ], - "amount": "-46.00" - } - ], - "sum": "-46.00" - }, - "tax": "-46.00", - "total_with_tax": "-246.00", - "payable": "-246.00" - } - } -} \ No newline at end of file diff --git a/test/data/credit-note.json b/test/data/credit-note.json new file mode 100644 index 0000000..3372f1a --- /dev/null +++ b/test/data/credit-note.json @@ -0,0 +1,120 @@ +{ + "$schema": "https://gobl.org/draft-0/envelope", + "head": { + "uuid": "8a51fd30-2a27-11ee-be56-0242ac120002", + "dig": { + "alg": "sha256", + "val": "2dfc5c1c3b11a69e10ba47256e5a1655f5c6dfca99ad6b0390a987588020bbb2" + }, + "draft": true + }, + "doc": { + "$schema": "https://gobl.org/draft-0/bill/invoice", + "type": "credit-note", + "series": "CN", + "code": "002", + "issue_date": "2023-12-21", + "currency": "PLN", + "preceding": [ + { + "type": "standard", + "series": "SAMPLE", + "code": "001", + "issue_date": "2023-12-20", + "reason": "Special Discount", + "stamps": [ + { + "prv": "ksef-id", + "val": "9876543210-20231220-107FDF72DB53-F7" + } + ], + "ext": { + "pl-ksef-effective-date": "2" + } + } + ], + "supplier": { + "name": "Provide One S.L.", + "tax_id": { + "country": "PL", + "code": "9876543210" + }, + "addresses": [ + { + "num": "42", + "street": "Calle Pradillo", + "locality": "Madrid", + "region": "Madrid", + "code": "00-015", + "country": "PL" + } + ], + "emails": [ + { + "addr": "billing@example.com" + } + ] + }, + "customer": { + "name": "Sample Consumer", + "tax_id": { + "country": "PL", + "code": "1234567788" + }, + "addresses": [ + { + "num": "43", + "street": "Calle Pradillo", + "locality": "Madrid", + "region": "Madrid", + "code": "00-015", + "country": "PL" + } + ] + }, + "lines": [ + { + "i": 1, + "quantity": "20", + "item": { + "name": "Development services", + "price": "10.00", + "unit": "h" + }, + "sum": "200.00", + "taxes": [ + { + "cat": "VAT", + "rate": "standard", + "percent": "23.0%" + } + ], + "total": "200.00" + } + ], + "totals": { + "sum": "200.00", + "total": "200.00", + "taxes": { + "categories": [ + { + "code": "VAT", + "rates": [ + { + "key": "standard", + "base": "200.00", + "percent": "23.0%", + "amount": "46.00" + } + ], + "amount": "46.00" + } + ], + "sum": "46.00" + }, + "tax": "46.00", + "total_with_tax": "246.00", + "payable": "246.00" + } + } +} \ No newline at end of file diff --git a/test/data/out/corrective-invoice.xml b/test/data/out/credit-note.xml similarity index 93% rename from test/data/out/corrective-invoice.xml rename to test/data/out/credit-note.xml index 06b1ba9..84de0db 100644 --- a/test/data/out/corrective-invoice.xml +++ b/test/data/out/credit-note.xml @@ -34,10 +34,10 @@ PLN 2023-12-21 - COR-002 - -200.00 - -46.00 - -246.00 + CN-002 + 200.00 + 46.00 + 246.00 2 2 @@ -68,8 +68,8 @@ Development services HUR 20 - -10.00 - -200.00 + 10.00 + 200.00 23