diff --git a/intrastat_base/tests/common.py b/intrastat_base/tests/common.py index 640c62a..58a2491 100644 --- a/intrastat_base/tests/common.py +++ b/intrastat_base/tests/common.py @@ -52,11 +52,6 @@ class IntrastatCommon(object): cls.shipping_cost = cls.env.ref("intrastat_base.shipping_costs_exclude") cls._load_test_declaration() - cls.declaration_test_obj = cls.env["intrastat.declaration.test"] - cls._load_xml("intrastat_base", "tests/data/mail_template.xml") - cls.mail_template_id = ( - "intrastat_base.base_intrastat_product_reminder_email_template" - ) @classmethod def tearDownClass(cls): diff --git a/intrastat_base/tests/test_all.py b/intrastat_base/tests/test_all.py index f25e1dc..cc7b203 100644 --- a/intrastat_base/tests/test_all.py +++ b/intrastat_base/tests/test_all.py @@ -7,6 +7,15 @@ from .common import IntrastatCommon class TestIntrastatBase(IntrastatCommon): """Tests for this module""" + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.declaration_test_obj = cls.env["intrastat.declaration.test"] + cls._load_xml("intrastat_base", "tests/data/mail_template.xml") + cls.mail_template_id = ( + "intrastat_base.base_intrastat_product_reminder_email_template" + ) + def test_company(self): # add 'Demo user' to intrastat_remind_user_ids self.demo_company.write( diff --git a/intrastat_product/tests/__init__.py b/intrastat_product/tests/__init__.py new file mode 100644 index 0000000..c8e439c --- /dev/null +++ b/intrastat_product/tests/__init__.py @@ -0,0 +1,5 @@ +from . import common +from . import common_sale +from . import test_intrastat_product +from . import test_company +from . import test_sale_order diff --git a/intrastat_product/tests/common.py b/intrastat_product/tests/common.py new file mode 100644 index 0000000..77e350d --- /dev/null +++ b/intrastat_product/tests/common.py @@ -0,0 +1,113 @@ +# Copyright 2021 ACSONE SA/NV +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo.addons.intrastat_base.tests.common import IntrastatCommon + + +class IntrastatProductCommon(IntrastatCommon): + @classmethod + def _init_products(cls): + # Create category - don't init intrastat values, do it in tests + vals = { + "name": "Robots", + "parent_id": cls.category_saleable.id, + } + cls.categ_robots = cls.category_obj.create(vals) + + vals = { + "name": "C3PO", + "categ_id": cls.categ_robots.id, + "origin_country_id": cls.env.ref("base.us").id, + "weight": 300, + # Computer - C3PO is one of them + "hs_code_id": cls.hs_code_computer.id, + } + cls.product_c3po = cls.product_template_obj.create(vals) + + @classmethod + def _init_company(cls): + # Default transport for company is Road + cls.demo_company.intrastat_transport_id = cls.transport_road + + @classmethod + def _init_fiscal_position(cls): + vals = { + "name": "Intrastat Fiscal Position", + "intrastat": True, + } + cls.position = cls.position_obj.create(vals) + + @classmethod + def _init_regions(cls): + # Create Belgium + cls._create_region() + + vals = { + "code": "DE", + "name": "Germany", + "country_id": cls.env.ref("base.de").id, + "description": "Germany", + } + cls._create_region(vals) + + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.region_obj = cls.env["intrastat.region"] + cls.transaction_obj = cls.env["intrastat.transaction"] + cls.transport_mode_obj = cls.env["intrastat.transport_mode"] + cls.partner_obj = cls.env["res.partner"] + cls.category_saleable = cls.env.ref("product.product_category_1") + cls.category_obj = cls.env["product.category"] + cls.product_template_obj = cls.env["product.template"] + cls.declaration_obj = cls.env["intrastat.product.declaration"] + cls.position_obj = cls.env["account.fiscal.position"] + cls.hs_code_computer = cls.env.ref("product_harmonized_system.84715000") + + cls.transport_rail = cls.env.ref("intrastat_product.intrastat_transport_2") + cls.transport_road = cls.env.ref("intrastat_product.intrastat_transport_3") + + cls._init_regions() + cls._init_company() + cls._init_fiscal_position() + cls._init_products() + + @classmethod + def _create_region(cls, vals=None): + values = { + "code": "BE", + "country_id": cls.env.ref("base.be").id, + "company_id": cls.env.company.id, + "description": "Belgium", + "name": "Belgium", + } + if vals is not None: + values.update(vals) + cls.region = cls.region_obj.create(values) + + @classmethod + def _create_transaction(cls, vals=None): + values = { + "code": "11", + "company_id": cls.env.company.id, + "description": "Sale / Purchase", + } + if vals is not None: + values.update(vals) + cls.transaction = cls.transaction_obj.create(values) + + @classmethod + def _create_transport_mode(cls, vals=None): + values = {} + if vals is not None: + values.update(vals) + cls.transport_mode = cls.transport_mode_obj.create(values) + + @classmethod + def _create_declaration(cls, vals=None): + values = { + "company_id": cls.env.company.id, + } + if vals is not None: + values.update(vals) + cls.declaration = cls.declaration_obj.create(values) diff --git a/intrastat_product/tests/common_sale.py b/intrastat_product/tests/common_sale.py new file mode 100644 index 0000000..9dc07ca --- /dev/null +++ b/intrastat_product/tests/common_sale.py @@ -0,0 +1,43 @@ +# Copyright 2021 ACSONE SA/NV +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +from odoo.tests import Form + +from .common import IntrastatProductCommon + + +class IntrastatSaleCommon(IntrastatProductCommon): + """ + We define common flow: + - Customer in Netherlands + """ + + @classmethod + def _init_customer(cls, vals=None): + values = { + "name": "NL Customer", + "country_id": cls.env.ref("base.nl").id, + "property_account_position_id": cls.position.id, + } + if vals is not None: + values.update(vals) + cls.customer = cls.partner_obj.create(values) + + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.sale_obj = cls.env["sale.order"] + cls._init_customer() + + @classmethod + def _create_sale_order(cls, vals=None): + vals = { + "partner_id": cls.customer.id, + } + sale_new = cls.sale_obj.new(vals) + sale_new.onchange_partner_id() + sale_vals = sale_new._convert_to_write(sale_new._cache) + cls.sale = cls.sale_obj.create(sale_vals) + with Form(cls.sale) as sale_form: + with sale_form.order_line.new() as line: + line.product_id = cls.product_c3po.product_variant_ids[0] + line.product_uom_qty = 3.0 diff --git a/intrastat_product/tests/test_company.py b/intrastat_product/tests/test_company.py new file mode 100644 index 0000000..7fe99ac --- /dev/null +++ b/intrastat_product/tests/test_company.py @@ -0,0 +1,40 @@ +# Copyright 2021 ACSONE SA/NV +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +from odoo.tests.common import SavepointCase + +from .common import IntrastatProductCommon + + +class TestIntrastatCompany(IntrastatProductCommon): + """Tests for this module""" + + def test_company_values(self): + # Exempt for arrivals and dispatches => exempt + self.demo_company.update( + { + "intrastat_arrivals": "exempt", + "intrastat_dispatches": "exempt", + } + ) + self.assertEqual("exempt", self.demo_company.intrastat) + + # Extended for arrivals or dispatches => extended + self.demo_company.update( + { + "intrastat_arrivals": "extended", + } + ) + self.assertEqual("extended", self.demo_company.intrastat) + + # standard for arrivals or dispatches => standard + self.demo_company.update( + { + "intrastat_arrivals": "exempt", + "intrastat_dispatches": "standard", + } + ) + self.assertEqual("standard", self.demo_company.intrastat) + + +class TestIntrastatProductCase(TestIntrastatCompany, SavepointCase): + """ Test Intrastat Product """ diff --git a/intrastat_product/tests/test_intrastat_product.py b/intrastat_product/tests/test_intrastat_product.py new file mode 100644 index 0000000..0e30a7a --- /dev/null +++ b/intrastat_product/tests/test_intrastat_product.py @@ -0,0 +1,34 @@ +# Copyright 2021 ACSONE SA/NV +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +from psycopg2 import IntegrityError + +from odoo.tests.common import SavepointCase +from odoo.tools import mute_logger + +from .common import IntrastatProductCommon + + +class TestIntrastatProduct(IntrastatProductCommon): + """Tests for this module""" + + # Test duplicates + @mute_logger("odoo.sql_db") + def test_region(self): + with self.assertRaises(IntegrityError): + self._create_region() + + @mute_logger("odoo.sql_db") + def test_transaction(self): + self._create_transaction() + with self.assertRaises(IntegrityError): + self._create_transaction() + + @mute_logger("odoo.sql_db") + def test_transport_mode(self): + vals = {"code": 1, "name": "Sea"} + with self.assertRaises(IntegrityError): + self._create_transport_mode(vals) + + +class TestIntrastatProductCase(TestIntrastatProduct, SavepointCase): + """ Test Intrastat Product """ diff --git a/intrastat_product/tests/test_sale_order.py b/intrastat_product/tests/test_sale_order.py new file mode 100644 index 0000000..e3e6819 --- /dev/null +++ b/intrastat_product/tests/test_sale_order.py @@ -0,0 +1,92 @@ +# Copyright 2021 ACSONE SA/NV +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +from freezegun import freeze_time + +from odoo.tests.common import SavepointCase + +from .common_sale import IntrastatSaleCommon + + +class TestIntrastatProductSale(IntrastatSaleCommon): + """Tests for this module""" + + def test_sale_to_invoice_default(self): + self._create_sale_order() + self.sale.action_confirm() + self.sale.picking_ids.action_assign() + for line in self.sale.picking_ids.move_line_ids: + line.qty_done = line.product_uom_qty + self.sale.picking_ids._action_done() + self.assertEqual("done", self.sale.picking_ids.state) + + invoice = self.sale._create_invoices() + invoice.action_post() + + # Check if transport mode has been transmitted to invoice + # It should be None as not defined on sale order + self.assertFalse( + invoice.intrastat_transport_id, + ) + + # Test specific transport set on sale to invoice + def test_sale_to_invoice(self): + self._create_sale_order() + # Set intrastat transport mode to rail + self.sale.intrastat_transport_id = self.transport_rail + self.sale.action_confirm() + self.sale.picking_ids.action_assign() + for line in self.sale.picking_ids.move_line_ids: + line.qty_done = line.product_uom_qty + self.sale.picking_ids._action_done() + self.assertEqual("done", self.sale.picking_ids.state) + + invoice = self.sale._create_invoices() + invoice.action_post() + + # Check if transport mode has been transmitted to invoice + self.assertEqual( + self.transport_rail, + invoice.intrastat_transport_id, + ) + + def test_sale_declaration(self): + date_order = "2021-09-01" + declaration_date = "2021-10-01" + with freeze_time(date_order): + self._create_sale_order() + # Set intrastat transport mode to rail + self.sale.intrastat_transport_id = self.transport_rail + self.sale.action_confirm() + self.sale.picking_ids.action_assign() + for line in self.sale.picking_ids.move_line_ids: + line.qty_done = line.product_uom_qty + self.sale.picking_ids._action_done() + self.assertEqual("done", self.sale.picking_ids.state) + + with freeze_time(date_order): + invoice = self.sale._create_invoices() + invoice.action_post() + + # Check if transport mode has been transmitted to invoice + self.assertEqual( + self.transport_rail, + invoice.intrastat_transport_id, + ) + vals = { + "declaration_type": "dispatches", + } + with freeze_time(declaration_date): + self._create_declaration(vals) + self.declaration.action_gather() + + expected_vals = { + "declaration_type": "dispatches", + "suppl_unit_qty": 3.0, + "hs_code_id": self.hs_code_computer, + } + line = self.declaration.computation_line_ids + self.assertDictContainsSubset(expected_vals, line) + + +class TestIntrastatProductSaleCase(TestIntrastatProductSale, SavepointCase): + """ Test Intrastat Sale """ diff --git a/test-requirements.txt b/test-requirements.txt index 4ad8e0e..864b829 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -1 +1,2 @@ odoo-test-helper +freezegun