Repository: OCA/intrastat-extrastat (language: python)

Issue:
change m2m table name to avoid naming conflicts with other modules
cf. https://github.com/OCA/intrastat-extrastat/issues/97
14.0 mig : invoice domain should be based on fiscal position in stead of country
Up till now the default domain to select intrastat transactions is based upon invoices to/from EU countries.
I propose that we change in 14.0 the logic to be based upon the "Intra EU" fiscal position.

On the Belgian market transactions subject to the 'intrastat' declaration are also subject to the 'intracommunity' tax declaration.
In the 13.0 version of the Belgium localisation module I already replaced the domain query, cf. 
https://github.com/Noviat/noviat-apps/blob/012c9a254b101c405126b1c0ce5276a0a9c16d9e/l10n_be_intrastat_product/models/l10n_be_intrastat_product_declaration.py#L219

But since these rules are decided on an european level, this should be applicable for all EU countries.
As a consequence I propose that for the 14.0 migration we add an 'intrastat' boolean to the fiscal position and base the domain on invoices with fiscal positions marked as 'intrastat'. In the localisation modules we can add the logic to set this flag automatically on the standard Intra EU fiscal position.

To give a concrete example why the country tabel is wrong:
If you ship goods to a customer without VAT number in an EU country that this shipment must not be included in the intrastat declaration.



Discussion / hints:

Fix patch:
diff --git a/intrastat_base/README.rst b/intrastat_base/README.rst
new file mode 100644
index 000000000..2246c4f7d
--- /dev/null
+++ b/intrastat_base/README.rst
@@ -0,0 +1,123 @@
+========================
+Intrastat Reporting Base
+========================
+
+.. 
+   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+   !! This file is generated by oca-gen-addon-readme !!
+   !! changes will be overwritten.                   !!
+   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+   !! source digest: sha256:28aa058f14d9b8414cad83bafa1c8d416330287450167531b2787c4d47348560
+   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
+    :target: https://odoo-community.org/page/development-status
+    :alt: Beta
+.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png
+    :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
+    :alt: License: AGPL-3
+.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fintrastat--extrastat-lightgray.png?logo=github
+    :target: https://github.com/OCA/intrastat-extrastat/tree/17.0/intrastat_base
+    :alt: OCA/intrastat-extrastat
+.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
+    :target: https://translation.odoo-community.org/projects/intrastat-extrastat-17-0/intrastat-extrastat-17-0-intrastat_base
+    :alt: Translate me on Weblate
+.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png
+    :target: https://runboat.odoo-community.org/builds?repo=OCA/intrastat-extrastat&target_branch=17.0
+    :alt: Try me on Runboat
+
+|badge1| |badge2| |badge3| |badge4| |badge5|
+
+This module contains common functions for the intrastat reporting and
+should be used in combination with the generic reporting module
+*intrastat_product* and with the country-specific reporting modules such
+as:
+
+-  *l10n_fr_intrastat_service*: the module for the *Déclaration
+   Européenne des Services* (DES) for France
+-  *l10n_fr_intrastat_product*: the module for the *Déclaration
+   d'Echange de Biens* (DEB) for France
+-  *l10n_be_intrastat_product*: the module for the Intrastat Declaration
+   for Belgium.
+
+**Table of contents**
+
+.. contents::
+   :local:
+
+Installation
+============
+
+WARNING:
+
+This module conflicts with the module *account_intrastat* from Odoo
+Enterprise. If you have already installed the module
+*account_intrastat*, you should uninstall it first before installing
+this module.
+
+Usage
+=====
+
+This module adds an intrastat property on fiscal positions.
+
+With this module, the country field on partners becomes a required
+field.
+
+It adds an *Intrastat* section on the *Invoicing* configuration page.
+
+Bug Tracker
+===========
+
+Bugs are tracked on `GitHub Issues <https://github.com/OCA/intrastat-extrastat/issues>`_.
+In case of trouble, please check there if your issue has already been reported.
+If you spotted it first, help us to smash it by providing a detailed and welcomed
+`feedback <https://github.com/OCA/intrastat-extrastat/issues/new?body=module:%20intrastat_base%0Aversion:%2017.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
+
+Do not contact contributors directly about support or help with technical issues.
+
+Credits
+=======
+
+Authors
+-------
+
+* ACSONE SA/NV
+* Akretion
+* Noviat
+
+Contributors
+------------
+
+-  Alexis de Lattre, Akretion <alexis.delattre@akretion.com>
+-  Luc De Meyer, Noviat <info@noviat.com>
+-  Kumar Aberer, brain-tec AG <kumar.aberer@braintec-group.com>
+-  Andrea Stirpe <a.stirpe@onestein.nl>
+-  Denis Roussel <denis.roussel@acsone.eu>
+
+Maintainers
+-----------
+
+This module is maintained by the OCA.
+
+.. image:: https://odoo-community.org/logo.png
+   :alt: Odoo Community Association
+   :target: https://odoo-community.org
+
+OCA, or the Odoo Community Association, is a nonprofit organization whose
+mission is to support the collaborative development of Odoo features and
+promote its widespread use.
+
+.. |maintainer-alexis-via| image:: https://github.com/alexis-via.png?size=40px
+    :target: https://github.com/alexis-via
+    :alt: alexis-via
+.. |maintainer-luc-demeyer| image:: https://github.com/luc-demeyer.png?size=40px
+    :target: https://github.com/luc-demeyer
+    :alt: luc-demeyer
+
+Current `maintainers <https://odoo-community.org/page/maintainer-role>`__:
+
+|maintainer-alexis-via| |maintainer-luc-demeyer| 
+
+This module is part of the `OCA/intrastat-extrastat <https://github.com/OCA/intrastat-extrastat/tree/17.0/intrastat_base>`_ project on GitHub.
+
+You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
diff --git a/intrastat_base/__init__.py b/intrastat_base/__init__.py
new file mode 100644
index 000000000..aee8895e7
--- /dev/null
+++ b/intrastat_base/__init__.py
@@ -0,0 +1,2 @@
+from . import models
+from . import wizards
diff --git a/intrastat_base/__manifest__.py b/intrastat_base/__manifest__.py
new file mode 100644
index 000000000..f55040e37
--- /dev/null
+++ b/intrastat_base/__manifest__.py
@@ -0,0 +1,26 @@
+# Copyright 2011-2022 Akretion (http://www.akretion.com)
+# Copyright 2018-2022 brain-tec AG (Kumar Aberer <kumar.aberer@braintec-group.com>)
+# Copyright 2009-2022 Noviat (http://www.noviat.com)
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+
+{
+    "name": "Intrastat Reporting Base",
+    "version": "17.0.1.0.0",
+    "category": "Intrastat",
+    "license": "AGPL-3",
+    "summary": "Base module for Intrastat reporting",
+    "author": "ACSONE SA/NV,Akretion,Noviat,Odoo Community Association (OCA)",
+    "maintainers": ["alexis-via", "luc-demeyer"],
+    "website": "https://github.com/OCA/intrastat-extrastat",
+    "depends": ["base_vat", "account"],
+    "excludes": ["account_intrastat"],
+    "data": [
+        "views/product_template.xml",
+        "views/res_partner.xml",
+        "views/res_config_settings.xml",
+        "views/intrastat.xml",
+        "views/account_fiscal_position.xml",
+    ],
+    "demo": ["demo/intrastat_demo.xml"],
+    "installable": True,
+}
diff --git a/intrastat_base/demo/intrastat_demo.xml b/intrastat_base/demo/intrastat_demo.xml
new file mode 100644
index 000000000..7c35ea719
--- /dev/null
+++ b/intrastat_base/demo/intrastat_demo.xml
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!--
+  Copyright 2011-2022 Akretion France (http://www.akretion.com/)
+  @author: Alexis de Lattre <alexis.delattre@akretion.com>
+  License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+-->
+<odoo noupdate="1">
+    <record id="base.main_partner" model="res.partner">
+        <field name="vat">FR58441019213</field>
+    </record>
+    <!-- Create a few partners from several EU countries
+    with real/valid VAT number -->
+    <record id="noviat" model="res.partner">
+        <field name="name">Noviat</field>
+        <field name="is_company">1</field>
+        <field name="website">https://www.noviat.com</field>
+        <field name="street">Avenue de Rusatiralaan 1</field>
+        <field name="city">Ganshoren</field>
+        <field name="zip">1083</field>
+        <field name="country_id" ref="base.be" />
+        <field name="vat">BE0820512013</field>
+    </record>
+    <record id="acsone" model="res.partner">
+        <field name="name">Acsone</field>
+        <field name="is_company">1</field>
+        <field name="website">https://www.acsone.eu</field>
+        <field name="street">Drève Richelle, 167</field>
+        <field name="city">Waterloo</field>
+        <field name="zip">1410</field>
+        <field name="country_id" ref="base.be" />
+        <field name="vat">BE0835207216</field>
+    </record>
+    <record id="tecnativa" model="res.partner">
+        <field name="name">Tecnativa</field>
+        <field name="is_company">1</field>
+        <field name="website">https://www.tecnativa.com</field>
+        <field name="street">Calle Tormos 1-A, 25</field>
+        <field name="city">Alicante</field>
+        <field name="zip">03008</field>
+        <field name="country_id" ref="base.es" />
+        <field name="vat">ESB87530432</field>
+    </record>
+    <record id="forgeflow" model="res.partner">
+        <field name="name">ForgeFlow</field>
+        <field name="is_company">1</field>
+        <field name="website">https://www.forgeflow.com</field>
+        <field name="street">Rosselló 319, 6-1</field>
+        <field name="city">Barcelona</field>
+        <field name="zip">08037</field>
+        <field name="country_id" ref="base.es" />
+        <field name="vat">ESB66676008</field>
+    </record>
+    <record id="akretion_france" model="res.partner">
+        <field name="name">Akretion France</field>
+        <field name="is_company">1</field>
+        <field name="website">https://www.akretion.com</field>
+        <field name="street">27 rue Henri Rolland</field>
+        <field name="city">Villeurbanne</field>
+        <field name="zip">69100</field>
+        <field name="country_id" ref="base.fr" />
+        <field name="vat">FR86792377731</field>
+    </record>
+    <record id="shipping_costs_exclude" model="product.product">
+        <field name="name">Shipping costs</field>
+        <field name="default_code">SHIP_S</field>
+        <field name="detailed_type">service</field>
+        <field name="categ_id" ref="product.product_category_all" />
+        <field name="list_price">30</field>
+        <field name="is_accessory_cost" eval="True" />
+    </record>
+</odoo>
diff --git a/intrastat_base/i18n/es.po b/intrastat_base/i18n/es.po
new file mode 100644
index 000000000..2d835ebb9
--- /dev/null
+++ b/intrastat_base/i18n/es.po
@@ -0,0 +1,192 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# 	* intrastat_base
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 16.0\n"
+"Report-Msgid-Bugs-To: \n"
+"PO-Revision-Date: 2023-08-04 13:10+0000\n"
+"Last-Translator: Ivorra78 <informatica@totmaterial.es>\n"
+"Language-Team: none\n"
+"Language: es\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+"X-Generator: Weblate 4.17\n"
+
+#. module: intrastat_base
+#: model:ir.model.fields,help:intrastat_base.field_product_product__is_accessory_cost
+#: model:ir.model.fields,help:intrastat_base.field_product_template__is_accessory_cost
+msgid ""
+"Activate this option for shipping costs, packaging costs and all services "
+"related to the sale of products. This option is used for Intrastat reports."
+msgstr ""
+"Active esta opción para costes de envío, costes de embalaje y todos los "
+"servicios relacionados con la venta de productos. Esta opción se utiliza "
+"para reportes de Instratat."
+
+#. module: intrastat_base
+#. odoo-python
+#: code:addons/intrastat_base/models/account_fiscal_position.py:0
+#, python-format
+msgid "B2B"
+msgstr "B2B"
+
+#. module: intrastat_base
+#. odoo-python
+#: code:addons/intrastat_base/models/account_fiscal_position.py:0
+#, python-format
+msgid "B2C"
+msgstr "B2C"
+
+#. module: intrastat_base
+#: model:ir.model,name:intrastat_base.model_res_company
+msgid "Companies"
+msgstr "Compañías"
+
+#. module: intrastat_base
+#: model:ir.model,name:intrastat_base.model_res_config_settings
+msgid "Config Settings"
+msgstr "Ajustes de Configuración"
+
+#. module: intrastat_base
+#: model:ir.model,name:intrastat_base.model_account_fiscal_position
+msgid "Fiscal Position"
+msgstr "Posición fiscal"
+
+#. module: intrastat_base
+#: model:ir.model.fields,field_description:intrastat_base.field_account_fiscal_position__intrastat
+#: model:ir.model.fields,field_description:intrastat_base.field_account_fiscal_position_template__intrastat
+#: model:ir.ui.menu,name:intrastat_base.menu_intrastat_base_root
+#: model:ir.ui.menu,name:intrastat_base.menu_intrastat_config_root
+#: model_terms:ir.ui.view,arch_db:intrastat_base.product_template_form_view
+#: model_terms:ir.ui.view,arch_db:intrastat_base.view_account_position_filter
+#: model_terms:ir.ui.view,arch_db:intrastat_base.view_account_position_template_search
+#: model_terms:ir.ui.view,arch_db:intrastat_base.view_intrastat_res_config_settings
+msgid "Intrastat"
+msgstr "Intrastat"
+
+#. module: intrastat_base
+#: model:ir.model.fields,field_description:intrastat_base.field_account_bank_statement_line__intrastat_fiscal_position
+#: model:ir.model.fields,field_description:intrastat_base.field_account_move__intrastat_fiscal_position
+#: model:ir.model.fields,field_description:intrastat_base.field_account_payment__intrastat_fiscal_position
+msgid "Intrastat Fiscal Position"
+msgstr "Posición fiscal Intrastat"
+
+#. module: intrastat_base
+#: model:ir.model.fields,field_description:intrastat_base.field_product_product__is_accessory_cost
+#: model:ir.model.fields,field_description:intrastat_base.field_product_template__is_accessory_cost
+msgid "Is Accessory Cost"
+msgstr "Es Coste de Accesorio"
+
+#. module: intrastat_base
+#: model:ir.model,name:intrastat_base.model_account_move
+msgid "Journal Entry"
+msgstr "Entrada diaria"
+
+#. module: intrastat_base
+#: model:ir.model.fields,help:intrastat_base.field_res_company__intrastat_remind_user_ids
+#: model:ir.model.fields,help:intrastat_base.field_res_config_settings__intrastat_remind_user_ids
+msgid ""
+"List of Odoo users who will receive a notification to remind them about the "
+"Intrastat declaration."
+msgstr ""
+"Lista de usuarios Odoo que recibirán una notificación para recordarles "
+"acerca de la declaración Intrastat."
+
+#. module: intrastat_base
+#: model:ir.model.fields,field_description:intrastat_base.field_res_company__intrastat_email_list
+msgid "List of emails of Users Receiving the Intrastat Reminder"
+msgstr "Lista de emails de Usuarios que recibirán un recordatorio Intrastat"
+
+#. module: intrastat_base
+#. odoo-python
+#: code:addons/intrastat_base/models/res_company.py:0
+#, python-format
+msgid "Missing e-mail address on user '%s'."
+msgstr "Falta la dirección de correo electrónico del usuario '%s'."
+
+#. module: intrastat_base
+#. odoo-python
+#: code:addons/intrastat_base/models/account_fiscal_position.py:0
+#, python-format
+msgid "No"
+msgstr "No"
+
+#. module: intrastat_base
+#: model:ir.model,name:intrastat_base.model_product_template
+msgid "Product"
+msgstr "Producto"
+
+#. module: intrastat_base
+#: model:product.template,name:intrastat_base.shipping_costs_exclude_product_template
+msgid "Shipping costs"
+msgstr "Gastos de envío"
+
+#. module: intrastat_base
+#: model:ir.model,name:intrastat_base.model_account_fiscal_position_template
+msgid "Template for Fiscal Position"
+msgstr "Plantilla de Posición Fiscal"
+
+#. module: intrastat_base
+#. odoo-python
+#: code:addons/intrastat_base/models/account_fiscal_position.py:0
+#, python-format
+msgid ""
+"The fiscal position '%s' has intrastat set to B2B, so the option 'VAT "
+"Required' must be enabled."
+msgstr ""
+"La posición fiscal '%s' tiene intrastat establecido en B2B, por lo que la "
+"opción 'IVA Requerido' debe estar activada."
+
+#. module: intrastat_base
+#. odoo-python
+#: code:addons/intrastat_base/models/account_fiscal_position.py:0
+#, python-format
+msgid ""
+"The fiscal position '%s' has intrastat set to B2C, so the option 'VAT "
+"Required' mustn't be enabled."
+msgstr ""
+"La posición fiscal '%s' tiene intrastat establecido en B2C, por lo que la "
+"opción 'IVA requerido' no debe estar activada."
+
+#. module: intrastat_base
+#. odoo-python
+#: code:addons/intrastat_base/models/product_template.py:0
+#, python-format
+msgid ""
+"The option 'Is accessory cost?' should only be activated on 'Service' "
+"products. You have activated this option for the product '%(product_name)s' "
+"which is configured with type '%(product_type)s'."
+msgstr ""
+"La opción '¿El costo del accesorio?' solo debe activarse en productos de "
+"'Servicio'. Ha activado esta opción para el producto '%(product_name)s' que "
+"está configurado con el tipo '%(product_type)s'."
+
+#. module: intrastat_base
+#. odoo-python
+#: code:addons/intrastat_base/models/res_company.py:0
+#, python-format
+msgid "Unknown Error"
+msgstr "Error Desconocido"
+
+#. module: intrastat_base
+#: model:ir.model.fields,field_description:intrastat_base.field_res_company__intrastat_remind_user_ids
+#: model:ir.model.fields,field_description:intrastat_base.field_res_config_settings__intrastat_remind_user_ids
+msgid "Users Receiving the Intrastat Reminder"
+msgstr "Usuarios Recibiendo el Recordatorio Intrastat"
+
+#. module: intrastat_base
+#: model:ir.model.fields,help:intrastat_base.field_account_bank_statement_line__intrastat_fiscal_position
+#: model:ir.model.fields,help:intrastat_base.field_account_fiscal_position__intrastat
+#: model:ir.model.fields,help:intrastat_base.field_account_fiscal_position_template__intrastat
+#: model:ir.model.fields,help:intrastat_base.field_account_move__intrastat_fiscal_position
+#: model:ir.model.fields,help:intrastat_base.field_account_payment__intrastat_fiscal_position
+msgid ""
+"When set to B2B or B2C, the invoices with this fiscal position will be taken "
+"into account for the generation of the intrastat reports."
+msgstr ""
+"Cuando se configura en B2B o B2C, las facturas con esta posición fiscal se "
+"tendrán en cuenta para la generación de los informes intrastat."
diff --git a/intrastat_base/i18n/fr.po b/intrastat_base/i18n/fr.po
new file mode 100644
index 000000000..174acbeec
--- /dev/null
+++ b/intrastat_base/i18n/fr.po
@@ -0,0 +1,328 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# 	* intrastat_base
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 11.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2018-12-29 09:52+0000\n"
+"PO-Revision-Date: 2023-06-20 17:08+0000\n"
+"Last-Translator: Alexis de Lattre <alexis@via.ecp.fr>\n"
+"Language-Team: \n"
+"Language: fr\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: nplurals=2; plural=n > 1;\n"
+"X-Generator: Weblate 4.17\n"
+
+#. module: intrastat_base
+#: model:ir.model.fields,help:intrastat_base.field_product_product__is_accessory_cost
+#: model:ir.model.fields,help:intrastat_base.field_product_template__is_accessory_cost
+msgid ""
+"Activate this option for shipping costs, packaging costs and all services "
+"related to the sale of products. This option is used for Intrastat reports."
+msgstr ""
+"Activer cette option pour les frais de port, les frais d'emballage et tous "
+"les services associés à la vente de produits. Cette option est utilisée pour "
+"l'EMEBI et la DES."
+
+#. module: intrastat_base
+#. odoo-python
+#: code:addons/intrastat_base/models/account_fiscal_position.py:0
+#, python-format
+msgid "B2B"
+msgstr "B2B"
+
+#. module: intrastat_base
+#. odoo-python
+#: code:addons/intrastat_base/models/account_fiscal_position.py:0
+#, python-format
+msgid "B2C"
+msgstr "B2C"
+
+#. module: intrastat_base
+#: model:ir.model,name:intrastat_base.model_res_company
+msgid "Companies"
+msgstr "Sociétés"
+
+#. module: intrastat_base
+#: model:ir.model,name:intrastat_base.model_res_config_settings
+msgid "Config Settings"
+msgstr "Configuration"
+
+#. module: intrastat_base
+#: model:ir.model,name:intrastat_base.model_account_fiscal_position
+msgid "Fiscal Position"
+msgstr "Position fiscale"
+
+#. module: intrastat_base
+#: model:ir.model.fields,field_description:intrastat_base.field_account_fiscal_position__intrastat
+#: model:ir.model.fields,field_description:intrastat_base.field_account_fiscal_position_template__intrastat
+#: model:ir.ui.menu,name:intrastat_base.menu_intrastat_base_root
+#: model:ir.ui.menu,name:intrastat_base.menu_intrastat_config_root
+#: model_terms:ir.ui.view,arch_db:intrastat_base.product_template_form_view
+#: model_terms:ir.ui.view,arch_db:intrastat_base.view_account_position_filter
+#: model_terms:ir.ui.view,arch_db:intrastat_base.view_account_position_template_search
+#: model_terms:ir.ui.view,arch_db:intrastat_base.view_intrastat_res_config_settings
+msgid "Intrastat"
+msgstr "EMEBI/DES"
+
+#. module: intrastat_base
+#: model:ir.model.fields,field_description:intrastat_base.field_account_bank_statement_line__intrastat_fiscal_position
+#: model:ir.model.fields,field_description:intrastat_base.field_account_move__intrastat_fiscal_position
+#: model:ir.model.fields,field_description:intrastat_base.field_account_payment__intrastat_fiscal_position
+msgid "Intrastat Fiscal Position"
+msgstr "Position fiscale intrastat"
+
+#. module: intrastat_base
+#: model:ir.model.fields,field_description:intrastat_base.field_product_product__is_accessory_cost
+#: model:ir.model.fields,field_description:intrastat_base.field_product_template__is_accessory_cost
+msgid "Is Accessory Cost"
+msgstr "Est un frais accessoire"
+
+#. module: intrastat_base
+#: model:ir.model,name:intrastat_base.model_account_move
+msgid "Journal Entry"
+msgstr "Pièce comptable"
+
+#. module: intrastat_base
+#: model:ir.model.fields,help:intrastat_base.field_res_company__intrastat_remind_user_ids
+#: model:ir.model.fields,help:intrastat_base.field_res_config_settings__intrastat_remind_user_ids
+msgid ""
+"List of Odoo users who will receive a notification to remind them about the "
+"Intrastat declaration."
+msgstr "Liste d'utilisateurs Odoo qui recevront un rappel pour l'EMEBI/DES."
+
+#. module: intrastat_base
+#: model:ir.model.fields,field_description:intrastat_base.field_res_company__intrastat_email_list
+msgid "List of emails of Users Receiving the Intrastat Reminder"
+msgstr "Liste des emails des utilisateurs qui reçoivent le rappel EMEBI/DES"
+
+#. module: intrastat_base
+#. odoo-python
+#: code:addons/intrastat_base/models/res_company.py:0
+#, python-format
+msgid "Missing e-mail address on user '%s'."
+msgstr "Adresse e-mail manquante pour l'utilisateur '%s'."
+
+#. module: intrastat_base
+#. odoo-python
+#: code:addons/intrastat_base/models/account_fiscal_position.py:0
+#, python-format
+msgid "No"
+msgstr "Non"
+
+#. module: intrastat_base
+#: model:ir.model,name:intrastat_base.model_product_template
+msgid "Product"
+msgstr "Article"
+
+#. module: intrastat_base
+#: model:product.template,name:intrastat_base.shipping_costs_exclude_product_template
+msgid "Shipping costs"
+msgstr "Frais de port"
+
+#. module: intrastat_base
+#: model:ir.model,name:intrastat_base.model_account_fiscal_position_template
+msgid "Template for Fiscal Position"
+msgstr "Modèle de position fiscale"
+
+#. module: intrastat_base
+#. odoo-python
+#: code:addons/intrastat_base/models/account_fiscal_position.py:0
+#, python-format
+msgid ""
+"The fiscal position '%s' has intrastat set to B2B, so the option 'VAT "
+"Required' must be enabled."
+msgstr ""
+"Sur la position fiscale '%s', le champ 'Intrastat' est configuré en 'B2B', "
+"donc l'option 'TVA requise' doit être activée."
+
+#. module: intrastat_base
+#. odoo-python
+#: code:addons/intrastat_base/models/account_fiscal_position.py:0
+#, python-format
+msgid ""
+"The fiscal position '%s' has intrastat set to B2C, so the option 'VAT "
+"Required' mustn't be enabled."
+msgstr ""
+"Sur la position fiscale '%s', le champ 'Intrastat' est configuré en 'B2C', "
+"donc l'option 'TVA requise' ne doit pas être activée."
+
+#. module: intrastat_base
+#. odoo-python
+#: code:addons/intrastat_base/models/product_template.py:0
+#, python-format
+msgid ""
+"The option 'Is accessory cost?' should only be activated on 'Service' "
+"products. You have activated this option for the product '%(product_name)s' "
+"which is configured with type '%(product_type)s'."
+msgstr ""
+"L'option 'Est un frais accessoire ?' ne doit être activée que pour les "
+"articles de type 'Service'. Vous avez activé cette option pour l'article "
+"'%(product_name)s' qui est de type '%(product_type)s'."
+
+#. module: intrastat_base
+#. odoo-python
+#: code:addons/intrastat_base/models/res_company.py:0
+#, python-format
+msgid "Unknown Error"
+msgstr "Erreur inconnue"
+
+#. module: intrastat_base
+#: model:ir.model.fields,field_description:intrastat_base.field_res_company__intrastat_remind_user_ids
+#: model:ir.model.fields,field_description:intrastat_base.field_res_config_settings__intrastat_remind_user_ids
+msgid "Users Receiving the Intrastat Reminder"
+msgstr "Utilisateurs qui reçoivent le rappel EMEBI/DES"
+
+#. module: intrastat_base
+#: model:ir.model.fields,help:intrastat_base.field_account_bank_statement_line__intrastat_fiscal_position
+#: model:ir.model.fields,help:intrastat_base.field_account_fiscal_position__intrastat
+#: model:ir.model.fields,help:intrastat_base.field_account_fiscal_position_template__intrastat
+#: model:ir.model.fields,help:intrastat_base.field_account_move__intrastat_fiscal_position
+#: model:ir.model.fields,help:intrastat_base.field_account_payment__intrastat_fiscal_position
+msgid ""
+"When set to B2B or B2C, the invoices with this fiscal position will be taken "
+"into account for the generation of the intrastat reports."
+msgstr ""
+"Quand ce champ est configuré en 'B2B' ou 'B2C', les factures avec cette "
+"position fiscale seront prises en compte pour la génération des rapports "
+"EMEBI/DES."
+
+#, python-format
+#~ msgid ""
+#~ "The option 'Is accessory cost?' should only be activated on 'Service' "
+#~ "products. You have activated this option for the product '{product_name}' "
+#~ "which is configured with type '{product_type}'."
+#~ msgstr ""
+#~ "L'option 'Est un frais accessoire ?' ne devrait être activée que sur les "
+#~ "produits de type 'Service'. Vous avez activé cette option pour le produit "
+#~ "'{product_name}' qui est configuré avec le type '{product_type}'."
+
+#~ msgid "Product Template"
+#~ msgstr "Modèle d'article"
+
+#~ msgid ""
+#~ "Set to True if the invoices with this fiscal position should be taken "
+#~ "into account for the generation of the intrastat reports."
+#~ msgstr ""
+#~ "Activer si les factures ayant cette position fiscale doivent être "
+#~ "sélectionnées pour la génération des rapports intrastat."
+
+#~ msgid "Units"
+#~ msgstr "Unités"
+
+#~ msgid "Account Chart Template"
+#~ msgstr "Modèle de plan comptable"
+
+#~ msgid "Cannot delete the declaration %s because it is in Done state"
+#~ msgstr ""
+#~ "Impossible de supprimer la déclaration %s parce qu'elle est à l'état "
+#~ "'Terminé'."
+
+#~ msgid "Common functions for intrastat reports for products "
+#~ msgstr "Fonctions communes pour les rapports intrastat des produits "
+
+#~ msgid "Created by"
+#~ msgstr "Créé par"
+
+#~ msgid "Created on"
+#~ msgstr "Créé le"
+
+#~ msgid "Display Name"
+#~ msgstr "Afficher le nom"
+
+#~ msgid "ID"
+#~ msgstr "ID"
+
+#~ msgid "Intrastat Result View"
+#~ msgstr "Résultat DEB"
+
+#~ msgid "Is accessory cost"
+#~ msgstr "Est un frais accessoire"
+
+#~ msgid "Last Modified on"
+#~ msgstr "Dernière modification le"
+
+#~ msgid "Last Updated by"
+#~ msgstr "Dernière modification par"
+
+#~ msgid "Last Updated on"
+#~ msgstr "Dernière modification le"
+
+#~ msgid "Notes"
+#~ msgstr "Notes"
+
+#~ msgid "Ok"
+#~ msgstr "Ok"
+
+#~ msgid "Pop-up to show errors on intrastat report generation"
+#~ msgstr ""
+#~ "Pop-up qui affiche les erreurs lors de la génération du rapport intrastat"
+
+#~ msgid "The VAT number is not set for the partner '%s'."
+#~ msgstr "Numéro de TVA non renseigné sur le partenaire '%s'."
+
+#~ msgid ""
+#~ "The option 'Is accessory cost?' should only be activated on 'Service' "
+#~ "products. You have activated this option for the product '%s' which is of "
+#~ "type '%s'"
+#~ msgstr ""
+#~ "L'option 'Est un frais accessoire' ne doit être activée que sur des "
+#~ "articles de service. Vous avez activé cette option pour l'article '%s' "
+#~ "qui est de type '%s'"
+
+#~ msgid "Company not yet set on intrastat report."
+#~ msgstr "Société non configurée sur le rapport DEB/DES."
+
+#~ msgid "Country"
+#~ msgstr "Pays"
+
+#~ msgid "EU Country"
+#~ msgstr "Membre de l'UE"
+
+#~ msgid "Exclude invoice line from intrastat if this tax is present"
+#~ msgstr ""
+#~ "Ligne de facture exclue de la DEB et de la DES si cette taxe est présente"
+
+#~ msgid ""
+#~ "If this tax is present on an invoice line, this invoice line will be "
+#~ "skipped when generating Intrastat Product or Service lines from invoices."
+#~ msgstr ""
+#~ "Si cette taxe est présente sur une ligne de facture, cette ligne de "
+#~ "facture sera sautée lors de la génération de la DEB et de la DES à partir "
+#~ "des factures."
+
+#~ msgid "Intrastat Properties"
+#~ msgstr "Propriétés DEB/DES"
+
+#~ msgid "Search Countries"
+#~ msgstr "Recherche pays"
+
+#~ msgid "Set to True for all European Union countries."
+#~ msgstr "Cocher la case pour tous les pays de l'Union Européenne."
+
+#~ msgid "Tax"
+#~ msgstr "Taxe"
+
+#~ msgid "Templates for Taxes"
+#~ msgstr "Modèles pour les taxes"
+
+#~ msgid "The country is not set on the company '%s'."
+#~ msgstr "Pays non renseigné sur la société '%s'."
+
+#~ msgid "intrastat.result.view"
+#~ msgstr "intrastat.result.view"
+
+#~ msgid ""
+#~ "The generated XML file is not valid against the official XML Schema "
+#~ "Definition. The generated XML file and the full error have been written "
+#~ "in the server logs. Here is the error, which may give you an idea on the "
+#~ "cause of the problem : %s."
+#~ msgstr ""
+#~ "Le fichier XML n'est pas valide au regard du schéma de définition XML. Le "
+#~ "fichier XML généré et l'erreur complète ont été écrits dans les logs du "
+#~ "serveur Odoo. Voici l'erreur, qui pourrait vous aiguiller sur la cause du "
+#~ "problème : %s."
diff --git a/intrastat_base/i18n/intrastat_base.pot b/intrastat_base/i18n/intrastat_base.pot
new file mode 100644
index 000000000..143a29dd0
--- /dev/null
+++ b/intrastat_base/i18n/intrastat_base.pot
@@ -0,0 +1,175 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# 	* intrastat_base
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 16.0\n"
+"Report-Msgid-Bugs-To: \n"
+"Last-Translator: \n"
+"Language-Team: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: \n"
+
+#. module: intrastat_base
+#: model:ir.model.fields,help:intrastat_base.field_product_product__is_accessory_cost
+#: model:ir.model.fields,help:intrastat_base.field_product_template__is_accessory_cost
+msgid ""
+"Activate this option for shipping costs, packaging costs and all services "
+"related to the sale of products. This option is used for Intrastat reports."
+msgstr ""
+
+#. module: intrastat_base
+#. odoo-python
+#: code:addons/intrastat_base/models/account_fiscal_position.py:0
+#, python-format
+msgid "B2B"
+msgstr ""
+
+#. module: intrastat_base
+#. odoo-python
+#: code:addons/intrastat_base/models/account_fiscal_position.py:0
+#, python-format
+msgid "B2C"
+msgstr ""
+
+#. module: intrastat_base
+#: model:ir.model,name:intrastat_base.model_res_company
+msgid "Companies"
+msgstr ""
+
+#. module: intrastat_base
+#: model:ir.model,name:intrastat_base.model_res_config_settings
+msgid "Config Settings"
+msgstr ""
+
+#. module: intrastat_base
+#: model:ir.model,name:intrastat_base.model_account_fiscal_position
+msgid "Fiscal Position"
+msgstr ""
+
+#. module: intrastat_base
+#: model:ir.model.fields,field_description:intrastat_base.field_account_fiscal_position__intrastat
+#: model:ir.model.fields,field_description:intrastat_base.field_account_fiscal_position_template__intrastat
+#: model:ir.ui.menu,name:intrastat_base.menu_intrastat_base_root
+#: model:ir.ui.menu,name:intrastat_base.menu_intrastat_config_root
+#: model_terms:ir.ui.view,arch_db:intrastat_base.product_template_form_view
+#: model_terms:ir.ui.view,arch_db:intrastat_base.view_account_position_filter
+#: model_terms:ir.ui.view,arch_db:intrastat_base.view_account_position_template_search
+#: model_terms:ir.ui.view,arch_db:intrastat_base.view_intrastat_res_config_settings
+msgid "Intrastat"
+msgstr ""
+
+#. module: intrastat_base
+#: model:ir.model.fields,field_description:intrastat_base.field_account_bank_statement_line__intrastat_fiscal_position
+#: model:ir.model.fields,field_description:intrastat_base.field_account_move__intrastat_fiscal_position
+#: model:ir.model.fields,field_description:intrastat_base.field_account_payment__intrastat_fiscal_position
+msgid "Intrastat Fiscal Position"
+msgstr ""
+
+#. module: intrastat_base
+#: model:ir.model.fields,field_description:intrastat_base.field_product_product__is_accessory_cost
+#: model:ir.model.fields,field_description:intrastat_base.field_product_template__is_accessory_cost
+msgid "Is Accessory Cost"
+msgstr ""
+
+#. module: intrastat_base
+#: model:ir.model,name:intrastat_base.model_account_move
+msgid "Journal Entry"
+msgstr ""
+
+#. module: intrastat_base
+#: model:ir.model.fields,help:intrastat_base.field_res_company__intrastat_remind_user_ids
+#: model:ir.model.fields,help:intrastat_base.field_res_config_settings__intrastat_remind_user_ids
+msgid ""
+"List of Odoo users who will receive a notification to remind them about the "
+"Intrastat declaration."
+msgstr ""
+
+#. module: intrastat_base
+#: model:ir.model.fields,field_description:intrastat_base.field_res_company__intrastat_email_list
+msgid "List of emails of Users Receiving the Intrastat Reminder"
+msgstr ""
+
+#. module: intrastat_base
+#. odoo-python
+#: code:addons/intrastat_base/models/res_company.py:0
+#, python-format
+msgid "Missing e-mail address on user '%s'."
+msgstr ""
+
+#. module: intrastat_base
+#. odoo-python
+#: code:addons/intrastat_base/models/account_fiscal_position.py:0
+#, python-format
+msgid "No"
+msgstr ""
+
+#. module: intrastat_base
+#: model:ir.model,name:intrastat_base.model_product_template
+msgid "Product"
+msgstr ""
+
+#. module: intrastat_base
+#: model:product.template,name:intrastat_base.shipping_costs_exclude_product_template
+msgid "Shipping costs"
+msgstr ""
+
+#. module: intrastat_base
+#: model:ir.model,name:intrastat_base.model_account_fiscal_position_template
+msgid "Template for Fiscal Position"
+msgstr ""
+
+#. module: intrastat_base
+#. odoo-python
+#: code:addons/intrastat_base/models/account_fiscal_position.py:0
+#, python-format
+msgid ""
+"The fiscal position '%s' has intrastat set to B2B, so the option 'VAT "
+"Required' must be enabled."
+msgstr ""
+
+#. module: intrastat_base
+#. odoo-python
+#: code:addons/intrastat_base/models/account_fiscal_position.py:0
+#, python-format
+msgid ""
+"The fiscal position '%s' has intrastat set to B2C, so the option 'VAT "
+"Required' mustn't be enabled."
+msgstr ""
+
+#. module: intrastat_base
+#. odoo-python
+#: code:addons/intrastat_base/models/product_template.py:0
+#, python-format
+msgid ""
+"The option 'Is accessory cost?' should only be activated on 'Service' "
+"products. You have activated this option for the product '%(product_name)s' "
+"which is configured with type '%(product_type)s'."
+msgstr ""
+
+#. module: intrastat_base
+#. odoo-python
+#: code:addons/intrastat_base/models/res_company.py:0
+#, python-format
+msgid "Unknown Error"
+msgstr ""
+
+#. module: intrastat_base
+#: model:ir.model.fields,field_description:intrastat_base.field_res_company__intrastat_remind_user_ids
+#: model:ir.model.fields,field_description:intrastat_base.field_res_config_settings__intrastat_remind_user_ids
+msgid "Users Receiving the Intrastat Reminder"
+msgstr ""
+
+#. module: intrastat_base
+#: model:ir.model.fields,help:intrastat_base.field_account_bank_statement_line__intrastat_fiscal_position
+#: model:ir.model.fields,help:intrastat_base.field_account_fiscal_position__intrastat
+#: model:ir.model.fields,help:intrastat_base.field_account_fiscal_position_template__intrastat
+#: model:ir.model.fields,help:intrastat_base.field_account_move__intrastat_fiscal_position
+#: model:ir.model.fields,help:intrastat_base.field_account_payment__intrastat_fiscal_position
+msgid ""
+"When set to B2B or B2C, the invoices with this fiscal position will be taken"
+" into account for the generation of the intrastat reports."
+msgstr ""
diff --git a/intrastat_base/models/__init__.py b/intrastat_base/models/__init__.py
new file mode 100644
index 000000000..8e78bef55
--- /dev/null
+++ b/intrastat_base/models/__init__.py
@@ -0,0 +1,4 @@
+from . import product_template
+from . import res_company
+from . import account_fiscal_position
+from . import account_move
diff --git a/intrastat_base/models/account_fiscal_position.py b/intrastat_base/models/account_fiscal_position.py
new file mode 100644
index 000000000..f7d5ba8ee
--- /dev/null
+++ b/intrastat_base/models/account_fiscal_position.py
@@ -0,0 +1,51 @@
+# Copyright 2020-2022 Akretion France (http://www.akretion.com/)
+# @author: <alexis.delattre@akretion.com>
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+
+from odoo import _, api, fields, models
+from odoo.exceptions import ValidationError
+
+
+class AccountFiscalPosition(models.Model):
+    _inherit = "account.fiscal.position"
+
+    intrastat = fields.Selection(
+        "_intrastat_selection",
+        help="When set to B2B or B2C, the invoices with this fiscal position will "
+        "be taken into account for the generation of the intrastat reports.",
+    )
+
+    @api.model
+    def _intrastat_selection(self):
+        return [
+            ("b2b", _("B2B")),
+            ("b2c", _("B2C")),
+            ("no", _("No")),
+        ]
+
+    @api.constrains("intrastat", "vat_required")
+    def _check_intrastat(self):
+        for position in self:
+            if position.intrastat == "b2b" and not position.vat_required:
+                raise ValidationError(
+                    _(
+                        "The fiscal position '%s' has intrastat set to B2B, "
+                        "so the option 'VAT Required' must be enabled."
+                    )
+                    % position.display_name
+                )
+            elif position.intrastat == "b2c" and position.vat_required:
+                raise ValidationError(
+                    _(
+                        "The fiscal position '%s' has intrastat set to B2C, "
+                        "so the option 'VAT Required' mustn't be enabled."
+                    )
+                    % position.display_name
+                )
+
+    @api.onchange("intrastat", "vat_required")
+    def intrastat_change(self):
+        if self.intrastat == "b2b" and not self.vat_required:
+            self.vat_required = True
+        elif self.intrastat == "b2c" and self.vat_required:
+            self.vat_required = False
diff --git a/intrastat_base/models/account_move.py b/intrastat_base/models/account_move.py
new file mode 100644
index 000000000..8ef526992
--- /dev/null
+++ b/intrastat_base/models/account_move.py
@@ -0,0 +1,15 @@
+# Copyright 2020-2022 Akretion France (http://www.akretion.com/)
+# @author: <alexis.delattre@akretion.com>
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+
+from odoo import fields, models
+
+
+class AccountMove(models.Model):
+    _inherit = "account.move"
+
+    intrastat_fiscal_position = fields.Selection(
+        related="fiscal_position_id.intrastat",
+        store=True,
+        string="Intrastat Fiscal Position",
+    )
diff --git a/intrastat_base/models/product_template.py b/intrastat_base/models/product_template.py
new file mode 100644
index 000000000..f4c3ae8db
--- /dev/null
+++ b/intrastat_base/models/product_template.py
@@ -0,0 +1,35 @@
+# Copyright 2010-2022 Akretion France (http://www.akretion.com/)
+# @author: <alexis.delattre@akretion.com>
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+
+from odoo import _, api, fields, models
+from odoo.exceptions import ValidationError
+
+
+class ProductTemplate(models.Model):
+    _inherit = "product.template"
+
+    is_accessory_cost = fields.Boolean(
+        help="Activate this option for shipping costs, packaging "
+        "costs and all services related to the sale of products. "
+        "This option is used for Intrastat reports.",
+    )
+
+    @api.constrains("type", "is_accessory_cost")
+    def _check_accessory_cost(self):
+        for this in self:
+            if this.is_accessory_cost and this.type != "service":
+                raise ValidationError(
+                    _(
+                        "The option 'Is accessory cost?' should only be "
+                        "activated on 'Service' products. You have activated "
+                        "this option for the product '%(product_name)s' which is "
+                        "configured with type '%(product_type)s'."
+                    )
+                    % {
+                        "product_name": this.display_name,
+                        "product_type": this._fields["type"].convert_to_export(
+                            this.type, this
+                        ),
+                    }
+                )
diff --git a/intrastat_base/models/res_company.py b/intrastat_base/models/res_company.py
new file mode 100644
index 000000000..eb6977e44
--- /dev/null
+++ b/intrastat_base/models/res_company.py
@@ -0,0 +1,71 @@
+# Copyright 2013-2022 Akretion France (http://www.akretion.com/)
+# @author: <alexis.delattre@akretion.com>
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+
+import logging
+from io import BytesIO
+from sys import exc_info
+from traceback import format_exception
+
+from lxml import etree
+
+from odoo import _, api, fields, models, tools
+from odoo.exceptions import UserError, ValidationError
+
+logger = logging.getLogger(__name__)
+
+
+class ResCompany(models.Model):
+    _inherit = "res.company"
+
+    intrastat_remind_user_ids = fields.Many2many(
+        comodel_name="res.users",
+        relation="company_intrastat_reminder_user_rel",
+        column1="company_id",
+        column2="user_id",
+        string="Users Receiving the Intrastat Reminder",
+        help="List of Odoo users who will receive a notification to "
+        "remind them about the Intrastat declaration.",
+    )
+    intrastat_email_list = fields.Char(
+        compute="_compute_intrastat_email_list",
+        string="List of emails of Users Receiving the Intrastat Reminder",
+    )
+
+    @api.depends("intrastat_remind_user_ids", "intrastat_remind_user_ids.email")
+    def _compute_intrastat_email_list(self):
+        for this in self:
+            emails = [
+                user.email for user in this.intrastat_remind_user_ids if user.email
+            ]
+            this.intrastat_email_list = ",".join(emails)
+
+    @api.constrains("intrastat_remind_user_ids")
+    def _check_intrastat_remind_users(self):
+        for this in self:
+            for user in this.intrastat_remind_user_ids:
+                if not user.email:
+                    raise ValidationError(
+                        _("Missing e-mail address on user '%s'.") % (user.name)
+                    )
+
+    @api.model
+    def _intrastat_check_xml_schema(self, xml_bytes, xsd_file):
+        """Validate the XML file against the XSD"""
+        xsd_etree_obj = etree.parse(tools.file_open(xsd_file, mode="rb"))
+        official_schema = etree.XMLSchema(xsd_etree_obj)
+        try:
+            t = etree.parse(BytesIO(xml_bytes))
+            official_schema.assertValid(t)
+        except (etree.XMLSchemaParseError, etree.DocumentInvalid) as e:
+            logger.warning("The XML file is invalid against the XML Schema Definition")
+            logger.warning(xml_bytes)
+            logger.warning(e)
+            usererror = f"{e.__class__.__name__}\n\n{str(e)}"
+            raise UserError(usererror) from e
+        except Exception as e:
+            error = _("Unknown Error")
+            tb = "".join(format_exception(*exc_info()))
+            error += "\n%s" % tb
+            logger.warning(error)
+            raise UserError(error) from e
diff --git a/intrastat_base/pyproject.toml b/intrastat_base/pyproject.toml
new file mode 100644
index 000000000..4231d0ccc
--- /dev/null
+++ b/intrastat_base/pyproject.toml
@@ -0,0 +1,3 @@
+[build-system]
+requires = ["whool"]
+build-backend = "whool.buildapi"
diff --git a/intrastat_base/readme/CONTRIBUTORS.md b/intrastat_base/readme/CONTRIBUTORS.md
new file mode 100644
index 000000000..319b1f5ef
--- /dev/null
+++ b/intrastat_base/readme/CONTRIBUTORS.md
@@ -0,0 +1,5 @@
+- Alexis de Lattre, Akretion \<<alexis.delattre@akretion.com>\>
+- Luc De Meyer, Noviat \<<info@noviat.com>\>
+- Kumar Aberer, brain-tec AG \<<kumar.aberer@braintec-group.com>\>
+- Andrea Stirpe \<<a.stirpe@onestein.nl>\>
+- Denis Roussel \<<denis.roussel@acsone.eu>\>
diff --git a/intrastat_base/readme/DESCRIPTION.md b/intrastat_base/readme/DESCRIPTION.md
new file mode 100644
index 000000000..ed84ff16e
--- /dev/null
+++ b/intrastat_base/readme/DESCRIPTION.md
@@ -0,0 +1,11 @@
+This module contains common functions for the intrastat reporting and
+should be used in combination with the generic reporting module
+*intrastat_product* and with the country-specific reporting modules such
+as:
+
+- *l10n_fr_intrastat_service*: the module for the *Déclaration
+  Européenne des Services* (DES) for France
+- *l10n_fr_intrastat_product*: the module for the *Déclaration d'Echange
+  de Biens* (DEB) for France
+- *l10n_be_intrastat_product*: the module for the Intrastat Declaration
+  for Belgium.
diff --git a/intrastat_base/readme/INSTALL.md b/intrastat_base/readme/INSTALL.md
new file mode 100644
index 000000000..ced70fe30
--- /dev/null
+++ b/intrastat_base/readme/INSTALL.md
@@ -0,0 +1,6 @@
+WARNING:
+
+This module conflicts with the module *account_intrastat* from Odoo
+Enterprise. If you have already installed the module
+*account_intrastat*, you should uninstall it first before installing
+this module.
diff --git a/intrastat_base/readme/USAGE.md b/intrastat_base/readme/USAGE.md
new file mode 100644
index 000000000..002423768
--- /dev/null
+++ b/intrastat_base/readme/USAGE.md
@@ -0,0 +1,6 @@
+This module adds an intrastat property on fiscal positions.
+
+With this module, the country field on partners becomes a required
+field.
+
+It adds an *Intrastat* section on the *Invoicing* configuration page.
diff --git a/intrastat_base/static/description/icon.png b/intrastat_base/static/description/icon.png
new file mode 100644
index 000000000..3a0328b51
Binary files /dev/null and b/intrastat_base/static/description/icon.png differ
diff --git a/intrastat_base/static/description/index.html b/intrastat_base/static/description/index.html
new file mode 100644
index 000000000..5d98b543a
--- /dev/null
+++ b/intrastat_base/static/description/index.html
@@ -0,0 +1,457 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="Docutils: https://docutils.sourceforge.io/" />
+<title>Intrastat Reporting Base</title>
+<style type="text/css">
+
+/*
+:Author: David Goodger (goodger@python.org)
+:Id: $Id: html4css1.css 8954 2022-01-20 10:10:25Z milde $
+:Copyright: This stylesheet has been placed in the public domain.
+
+Default cascading style sheet for the HTML output of Docutils.
+
+See https://docutils.sourceforge.io/docs/howto/html-stylesheets.html for how to
+customize this style sheet.
+*/
+
+/* used to remove borders from tables and images */
+.borderless, table.borderless td, table.borderless th {
+  border: 0 }
+
+table.borderless td, table.borderless th {
+  /* Override padding for "table.docutils td" with "! important".
+     The right padding separates the table cells. */
+  padding: 0 0.5em 0 0 ! important }
+
+.first {
+  /* Override more specific margin styles with "! important". */
+  margin-top: 0 ! important }
+
+.last, .with-subtitle {
+  margin-bottom: 0 ! important }
+
+.hidden {
+  display: none }
+
+.subscript {
+  vertical-align: sub;
+  font-size: smaller }
+
+.superscript {
+  vertical-align: super;
+  font-size: smaller }
+
+a.toc-backref {
+  text-decoration: none ;
+  color: black }
+
+blockquote.epigraph {
+  margin: 2em 5em ; }
+
+dl.docutils dd {
+  margin-bottom: 0.5em }
+
+object[type="image/svg+xml"], object[type="application/x-shockwave-flash"] {
+  overflow: hidden;
+}
+
+/* Uncomment (and remove this text!) to get bold-faced definition list terms
+dl.docutils dt {
+  font-weight: bold }
+*/
+
+div.abstract {
+  margin: 2em 5em }
+
+div.abstract p.topic-title {
+  font-weight: bold ;
+  text-align: center }
+
+div.admonition, div.attention, div.caution, div.danger, div.error,
+div.hint, div.important, div.note, div.tip, div.warning {
+  margin: 2em ;
+  border: medium outset ;
+  padding: 1em }
+
+div.admonition p.admonition-title, div.hint p.admonition-title,
+div.important p.admonition-title, div.note p.admonition-title,
+div.tip p.admonition-title {
+  font-weight: bold ;
+  font-family: sans-serif }
+
+div.attention p.admonition-title, div.caution p.admonition-title,
+div.danger p.admonition-title, div.error p.admonition-title,
+div.warning p.admonition-title, .code .error {
+  color: red ;
+  font-weight: bold ;
+  font-family: sans-serif }
+
+/* Uncomment (and remove this text!) to get reduced vertical space in
+   compound paragraphs.
+div.compound .compound-first, div.compound .compound-middle {
+  margin-bottom: 0.5em }
+
+div.compound .compound-last, div.compound .compound-middle {
+  margin-top: 0.5em }
+*/
+
+div.dedication {
+  margin: 2em 5em ;
+  text-align: center ;
+  font-style: italic }
+
+div.dedication p.topic-title {
+  font-weight: bold ;
+  font-style: normal }
+
+div.figure {
+  margin-left: 2em ;
+  margin-right: 2em }
+
+div.footer, div.header {
+  clear: both;
+  font-size: smaller }
+
+div.line-block {
+  display: block ;
+  margin-top: 1em ;
+  margin-bottom: 1em }
+
+div.line-block div.line-block {
+  margin-top: 0 ;
+  margin-bottom: 0 ;
+  margin-left: 1.5em }
+
+div.sidebar {
+  margin: 0 0 0.5em 1em ;
+  border: medium outset ;
+  padding: 1em ;
+  background-color: #ffffee ;
+  width: 40% ;
+  float: right ;
+  clear: right }
+
+div.sidebar p.rubric {
+  font-family: sans-serif ;
+  font-size: medium }
+
+div.system-messages {
+  margin: 5em }
+
+div.system-messages h1 {
+  color: red }
+
+div.system-message {
+  border: medium outset ;
+  padding: 1em }
+
+div.system-message p.system-message-title {
+  color: red ;
+  font-weight: bold }
+
+div.topic {
+  margin: 2em }
+
+h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,
+h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {
+  margin-top: 0.4em }
+
+h1.title {
+  text-align: center }
+
+h2.subtitle {
+  text-align: center }
+
+hr.docutils {
+  width: 75% }
+
+img.align-left, .figure.align-left, object.align-left, table.align-left {
+  clear: left ;
+  float: left ;
+  margin-right: 1em }
+
+img.align-right, .figure.align-right, object.align-right, table.align-right {
+  clear: right ;
+  float: right ;
+  margin-left: 1em }
+
+img.align-center, .figure.align-center, object.align-center {
+  display: block;
+  margin-left: auto;
+  margin-right: auto;
+}
+
+table.align-center {
+  margin-left: auto;
+  margin-right: auto;
+}
+
+.align-left {
+  text-align: left }
+
+.align-center {
+  clear: both ;
+  text-align: center }
+
+.align-right {
+  text-align: right }
+
+/* reset inner alignment in figures */
+div.align-right {
+  text-align: inherit }
+
+/* div.align-center * { */
+/*   text-align: left } */
+
+.align-top    {
+  vertical-align: top }
+
+.align-middle {
+  vertical-align: middle }
+
+.align-bottom {
+  vertical-align: bottom }
+
+ol.simple, ul.simple {
+  margin-bottom: 1em }
+
+ol.arabic {
+  list-style: decimal }
+
+ol.loweralpha {
+  list-style: lower-alpha }
+
+ol.upperalpha {
+  list-style: upper-alpha }
+
+ol.lowerroman {
+  list-style: lower-roman }
+
+ol.upperroman {
+  list-style: upper-roman }
+
+p.attribution {
+  text-align: right ;
+  margin-left: 50% }
+
+p.caption {
+  font-style: italic }
+
+p.credits {
+  font-style: italic ;
+  font-size: smaller }
+
+p.label {
+  white-space: nowrap }
+
+p.rubric {
+  font-weight: bold ;
+  font-size: larger ;
+  color: maroon ;
+  text-align: center }
+
+p.sidebar-title {
+  font-family: sans-serif ;
+  font-weight: bold ;
+  font-size: larger }
+
+p.sidebar-subtitle {
+  font-family: sans-serif ;
+  font-weight: bold }
+
+p.topic-title {
+  font-weight: bold }
+
+pre.address {
+  margin-bottom: 0 ;
+  margin-top: 0 ;
+  font: inherit }
+
+pre.literal-block, pre.doctest-block, pre.math, pre.code {
+  margin-left: 2em ;
+  margin-right: 2em }
+
+pre.code .ln { color: grey; } /* line numbers */
+pre.code, code { background-color: #eeeeee }
+pre.code .comment, code .comment { color: #5C6576 }
+pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold }
+pre.code .literal.string, code .literal.string { color: #0C5404 }
+pre.code .name.builtin, code .name.builtin { color: #352B84 }
+pre.code .deleted, code .deleted { background-color: #DEB0A1}
+pre.code .inserted, code .inserted { background-color: #A3D289}
+
+span.classifier {
+  font-family: sans-serif ;
+  font-style: oblique }
+
+span.classifier-delimiter {
+  font-family: sans-serif ;
+  font-weight: bold }
+
+span.interpreted {
+  font-family: sans-serif }
+
+span.option {
+  white-space: nowrap }
+
+span.pre {
+  white-space: pre }
+
+span.problematic {
+  color: red }
+
+span.section-subtitle {
+  /* font-size relative to parent (h1..h6 element) */
+  font-size: 80% }
+
+table.citation {
+  border-left: solid 1px gray;
+  margin-left: 1px }
+
+table.docinfo {
+  margin: 2em 4em }
+
+table.docutils {
+  margin-top: 0.5em ;
+  margin-bottom: 0.5em }
+
+table.footnote {
+  border-left: solid 1px black;
+  margin-left: 1px }
+
+table.docutils td, table.docutils th,
+table.docinfo td, table.docinfo th {
+  padding-left: 0.5em ;
+  padding-right: 0.5em ;
+  vertical-align: top }
+
+table.docutils th.field-name, table.docinfo th.docinfo-name {
+  font-weight: bold ;
+  text-align: left ;
+  white-space: nowrap ;
+  padding-left: 0 }
+
+/* "booktabs" style (no vertical lines) */
+table.docutils.booktabs {
+  border: 0px;
+  border-top: 2px solid;
+  border-bottom: 2px solid;
+  border-collapse: collapse;
+}
+table.docutils.booktabs * {
+  border: 0px;
+}
+table.docutils.booktabs th {
+  border-bottom: thin solid;
+  text-align: left;
+}
+
+h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
+h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {
+  font-size: 100% }
+
+ul.auto-toc {
+  list-style-type: none }
+
+</style>
+</head>
+<body>
+<div class="document" id="intrastat-reporting-base">
+<h1 class="title">Intrastat Reporting Base</h1>
+
+<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!! This file is generated by oca-gen-addon-readme !!
+!! changes will be overwritten.                   !!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!! source digest: sha256:28aa058f14d9b8414cad83bafa1c8d416330287450167531b2787c4d47348560
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
+<p><a class="reference external image-reference" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external image-reference" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external image-reference" href="https://github.com/OCA/intrastat-extrastat/tree/17.0/intrastat_base"><img alt="OCA/intrastat-extrastat" src="https://img.shields.io/badge/github-OCA%2Fintrastat--extrastat-lightgray.png?logo=github" /></a> <a class="reference external image-reference" href="https://translation.odoo-community.org/projects/intrastat-extrastat-17-0/intrastat-extrastat-17-0-intrastat_base"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external image-reference" href="https://runboat.odoo-community.org/builds?repo=OCA/intrastat-extrastat&amp;target_branch=17.0"><img alt="Try me on Runboat" src="https://img.shields.io/badge/runboat-Try%20me-875A7B.png" /></a></p>
+<p>This module contains common functions for the intrastat reporting and
+should be used in combination with the generic reporting module
+<em>intrastat_product</em> and with the country-specific reporting modules such
+as:</p>
+<ul class="simple">
+<li><em>l10n_fr_intrastat_service</em>: the module for the <em>Déclaration
+Européenne des Services</em> (DES) for France</li>
+<li><em>l10n_fr_intrastat_product</em>: the module for the <em>Déclaration
+d’Echange de Biens</em> (DEB) for France</li>
+<li><em>l10n_be_intrastat_product</em>: the module for the Intrastat Declaration
+for Belgium.</li>
+</ul>
+<p><strong>Table of contents</strong></p>
+<div class="contents local topic" id="contents">
+<ul class="simple">
+<li><a class="reference internal" href="#installation" id="toc-entry-1">Installation</a></li>
+<li><a class="reference internal" href="#usage" id="toc-entry-2">Usage</a></li>
+<li><a class="reference internal" href="#bug-tracker" id="toc-entry-3">Bug Tracker</a></li>
+<li><a class="reference internal" href="#credits" id="toc-entry-4">Credits</a><ul>
+<li><a class="reference internal" href="#authors" id="toc-entry-5">Authors</a></li>
+<li><a class="reference internal" href="#contributors" id="toc-entry-6">Contributors</a></li>
+<li><a class="reference internal" href="#maintainers" id="toc-entry-7">Maintainers</a></li>
+</ul>
+</li>
+</ul>
+</div>
+<div class="section" id="installation">
+<h1><a class="toc-backref" href="#toc-entry-1">Installation</a></h1>
+<p>WARNING:</p>
+<p>This module conflicts with the module <em>account_intrastat</em> from Odoo
+Enterprise. If you have already installed the module
+<em>account_intrastat</em>, you should uninstall it first before installing
+this module.</p>
+</div>
+<div class="section" id="usage">
+<h1><a class="toc-backref" href="#toc-entry-2">Usage</a></h1>
+<p>This module adds an intrastat property on fiscal positions.</p>
+<p>With this module, the country field on partners becomes a required
+field.</p>
+<p>It adds an <em>Intrastat</em> section on the <em>Invoicing</em> configuration page.</p>
+</div>
+<div class="section" id="bug-tracker">
+<h1><a class="toc-backref" href="#toc-entry-3">Bug Tracker</a></h1>
+<p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/intrastat-extrastat/issues">GitHub Issues</a>.
+In case of trouble, please check there if your issue has already been reported.
+If you spotted it first, help us to smash it by providing a detailed and welcomed
+<a class="reference external" href="https://github.com/OCA/intrastat-extrastat/issues/new?body=module:%20intrastat_base%0Aversion:%2017.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
+<p>Do not contact contributors directly about support or help with technical issues.</p>
+</div>
+<div class="section" id="credits">
+<h1><a class="toc-backref" href="#toc-entry-4">Credits</a></h1>
+<div class="section" id="authors">
+<h2><a class="toc-backref" href="#toc-entry-5">Authors</a></h2>
+<ul class="simple">
+<li>ACSONE SA/NV</li>
+<li>Akretion</li>
+<li>Noviat</li>
+</ul>
+</div>
+<div class="section" id="contributors">
+<h2><a class="toc-backref" href="#toc-entry-6">Contributors</a></h2>
+<ul class="simple">
+<li>Alexis de Lattre, Akretion &lt;<a class="reference external" href="mailto:alexis.delattre&#64;akretion.com">alexis.delattre&#64;akretion.com</a>&gt;</li>
+<li>Luc De Meyer, Noviat &lt;<a class="reference external" href="mailto:info&#64;noviat.com">info&#64;noviat.com</a>&gt;</li>
+<li>Kumar Aberer, brain-tec AG &lt;<a class="reference external" href="mailto:kumar.aberer&#64;braintec-group.com">kumar.aberer&#64;braintec-group.com</a>&gt;</li>
+<li>Andrea Stirpe &lt;<a class="reference external" href="mailto:a.stirpe&#64;onestein.nl">a.stirpe&#64;onestein.nl</a>&gt;</li>
+<li>Denis Roussel &lt;<a class="reference external" href="mailto:denis.roussel&#64;acsone.eu">denis.roussel&#64;acsone.eu</a>&gt;</li>
+</ul>
+</div>
+<div class="section" id="maintainers">
+<h2><a class="toc-backref" href="#toc-entry-7">Maintainers</a></h2>
+<p>This module is maintained by the OCA.</p>
+<a class="reference external image-reference" href="https://odoo-community.org"><img alt="Odoo Community Association" src="https://odoo-community.org/logo.png" /></a>
+<p>OCA, or the Odoo Community Association, is a nonprofit organization whose
+mission is to support the collaborative development of Odoo features and
+promote its widespread use.</p>
+<p>Current <a class="reference external" href="https://odoo-community.org/page/maintainer-role">maintainers</a>:</p>
+<p><a class="reference external image-reference" href="https://github.com/alexis-via"><img alt="alexis-via" src="https://github.com/alexis-via.png?size=40px" /></a> <a class="reference external image-reference" href="https://github.com/luc-demeyer"><img alt="luc-demeyer" src="https://github.com/luc-demeyer.png?size=40px" /></a></p>
+<p>This module is part of the <a class="reference external" href="https://github.com/OCA/intrastat-extrastat/tree/17.0/intrastat_base">OCA/intrastat-extrastat</a> project on GitHub.</p>
+<p>You are welcome to contribute. To learn how please visit <a class="reference external" href="https://odoo-community.org/page/Contribute">https://odoo-community.org/page/Contribute</a>.</p>
+</div>
+</div>
+</div>
+</body>
+</html>
diff --git a/intrastat_base/views/account_fiscal_position.xml b/intrastat_base/views/account_fiscal_position.xml
new file mode 100644
index 000000000..ffde9dadb
--- /dev/null
+++ b/intrastat_base/views/account_fiscal_position.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!--
+  Copyright 2020-2022 Akretion France (https://akretion.com/)
+  @author: Alexis de Lattre <alexis.delattre@akretion.com>
+  License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+-->
+<odoo>
+    <record id="view_account_position_form" model="ir.ui.view">
+        <field name="name">intrastat.account.fiscal.position.form</field>
+        <field name="model">account.fiscal.position</field>
+        <field name="inherit_id" ref="account.view_account_position_form" />
+        <field name="arch" type="xml">
+            <field name="auto_apply" position="after">
+                <field name="intrastat" />
+            </field>
+        </field>
+    </record>
+    <record id="view_account_position_tree" model="ir.ui.view">
+        <field name="name">intrastat.account.fiscal.position.tree</field>
+        <field name="model">account.fiscal.position</field>
+        <field name="inherit_id" ref="account.view_account_position_tree" />
+        <field name="arch" type="xml">
+            <field name="name" position="after">
+                <field name="intrastat" optional="show" />
+            </field>
+        </field>
+    </record>
+    <record id="view_account_position_filter" model="ir.ui.view">
+        <field name="model">account.fiscal.position</field>
+        <field name="inherit_id" ref="account.view_account_position_filter" />
+        <field name="arch" type="xml">
+            <field name="name" position="after">
+                <filter
+                    name="intrastat"
+                    domain="[('intrastat', 'in', ('b2b', 'b2c'))]"
+                    string="Intrastat"
+                />
+                <separator />
+            </field>
+            <filter name="active" position="after">
+                <group name="groupby">
+                    <filter
+                        name="intrastat_groupby"
+                        string="Intrastat"
+                        context="{'group_by': 'intrastat'}"
+                    />
+                </group>
+            </filter>
+        </field>
+    </record>
+</odoo>
diff --git a/intrastat_base/views/intrastat.xml b/intrastat_base/views/intrastat.xml
new file mode 100644
index 000000000..8469cd7ca
--- /dev/null
+++ b/intrastat_base/views/intrastat.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!--
+  Copyright 2011-2022 Akretion France (http://www.akretion.com/)
+  Copyright 2015-2022 Noviat (http://www.noviat.com/)
+  License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+-->
+<odoo>
+    <!-- Menu entries for Intrastat -->
+    <menuitem
+        id="menu_intrastat_base_root"
+        name="Intrastat"
+        parent="account.menu_finance_reports"
+        sequence="50"
+    />
+    <menuitem
+        id="menu_intrastat_config_root"
+        name="Intrastat"
+        parent="account.menu_finance_configuration"
+        sequence="50"
+    />
+</odoo>
diff --git a/intrastat_base/views/product_template.xml b/intrastat_base/views/product_template.xml
new file mode 100644
index 000000000..be100a5c0
--- /dev/null
+++ b/intrastat_base/views/product_template.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!--
+  Copyright 2010-2022 Akretion France (http://www.akretion.com/)
+  @author: Alexis de Lattre <alexis.delattre@akretion.com>
+  License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+-->
+<odoo>
+    <record id="product_template_form_view" model="ir.ui.view">
+        <field name="name">intrastat.base.product.template.form</field>
+        <field name="model">product.template</field>
+        <field name="inherit_id" ref="account.product_template_form_view" />
+        <field name="arch" type="xml">
+            <group name="accounting" position="inside">
+                <group string="Intrastat" name="intrastat">
+                    <!-- If you need this field, inherit this view in a
+                         localisation module to set invisible="type != 'service'" -->
+                    <field name="is_accessory_cost" invisible="1" />
+                </group>
+            </group>
+        </field>
+    </record>
+</odoo>
diff --git a/intrastat_base/views/res_config_settings.xml b/intrastat_base/views/res_config_settings.xml
new file mode 100644
index 000000000..d2837811b
--- /dev/null
+++ b/intrastat_base/views/res_config_settings.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!--
+  Copyright 2013-2022 Akretion France (http://www.akretion.com/)
+  @author: Alexis de Lattre <alexis.delattre@akretion.com>
+  Copyright 2018-2022 brain-tec AG (Kumar Aberer <kumar.aberer@braintec-group.com>)
+  License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+-->
+<odoo>
+    <record id="view_intrastat_res_config_settings" model="ir.ui.view">
+        <field name="name">intrastat.res.config.settings.form</field>
+        <field name="model">res.config.settings</field>
+        <field name="inherit_id" ref="account.res_config_settings_view_form" />
+        <field name="arch" type="xml">
+            <block id="storno" position="after">
+                <block id="intrastat" title="Intrastat">
+                <setting id="intrastat">
+                        <div class="content-group">
+                            <div class="row mt16">
+                                <label
+                                    for="intrastat_remind_user_ids"
+                                    class="col-lg-5 o_light_label"
+                                />
+                                <field
+                                    name="intrastat_remind_user_ids"
+                                    widget="many2many_tags"
+                                />
+                            </div>
+                        </div>
+                    </setting>
+                </block>
+            </block>
+        </field>
+    </record>
+</odoo>
diff --git a/intrastat_base/views/res_partner.xml b/intrastat_base/views/res_partner.xml
new file mode 100644
index 000000000..e9daf0a84
--- /dev/null
+++ b/intrastat_base/views/res_partner.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!--
+  Copyright 2010-2022 Akretion France (http://www.akretion.com/)
+  @author David BEAL <david.beal@akretion.com>
+  License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+-->
+<odoo>
+    <!-- Set country_id field to required on partner form view -->
+    <record id="view_partner_form" model="ir.ui.view">
+        <field name="model">res.partner</field>
+        <field name="inherit_id" ref="base.view_partner_form" />
+        <field name="arch" type="xml">
+            <xpath expr="//field[@name='country_id']" position="attributes">
+                <attribute name="required">1</attribute>
+            </xpath>
+            <xpath
+                expr="//field[@name='child_ids']/form//field[@name='country_id']"
+                position="attributes"
+            >
+                <attribute name="required">1</attribute>
+            </xpath>
+        </field>
+    </record>
+
+    <record id="view_partner_address_form" model="ir.ui.view">
+        <field name="model">res.partner</field>
+        <field name="inherit_id" ref="base.view_partner_address_form" />
+        <field name="arch" type="xml">
+            <field name="country_id" position="attributes">
+                    <attribute name="required">1</attribute>
+            </field>
+        </field>
+    </record>
+
+</odoo>
diff --git a/intrastat_base/wizards/__init__.py b/intrastat_base/wizards/__init__.py
new file mode 100644
index 000000000..0deb68c46
--- /dev/null
+++ b/intrastat_base/wizards/__init__.py
@@ -0,0 +1,1 @@
+from . import res_config_settings
diff --git a/intrastat_base/wizards/res_config_settings.py b/intrastat_base/wizards/res_config_settings.py
new file mode 100644
index 000000000..9806cb437
--- /dev/null
+++ b/intrastat_base/wizards/res_config_settings.py
@@ -0,0 +1,14 @@
+# Copyright 2017-2022 Akretion France (http://www.akretion.com/)
+# Copyright 2018-2022 brain-tec AG (Kumar Aberer <kumar.aberer@braintec-group.com>)
+# @author: Alexis de Lattre <alexis.delattre@akretion.com>
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
+
+from odoo import fields, models
+
+
+class ResConfigSettings(models.TransientModel):
+    _inherit = "res.config.settings"
+
+    intrastat_remind_user_ids = fields.Many2many(
+        related="company_id.intrastat_remind_user_ids", readonly=False
+    )


Test patch:
diff --git a/intrastat_base/tests/__init__.py b/intrastat_base/tests/__init__.py
new file mode 100644
index 000000000..a2afb4b92
--- /dev/null
+++ b/intrastat_base/tests/__init__.py
@@ -0,0 +1,2 @@
+from . import common
+from . import test_all
diff --git a/intrastat_base/tests/common.py b/intrastat_base/tests/common.py
new file mode 100644
index 000000000..7190bae7a
--- /dev/null
+++ b/intrastat_base/tests/common.py
@@ -0,0 +1,16 @@
+# Copyright 2021 ACSONE SA/NV
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+
+
+class IntrastatCommon:
+    @classmethod
+    def setUpClass(cls):
+        super().setUpClass()
+        cls.env = cls.env(context=dict(cls.env.context, tracking_disable=True))
+        cls.chart_template_obj = cls.env["account.chart.template"]
+        cls.mail_obj = cls.env["mail.mail"]
+
+        cls.demo_user = cls.env.ref("base.user_demo")
+        cls.demo_company = cls.env.ref("base.main_company")
+
+        cls.shipping_cost = cls.env.ref("intrastat_base.shipping_costs_exclude")
diff --git a/intrastat_base/tests/models.py b/intrastat_base/tests/models.py
new file mode 100644
index 000000000..302914c6f
--- /dev/null
+++ b/intrastat_base/tests/models.py
@@ -0,0 +1,10 @@
+# Copyright 2021 ACSONE SA/NV
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+
+from odoo import models
+
+
+class IntrastatDeclarationTest(models.Model):
+    _inherit = ["mail.thread", "mail.activity.mixin", "intrastat.common"]
+    _name = "intrastat.declaration.test"
+    _description = "Intrastat Declaration Test"
diff --git a/intrastat_base/tests/test_all.py b/intrastat_base/tests/test_all.py
new file mode 100644
index 000000000..98018bf10
--- /dev/null
+++ b/intrastat_base/tests/test_all.py
@@ -0,0 +1,48 @@
+from odoo.exceptions import ValidationError
+
+from .common import IntrastatCommon
+
+
+class TestIntrastatBase(IntrastatCommon):
+    """Tests for this module"""
+
+    @classmethod
+    def setUpClass(cls):
+        super().setUpClass()
+
+    def test_company(self):
+        # add 'Demo user' to intrastat_remind_user_ids
+        self.demo_company.write(
+            {"intrastat_remind_user_ids": [(6, False, [self.demo_user.id])]}
+        )
+        # then check if intrastat_email_list contains the email of the user
+        self.assertEqual(self.demo_company.intrastat_email_list, self.demo_user.email)
+
+    def test_no_email(self):
+        self.demo_user.email = False
+        with self.assertRaises(ValidationError):
+            self.demo_company.write(
+                {"intrastat_remind_user_ids": [(6, False, [self.demo_user.id])]}
+            )
+
+    def test_accessory(self):
+        with self.assertRaises(ValidationError):
+            self.shipping_cost.detailed_type = "consu"
+
+    def test_fiscal_position(self):
+        with self.assertRaises(ValidationError):
+            self.env["account.fiscal.position"].create(
+                {
+                    "name": "TestB2B",
+                    "vat_required": False,
+                    "intrastat": "b2b",
+                }
+            )
+        with self.assertRaises(ValidationError):
+            self.env["account.fiscal.position"].create(
+                {
+                    "name": "TestB2C",
+                    "vat_required": True,
+                    "intrastat": "b2c",
+                }
+            )