-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'regime-pl' of github.com:Risers/gobl into Risers-regime-pl
- Loading branch information
Showing
8 changed files
with
830 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,222 @@ | ||
{ | ||
"$schema": "https://gobl.org/draft-0/tax/regime", | ||
"name": { | ||
"en": "Poland", | ||
"pl": "Polska" | ||
}, | ||
"time_zone": "Europe/Warsaw", | ||
"country": "PL", | ||
"currency": "PLN", | ||
"payment_means": [ | ||
{ | ||
"key": "cash", | ||
"name": { | ||
"en": "Cash", | ||
"pl": "Gotówka" | ||
}, | ||
"map": { | ||
"favat-forma-platnosci": "1" | ||
} | ||
}, | ||
{ | ||
"key": "card", | ||
"name": { | ||
"en": "Card", | ||
"pl": "Karta" | ||
}, | ||
"map": { | ||
"favat-forma-platnosci": "2" | ||
} | ||
}, | ||
{ | ||
"key": "other+coupon", | ||
"name": { | ||
"en": "Coupon", | ||
"pl": "Bon" | ||
}, | ||
"map": { | ||
"favat-forma-platnosci": "3" | ||
} | ||
}, | ||
{ | ||
"key": "cheque", | ||
"name": { | ||
"en": "Cheque", | ||
"pl": "Czek" | ||
}, | ||
"map": { | ||
"favat-forma-platnosci": "4" | ||
} | ||
}, | ||
{ | ||
"key": "online+loan", | ||
"name": { | ||
"en": "Loan", | ||
"pl": "Kredyt" | ||
}, | ||
"map": { | ||
"favat-forma-platnosci": "5" | ||
} | ||
}, | ||
{ | ||
"key": "credit-transfer", | ||
"name": { | ||
"en": "Wire Transfer", | ||
"pl": "Przelew" | ||
}, | ||
"map": { | ||
"favat-forma-platnosci": "6" | ||
} | ||
}, | ||
{ | ||
"key": "other+mobile", | ||
"name": { | ||
"en": "Mobile", | ||
"pl": "Mobilna" | ||
}, | ||
"map": { | ||
"favat-forma-platnosci": "7" | ||
} | ||
} | ||
], | ||
"categories": [ | ||
{ | ||
"code": "VAT", | ||
"name": { | ||
"en": "VAT", | ||
"pl": "VAT" | ||
}, | ||
"title": { | ||
"en": "Value Added Tax", | ||
"pl": "Podatek od wartości dodanej" | ||
}, | ||
"rates": [ | ||
{ | ||
"key": "standard", | ||
"name": { | ||
"en": "Standard Rate", | ||
"pl": "Stawka Podstawowa" | ||
}, | ||
"values": [ | ||
{ | ||
"percent": "23.0%" | ||
}, | ||
{ | ||
"percent": "22.0%" | ||
} | ||
] | ||
}, | ||
{ | ||
"key": "reduced", | ||
"name": { | ||
"en": "First Reduced Rate", | ||
"pl": "Stawka Obniżona Pierwsza" | ||
}, | ||
"values": [ | ||
{ | ||
"percent": "8.0%" | ||
}, | ||
{ | ||
"percent": "7.0%" | ||
} | ||
] | ||
}, | ||
{ | ||
"key": "super-reduced", | ||
"name": { | ||
"en": "Second Reduced Rate", | ||
"pl": "Stawka Obniżona Druga" | ||
}, | ||
"values": [ | ||
{ | ||
"percent": "5.0%" | ||
} | ||
] | ||
}, | ||
{ | ||
"key": "special", | ||
"name": { | ||
"en": "Lump sum taxi rate", | ||
"pl": "Ryczałt dla taksówek" | ||
}, | ||
"values": [ | ||
{ | ||
"percent": "4.0%" | ||
}, | ||
{ | ||
"percent": "3.0%" | ||
} | ||
] | ||
}, | ||
{ | ||
"key": "zero-wdt", | ||
"name": { | ||
"en": "Zero Rate - WDT", | ||
"pl": "Stawka Zerowa - WDT" | ||
}, | ||
"values": [ | ||
{ | ||
"percent": "0.0%" | ||
} | ||
] | ||
}, | ||
{ | ||
"key": "zero-domestic", | ||
"name": { | ||
"en": "Zero Rate - domestic", | ||
"pl": "Stawka Zerowa - krajowe" | ||
}, | ||
"values": [ | ||
{ | ||
"percent": "0.0%" | ||
} | ||
] | ||
}, | ||
{ | ||
"key": "zero-export", | ||
"name": { | ||
"en": "Zero Rate - export", | ||
"pl": "Stawka Zerowa - export" | ||
}, | ||
"values": [ | ||
{ | ||
"percent": "0.0%" | ||
} | ||
] | ||
}, | ||
{ | ||
"key": "exempt", | ||
"name": { | ||
"en": "Exempt", | ||
"pl": "Zwolnione z opodatkowania" | ||
}, | ||
"exempt": true | ||
}, | ||
{ | ||
"key": "np", | ||
"name": { | ||
"en": "Not pursuant, pursuant to art100 section 1 point4", | ||
"pl": "Niepodlegające opodatkowaniu na postawie wyłączeniem art100 sekcja 1 punkt 4" | ||
}, | ||
"exempt": true | ||
}, | ||
{ | ||
"key": "np-art100sec1point4", | ||
"name": { | ||
"en": "Not pursuant excluding art100 section 1 point4", | ||
"pl": "Niepodlegające opodatkowaniu z wyłączeniem art100 sekcja 1 punkt 4" | ||
}, | ||
"exempt": true | ||
}, | ||
{ | ||
"key": "reverse-charge", | ||
"name": { | ||
"en": "Reverse Charge", | ||
"pl": "Odwrotne obciążenie" | ||
}, | ||
"exempt": true | ||
} | ||
] | ||
} | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
# pl GOBL Polish Tax Regime | ||
|
||
Poland uses the FA_VAT format for their e-invoicing system. | ||
|
||
Example PL GOBL files can be found in the [`examples`](./examples) (YAML uncalculated documents) and [`examples/out`](./examples/out) (JSON calculated envelopes) subdirectories. | ||
|
||
## Table of contents | ||
|
||
* [Public Documentation](#public-documentation) | ||
* [Zones](#zones) | ||
* [Local Codes](#local-codes) | ||
* [Complements](#complements) | ||
|
||
## Public Documentation | ||
|
||
- [Wzór faktury)](http://crd.gov.pl/wzor/2021/11/29/11089/) | ||
|
||
### `TFormaPlatnosci` - Payment Means | ||
|
||
The FA_VAT `TFormaPlatnosci` field specifies an invoice's means of payment. The following table lists all the supported values and how GOBL will map them from the invoice's payment instructions key: | ||
|
||
| Code | Name | GOBL Payment Instructions Key | | ||
| ---- | ----------------------------------- | ----------------------------- | | ||
| 1 | Gotówka | `cash` | | ||
| 2 | Karta | `card` | | ||
| 3 | Bon | `coupon` | | ||
| 4 | Czek | `cheque` | | ||
| 5 | Kredyt | `loan` | | ||
| 6 | Przelew | `credit-transfer` | | ||
| 7 | Mobilna | `mobile` | | ||
|
||
#### Example | ||
|
||
The following GOBL maps to the `1` (gotówka) value of the `TFormaPlatnosci` field: | ||
|
||
```js | ||
{ | ||
"$schema": "https://gobl.org/draft-0/bill/invoice", | ||
|
||
// [...] | ||
|
||
"payment": { | ||
"instructions": { | ||
"key": "cash" | ||
} | ||
} | ||
} | ||
``` | ||
|
||
#### Document Type (TRodzajFaktury) | ||
|
||
All Polish invoices must be identified with a specific type code defined by the FA_VAT format. The following table helps identify how GOBL will map the expected Polish code with a combination of the Invoice Type and tax tags. | ||
|
||
| Code | Type | Tax Tags | Description | | ||
| ------- | ------------- | ----------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | ||
| VAT | `standard` | | Regular invoice | | ||
| UPR | `standard` | `simplified` | Simplified (no customer) | | ||
| ZAL | `standard` | `partial` | Advance invioce | | ||
| ROZ | `standard` | `settlement` | Settlement invoice | | ||
| KOR | `corrective` | | Corrective (regular) | | ||
| KOR_ZAL | `corrective` | `partial` | Corrective (advance) | | ||
| KOR_ROZ | `corrective` | `settlement` | Corrective (settlement) | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
package pl | ||
|
||
import ( | ||
"github.com/invopop/gobl/bill" | ||
"github.com/invopop/gobl/currency" | ||
"github.com/invopop/gobl/l10n" | ||
"github.com/invopop/gobl/org" | ||
"github.com/invopop/gobl/regimes/common" | ||
"github.com/invopop/gobl/tax" | ||
"github.com/invopop/validation" | ||
) | ||
|
||
// invoiceValidator adds validation checks to invoices which are relevant | ||
// for the region. | ||
type invoiceValidator struct { | ||
inv *bill.Invoice | ||
} | ||
|
||
func validateInvoice(inv *bill.Invoice) error { | ||
v := &invoiceValidator{inv: inv} | ||
return v.validate() | ||
} | ||
|
||
func (v *invoiceValidator) validate() error { | ||
inv := v.inv | ||
return validation.ValidateStruct(inv, | ||
validation.Field(&inv.Currency, validation.In(currency.PLN, currency.EUR)), | ||
// Only commercial and simplified supported at this time for Poland. | ||
// Rectification state determined by Preceding value. | ||
validation.Field(&inv.Type, validation.In( | ||
bill.InvoiceTypeStandard, | ||
bill.InvoiceTypeCorrective, | ||
bill.InvoiceTypeProforma, | ||
)), | ||
// validation.Field(&inv.Preceding, | ||
// validation.Each(validation.By(v.preceding)), | ||
// ), | ||
validation.Field(&inv.Supplier, | ||
validation.Required, | ||
validation.By(v.supplier), | ||
), | ||
validation.Field(&inv.Customer, | ||
validation.When( | ||
!inv.Tax.ContainsTag(common.TagSimplified), | ||
validation.Required, | ||
validation.By(v.commercialCustomer), | ||
), | ||
), | ||
) | ||
} | ||
|
||
func (v *invoiceValidator) supplier(value interface{}) error { | ||
obj, _ := value.(*org.Party) | ||
if obj == nil { | ||
return nil | ||
} | ||
return validation.ValidateStruct(obj, | ||
validation.Field(&obj.TaxID, | ||
validation.Required, | ||
tax.RequireIdentityCode, | ||
validation.By(validatePolishTaxIdentity), | ||
), | ||
// TODO check if name exists | ||
) | ||
} | ||
|
||
func (v *invoiceValidator) commercialCustomer(value interface{}) error { | ||
obj, _ := value.(*org.Party) | ||
if obj == nil { | ||
return nil | ||
} | ||
if obj.TaxID == nil { | ||
return nil // validation already handled, this prevents panics | ||
} | ||
// Customers must have a tax ID if a Polish entity | ||
return validation.ValidateStruct(obj, | ||
validation.Field(&obj.TaxID, | ||
validation.Required, | ||
validation.When( | ||
obj.TaxID.Country.In(l10n.PL), | ||
validation.By(validatePolishTaxIdentity), | ||
), // TODO check if id is valid when other entity | ||
// TODO check if name exists | ||
), | ||
) | ||
} | ||
|
||
// func (v *invoiceValidator) preceding(value interface{}) error { | ||
// obj, _ := value.(*bill.Preceding) | ||
// if obj == nil { | ||
// return nil | ||
// } | ||
// return validation.ValidateStruct(obj, | ||
// validation.Field(&obj.Changes, | ||
// validation.Required, | ||
// validation.Each(isValidCorrectionChangeKey), | ||
// ), | ||
// validation.Field(&obj.CorrectionMethod, | ||
// validation.Required, | ||
// isValidCorrectionMethodKey, | ||
// ), | ||
// ) | ||
// } |
Oops, something went wrong.