@@ -1,3 +1,4 @@
|
||||
* Add VAT exemption code on tax
|
||||
* Add support for Python 3.14
|
||||
* Remove support for Python 3.9
|
||||
|
||||
|
||||
@@ -10,18 +10,190 @@ from trytond.pool import Pool, PoolMeta
|
||||
from trytond.pyson import Bool, Eval
|
||||
from trytond.transaction import Transaction
|
||||
|
||||
VATEX_CODES = [
|
||||
('VATEX-EU-79-C',
|
||||
"Exempt based on article 79, point c of Council Directive "
|
||||
"2006/112/EC"),
|
||||
('VATEX-EU-132',
|
||||
"Exempt based on article 132 of Council Directive 2006/112/EC"),
|
||||
('VATEX-EU-132-1A',
|
||||
"Exempt based on article 132, section 1 (a) of Council Directive "
|
||||
"2006/112/EC"),
|
||||
('VATEX-EU-132-1B',
|
||||
"Exempt based on article 132, section 1 (b) of Council Directive "
|
||||
"2006/112/EC"),
|
||||
('VATEX-EU-132-1C',
|
||||
"Exempt based on article 132, section 1 (c) of Council Directive "
|
||||
"2006/112/EC"),
|
||||
('VATEX-EU-132-1D',
|
||||
"Exempt based on article 132, section 1 (d) of Council Directive "
|
||||
"2006/112/EC"),
|
||||
('VATEX-EU-132-1E',
|
||||
"Exempt based on article 132, section 1 (e) of Council Directive "
|
||||
"2006/112/EC"),
|
||||
('VATEX-EU-132-1F',
|
||||
"Exempt based on article 132, section 1 (f) of Council Directive "
|
||||
"2006/112/EC"),
|
||||
('VATEX-EU-132-1G',
|
||||
"Exempt based on article 132, section 1 (g) of Council Directive "
|
||||
"2006/112/EC"),
|
||||
('VATEX-EU-132-1H',
|
||||
"Exempt based on article 132, section 1 (h) of Council Directive "
|
||||
"2006/112/EC"),
|
||||
('VATEX-EU-132-1I',
|
||||
"Exempt based on article 132, section 1 (i) of Council Directive "
|
||||
"2006/112/EC"),
|
||||
('VATEX-EU-132-1J',
|
||||
"Exempt based on article 132, section 1 (j) of Council Directive "
|
||||
"2006/112/EC"),
|
||||
('VATEX-EU-132-1K',
|
||||
"Exempt based on article 132, section 1 (k) of Council Directive "
|
||||
"2006/112/EC"),
|
||||
('VATEX-EU-132-1L',
|
||||
"Exempt based on article 132, section 1 (l) of Council Directive "
|
||||
"2006/112/EC"),
|
||||
('VATEX-EU-132-1M',
|
||||
"Exempt based on article 132, section 1 (m) of Council Directive "
|
||||
"2006/112/EC"),
|
||||
('VATEX-EU-132-1N',
|
||||
"Exempt based on article 132, section 1 (n) of Council Directive "
|
||||
"2006/112/EC"),
|
||||
('VATEX-EU-132-1O',
|
||||
"Exempt based on article 132, section 1 (o) of Council Directive "
|
||||
"2006/112/EC"),
|
||||
('VATEX-EU-132-1P',
|
||||
"Exempt based on article 132, section 1 (p) of Council Directive "
|
||||
"2006/112/EC"),
|
||||
('VATEX-EU-132-1Q',
|
||||
"Exempt based on article 132, section 1 (q) of Council Directive "
|
||||
"2006/112/EC"),
|
||||
('VATEX-EU-143',
|
||||
"Exempt based on article 143 of Council Directive 2006/112/EC"),
|
||||
('VATEX-EU-143-1A',
|
||||
"Exempt based on article 143, section 1 (a) of Council Directive "
|
||||
"2006/112/EC"),
|
||||
('VATEX-EU-143-1B',
|
||||
"Exempt based on article 143, section 1 (b) of Council Directive "
|
||||
"2006/112/EC"),
|
||||
('VATEX-EU-143-1C',
|
||||
"Exempt based on article 143, section 1 (c) of Council Directive "
|
||||
"2006/112/EC"),
|
||||
('VATEX-EU-143-1D',
|
||||
"Exempt based on article 143, section 1 (d) of Council Directive "
|
||||
"2006/112/EC"),
|
||||
('VATEX-EU-143-1E',
|
||||
"Exempt based on article 143, section 1 (e) of Council Directive "
|
||||
"2006/112/EC"),
|
||||
('VATEX-EU-143-1F',
|
||||
"Exempt based on article 143, section 1 (f) of Council Directive "
|
||||
"2006/112/EC"),
|
||||
('VATEX-EU-143-1FA',
|
||||
"Exempt based on article 143, section 1 (fa) of Council Directive "
|
||||
"2006/112/EC"),
|
||||
('VATEX-EU-143-1G',
|
||||
"Exempt based on article 143, section 1 (g) of Council Directive "
|
||||
"2006/112/EC"),
|
||||
('VATEX-EU-143-1H',
|
||||
"Exempt based on article 143, section 1 (h) of Council Directive "
|
||||
"2006/112/EC"),
|
||||
('VATEX-EU-143-1I',
|
||||
"Exempt based on article 143, section 1 (i) of Council Directive "
|
||||
"2006/112/EC"),
|
||||
('VATEX-EU-143-1J',
|
||||
"Exempt based on article 143, section 1 (j) of Council Directive "
|
||||
"2006/112/EC"),
|
||||
('VATEX-EU-143-1K',
|
||||
"Exempt based on article 143, section 1 (k) of Council Directive "
|
||||
"2006/112/EC"),
|
||||
('VATEX-EU-143-1L',
|
||||
"Exempt based on article 143, section 1 (l) of Council Directive "
|
||||
"2006/112/EC"),
|
||||
('VATEX-EU-144',
|
||||
"Exempt based on article 144 of Council Directive 2006/112/EC"),
|
||||
('VATEX-EU-146-1E',
|
||||
"Exempt based on article 146 section 1 (e) of Council Directive "
|
||||
"2006/112/EC"),
|
||||
('VATEX-EU-148',
|
||||
"Exempt based on article 148 of Council Directive 2006/112/EC"),
|
||||
('VATEX-EU-148-A',
|
||||
"Exempt based on article 148, section (a) of Council Directive "
|
||||
"2006/112/EC"),
|
||||
('VATEX-EU-148-B',
|
||||
"Exempt based on article 148, section (b) of Council Directive "
|
||||
"2006/112/EC"),
|
||||
('VATEX-EU-148-C',
|
||||
"Exempt based on article 148, section (c) of Council Directive "
|
||||
"2006/112/EC"),
|
||||
('VATEX-EU-148-D',
|
||||
"Exempt based on article 148, section (d) of Council Directive "
|
||||
"2006/112/EC"),
|
||||
('VATEX-EU-148-E',
|
||||
"Exempt based on article 148, section (e) of Council Directive "
|
||||
"2006/112/EC"),
|
||||
('VATEX-EU-148-F',
|
||||
"Exempt based on article 148, section (f) of Council Directive "
|
||||
"2006/112/EC"),
|
||||
('VATEX-EU-148-G',
|
||||
"Exempt based on article 148, section (g) of Council Directive "
|
||||
"2006/112/EC"),
|
||||
('VATEX-EU-151',
|
||||
"Exempt based on article 151 of Council Directive 2006/112/EC"),
|
||||
('VATEX-EU-151-1A',
|
||||
"Exempt based on article 151, section 1 (a) of Council Directive "
|
||||
"2006/112/EC"),
|
||||
('VATEX-EU-151-1AA',
|
||||
"Exempt based on article 151, section 1 (aa) of Council Directive "
|
||||
"2006/112/EC"),
|
||||
('VATEX-EU-151-1B',
|
||||
"Exempt based on article 151, section 1 (b) of Council Directive "
|
||||
"2006/112/EC"),
|
||||
('VATEX-EU-151-1C',
|
||||
"Exempt based on article 151, section 1 (c) of Council Directive "
|
||||
"2006/112/EC"),
|
||||
('VATEX-EU-151-1D',
|
||||
"Exempt based on article 151, section 1 (d) of Council Directive "
|
||||
"2006/112/EC"),
|
||||
('VATEX-EU-151-1E',
|
||||
"Exempt based on article 151, section 1 (e) of Council Directive "
|
||||
"2006/112/EC"),
|
||||
('VATEX-EU-159',
|
||||
"Exempt based on article 159 of Council Directive 2006/112/EC"),
|
||||
('VATEX-EU-309',
|
||||
"Exempt based on article 309 of Council Directive 2006/112/EC"),
|
||||
('VATEX-EU-AE', "Reverse charge"),
|
||||
('VATEX-EU-D',
|
||||
"Intra-Community acquisition from second hand means of transport"),
|
||||
('VATEX-EU-F', "Intra-Community acquisition of second hand goods"),
|
||||
('VATEX-EU-G', "Export outside the EU"),
|
||||
('VATEX-EU-I', "Intra-Community acquisition of works of art"),
|
||||
('VATEX-EU-IC', "Intra-Community supply"),
|
||||
('VATEX-EU-O', "Not subject to VAT"),
|
||||
('VATEX-EU-J',
|
||||
"Intra-Community acquisition of collectors items and antiques"),
|
||||
]
|
||||
|
||||
|
||||
class TaxTemplate(metaclass=PoolMeta):
|
||||
__name__ = 'account.tax.template'
|
||||
|
||||
ec_sales_list_code = fields.Char("EC Sales List Code")
|
||||
vatex_code = fields.Selection(
|
||||
'get_vatex_codes', "Tax Exemption Code")
|
||||
|
||||
def _get_tax_value(self, tax=None):
|
||||
value = super()._get_tax_value(tax=tax)
|
||||
if not tax or tax.ec_sales_list_code != self.ec_sales_list_code:
|
||||
value['ec_sales_list_code'] = self.ec_sales_list_code
|
||||
if not tax or tax.vatex_code != self.vatex_code:
|
||||
value['vatex_code'] = self.vatex_code
|
||||
return value
|
||||
|
||||
@classmethod
|
||||
def get_vatex_codes(cls):
|
||||
pool = Pool()
|
||||
Tax = pool.get('account.tax')
|
||||
return Tax.fields_get(['vatex_code'])['vatex_code']['selection']
|
||||
|
||||
|
||||
class Tax(metaclass=PoolMeta):
|
||||
__name__ = 'account.tax'
|
||||
@@ -31,6 +203,13 @@ class Tax(metaclass=PoolMeta):
|
||||
'readonly': (Bool(Eval('template', -1))
|
||||
& ~Eval('template_override', False)),
|
||||
})
|
||||
vatex_code = fields.Selection(
|
||||
[(None, "")] + VATEX_CODES, "Tax Exemption Code", sort=False,
|
||||
states={
|
||||
'readonly': (Bool(Eval('template', -1))
|
||||
& ~Eval('template_override', False)),
|
||||
},
|
||||
help="The reason why the amount is exempted from VAT.")
|
||||
|
||||
|
||||
class ECSalesList(ModelSQL, ModelView):
|
||||
|
||||
@@ -3,9 +3,13 @@
|
||||
this repository contains the full copyright notices and license terms. -->
|
||||
<data>
|
||||
<xpath expr="/form/notebook" position="inside">
|
||||
<page id="ec_sales_list" string="EC Sales List">
|
||||
<page id="eu_code" string="European Codes">
|
||||
<label name="ec_sales_list_code"/>
|
||||
<field name="ec_sales_list_code"/>
|
||||
<newline/>
|
||||
|
||||
<label name="vatex_code"/>
|
||||
<field name="vatex_code"/>
|
||||
</page>
|
||||
</xpath>
|
||||
</data>
|
||||
|
||||
@@ -3,9 +3,13 @@
|
||||
this repository contains the full copyright notices and license terms. -->
|
||||
<data>
|
||||
<xpath expr="/form/notebook" position="inside">
|
||||
<page id="ec_sales_list" string="EC Sales List">
|
||||
<page id="eu_code" string="European Codes">
|
||||
<label name="ec_sales_list_code"/>
|
||||
<field name="ec_sales_list_code"/>
|
||||
<newline/>
|
||||
|
||||
<label name="vatex_code"/>
|
||||
<field name="vatex_code"/>
|
||||
</page>
|
||||
</xpath>
|
||||
</data>
|
||||
|
||||
@@ -14,6 +14,88 @@ from trytond.pyson import Eval
|
||||
from trytond.transaction import Transaction
|
||||
from trytond.wizard import Button, StateTransition, StateView, Wizard
|
||||
|
||||
VATEX_CODES = [
|
||||
('VATEX-FR-FRANCHISE', "France domestic VAT franchise in base"),
|
||||
('VATEX-FR-CNWVAT',
|
||||
"France domestic Credit Notes without VAT, due to supplier forfeit of "
|
||||
"VAT for discount"),
|
||||
('VATEX-EU-153',
|
||||
"Exempt based on article 153 of Council Directive 2006/112/EC"),
|
||||
('VATEX-FR-CGI261-1',
|
||||
"Exempt based on 1 of article 261 of the Code Général des Impôts "
|
||||
"(CGI; General tax code)"),
|
||||
('VATEX-FR-CGI261-2',
|
||||
"Exempt based on 2 of article 261 of the Code Général des Impôts "
|
||||
"(CGI ; General tax code)"),
|
||||
('VATEX-FR-CGI261-3',
|
||||
"Exempt based on 3 of article 261 of the Code Général des Impôts "
|
||||
"(CGI ; General tax code"),
|
||||
('VATEX-FR-CGI261-4',
|
||||
"Exempt based on 4 of article 261 of the Code Général des Impôts "
|
||||
"(CGI ; General tax code)"),
|
||||
('VATEX-FR-CGI261-5',
|
||||
"Exempt based on 5 of article 261 of the Code Général des Impôts "
|
||||
"(CGI ; General tax code)"),
|
||||
('VATEX-FR-CGI261-7',
|
||||
"Exempt based on 7 of article 261 of the Code Général des Impôts "
|
||||
"(CGI ; General tax code)"),
|
||||
('VATEX-FR-CGI261-8',
|
||||
"Exempt based on 8 of article 261 of the Code Général des Impôts "
|
||||
"(CGI ; General tax code)"),
|
||||
('VATEX-FR-CGI261A',
|
||||
"Exempt based on article 261 A of the Code Général des Impôts "
|
||||
"(CGI ; General tax code)"),
|
||||
('VATEX-FR-CGI261B',
|
||||
"Exempt based on article 261 B of the Code Général des Impôts "
|
||||
"(CGI ; General tax code)"),
|
||||
('VATEX-FR-CGI261C-1',
|
||||
"Exempt based on 1° of article 261 C of the Code Général des Impôts "
|
||||
"(CGI ; General tax code)"),
|
||||
('VATEX-FR-CGI261C-2',
|
||||
"Exempt based on 2° of article 261 C of the Code Général des Impôts "
|
||||
"(CGI ; General tax code)"),
|
||||
('VATEX-FR-CGI261C-3',
|
||||
"Exempt based on 3° of article 261 C of the Code Général des Impôts "
|
||||
"(CGI ; General tax code)"),
|
||||
('VATEX-FR-CGI261D-1',
|
||||
"Exempt based on 1° of article 261 D of the Code Général des Impôts "
|
||||
"(CGI ; General tax code)"),
|
||||
('VATEX-FR-CGI261D-1BIS',
|
||||
"Exempt based on 1°bis of article 261 D of the Code Général des "
|
||||
"Impôts (CGI ; General tax code)"),
|
||||
('VATEX-FR-CGI261D-2',
|
||||
"Exempt based on 2° of article 261 D of the Code Général des Impôts "
|
||||
"(CGI ; General tax code)"),
|
||||
('VATEX-FR-CGI261D-3',
|
||||
"Exempt based on 3° of article 261 D of the Code Général des Impôts "
|
||||
"(CGI ; General tax code) "
|
||||
"Exonération de TVA - Article 261 D-3° du Code Général des Impôts"),
|
||||
('VATEX-FR-CGI261D-4',
|
||||
"Exempt based on 4° of article 261 D of the Code Général des Impôts "
|
||||
"(CGI ; General tax code)"),
|
||||
('VATEX-FR-CGI261E-1',
|
||||
"Exempt based on 1° of article 261 E of the Code Général des Impôts "
|
||||
"(CGI ; General tax code)"),
|
||||
('VATEX-FR-CGI261E-2',
|
||||
"Exempt based on 2° of article 261 E of the Code Général des Impôts "
|
||||
"(CGI ; General tax code)"),
|
||||
('VATEX-FR-CGI277A',
|
||||
"Exempt based on article 277 A of the Code Général des Impôts "
|
||||
"(CGI ; General tax code)"),
|
||||
('VATEX-FR-CGI275',
|
||||
" Exempt based on article 275 of the Code Général des Impôts "
|
||||
"(CGI ; General tax code)"),
|
||||
('VATEX-FR-298SEXDECIESA',
|
||||
" Exempt based on article 298 sexdecies A of the Code Général des "
|
||||
"Impôts (CGI ; General tax code)"),
|
||||
('VATEX-FR-CGI295',
|
||||
"Exempt based on article 295 of the Code Général des Impôts "
|
||||
"(CGI ; General tax code)"),
|
||||
('VATEX-FR-AE',
|
||||
" Exempt based on 2 of article 283 of the Code Général des Impôts "
|
||||
"(CGI ; General tax code)"),
|
||||
]
|
||||
|
||||
|
||||
class AccountTemplate(metaclass=PoolMeta):
|
||||
__name__ = 'account.account.template'
|
||||
@@ -45,6 +127,16 @@ class AccountTemplate(metaclass=PoolMeta):
|
||||
super().__register__(module_name)
|
||||
|
||||
|
||||
class Tax(metaclass=PoolMeta):
|
||||
__name__ = 'account.tax'
|
||||
|
||||
@classmethod
|
||||
def __setup__(cls):
|
||||
super().__setup__()
|
||||
if hasattr(cls, 'vatex_code'):
|
||||
cls.vatex_code.selection.extend(VATEX_CODES)
|
||||
|
||||
|
||||
class CreateChart(metaclass=PoolMeta):
|
||||
__name__ = 'account.create_chart'
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ from trytond.tests.test_tryton import ModuleTestCase, with_transaction
|
||||
class AccountFRTestCase(ModuleTestCase):
|
||||
'Test Account FR module'
|
||||
module = 'account_fr'
|
||||
extras = ['account_eu']
|
||||
|
||||
@with_transaction()
|
||||
def test_create_chart(self):
|
||||
|
||||
@@ -6,6 +6,7 @@ depends:
|
||||
extras_depend:
|
||||
account_asset
|
||||
account_deposit
|
||||
account_eu
|
||||
account_invoice
|
||||
sale_advance_payment
|
||||
xml:
|
||||
@@ -16,6 +17,7 @@ xml:
|
||||
[register]
|
||||
model:
|
||||
account.AccountTemplate
|
||||
account.Tax
|
||||
account.FrFECStart
|
||||
account.FrFECResult
|
||||
wizard:
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
* Use VATEX as tax exemption reason code
|
||||
* Add support for Python 3.14
|
||||
* Remove support for Python 3.9
|
||||
* Fill payment means
|
||||
|
||||
@@ -194,7 +194,7 @@ class Invoice(Model):
|
||||
class Tax(namedtuple(
|
||||
'Tax',
|
||||
('type', 'rate', 'unece_category_code', 'unece_code',
|
||||
'legal_notice'))):
|
||||
'vatex_code', 'legal_notice'))):
|
||||
@classmethod
|
||||
def from_line(cls, line):
|
||||
return Tax(
|
||||
@@ -202,6 +202,7 @@ class Invoice(Model):
|
||||
rate=line.tax.rate,
|
||||
unece_category_code=line.tax.unece_category_code,
|
||||
unece_code=line.tax.unece_code,
|
||||
vatex_code=getattr(line.tax, 'vatex_code', ''),
|
||||
legal_notice=line.legal_notice or '')
|
||||
TaxLine = namedtuple('TaxLine', ('base', 'amount', 'tax'))
|
||||
for group, lines in groupby(sorted(
|
||||
@@ -570,8 +571,11 @@ class Invoice(Model):
|
||||
],
|
||||
('company', '=', company.id),
|
||||
])
|
||||
order = []
|
||||
if hasattr(Tax, 'vatex_code'):
|
||||
order.append(('vatex_code', 'ASC NULLS LAST'))
|
||||
try:
|
||||
tax, = Tax.search(domain, limit=1)
|
||||
tax, = Tax.search(domain, limit=1, order=order)
|
||||
except ValueError:
|
||||
raise InvoiceError(gettext(
|
||||
'edocument_ubl.msg_tax_not_found',
|
||||
@@ -1135,6 +1139,8 @@ class Invoice(Model):
|
||||
|
||||
@classmethod
|
||||
def _parse_2_tax_category(cls, tax_category):
|
||||
pool = Pool()
|
||||
Tax = pool.get('account.tax')
|
||||
domain = [
|
||||
('parent', '=', None),
|
||||
]
|
||||
@@ -1148,6 +1154,13 @@ class Invoice(Model):
|
||||
if percent:
|
||||
domain.append(('type', '=', 'percentage'))
|
||||
domain.append(('rate', '=', Decimal(percent) / 100))
|
||||
if (hasattr(Tax, 'vatex_code')
|
||||
and (tax_exemption_reason_code := tax_category.findtext(
|
||||
'./{*}TaxExemptionReasonCode'))):
|
||||
domain.append(['OR',
|
||||
('vatex_code', '=', tax_exemption_reason_code),
|
||||
('vatex_code', '=', None),
|
||||
])
|
||||
return domain
|
||||
|
||||
@classmethod
|
||||
|
||||
@@ -84,6 +84,7 @@ this repository contains the full copyright notices and license terms. -->
|
||||
<py:def function="TaxCategory(tax)">
|
||||
<cbc:ID py:if="tax.unece_category_code">${tax.unece_category_code}</cbc:ID>
|
||||
<cbc:Percent py:if="tax.type == 'percentage'">${format((tax.rate * 100).normalize(), 'f')}</cbc:Percent>
|
||||
<cbc:TaxExemptionReasonCode py:if="getattr(tax, 'vatex_code', None)">${tax.vatex_code}</cbc:TaxExemptionReasonCode>
|
||||
<cbc:TaxExemptionReason py:if="tax.legal_notice">${tax.legal_notice}</cbc:TaxExemptionReason>
|
||||
<cac:TaxScheme py:if="tax.unece_code">
|
||||
<cbc:ID>${tax.unece_code}</cbc:ID>
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
* Use VATEX as tax exemption reason code
|
||||
* Add support for Python 3.14
|
||||
* Remove support for Python 3.9
|
||||
* Render payment means
|
||||
|
||||
@@ -45,6 +45,7 @@ this repository contains the full copyright notices and license terms. -->
|
||||
<ram:ApplicableTradeTax>
|
||||
<ram:CalculatedAmount py:if="amount" py:attrs="{'currencyID': this.invoice.currency.code}">${amount * this.type_sign}</ram:CalculatedAmount>
|
||||
<ram:TypeCode py:if="tax.unece_code">${tax.unece_code}</ram:TypeCode>
|
||||
<ram:ExemptionReasonCode py:if="getattr(tax, 'vatex_code', None)">${tax.vatex_code}</ram:ExemptionReasonCode>
|
||||
<ram:ExemptionReason py:if="tax.legal_notice">${tax.legal_notice}</ram:ExemptionReason>
|
||||
<ram:BasisAmount py:if="base">${base * this.type_sign}</ram:BasisAmount>
|
||||
<ram:CategoryCode py:if="tax.unece_category_code">${tax.unece_category_code}</ram:CategoryCode>
|
||||
|
||||
Reference in New Issue
Block a user