diff --git a/CHANGELOG.md b/CHANGELOG.md index 7a8075a1..17398118 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,12 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p - `es-verifactu-v1`: added initial Spain VeriFactu addon. +## [v0.206.1] - 2024-11-28 + +### Fixed + +- `org`: Party validation now working with regimes when defined. + ## [v0.206.0] - 2024-11-26 ### Added diff --git a/examples/gr/invoice-b2c.yaml b/examples/gr/invoice-b2c.yaml index 517c6018..d59cefaf 100644 --- a/examples/gr/invoice-b2c.yaml +++ b/examples/gr/invoice-b2c.yaml @@ -13,7 +13,7 @@ tax: supplier: tax_id: country: "EL" - code: "728089281" + code: "177472438" name: "Ελληνικά Τρόφιμα Α.Ε." emails: - addr: "hellenicfoods@example.com" @@ -33,15 +33,10 @@ lines: taxes: - cat: VAT rate: standard - - quantity: 1 - item: - name: "Cleaning" - price: "8.44" - taxes: - - cat: VAT - rate: reduced payment: + instructions: + key: card advances: - key: card percent: "100%" diff --git a/examples/gr/invoice-el-el.yaml b/examples/gr/invoice-el-el.yaml index a79c0df5..768cb187 100644 --- a/examples/gr/invoice-el-el.yaml +++ b/examples/gr/invoice-el-el.yaml @@ -11,7 +11,7 @@ $tags: supplier: tax_id: country: "EL" - code: "728089281" + code: "177472438" name: "Ελληνικά Τρόφιμα Α.Ε." emails: - addr: "hellenicfoods@example.com" @@ -42,19 +42,22 @@ lines: name: "Υπηρεσίες Ανάπτυξης" price: "90.00" unit: "h" + ext: + "gr-mydata-income-cat": "category1_3" + "gr-mydata-income-type": "E3_561_001" discounts: - percent: "10%" reason: "Ειδική Έκπτωση" taxes: - cat: VAT rate: standard - ext: - "gr-mydata-income-cat": "category1_1" - "gr-mydata-income-type": "E3_106" - quantity: 1 item: name: "Tax exempt item" price: "100.00" + ext: + "gr-mydata-income-cat": "category1_3" + "gr-mydata-income-type": "E3_561_001" taxes: - cat: VAT rate: exempt diff --git a/examples/gr/invoice-islands.yaml b/examples/gr/invoice-islands.yaml index 0ea571f4..165a6d8b 100644 --- a/examples/gr/invoice-islands.yaml +++ b/examples/gr/invoice-islands.yaml @@ -11,7 +11,7 @@ $tags: supplier: tax_id: country: "EL" - code: "728089281" + code: "177472438" name: "Ελληνικά Τρόφιμα Α.Ε." emails: - addr: "hellenicfoods@example.com" diff --git a/examples/gr/out/invoice-b2c.json b/examples/gr/out/invoice-b2c.json index c66783a6..ef370249 100644 --- a/examples/gr/out/invoice-b2c.json +++ b/examples/gr/out/invoice-b2c.json @@ -4,7 +4,7 @@ "uuid": "8a51fd30-2a27-11ee-be56-0242ac120002", "dig": { "alg": "sha256", - "val": "7b1f15e3697d8d68d22caa0557078fc772e90ddcff058712f0cbab0013e5c08f" + "val": "e0933613d76459243623c7f1c78dc0665214e06f6649113b7ccd4530e04d1948" } }, "doc": { @@ -31,7 +31,7 @@ "name": "Ελληνικά Τρόφιμα Α.Ε.", "tax_id": { "country": "EL", - "code": "728089281" + "code": "177472438" }, "addresses": [ { @@ -69,26 +69,6 @@ } ], "total": "8.44" - }, - { - "i": 2, - "quantity": "1", - "item": { - "name": "Cleaning", - "price": "8.44" - }, - "sum": "8.44", - "taxes": [ - { - "cat": "VAT", - "rate": "reduced", - "percent": "13%", - "ext": { - "gr-mydata-vat-rate": "2" - } - } - ], - "total": "8.44" } ], "payment": { @@ -97,16 +77,22 @@ "key": "card", "description": "Prepaid amount", "percent": "100%", - "amount": "20.01", + "amount": "10.47", "ext": { "gr-mydata-payment-means": "7" } } - ] + ], + "instructions": { + "key": "card", + "ext": { + "gr-mydata-payment-means": "7" + } + } }, "totals": { - "sum": "16.88", - "total": "16.88", + "sum": "8.44", + "total": "8.44", "taxes": { "categories": [ { @@ -120,26 +106,17 @@ "base": "8.44", "percent": "24%", "amount": "2.03" - }, - { - "key": "reduced", - "ext": { - "gr-mydata-vat-rate": "2" - }, - "base": "8.44", - "percent": "13%", - "amount": "1.10" } ], - "amount": "3.13" + "amount": "2.03" } ], - "sum": "3.13" + "sum": "2.03" }, - "tax": "3.13", - "total_with_tax": "20.01", - "payable": "20.01", - "advance": "20.01", + "tax": "2.03", + "total_with_tax": "10.47", + "payable": "10.47", + "advance": "10.47", "due": "0.00" } } diff --git a/examples/gr/out/invoice-el-el.json b/examples/gr/out/invoice-el-el.json index 6cb69e6b..6866ae36 100644 --- a/examples/gr/out/invoice-el-el.json +++ b/examples/gr/out/invoice-el-el.json @@ -4,7 +4,7 @@ "uuid": "8a51fd30-2a27-11ee-be56-0242ac120002", "dig": { "alg": "sha256", - "val": "0adb783cf39fd01962abbc45755da8a3cf16b16f5a3d0fec3eba7edd68a1bc66" + "val": "2946cc07a733a1eaa682226ace3b321077e8f97033642042a67b75c0cf98ffbf" } }, "doc": { @@ -31,7 +31,7 @@ "name": "Ελληνικά Τρόφιμα Α.Ε.", "tax_id": { "country": "EL", - "code": "728089281" + "code": "177472438" }, "addresses": [ { @@ -76,7 +76,11 @@ "item": { "name": "Υπηρεσίες Ανάπτυξης", "price": "90.00", - "unit": "h" + "unit": "h", + "ext": { + "gr-mydata-income-cat": "category1_3", + "gr-mydata-income-type": "E3_561_001" + } }, "sum": "1800.00", "discounts": [ @@ -92,8 +96,6 @@ "rate": "standard", "percent": "24%", "ext": { - "gr-mydata-income-cat": "category1_1", - "gr-mydata-income-type": "E3_106", "gr-mydata-vat-rate": "1" } } @@ -105,7 +107,11 @@ "quantity": "1", "item": { "name": "Tax exempt item", - "price": "100.00" + "price": "100.00", + "ext": { + "gr-mydata-income-cat": "category1_3", + "gr-mydata-income-type": "E3_561_001" + } }, "sum": "100.00", "taxes": [ @@ -140,8 +146,6 @@ { "key": "standard", "ext": { - "gr-mydata-income-cat": "category1_1", - "gr-mydata-income-type": "E3_106", "gr-mydata-vat-rate": "1" }, "base": "1620.00", diff --git a/examples/gr/out/invoice-islands.json b/examples/gr/out/invoice-islands.json index 11a3dcb0..90151050 100644 --- a/examples/gr/out/invoice-islands.json +++ b/examples/gr/out/invoice-islands.json @@ -4,7 +4,7 @@ "uuid": "8a51fd30-2a27-11ee-be56-0242ac120002", "dig": { "alg": "sha256", - "val": "dda9cc633ac5050877271cc1bd6631bd95b1190a4e4b26a69725d86e4f2a6d55" + "val": "24b8131e19c332262a8d8afe0bddfaadc7213f841d377fdcfeca8526641cddba" } }, "doc": { @@ -31,7 +31,7 @@ "name": "Ελληνικά Τρόφιμα Α.Ε.", "tax_id": { "country": "EL", - "code": "728089281" + "code": "177472438" }, "addresses": [ { diff --git a/org/party.go b/org/party.go index 867b7af1..8f89d364 100644 --- a/org/party.go +++ b/org/party.go @@ -92,7 +92,9 @@ func (p *Party) Validate() error { // ValidateWithContext is used to check the party's data meets minimum expectations. func (p *Party) ValidateWithContext(ctx context.Context) error { + ctx = p.ValidationContext(ctx) return tax.ValidateStructWithContext(ctx, p, + validation.Field(&p.Regime), validation.Field(&p.Name), validation.Field(&p.TaxID), validation.Field(&p.Identities), @@ -109,6 +111,14 @@ func (p *Party) ValidateWithContext(ctx context.Context) error { ) } +// ValidationContext returns a context with the regime's validation rules. +func (p *Party) ValidationContext(ctx context.Context) context.Context { + if r := p.RegimeDef(); r != nil { + ctx = r.WithContext(ctx) + } + return ctx +} + // JSONSchemaExtend adds extra details to the schema. func (Party) JSONSchemaExtend(js *jsonschema.Schema) { js.Extras = map[string]any{ diff --git a/org/party_test.go b/org/party_test.go index bffbf250..9c40ee70 100644 --- a/org/party_test.go +++ b/org/party_test.go @@ -88,3 +88,36 @@ func TestPartyAddressNill(t *testing.T) { party.Normalize(nil) assert.NoError(t, party.Validate()) } + +func TestPartyValidation(t *testing.T) { + t.Run("with regime", func(t *testing.T) { + party := org.Party{ + Regime: tax.WithRegime("DE"), + Name: "Invopop", + Identities: []*org.Identity{ + { + Key: "de-tax-number", + Code: "123 456 78901", + }, + }, + } + require.NoError(t, party.Calculate()) + assert.NoError(t, party.Validate()) + assert.Equal(t, "DE", party.GetRegime().String()) + }) + t.Run("with regime and bad code", func(t *testing.T) { + party := org.Party{ + Regime: tax.WithRegime("DE"), + Name: "Invopop", + Identities: []*org.Identity{ + { + Key: "de-tax-number", + Code: "1231312423432422", + }, + }, + } + require.NoError(t, party.Calculate()) + err := party.Validate() + assert.ErrorContains(t, err, "identities: (0: (code: must be in a valid format.).).") + }) +} diff --git a/version.go b/version.go index 2c5b1f5a..73cbda61 100644 --- a/version.go +++ b/version.go @@ -8,7 +8,7 @@ import ( type Version string // VERSION is the current version of the GOBL library. -const VERSION Version = "v0.206.0" +const VERSION Version = "v0.206.1" // Semver parses and returns semver func (v Version) Semver() *semver.Version {