+
DAS2
+
+
+

+
This module adds support for DAS2 <https://www.impots.gouv.fr/portail/formulaire/das2/etat-des-honoraires-vacations-commissions-courtages-ristournes-et-jetons>_, which is an annual fiscal declaration also called Déclaration d’honoraires. It will allow you to auto-generate the lines of DAS2 from the accounting entries, check the result, manually update lines if needed and eventually generate a declaration file. Then send the declaration file to the French tax office via your professional account on impots.gouv.fr
+
The specifications of the file are available on this page.
+
Table of contents
+
+
+
+
This module requires the Python lib pyfrdas2. As this lib contains the PGP encryption keys of the DGFiP used to encrypt the declaration file and as these keys are changed every year, check that the lib is up-to-date before using the module for a new year.
+
To install this lib, run:
+
+pip3 install --upgrade pyfrdas2
+
+
+
+<<<<<<< HEAD
+
+=======
+
+>>>>>>> 7ffd40ba (l10n_fr_das2: update for millesime 2024 using pyfrdas2)
+
On the supplier form view, in the Accounting tab, you will see a section DAS2. For the suppliers that must be declared in DAS2, you must set:
+
+- the DAS2 Type,
+- the job for the DAS2 declaration,
+- their SIRET number (for French suppliers only),
+- their full address (street, zip code, city and country).
+
+
On the company configuration form, the APE code, SIRET and address must be set.
+
For the user responsible for the declaration, the phone number and email must be set on his related partner form (name, email and phone number are used in the DAS2 declaration file).
+
+
+<<<<<<< HEAD
+
+=======
+
+>>>>>>> 7ffd40ba (l10n_fr_das2: update for millesime 2024 using pyfrdas2)
+
Go to the menu Accounting > Reports > French Statements > DAS2 and create a new DAS2 report.
+
Then click on the button Generate Lines. Check and edit the generated lines. You can get the details of the computation performed by Odoo in the Note fields of each line.
+
You may have a yellow warning banner that warn you about suppliers that have expenses recorded in accounts such as 622100 Commissions et courtages sur achats, 622200 Commissions et courtages sur ventes, 622600 Honoraires, 622800 Rémunérations d’intermédiaires divers, 653000 Jetons de présence, 651600 Droits d’auteur et de reproduction that are not configured for DAS2.
+
Once your declaration is OK, click on the button Done: it will generate the DAS2 file and set the declaration to Done state (all the fields become readonly).
+
To send the file to the French tax office, go to your professional account on impots.gouv.fr, go to the menu Déclarer > Tiers déclarant and then click on the button Déposer un fichier. Select Salaires et/ou honoraires and follow the instructions.
+
+
+<<<<<<< HEAD
+
+=======
+
+>>>>>>> 7ffd40ba (l10n_fr_das2: update for millesime 2024 using pyfrdas2)
+
Bugs are tracked on GitHub Issues.
+In case of trouble, please check there if your issue has already been reported.
+If you spotted it first, help us smashing it by providing a detailed and welcomed
+feedback.
+
Do not contact contributors directly about support or help with technical issues.
+
+
+<<<<<<< HEAD
+
+
+
+=======
+
+
+
+>>>>>>> 7ffd40ba (l10n_fr_das2: update for millesime 2024 using pyfrdas2)
+
+
+
+<<<<<<< HEAD
+
+=======
+
+>>>>>>> 7ffd40ba (l10n_fr_das2: update for millesime 2024 using pyfrdas2)
+
+
+
+<<<<<<< HEAD
+
+=======
+
+>>>>>>> 7ffd40ba (l10n_fr_das2: update for millesime 2024 using pyfrdas2)
+
This module is maintained by the OCA.
+

+
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.
+
Current maintainer:
+

+
This module is part of the OCA/l10n-france project on GitHub.
+
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
+
+
+
+
+
diff --git a/l10n_fr_das2/tests/__init__.py b/l10n_fr_das2/tests/__init__.py
new file mode 100644
index 0000000000..26e0d6fddd
--- /dev/null
+++ b/l10n_fr_das2/tests/__init__.py
@@ -0,0 +1 @@
+from . import test_das2
diff --git a/l10n_fr_das2/tests/test_das2.py b/l10n_fr_das2/tests/test_das2.py
new file mode 100644
index 0000000000..d374f808fa
--- /dev/null
+++ b/l10n_fr_das2/tests/test_das2.py
@@ -0,0 +1,94 @@
+# Copyright 2024 Akretion France (http://www.akretion.com/)
+# @author: Alexis de Lattre
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
+
+from odoo.tests import tagged
+from odoo.tests.common import TransactionCase
+
+
+@tagged("post_install", "-at_install")
+class TestFrDas2(TransactionCase):
+ @classmethod
+ def setUpClass(cls):
+ super().setUpClass()
+ cls.env = cls.env(context=dict(cls.env.context, tracking_disable=True))
+ cls.company = cls.env["res.company"].create(
+ {
+ "name": "Test company DAS2",
+ "street": "42, rue de la paix",
+ "zip": "69100",
+ "city": "Villeurbanne",
+ "country_id": cls.env.ref("base.fr").id,
+ "currency_id": cls.env.ref("base.EUR").id,
+ "siren": "792377731",
+ "nic": "00023",
+ "ape": "6202Z",
+ }
+ )
+ cls.env.user.phone = "+33742124212"
+ cls.partner1 = cls.env["res.partner"].create(
+ {
+ "is_company": True,
+ "name": "Mon expert comptable préféré",
+ "street": "42 rue du chiffre",
+ "zip": "69009",
+ "city": "Lyon",
+ "country_id": cls.env.ref("base.fr").id,
+ "email": "experts@comptables.example.com",
+ "fr_das2_type": "fee",
+ "fr_das2_job": "Expert comptable",
+ "siren": "555555556",
+ "nic": "00011",
+ }
+ )
+ cls.partner2 = cls.env["res.partner"].create(
+ {
+ "is_company": True,
+ "name": "Mon avocat",
+ "street": "12 rue du tribunal",
+ "zip": "69009",
+ "city": "Lyon",
+ "country_id": cls.env.ref("base.fr").id,
+ "email": "avocat@example.com",
+ "fr_das2_type": "fee",
+ "fr_das2_job": "Avocat",
+ "siren": "666666664",
+ "nic": "00014",
+ }
+ )
+
+ def test_das2(self):
+ decl = self.env["l10n.fr.das2"].create(
+ {
+ "year": 2023,
+ "company_id": self.company.id,
+ "payment_journal_ids": [],
+ }
+ )
+ self.assertEqual(self.partner1.siret, "55555555600011")
+ self.env["l10n.fr.das2.line"].create(
+ {
+ "partner_id": self.partner1.id,
+ "parent_id": decl.id,
+ "fee_amount": 2000,
+ }
+ )
+ self.env["l10n.fr.das2.line"].create(
+ {
+ "partner_id": self.partner2.id,
+ "parent_id": decl.id,
+ "fee_amount": 3123,
+ }
+ )
+ self.assertEqual(decl.state, "draft")
+ decl.done()
+ self.assertEqual(decl.state, "done")
+ self.assertTrue(decl.attachment_id)
+ self.assertTrue(
+ decl.attachment_id.name.startswith(
+ f"DSAL_{decl.year}_{decl.company_id.siren}_000_"
+ )
+ )
+ self.assertTrue(decl.attachment_id.name.endswith(".txt.gz.gpg"))
+ self.assertTrue(decl.unencrypted_attachment_id)
+ self.assertTrue(decl.unencrypted_attachment_id.name.endswith(".txt"))
diff --git a/l10n_fr_das2/views/l10n_fr_das2.xml b/l10n_fr_das2/views/l10n_fr_das2.xml
new file mode 100644
index 0000000000..a518cfe2d8
--- /dev/null
+++ b/l10n_fr_das2/views/l10n_fr_das2.xml
@@ -0,0 +1,260 @@
+
+
+
+
+
+
+ l10n.fr.das2.form
+ l10n.fr.das2
+
+
+
+
+
+
+
+ l10n.fr.das2.tree
+ l10n.fr.das2
+
+
+
+
+
+
+
+
+
+
+
+ l10n.fr.das2.search
+ l10n.fr.das2
+
+
+
+
+
+
+
+
+
+
+ DAS2
+ l10n.fr.das2
+ tree,form
+
+
+
+
+
+
+ l10n.fr.das2.line.form
+ l10n.fr.das2.line
+
+
+
+
+
+
+ l10n.fr.das2.line.tree
+ l10n.fr.das2.line
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ l10n.fr.das2.line.search
+ l10n.fr.das2.line
+
+
+
+
+
+
+
+
+
+
+
+ DAS2 Lines
+ l10n.fr.das2.line
+ tree,form
+
+
+
+
diff --git a/l10n_fr_das2/views/res_config_settings.xml b/l10n_fr_das2/views/res_config_settings.xml
new file mode 100644
index 0000000000..c916d7026c
--- /dev/null
+++ b/l10n_fr_das2/views/res_config_settings.xml
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+ das2.res.config.settings.form
+ res.config.settings
+
+
+
+ DAS2
+
+
+
+
+
+
+
diff --git a/l10n_fr_das2/views/res_partner.xml b/l10n_fr_das2/views/res_partner.xml
new file mode 100644
index 0000000000..c2573021a7
--- /dev/null
+++ b/l10n_fr_das2/views/res_partner.xml
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+ l10n.fr.das2.res.partner.form
+ res.partner
+
+
+
+
+
+
+
+
+
+
+
+
+ l10n.fr.das2.res.partner.search
+ res.partner
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/l10n_fr_das2/wizards/__init__.py b/l10n_fr_das2/wizards/__init__.py
new file mode 100644
index 0000000000..0deb68c468
--- /dev/null
+++ b/l10n_fr_das2/wizards/__init__.py
@@ -0,0 +1 @@
+from . import res_config_settings
diff --git a/l10n_fr_das2/wizards/res_config_settings.py b/l10n_fr_das2/wizards/res_config_settings.py
new file mode 100644
index 0000000000..ff3f48b84d
--- /dev/null
+++ b/l10n_fr_das2/wizards/res_config_settings.py
@@ -0,0 +1,13 @@
+# Copyright 2020-2021 Akretion France (http://www.akretion.com/)
+# @author: Alexis de Lattre
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+
+from odoo import fields, models
+
+
+class ResConfigSettings(models.TransientModel):
+ _inherit = "res.config.settings"
+
+ fr_das2_partner_declare_threshold = fields.Integer(
+ related="company_id.fr_das2_partner_declare_threshold", readonly=False
+ )
diff --git a/requirements.txt b/requirements.txt
index b59013820e..0230dee4cf 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,4 +1,6 @@
# generated from manifests external_dependencies
+pyfrdas2
+python-stdnum
python-stdnum>=1.18
requests_oauthlib
unidecode
diff --git a/setup/l10n_fr_cog/odoo/addons/l10n_fr_cog b/setup/l10n_fr_cog/odoo/addons/l10n_fr_cog
new file mode 120000
index 0000000000..7c3200b326
--- /dev/null
+++ b/setup/l10n_fr_cog/odoo/addons/l10n_fr_cog
@@ -0,0 +1 @@
+../../../../l10n_fr_cog
\ No newline at end of file
diff --git a/setup/l10n_fr_cog/setup.py b/setup/l10n_fr_cog/setup.py
new file mode 100644
index 0000000000..28c57bb640
--- /dev/null
+++ b/setup/l10n_fr_cog/setup.py
@@ -0,0 +1,6 @@
+import setuptools
+
+setuptools.setup(
+ setup_requires=['setuptools-odoo'],
+ odoo_addon=True,
+)
diff --git a/setup/l10n_fr_das2/odoo/addons/l10n_fr_das2 b/setup/l10n_fr_das2/odoo/addons/l10n_fr_das2
new file mode 120000
index 0000000000..c023e85546
--- /dev/null
+++ b/setup/l10n_fr_das2/odoo/addons/l10n_fr_das2
@@ -0,0 +1 @@
+../../../../l10n_fr_das2
\ No newline at end of file
diff --git a/setup/l10n_fr_das2/setup.py b/setup/l10n_fr_das2/setup.py
new file mode 100644
index 0000000000..28c57bb640
--- /dev/null
+++ b/setup/l10n_fr_das2/setup.py
@@ -0,0 +1,6 @@
+import setuptools
+
+setuptools.setup(
+ setup_requires=['setuptools-odoo'],
+ odoo_addon=True,
+)