314 lines
14 KiB
Python
314 lines
14 KiB
Python
# -*- coding: utf-8 -*-
|
|
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
|
|
|
import datetime
|
|
from collections import namedtuple
|
|
|
|
from odoo import fields
|
|
from odoo.tests import tagged
|
|
from odoo.exceptions import ValidationError
|
|
from odoo.addons.l10n_it_edi.tests.common import TestItEdi
|
|
|
|
|
|
@tagged('post_install_l10n', 'post_install', '-at_install')
|
|
class TestWithholdingAndPensionFundTaxes(TestItEdi):
|
|
|
|
@classmethod
|
|
def setUpClass(cls):
|
|
super().setUpClass()
|
|
|
|
def find_tax_by_ref(ref_name):
|
|
return cls.env['account.chart.template'].with_company(cls.company).ref(ref_name)
|
|
|
|
cls.withholding_sale_tax = find_tax_by_ref('20vwc')
|
|
cls.withholding_sale_tax_23 = find_tax_by_ref('23vwo')
|
|
cls.pension_fund_sale_tax = find_tax_by_ref('4vcp')
|
|
cls.enasarco_sale_tax = find_tax_by_ref('enasarcov')
|
|
cls.withholding_purchase_tax_23 = find_tax_by_ref('23awo')
|
|
cls.enasarco_purchase_tax = find_tax_by_ref('enasarcoa')
|
|
cls.inps_tax = find_tax_by_ref('4vinps')
|
|
|
|
cls.zero_tax = cls.env['account.tax'].with_company(cls.company).create({
|
|
'name': 'ZeroTax',
|
|
'sequence': 31,
|
|
'type_tax_use': 'sale',
|
|
'amount': 0.0,
|
|
'amount_type': 'percent',
|
|
'l10n_it_exempt_reason': 'N2.2',
|
|
'l10n_it_law_reference': 'Fatture emesse o ricevute da contribuenti forfettari o minimi',
|
|
})
|
|
|
|
cls.withholding_sale_line = {
|
|
'name': 'withholding_line',
|
|
'quantity': 1,
|
|
'tax_ids': [(6, 0, [
|
|
cls.withholding_sale_tax.id,
|
|
cls.company.account_sale_tax_id.id,
|
|
])]
|
|
}
|
|
|
|
cls.pension_fund_sale_line = {
|
|
'name': 'pension_fund_line',
|
|
'quantity': 1,
|
|
'tax_ids': [(6, 0, [
|
|
cls.withholding_sale_tax.id,
|
|
cls.pension_fund_sale_tax.id,
|
|
cls.company.account_sale_tax_id.id,
|
|
])]
|
|
}
|
|
|
|
cls.enasarco_sale_line = {
|
|
'name': 'enasarco_line',
|
|
'quantity': 1,
|
|
'tax_ids': [(6, 0, [
|
|
cls.enasarco_sale_tax.id,
|
|
cls.withholding_sale_tax_23.id,
|
|
cls.company.account_sale_tax_id.id,
|
|
])]
|
|
}
|
|
|
|
cls.inps_sale_line = {
|
|
'name': 'inps_line',
|
|
'quantity': 1,
|
|
'tax_ids': [(6, 0, [cls.inps_tax.id, cls.zero_tax.id])]
|
|
}
|
|
|
|
invoice_data = cls.get_real_client_invoice_data()
|
|
|
|
cls.withholding_tax_invoice = cls.env['account.move'].with_company(cls.company).create({
|
|
'move_type': 'out_invoice',
|
|
'company_id': cls.company.id,
|
|
'partner_id': cls.italian_partner_a.id,
|
|
'invoice_date': datetime.date(2022, 3, 24),
|
|
'invoice_date_due': datetime.date(2022, 3, 24),
|
|
'invoice_line_ids': [
|
|
(0, 0, {
|
|
**cls.withholding_sale_line,
|
|
'name': name,
|
|
'price_unit': price,
|
|
}) for (name, price) in invoice_data.lines
|
|
],
|
|
})
|
|
|
|
cls.pension_fund_tax_invoice = cls.env['account.move'].with_company(cls.company).create({
|
|
'move_type': 'out_invoice',
|
|
'company_id': cls.company.id,
|
|
'partner_id': cls.italian_partner_a.id,
|
|
'invoice_date': datetime.date(2022, 3, 24),
|
|
'invoice_date_due': datetime.date(2022, 3, 24),
|
|
'invoice_line_ids': [
|
|
(0, 0, {
|
|
**cls.pension_fund_sale_line,
|
|
'name': name,
|
|
'price_unit': price,
|
|
}) for (name, price) in invoice_data.lines
|
|
]
|
|
})
|
|
|
|
cls.enasarco_tax_invoice = cls.env['account.move'].with_company(cls.company).create({
|
|
'move_type': 'out_invoice',
|
|
'company_id': cls.company.id,
|
|
'partner_id': cls.italian_partner_a.id,
|
|
'invoice_date': datetime.date(2022, 3, 24),
|
|
'invoice_date_due': datetime.date(2022, 3, 24),
|
|
'invoice_line_ids': [
|
|
(0, 0, {
|
|
**cls.enasarco_sale_line,
|
|
'name': name,
|
|
'price_unit': price,
|
|
}) for (name, price) in invoice_data.lines
|
|
]
|
|
})
|
|
|
|
cls.inps_tax_invoice = cls.env['account.move'].with_company(cls.company).create({
|
|
'move_type': 'out_invoice',
|
|
'company_id': cls.company.id,
|
|
'partner_id': cls.italian_partner_a.id,
|
|
'invoice_date': datetime.date(2022, 3, 24),
|
|
'invoice_date_due': datetime.date(2022, 3, 24),
|
|
'invoice_line_ids': [
|
|
(0, 0, {
|
|
**cls.inps_sale_line,
|
|
'name': name,
|
|
'price_unit': price,
|
|
}) for (name, price) in invoice_data.lines
|
|
]
|
|
})
|
|
|
|
cls.withholding_tax_invoice._post()
|
|
cls.pension_fund_tax_invoice._post()
|
|
cls.enasarco_tax_invoice._post()
|
|
cls.inps_tax_invoice._post()
|
|
|
|
cls.module = 'l10n_it_edi_withholding'
|
|
|
|
@classmethod
|
|
def get_real_client_invoice_data(cls):
|
|
data = {
|
|
'lines': [
|
|
('Ordinary accounting service for the year', 350.0),
|
|
('Balance deposit for the past year', 300.0),
|
|
('Ordinary accounting service for the trimester', 50.0),
|
|
('Electronic invoices management', 50.0),
|
|
],
|
|
'base': 750.0,
|
|
'tax_amount': 165.0,
|
|
'with_tax': 915.0,
|
|
'withholding_amount': 150.0,
|
|
'with_withholding': 765.0,
|
|
'pension_fund_amount': 30.0,
|
|
'with_pension_fund': 951.6,
|
|
'tax_amount_with_pension_fund': 171.6,
|
|
'payment_amount': 801.6,
|
|
}
|
|
return namedtuple('ClientInvoice', data.keys())(**data)
|
|
|
|
def test_withholding_tax_constraints(self):
|
|
with self.assertRaises(ValidationError):
|
|
self.withholding_sale_tax.amount = 10
|
|
with self.assertRaises(ValidationError):
|
|
self.withholding_sale_tax.l10n_it_withholding_type = False
|
|
with self.assertRaises(ValidationError):
|
|
self.withholding_sale_tax.l10n_it_withholding_reason = False
|
|
with self.assertRaises(ValidationError):
|
|
self.company.account_sale_tax_id.l10n_it_withholding_type = "RT02"
|
|
|
|
####################################################
|
|
# WITHHOLDING TAX
|
|
####################################################
|
|
|
|
def test_withholding_taxes_export(self):
|
|
"""
|
|
Invoice
|
|
-------------------------------------------------------------
|
|
Ordinary accounting service for the year 350.00
|
|
Balance deposit for the past year 300.00
|
|
Ordinary accounting service for the trimester 50.00
|
|
Electronic invoices management 50.00
|
|
-------------------------------------------------------------
|
|
Total untaxed: 750.00
|
|
Withholding: 20% of Untaxed Amount -150.00
|
|
VAT: 22% of Untaxed Amount 165.00
|
|
Document total: Untaxed Amount + VAT 915.00
|
|
Payment amount: Document total - Withholding 765.00
|
|
"""
|
|
self._assert_export_invoice(self.withholding_tax_invoice, 'withholding_tax_invoice.xml')
|
|
|
|
def test_withholding_taxes_import(self):
|
|
invoice = self._assert_import_invoice('IT00470550013_withh.xml', [{
|
|
'invoice_date': fields.Date.from_string('2022-03-24'),
|
|
'amount_untaxed': 750.0,
|
|
'amount_total': 765.00,
|
|
'amount_tax': 15.0,
|
|
'invoice_line_ids': [{
|
|
'name': name,
|
|
'price_unit': price_unit,
|
|
} for name, price_unit in self.get_real_client_invoice_data().lines]
|
|
}])
|
|
|
|
invoice_data = self.get_real_client_invoice_data()
|
|
for line in invoice.line_ids.filtered(lambda x: x.name in [data[0] for data in invoice_data.lines]):
|
|
withholding_taxes = line.tax_ids.filtered(lambda x: x.l10n_it_withholding_type)
|
|
pension_fund_taxes = line.tax_ids.filtered(lambda x: x.l10n_it_pension_fund_type)
|
|
vat_taxes = line.tax_ids - withholding_taxes - pension_fund_taxes
|
|
self.assertEqual([1, 1, 0], [len(x) for x in (vat_taxes, withholding_taxes, pension_fund_taxes)])
|
|
|
|
####################################################
|
|
# PENSION FUND TAX
|
|
####################################################
|
|
|
|
def test_pension_fund_taxes_export(self):
|
|
"""
|
|
Invoice
|
|
-------------------------------------------------------------
|
|
Ordinary accounting service for the year 350.00
|
|
Balance deposit for the past year 300.00
|
|
Ordinary accounting service for the trimester 50.00
|
|
Electronic invoices management 50.00
|
|
-------------------------------------------------------------
|
|
Total untaxed: 750.00
|
|
Pension fund: 4% of Untaxed Amount 30.00
|
|
Withholding: 20% of Untaxed Amount -150.00
|
|
VAT: 22% of Untaxed Amount + Pension fund 171.60
|
|
Document total: Taxed Amount 951.60
|
|
Payment amount: Document total - Withholding 801.60
|
|
"""
|
|
self._assert_export_invoice(self.pension_fund_tax_invoice, 'pension_fund_tax_invoice.xml')
|
|
|
|
def test_pension_fund_taxes_import(self):
|
|
invoice = self._assert_import_invoice('IT00470550013_pfund.xml', [{
|
|
'invoice_date': fields.Date.from_string('2022-03-24'),
|
|
'amount_untaxed': 750.0,
|
|
'amount_total': 795.6,
|
|
'amount_tax': 45.6,
|
|
'invoice_line_ids': [{
|
|
'name': name,
|
|
'price_unit': price_unit,
|
|
} for name, price_unit in self.get_real_client_invoice_data().lines]
|
|
}])
|
|
|
|
invoice_data = self.get_real_client_invoice_data()
|
|
for line in invoice.line_ids.filtered(lambda x: x.name in [data[0] for data in invoice_data.lines]):
|
|
withholding_taxes = line.tax_ids.filtered(lambda x: x.l10n_it_withholding_type)
|
|
pension_fund_taxes = line.tax_ids.filtered(lambda x: x.l10n_it_pension_fund_type)
|
|
vat_taxes = line.tax_ids - withholding_taxes - pension_fund_taxes
|
|
self.assertEqual([1, 1, 1], [len(x) for x in (vat_taxes, withholding_taxes, pension_fund_taxes)])
|
|
|
|
####################################################
|
|
# ENASARCO TAX
|
|
####################################################
|
|
|
|
def test_enasarco_tax_export(self):
|
|
"""
|
|
Invoice
|
|
-----------------------------------------------------------------
|
|
Ordinary accounting service for the year 350.00
|
|
Balance deposit for the past year 300.00
|
|
Ordinary accounting service for the trimester 50.00
|
|
Electronic invoices management 50.00
|
|
-----------------------------------------------------------------
|
|
Total untaxed: 750.00
|
|
VAT: 22% of Untaxed Amount 165.00
|
|
ENASARCO: 8.5% of Untaxed Amount -63.75
|
|
Withholding Tax: 23% on 50% of Untaxed Amount -86.25
|
|
Document total: Taxed Amount 915.00
|
|
Payment amount: Document total - Withholding - Enasarco 765.00
|
|
"""
|
|
self._assert_export_invoice(self.enasarco_tax_invoice, 'enasarco_tax_invoice.xml')
|
|
|
|
def test_enasarco_tax_import(self):
|
|
invoice = self._assert_import_invoice('IT00470550013_enasa.xml', [{
|
|
'invoice_date': fields.Date.from_string('2022-03-24'),
|
|
'amount_untaxed': 750.0,
|
|
'amount_total': 765.0,
|
|
'amount_tax': 15.0,
|
|
'invoice_line_ids': [{
|
|
'name': name,
|
|
'price_unit': price_unit,
|
|
} for name, price_unit in self.get_real_client_invoice_data().lines]
|
|
}])
|
|
|
|
invoice_data = self.get_real_client_invoice_data()
|
|
for line in invoice.line_ids.filtered(lambda x: x.name in [data[0] for data in invoice_data.lines]):
|
|
enasarco_imported_tax = line.tax_ids.filtered(lambda x: x.l10n_it_pension_fund_type == 'TC07')
|
|
self.assertEqual(self.enasarco_purchase_tax, enasarco_imported_tax)
|
|
self.assertEqual(-8.5, enasarco_imported_tax.amount)
|
|
self.assertEqual(self.withholding_purchase_tax_23, line.tax_ids.filtered(lambda x: x.l10n_it_withholding_reason == 'ZO'))
|
|
|
|
def test_inps_tax_export(self):
|
|
"""
|
|
Invoice
|
|
-----------------------------------------------------------------
|
|
Ordinary accounting service for the year 350.00
|
|
Balance deposit for the past year 300.00
|
|
Ordinary accounting service for the trimester 50.00
|
|
Electronic invoices management 50.00
|
|
-----------------------------------------------------------------
|
|
Total untaxed: 750.00
|
|
VAT: 0% of Untaxed Amount 0.00
|
|
INPS: 4% of Untaxed Amount 30.00
|
|
Document total: Taxed Amount 780.00
|
|
Payment amount: Document total 780.00
|
|
"""
|
|
self._assert_export_invoice(self.inps_tax_invoice, 'inps_tax_invoice.xml')
|