diff --git a/l10n_fr_siret_lookup/README.rst b/l10n_fr_siret_lookup/README.rst new file mode 100644 index 000000000..e73c03630 --- /dev/null +++ b/l10n_fr_siret_lookup/README.rst @@ -0,0 +1,139 @@ +============ +SIRET Lookup +============ + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:03fba67efc8266229377bb6b509fc696ca15a5c46eef0db0a8d749d51c7d7cdd + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |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%2Fl10n--france-lightgray.png?logo=github + :target: https://github.com/OCA/l10n-france/tree/18.0/l10n_fr_siret_lookup + :alt: OCA/l10n-france +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/l10n-france-18-0/l10n-france-18-0-l10n_fr_siret_lookup + :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/l10n-france&target_branch=18.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +This modules updates partner fields via the SIRENE database +. It uses the dataset +*economicref-france-sirene-v3* of opendatasoft +. +It computes a theorical VAT number from the SIREN and then checks the +validity of the VAT number on +`VIES `__ (if invalid, the +VAT number is discarded). + +The module supports 2 scenarios: + +- update of an existing partner via the menu *Action > SIREN Lookup*, +- creation of a new partner: start by setting the VAT number field, the + SIREN field or SIRET field and Odoo will set the other fields. For + usability purposes, it also work when you write the VAT number, SIREN + or SIRET in the company name field. + +In the 2 scenarios, it will update the following fields: + +- Company Name +- Street +- Postal Code +- City +- Country +- SIREN and NIC (i.e. SIRET) +- VAT Number +- Language (creation scenario only) + +**Table of contents** + +.. contents:: + :local: + +Usage +===== + +To update an existing parter, go to the partner form view and click on +*Action > SIREN Lookup*. + +By default, the search field is filled with Company name. To get more +accurate results, you may want to add the City name where the company is +registered. Then click on *Lookup*. + +A list of company is displayed. You may want to click on one in order to +see corresponding information or directly selecting company from tree +view. Once a company is selected, the partner information is updated and +a message is logged in the chatter. + +Bug Tracker +=========== + +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 to smash it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +------- + +* Le Filament +* Akretion + +Contributors +------------ + +- Benjamin Rivier (https://le-filament.com) +- Remi Cazenave (https://le-filament.com) +- Alexis de Lattre +- Frederic Grall + +Other credits +------------- + +The development of this module has been financially supported by: + +- Le Filament + +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-remi-filament| image:: https://github.com/remi-filament.png?size=40px + :target: https://github.com/remi-filament + :alt: remi-filament +.. |maintainer-alexis-via| image:: https://github.com/alexis-via.png?size=40px + :target: https://github.com/alexis-via + :alt: alexis-via + +Current `maintainers `__: + +|maintainer-remi-filament| |maintainer-alexis-via| + +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_siret_lookup/__init__.py b/l10n_fr_siret_lookup/__init__.py new file mode 100644 index 000000000..9b4296142 --- /dev/null +++ b/l10n_fr_siret_lookup/__init__.py @@ -0,0 +1,2 @@ +from . import models +from . import wizard diff --git a/l10n_fr_siret_lookup/__manifest__.py b/l10n_fr_siret_lookup/__manifest__.py new file mode 100644 index 000000000..60c01d1b8 --- /dev/null +++ b/l10n_fr_siret_lookup/__manifest__.py @@ -0,0 +1,24 @@ +# Copyright 2018-2022 Le Filament () +# Copyright 2021-2022 Akretion France (http://www.akretion.com/) +# @author: Alexis de Lattre +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). +{ + "name": "SIRET Lookup", + "summary": "Lookup partner via an API on the SIRENE directory", + "version": "18.0.1.0.0", + "category": "Partner", + "website": "https://github.com/OCA/l10n-france", + "author": "Le Filament, Akretion, Odoo Community Association (OCA)", + "maintainers": ["remi-filament", "alexis-via"], + "license": "AGPL-3", + "depends": [ + "l10n_fr_siret", + ], + "external_dependencies": {"python": ["requests", "python-stdnum"]}, + "data": [ + "wizard/fr_siret_lookup_view.xml", + "views/res_partner.xml", + "security/ir.model.access.csv", + ], + "installable": True, +} diff --git a/l10n_fr_siret_lookup/i18n/es.po b/l10n_fr_siret_lookup/i18n/es.po new file mode 100644 index 000000000..17c7affdd --- /dev/null +++ b/l10n_fr_siret_lookup/i18n/es.po @@ -0,0 +1,265 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * l10n_fr_siret_lookup +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 16.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2023-09-03 13:35+0000\n" +"Last-Translator: Ivorra78 \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: l10n_fr_siret_lookup +#: model:ir.model.fields,field_description:l10n_fr_siret_lookup.field_fr_siret_lookup_line__staff +msgid "# Staff" +msgstr "# Empleados" + +#. module: l10n_fr_siret_lookup +#: model:ir.model.fields,field_description:l10n_fr_siret_lookup.field_fr_siret_lookup_line__ape +msgid "APE Code" +msgstr "Código APE" + +#. module: l10n_fr_siret_lookup +#: model:ir.model.fields,field_description:l10n_fr_siret_lookup.field_fr_siret_lookup_line__ape_label +msgid "APE Label" +msgstr "Etiqueta APE" + +#. module: l10n_fr_siret_lookup +#: model_terms:ir.ui.view,arch_db:l10n_fr_siret_lookup.fr_siret_lookup_line_form +msgid "Address" +msgstr "Dirección" + +#. module: l10n_fr_siret_lookup +#: model:ir.model.fields,field_description:l10n_fr_siret_lookup.field_fr_siret_lookup_line__category +msgid "Category" +msgstr "Categoría" + +#. module: l10n_fr_siret_lookup +#: model:ir.model.fields,field_description:l10n_fr_siret_lookup.field_fr_siret_lookup_line__city +msgid "City" +msgstr "Ciudad" + +#. module: l10n_fr_siret_lookup +#: model_terms:ir.ui.view,arch_db:l10n_fr_siret_lookup.fr_siret_lookup_form +msgid "Close" +msgstr "Cerrar" + +#. module: l10n_fr_siret_lookup +#: model_terms:ir.ui.view,arch_db:l10n_fr_siret_lookup.fr_siret_lookup_line_form +msgid "Company" +msgstr "Companía" + +#. module: l10n_fr_siret_lookup +#: model_terms:ir.ui.view,arch_db:l10n_fr_siret_lookup.fr_siret_lookup_line_form +msgid "Company Infos" +msgstr "Información de la empresa" + +#. module: l10n_fr_siret_lookup +#: model:ir.model,name:l10n_fr_siret_lookup.model_fr_siret_lookup_line +msgid "Company Selection" +msgstr "Selección de empresa" + +#. module: l10n_fr_siret_lookup +#: model_terms:ir.ui.view,arch_db:l10n_fr_siret_lookup.fr_siret_lookup_form +#: model_terms:ir.ui.view,arch_db:l10n_fr_siret_lookup.fr_siret_lookup_line_form +msgid "Confirm selected company ?" +msgstr "¿Confirmar empresa seleccionada?" + +#. module: l10n_fr_siret_lookup +#: model:ir.model,name:l10n_fr_siret_lookup.model_res_partner +msgid "Contact" +msgstr "Contacto" + +#. module: l10n_fr_siret_lookup +#: model:ir.model.fields,field_description:l10n_fr_siret_lookup.field_fr_siret_lookup_line__country_id +msgid "Country" +msgstr "País" + +#. module: l10n_fr_siret_lookup +#: model:ir.model.fields,field_description:l10n_fr_siret_lookup.field_fr_siret_lookup__create_uid +#: model:ir.model.fields,field_description:l10n_fr_siret_lookup.field_fr_siret_lookup_line__create_uid +msgid "Created by" +msgstr "Creado por" + +#. module: l10n_fr_siret_lookup +#: model:ir.model.fields,field_description:l10n_fr_siret_lookup.field_fr_siret_lookup__create_date +#: model:ir.model.fields,field_description:l10n_fr_siret_lookup.field_fr_siret_lookup_line__create_date +msgid "Created on" +msgstr "Creado el" + +#. module: l10n_fr_siret_lookup +#: model:ir.model.fields,field_description:l10n_fr_siret_lookup.field_fr_siret_lookup_line__creation_date +msgid "Creation Date" +msgstr "Fecha de Creación" + +#. module: l10n_fr_siret_lookup +#: model:ir.model.fields,field_description:l10n_fr_siret_lookup.field_fr_siret_lookup__display_name +#: model:ir.model.fields,field_description:l10n_fr_siret_lookup.field_fr_siret_lookup_line__display_name +msgid "Display Name" +msgstr "Mostrar Nombre" + +#. module: l10n_fr_siret_lookup +#. odoo-python +#: code:addons/l10n_fr_siret_lookup/models/res_partner.py:0 +#, python-format +msgid "" +"Failed to query VIES.\n" +"Technical error: %s." +msgstr "" +"Error en la consulta VIES.\n" +"Error técnico: %s." + +#. module: l10n_fr_siret_lookup +#. odoo-python +#: code:addons/l10n_fr_siret_lookup/models/res_partner.py:0 +#, python-format +msgid "" +"Failure in the request on data.opendatasoft.com to create or update partner " +"from SIREN or SIRET. Technical error: %s." +msgstr "" +"Fallo en la petición en data.opendatasoft.com para crear o actualizar socio " +"desde SIREN o SIRET. Error técnico: %s." + +#. module: l10n_fr_siret_lookup +#: model:ir.model,name:l10n_fr_siret_lookup.model_fr_siret_lookup +msgid "Get values from companies" +msgstr "Obtener valores de las compañías" + +#. module: l10n_fr_siret_lookup +#: model:ir.model.fields,field_description:l10n_fr_siret_lookup.field_fr_siret_lookup__id +#: model:ir.model.fields,field_description:l10n_fr_siret_lookup.field_fr_siret_lookup_line__id +msgid "ID" +msgstr "ID(identificación)" + +#. module: l10n_fr_siret_lookup +#: model:ir.model.fields,field_description:l10n_fr_siret_lookup.field_fr_siret_lookup____last_update +#: model:ir.model.fields,field_description:l10n_fr_siret_lookup.field_fr_siret_lookup_line____last_update +msgid "Last Modified on" +msgstr "Última modificación el" + +#. module: l10n_fr_siret_lookup +#: model:ir.model.fields,field_description:l10n_fr_siret_lookup.field_fr_siret_lookup__write_uid +#: model:ir.model.fields,field_description:l10n_fr_siret_lookup.field_fr_siret_lookup_line__write_uid +msgid "Last Updated by" +msgstr "Actualizado por última vez por" + +#. module: l10n_fr_siret_lookup +#: model:ir.model.fields,field_description:l10n_fr_siret_lookup.field_fr_siret_lookup__write_date +#: model:ir.model.fields,field_description:l10n_fr_siret_lookup.field_fr_siret_lookup_line__write_date +msgid "Last Updated on" +msgstr "Última Actualización el" + +#. module: l10n_fr_siret_lookup +#: model_terms:ir.ui.view,arch_db:l10n_fr_siret_lookup.fr_siret_lookup_line_form +msgid "Legal Infos" +msgstr "Información legal" + +#. module: l10n_fr_siret_lookup +#: model:ir.model.fields,field_description:l10n_fr_siret_lookup.field_fr_siret_lookup_line__legal_type +msgid "Legal Type" +msgstr "Tipo legal" + +#. module: l10n_fr_siret_lookup +#: model_terms:ir.ui.view,arch_db:l10n_fr_siret_lookup.fr_siret_lookup_form +msgid "Lookup" +msgstr "Búsqueda" + +#. module: l10n_fr_siret_lookup +#: model:ir.model.fields,field_description:l10n_fr_siret_lookup.field_fr_siret_lookup_line__name +msgid "Name" +msgstr "Nombre" + +#. module: l10n_fr_siret_lookup +#: model:ir.model.fields,field_description:l10n_fr_siret_lookup.field_fr_siret_lookup__name +msgid "Name to Search" +msgstr "Nombre a buscar" + +#. module: l10n_fr_siret_lookup +#: model:ir.model.fields,field_description:l10n_fr_siret_lookup.field_fr_siret_lookup__partner_id +msgid "Partner" +msgstr "Socio" + +#. module: l10n_fr_siret_lookup +#. odoo-python +#: code:addons/l10n_fr_siret_lookup/wizard/fr_siret_lookup.py:0 +#, python-format +msgid "Partner '%s' is not a company. This action is not relevant." +msgstr "El socio '%s' no es una empresa. Esta acción no es relevante." + +#. module: l10n_fr_siret_lookup +#. odoo-python +#: code:addons/l10n_fr_siret_lookup/wizard/fr_siret_lookup.py:0 +#, python-format +msgid "Partner updated via the opendatasoft.com API." +msgstr "Socio actualizado a través de la API de opendatasoft.com." + +#. module: l10n_fr_siret_lookup +#: model:ir.model.fields,field_description:l10n_fr_siret_lookup.field_fr_siret_lookup__line_ids +msgid "Results" +msgstr "Resultados" + +#. module: l10n_fr_siret_lookup +#: model:ir.model.fields,field_description:l10n_fr_siret_lookup.field_fr_siret_lookup_line__siren +msgid "SIREN" +msgstr "SIREN" + +#. module: l10n_fr_siret_lookup +#: model:ir.actions.act_window,name:l10n_fr_siret_lookup.fr_siret_lookup_partner_action +msgid "SIREN Lookup" +msgstr "Búsqueda SIREN" + +#. module: l10n_fr_siret_lookup +#: model_terms:ir.ui.view,arch_db:l10n_fr_siret_lookup.fr_siret_lookup_form +msgid "SIREN Lookup via opendatasoft.com" +msgstr "Búsqueda SIREN vía opendatasoft.com" + +#. module: l10n_fr_siret_lookup +#: model:ir.actions.act_window,name:l10n_fr_siret_lookup.fr_siret_lookup_action +msgid "SIREN lookup via opendatasoft.com" +msgstr "Búsqueda SIREN vía opendatasoft.com" + +#. module: l10n_fr_siret_lookup +#: model:ir.model.fields,field_description:l10n_fr_siret_lookup.field_fr_siret_lookup_line__siret +msgid "SIRET" +msgstr "SIRET" + +#. module: l10n_fr_siret_lookup +#: model_terms:ir.ui.view,arch_db:l10n_fr_siret_lookup.fr_siret_lookup_form +msgid "Search Results" +msgstr "Resultados de búsqueda" + +#. module: l10n_fr_siret_lookup +#: model_terms:ir.ui.view,arch_db:l10n_fr_siret_lookup.fr_siret_lookup_form +#: model_terms:ir.ui.view,arch_db:l10n_fr_siret_lookup.fr_siret_lookup_line_form +msgid "Select" +msgstr "Seleccionar" + +#. module: l10n_fr_siret_lookup +#: model:ir.model.fields,field_description:l10n_fr_siret_lookup.field_fr_siret_lookup_line__street +msgid "Street" +msgstr "Calle" + +#. module: l10n_fr_siret_lookup +#. odoo-python +#: code:addons/l10n_fr_siret_lookup/models/res_partner.py:0 +#, python-format +msgid "The webservice data.opendatasoft.com returned an HTTP error code %s." +msgstr "" +"El servicio web data.opendatasoft.com ha devuelto un código de error HTTP %s." + +#. module: l10n_fr_siret_lookup +#: model:ir.model.fields,field_description:l10n_fr_siret_lookup.field_fr_siret_lookup_line__wizard_id +msgid "Wizard" +msgstr "Asistente" + +#. module: l10n_fr_siret_lookup +#: model:ir.model.fields,field_description:l10n_fr_siret_lookup.field_fr_siret_lookup_line__zip +msgid "Zip" +msgstr "CP" diff --git a/l10n_fr_siret_lookup/i18n/fr.po b/l10n_fr_siret_lookup/i18n/fr.po new file mode 100644 index 000000000..5699c211f --- /dev/null +++ b/l10n_fr_siret_lookup/i18n/fr.po @@ -0,0 +1,284 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * l10n_fr_siren_lookup +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 10.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2018-12-04 14:28+0000\n" +"PO-Revision-Date: 2022-09-15 22:07+0000\n" +"Last-Translator: Claude R Perrin \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.3.2\n" + +#. module: l10n_fr_siret_lookup +#: model:ir.model.fields,field_description:l10n_fr_siret_lookup.field_fr_siret_lookup_line__staff +msgid "# Staff" +msgstr "Nb Employés" + +#. module: l10n_fr_siret_lookup +#: model:ir.model.fields,field_description:l10n_fr_siret_lookup.field_fr_siret_lookup_line__ape +msgid "APE Code" +msgstr "Code NAF" + +#. module: l10n_fr_siret_lookup +#: model:ir.model.fields,field_description:l10n_fr_siret_lookup.field_fr_siret_lookup_line__ape_label +msgid "APE Label" +msgstr "Libellé NAF" + +#. module: l10n_fr_siret_lookup +#: model_terms:ir.ui.view,arch_db:l10n_fr_siret_lookup.fr_siret_lookup_line_form +msgid "Address" +msgstr "Adresse" + +#. module: l10n_fr_siret_lookup +#: model:ir.model.fields,field_description:l10n_fr_siret_lookup.field_fr_siret_lookup_line__category +msgid "Category" +msgstr "Catégorie" + +#. module: l10n_fr_siret_lookup +#: model:ir.model.fields,field_description:l10n_fr_siret_lookup.field_fr_siret_lookup_line__city +msgid "City" +msgstr "Ville" + +#. module: l10n_fr_siret_lookup +#: model_terms:ir.ui.view,arch_db:l10n_fr_siret_lookup.fr_siret_lookup_form +msgid "Close" +msgstr "Fermer" + +#. module: l10n_fr_siret_lookup +#: model_terms:ir.ui.view,arch_db:l10n_fr_siret_lookup.fr_siret_lookup_line_form +msgid "Company" +msgstr "Société" + +#. module: l10n_fr_siret_lookup +#: model_terms:ir.ui.view,arch_db:l10n_fr_siret_lookup.fr_siret_lookup_line_form +msgid "Company Infos" +msgstr "Infos Entreprise" + +#. module: l10n_fr_siret_lookup +#: model:ir.model,name:l10n_fr_siret_lookup.model_fr_siret_lookup_line +msgid "Company Selection" +msgstr "Sélection Entreprise" + +#. module: l10n_fr_siret_lookup +#: model_terms:ir.ui.view,arch_db:l10n_fr_siret_lookup.fr_siret_lookup_form +#: model_terms:ir.ui.view,arch_db:l10n_fr_siret_lookup.fr_siret_lookup_line_form +msgid "Confirm selected company ?" +msgstr "Valider l'entreprise sélectionnée ?" + +#. module: l10n_fr_siret_lookup +#: model:ir.model,name:l10n_fr_siret_lookup.model_res_partner +msgid "Contact" +msgstr "Contact" + +#. module: l10n_fr_siret_lookup +#: model:ir.model.fields,field_description:l10n_fr_siret_lookup.field_fr_siret_lookup_line__country_id +msgid "Country" +msgstr "Pays" + +#. module: l10n_fr_siret_lookup +#: model:ir.model.fields,field_description:l10n_fr_siret_lookup.field_fr_siret_lookup__create_uid +#: model:ir.model.fields,field_description:l10n_fr_siret_lookup.field_fr_siret_lookup_line__create_uid +msgid "Created by" +msgstr "Créé par" + +#. module: l10n_fr_siret_lookup +#: model:ir.model.fields,field_description:l10n_fr_siret_lookup.field_fr_siret_lookup__create_date +#: model:ir.model.fields,field_description:l10n_fr_siret_lookup.field_fr_siret_lookup_line__create_date +msgid "Created on" +msgstr "Créé le" + +#. module: l10n_fr_siret_lookup +#: model:ir.model.fields,field_description:l10n_fr_siret_lookup.field_fr_siret_lookup_line__creation_date +msgid "Creation Date" +msgstr "" + +#. module: l10n_fr_siret_lookup +#: model:ir.model.fields,field_description:l10n_fr_siret_lookup.field_fr_siret_lookup__display_name +#: model:ir.model.fields,field_description:l10n_fr_siret_lookup.field_fr_siret_lookup_line__display_name +msgid "Display Name" +msgstr "Nom affiché" + +#. module: l10n_fr_siret_lookup +#. odoo-python +#: code:addons/l10n_fr_siret_lookup/models/res_partner.py:0 +#, python-format +msgid "" +"Failed to query VIES.\n" +"Technical error: %s." +msgstr "" +"Erreur pendant l'interrogation du VIES.\n" +"Erreur technique : %s." + +#. module: l10n_fr_siret_lookup +#. odoo-python +#: code:addons/l10n_fr_siret_lookup/models/res_partner.py:0 +#, python-format +msgid "" +"Failure in the request on data.opendatasoft.com to create or update partner " +"from SIREN or SIRET. Technical error: %s." +msgstr "" +"Échec de la requête à l'API data.opendatasoft.com pour créer ou mettre à " +"jour le contact à partir du SIREN ou SIRET. Erreur technique : %s." + +#. module: l10n_fr_siret_lookup +#: model:ir.model,name:l10n_fr_siret_lookup.model_fr_siret_lookup +msgid "Get values from companies" +msgstr "Obtenir les informations sur les entreprises" + +#. module: l10n_fr_siret_lookup +#: model:ir.model.fields,field_description:l10n_fr_siret_lookup.field_fr_siret_lookup__id +#: model:ir.model.fields,field_description:l10n_fr_siret_lookup.field_fr_siret_lookup_line__id +msgid "ID" +msgstr "ID" + +#. module: l10n_fr_siret_lookup +#: model:ir.model.fields,field_description:l10n_fr_siret_lookup.field_fr_siret_lookup____last_update +#: model:ir.model.fields,field_description:l10n_fr_siret_lookup.field_fr_siret_lookup_line____last_update +msgid "Last Modified on" +msgstr "Dernière Modification le" + +#. module: l10n_fr_siret_lookup +#: model:ir.model.fields,field_description:l10n_fr_siret_lookup.field_fr_siret_lookup__write_uid +#: model:ir.model.fields,field_description:l10n_fr_siret_lookup.field_fr_siret_lookup_line__write_uid +msgid "Last Updated by" +msgstr "Dernière mise à jour par" + +#. module: l10n_fr_siret_lookup +#: model:ir.model.fields,field_description:l10n_fr_siret_lookup.field_fr_siret_lookup__write_date +#: model:ir.model.fields,field_description:l10n_fr_siret_lookup.field_fr_siret_lookup_line__write_date +msgid "Last Updated on" +msgstr "Dernière mise à jour le" + +#. module: l10n_fr_siret_lookup +#: model_terms:ir.ui.view,arch_db:l10n_fr_siret_lookup.fr_siret_lookup_line_form +msgid "Legal Infos" +msgstr "Infos Légales" + +#. module: l10n_fr_siret_lookup +#: model:ir.model.fields,field_description:l10n_fr_siret_lookup.field_fr_siret_lookup_line__legal_type +msgid "Legal Type" +msgstr "Forme Juridique" + +#. module: l10n_fr_siret_lookup +#: model_terms:ir.ui.view,arch_db:l10n_fr_siret_lookup.fr_siret_lookup_form +msgid "Lookup" +msgstr "Recherche" + +#. module: l10n_fr_siret_lookup +#: model:ir.model.fields,field_description:l10n_fr_siret_lookup.field_fr_siret_lookup_line__name +msgid "Name" +msgstr "Nom" + +#. module: l10n_fr_siret_lookup +#: model:ir.model.fields,field_description:l10n_fr_siret_lookup.field_fr_siret_lookup__name +msgid "Name to Search" +msgstr "Nom à rechercher" + +#. module: l10n_fr_siret_lookup +#: model:ir.model.fields,field_description:l10n_fr_siret_lookup.field_fr_siret_lookup__partner_id +msgid "Partner" +msgstr "Partenaire" + +#. module: l10n_fr_siret_lookup +#. odoo-python +#: code:addons/l10n_fr_siret_lookup/wizard/fr_siret_lookup.py:0 +#, python-format +msgid "Partner '%s' is not a company. This action is not relevant." +msgstr "" +"Le contact '%s' n'est pas une société. Cette action n'est pas applicable." + +#. module: l10n_fr_siret_lookup +#. odoo-python +#: code:addons/l10n_fr_siret_lookup/wizard/fr_siret_lookup.py:0 +#, python-format +msgid "Partner updated via the opendatasoft.com API." +msgstr "Contact mis à jour à partir de l'API opendatasoft.com." + +#. module: l10n_fr_siret_lookup +#: model:ir.model.fields,field_description:l10n_fr_siret_lookup.field_fr_siret_lookup__line_ids +msgid "Results" +msgstr "Résultats" + +#. module: l10n_fr_siret_lookup +#: model:ir.model.fields,field_description:l10n_fr_siret_lookup.field_fr_siret_lookup_line__siren +msgid "SIREN" +msgstr "SIREN" + +#. module: l10n_fr_siret_lookup +#: model:ir.actions.act_window,name:l10n_fr_siret_lookup.fr_siret_lookup_partner_action +msgid "SIREN Lookup" +msgstr "Recherche via l'API SIRENE" + +#. module: l10n_fr_siret_lookup +#: model_terms:ir.ui.view,arch_db:l10n_fr_siret_lookup.fr_siret_lookup_form +msgid "SIREN Lookup via opendatasoft.com" +msgstr "Recherche SIREN via opendatasoft.com" + +#. module: l10n_fr_siret_lookup +#: model:ir.actions.act_window,name:l10n_fr_siret_lookup.fr_siret_lookup_action +msgid "SIREN lookup via opendatasoft.com" +msgstr "Recherche SIREN via opendatasoft.com" + +#. module: l10n_fr_siret_lookup +#: model:ir.model.fields,field_description:l10n_fr_siret_lookup.field_fr_siret_lookup_line__siret +msgid "SIRET" +msgstr "SIRET" + +#. module: l10n_fr_siret_lookup +#: model_terms:ir.ui.view,arch_db:l10n_fr_siret_lookup.fr_siret_lookup_form +msgid "Search Results" +msgstr "Résultats de recherche" + +#. module: l10n_fr_siret_lookup +#: model_terms:ir.ui.view,arch_db:l10n_fr_siret_lookup.fr_siret_lookup_form +#: model_terms:ir.ui.view,arch_db:l10n_fr_siret_lookup.fr_siret_lookup_line_form +msgid "Select" +msgstr "Sélectionner" + +#. module: l10n_fr_siret_lookup +#: model:ir.model.fields,field_description:l10n_fr_siret_lookup.field_fr_siret_lookup_line__street +msgid "Street" +msgstr "Rue" + +#. module: l10n_fr_siret_lookup +#. odoo-python +#: code:addons/l10n_fr_siret_lookup/models/res_partner.py:0 +#, python-format +msgid "The webservice data.opendatasoft.com returned an HTTP error code %s." +msgstr "L'API data.opendatasoft.com a renvoyé le code d'erreur HTTP %s." + +#. module: l10n_fr_siret_lookup +#: model:ir.model.fields,field_description:l10n_fr_siret_lookup.field_fr_siret_lookup_line__wizard_id +msgid "Wizard" +msgstr "Assistant" + +#. module: l10n_fr_siret_lookup +#: model:ir.model.fields,field_description:l10n_fr_siret_lookup.field_fr_siret_lookup_line__zip +msgid "Zip" +msgstr "Code Postal" + +#~ msgid "Creation date" +#~ msgstr "Date de création" + +#~ msgid "CP" +#~ msgstr "CP" + +#~ msgid "Companies Selection" +#~ msgstr "Sélection d'Entreprises" + +#~ msgid "Informations base Siren" +#~ msgstr "Informations base Siren" + +#~ msgid "Lookup Company" +#~ msgstr "Rechercher une Entreprise" + +#~ msgid "Pre-Fill / Update" +#~ msgstr "Pré-Remplir / Mettre à jour" diff --git a/l10n_fr_siret_lookup/i18n/l10n_fr_siret_lookup.pot b/l10n_fr_siret_lookup/i18n/l10n_fr_siret_lookup.pot new file mode 100644 index 000000000..3f4f76ac0 --- /dev/null +++ b/l10n_fr_siret_lookup/i18n/l10n_fr_siret_lookup.pot @@ -0,0 +1,257 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * l10n_fr_siret_lookup +# +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: l10n_fr_siret_lookup +#: model:ir.model.fields,field_description:l10n_fr_siret_lookup.field_fr_siret_lookup_line__staff +msgid "# Staff" +msgstr "" + +#. module: l10n_fr_siret_lookup +#: model:ir.model.fields,field_description:l10n_fr_siret_lookup.field_fr_siret_lookup_line__ape +msgid "APE Code" +msgstr "" + +#. module: l10n_fr_siret_lookup +#: model:ir.model.fields,field_description:l10n_fr_siret_lookup.field_fr_siret_lookup_line__ape_label +msgid "APE Label" +msgstr "" + +#. module: l10n_fr_siret_lookup +#: model_terms:ir.ui.view,arch_db:l10n_fr_siret_lookup.fr_siret_lookup_line_form +msgid "Address" +msgstr "" + +#. module: l10n_fr_siret_lookup +#: model:ir.model.fields,field_description:l10n_fr_siret_lookup.field_fr_siret_lookup_line__category +msgid "Category" +msgstr "" + +#. module: l10n_fr_siret_lookup +#: model:ir.model.fields,field_description:l10n_fr_siret_lookup.field_fr_siret_lookup_line__city +msgid "City" +msgstr "" + +#. module: l10n_fr_siret_lookup +#: model_terms:ir.ui.view,arch_db:l10n_fr_siret_lookup.fr_siret_lookup_form +msgid "Close" +msgstr "" + +#. module: l10n_fr_siret_lookup +#: model_terms:ir.ui.view,arch_db:l10n_fr_siret_lookup.fr_siret_lookup_line_form +msgid "Company" +msgstr "" + +#. module: l10n_fr_siret_lookup +#: model_terms:ir.ui.view,arch_db:l10n_fr_siret_lookup.fr_siret_lookup_line_form +msgid "Company Infos" +msgstr "" + +#. module: l10n_fr_siret_lookup +#: model:ir.model,name:l10n_fr_siret_lookup.model_fr_siret_lookup_line +msgid "Company Selection" +msgstr "" + +#. module: l10n_fr_siret_lookup +#: model_terms:ir.ui.view,arch_db:l10n_fr_siret_lookup.fr_siret_lookup_form +#: model_terms:ir.ui.view,arch_db:l10n_fr_siret_lookup.fr_siret_lookup_line_form +msgid "Confirm selected company ?" +msgstr "" + +#. module: l10n_fr_siret_lookup +#: model:ir.model,name:l10n_fr_siret_lookup.model_res_partner +msgid "Contact" +msgstr "" + +#. module: l10n_fr_siret_lookup +#: model:ir.model.fields,field_description:l10n_fr_siret_lookup.field_fr_siret_lookup_line__country_id +msgid "Country" +msgstr "" + +#. module: l10n_fr_siret_lookup +#: model:ir.model.fields,field_description:l10n_fr_siret_lookup.field_fr_siret_lookup__create_uid +#: model:ir.model.fields,field_description:l10n_fr_siret_lookup.field_fr_siret_lookup_line__create_uid +msgid "Created by" +msgstr "" + +#. module: l10n_fr_siret_lookup +#: model:ir.model.fields,field_description:l10n_fr_siret_lookup.field_fr_siret_lookup__create_date +#: model:ir.model.fields,field_description:l10n_fr_siret_lookup.field_fr_siret_lookup_line__create_date +msgid "Created on" +msgstr "" + +#. module: l10n_fr_siret_lookup +#: model:ir.model.fields,field_description:l10n_fr_siret_lookup.field_fr_siret_lookup_line__creation_date +msgid "Creation Date" +msgstr "" + +#. module: l10n_fr_siret_lookup +#: model:ir.model.fields,field_description:l10n_fr_siret_lookup.field_fr_siret_lookup__display_name +#: model:ir.model.fields,field_description:l10n_fr_siret_lookup.field_fr_siret_lookup_line__display_name +msgid "Display Name" +msgstr "" + +#. module: l10n_fr_siret_lookup +#. odoo-python +#: code:addons/l10n_fr_siret_lookup/models/res_partner.py:0 +#, python-format +msgid "" +"Failed to query VIES.\n" +"Technical error: %s." +msgstr "" + +#. module: l10n_fr_siret_lookup +#. odoo-python +#: code:addons/l10n_fr_siret_lookup/models/res_partner.py:0 +#, python-format +msgid "" +"Failure in the request on data.opendatasoft.com to create or update partner " +"from SIREN or SIRET. Technical error: %s." +msgstr "" + +#. module: l10n_fr_siret_lookup +#: model:ir.model,name:l10n_fr_siret_lookup.model_fr_siret_lookup +msgid "Get values from companies" +msgstr "" + +#. module: l10n_fr_siret_lookup +#: model:ir.model.fields,field_description:l10n_fr_siret_lookup.field_fr_siret_lookup__id +#: model:ir.model.fields,field_description:l10n_fr_siret_lookup.field_fr_siret_lookup_line__id +msgid "ID" +msgstr "" + +#. module: l10n_fr_siret_lookup +#: model:ir.model.fields,field_description:l10n_fr_siret_lookup.field_fr_siret_lookup____last_update +#: model:ir.model.fields,field_description:l10n_fr_siret_lookup.field_fr_siret_lookup_line____last_update +msgid "Last Modified on" +msgstr "" + +#. module: l10n_fr_siret_lookup +#: model:ir.model.fields,field_description:l10n_fr_siret_lookup.field_fr_siret_lookup__write_uid +#: model:ir.model.fields,field_description:l10n_fr_siret_lookup.field_fr_siret_lookup_line__write_uid +msgid "Last Updated by" +msgstr "" + +#. module: l10n_fr_siret_lookup +#: model:ir.model.fields,field_description:l10n_fr_siret_lookup.field_fr_siret_lookup__write_date +#: model:ir.model.fields,field_description:l10n_fr_siret_lookup.field_fr_siret_lookup_line__write_date +msgid "Last Updated on" +msgstr "" + +#. module: l10n_fr_siret_lookup +#: model_terms:ir.ui.view,arch_db:l10n_fr_siret_lookup.fr_siret_lookup_line_form +msgid "Legal Infos" +msgstr "" + +#. module: l10n_fr_siret_lookup +#: model:ir.model.fields,field_description:l10n_fr_siret_lookup.field_fr_siret_lookup_line__legal_type +msgid "Legal Type" +msgstr "" + +#. module: l10n_fr_siret_lookup +#: model_terms:ir.ui.view,arch_db:l10n_fr_siret_lookup.fr_siret_lookup_form +msgid "Lookup" +msgstr "" + +#. module: l10n_fr_siret_lookup +#: model:ir.model.fields,field_description:l10n_fr_siret_lookup.field_fr_siret_lookup_line__name +msgid "Name" +msgstr "" + +#. module: l10n_fr_siret_lookup +#: model:ir.model.fields,field_description:l10n_fr_siret_lookup.field_fr_siret_lookup__name +msgid "Name to Search" +msgstr "" + +#. module: l10n_fr_siret_lookup +#: model:ir.model.fields,field_description:l10n_fr_siret_lookup.field_fr_siret_lookup__partner_id +msgid "Partner" +msgstr "" + +#. module: l10n_fr_siret_lookup +#. odoo-python +#: code:addons/l10n_fr_siret_lookup/wizard/fr_siret_lookup.py:0 +#, python-format +msgid "Partner '%s' is not a company. This action is not relevant." +msgstr "" + +#. module: l10n_fr_siret_lookup +#. odoo-python +#: code:addons/l10n_fr_siret_lookup/wizard/fr_siret_lookup.py:0 +#, python-format +msgid "Partner updated via the opendatasoft.com API." +msgstr "" + +#. module: l10n_fr_siret_lookup +#: model:ir.model.fields,field_description:l10n_fr_siret_lookup.field_fr_siret_lookup__line_ids +msgid "Results" +msgstr "" + +#. module: l10n_fr_siret_lookup +#: model:ir.model.fields,field_description:l10n_fr_siret_lookup.field_fr_siret_lookup_line__siren +msgid "SIREN" +msgstr "" + +#. module: l10n_fr_siret_lookup +#: model:ir.actions.act_window,name:l10n_fr_siret_lookup.fr_siret_lookup_partner_action +msgid "SIREN Lookup" +msgstr "" + +#. module: l10n_fr_siret_lookup +#: model_terms:ir.ui.view,arch_db:l10n_fr_siret_lookup.fr_siret_lookup_form +msgid "SIREN Lookup via opendatasoft.com" +msgstr "" + +#. module: l10n_fr_siret_lookup +#: model:ir.actions.act_window,name:l10n_fr_siret_lookup.fr_siret_lookup_action +msgid "SIREN lookup via opendatasoft.com" +msgstr "" + +#. module: l10n_fr_siret_lookup +#: model:ir.model.fields,field_description:l10n_fr_siret_lookup.field_fr_siret_lookup_line__siret +msgid "SIRET" +msgstr "" + +#. module: l10n_fr_siret_lookup +#: model_terms:ir.ui.view,arch_db:l10n_fr_siret_lookup.fr_siret_lookup_form +msgid "Search Results" +msgstr "" + +#. module: l10n_fr_siret_lookup +#: model_terms:ir.ui.view,arch_db:l10n_fr_siret_lookup.fr_siret_lookup_form +#: model_terms:ir.ui.view,arch_db:l10n_fr_siret_lookup.fr_siret_lookup_line_form +msgid "Select" +msgstr "" + +#. module: l10n_fr_siret_lookup +#: model:ir.model.fields,field_description:l10n_fr_siret_lookup.field_fr_siret_lookup_line__street +msgid "Street" +msgstr "" + +#. module: l10n_fr_siret_lookup +#. odoo-python +#: code:addons/l10n_fr_siret_lookup/models/res_partner.py:0 +#, python-format +msgid "The webservice data.opendatasoft.com returned an HTTP error code %s." +msgstr "" + +#. module: l10n_fr_siret_lookup +#: model:ir.model.fields,field_description:l10n_fr_siret_lookup.field_fr_siret_lookup_line__wizard_id +msgid "Wizard" +msgstr "" + +#. module: l10n_fr_siret_lookup +#: model:ir.model.fields,field_description:l10n_fr_siret_lookup.field_fr_siret_lookup_line__zip +msgid "Zip" +msgstr "" diff --git a/l10n_fr_siret_lookup/models/__init__.py b/l10n_fr_siret_lookup/models/__init__.py new file mode 100644 index 000000000..91fed54d4 --- /dev/null +++ b/l10n_fr_siret_lookup/models/__init__.py @@ -0,0 +1 @@ +from . import res_partner diff --git a/l10n_fr_siret_lookup/models/res_partner.py b/l10n_fr_siret_lookup/models/res_partner.py new file mode 100644 index 000000000..704cf0be2 --- /dev/null +++ b/l10n_fr_siret_lookup/models/res_partner.py @@ -0,0 +1,314 @@ +# Copyright 2018-2022 Le Filament () +# Copyright 2021-2022 Akretion France (http://www.akretion.com/) +# @author: Alexis de Lattre +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +import logging + +import requests + +from odoo import _, api, models +from odoo.exceptions import UserError + +logger = logging.getLogger(__name__) +try: + from stdnum.eu.vat import check_vies + from stdnum.fr.siren import is_valid as siren_is_valid + from stdnum.fr.siren import to_tva as siren_to_vat + from stdnum.fr.siret import is_valid as siret_is_valid +except ImportError: + logger.debug("Cannot import stdnum") + +TIMEOUT = 5 + + +class ResPartner(models.Model): + _inherit = "res.partner" + + @api.model + def _opendatasoft_fields_list(self): + return [ + "datefermetureunitelegale", + "datefermetureetablissement", + "denominationunitelegale", + "l1_adressage_unitelegale", + "adresseetablissement", + "codepostaletablissement", + "libellecommuneetablissement", + "siren", + "nic", + "codedepartementetablissement", + # for the wizard + "siret", + "categorieentreprise", + "datecreationunitelegale", + "activiteprincipaleunitelegale", + "divisionunitelegale", + "naturejuridiqueunitelegale", + "trancheeffectifsunitelegale", + ] + + @api.model + def _opendatasoft_get_raw_data( + self, query, raise_if_fail=False, exclude_dead=False, rows=10 + ): + assert isinstance(query, str) + assert isinstance(rows, int) and rows > 0 + url = "https://data.opendatasoft.com/api/records/1.0/search/" + params = { + "dataset": "economicref-france-sirene-v3@public", + "q": query, + "rows": rows, + "fields": ",".join(self._opendatasoft_fields_list()), + } + # It seems that datefermetureetablissement and datefermetureunitelegale + # often have a value for a SIRET that is still open + # For example, SIRET 55208131766522 (siège social d'EDF) + # has datefermetureetablissement=2009-02-22 + # and datefermetureunitelegale=2018-12-01 !!! + # So I now set exclude_dead=False by default + if exclude_dead: + params["q"] += ( + " AND #null(datefermetureetablissement) AND #null(datefermetureunitelegale)" # noqa: E501 + ) + try: + logger.info("Sending query to https://data.opendatasoft.com/api") + logger.debug("url=%s params=%s", url, params) + res = requests.get(url, params=params, timeout=TIMEOUT) + if res.status_code in (200, 201): + res_json = res.json() + # from pprint import pprint + # pprint(res_json) + return res_json + else: + logger.warning( + "HTTP error %s returned by GET on data.opendatasoft.com/api", + res.status_code, + ) + if raise_if_fail: + raise UserError( + _( + "The webservice data.opendatasoft.com " + "returned an HTTP error code %s." + ) + % res.status_code + ) + except Exception as e: + logger.warning("Failure in the GET request on data.opendatasoft.com: %s", e) + if raise_if_fail: + raise UserError( + _( + "Failure in the request on data.opendatasoft.com " + "to create or update partner from SIREN or SIRET. " + "Technical error: %s." + ) + % e + ) from e + return False + + @api.model + def _opendatasoft_parse_record( + self, raw_record, exclude_dead=False, vat_vies_query=True + ): + res = False + if raw_record and isinstance(raw_record, dict): + if exclude_dead and raw_record.get("datefermetureunitelegale"): + return res + if exclude_dead and raw_record.get("datefermetureetablissement"): + return res + res = { + "name": raw_record.get("denominationunitelegale") + or raw_record.get("l1_adressage_unitelegale"), + "street": raw_record.get("adresseetablissement"), + "city": raw_record.get("libellecommuneetablissement"), + "siren": raw_record.get("siren") and str(raw_record["siren"]) or False, + "nic": raw_record.get("nic"), + } + # In feb 2022, they changed codepostaletablissement and + # codedepartementetablissement from string to integer + # So I now want to support both, it case they change it back ! + if raw_record.get("codepostaletablissement"): + res["zip"] = raw_record["codepostaletablissement"] + if isinstance(res["zip"], int): + res["zip"] = str(res["zip"]) + res["zip"] = res["zip"].zfill(5) + + # I don't use "codedepartementetablissement" to compute + # the country, because it is not always set, in particular + # for partners in Corsica + if res.get("zip"): + res["country_id"] = self._opendatasoft_compute_country(res["zip"]) + # set lang to French if installed + fr_lang = self.env["res.lang"].search([("code", "=", "fr_FR")]) + if fr_lang: + res["lang"] = "fr_FR" + if res.get("siren") and vat_vies_query: + vat = self._siren2vat_vies(res["siren"]) + if vat is not None: + res["vat"] = vat + return res + + @api.model + def _opendatasoft_compute_country(self, zipcode): + domtom2xmlid = { + "971": "gp", + "972": "mq", + "973": "gf", + "974": "re", + "975": "pm", # Saint Pierre and Miquelon + "976": "yt", # Mayotte + "977": "bl", # Saint-Barthélemy + "978": "mf", # Saint-Martin + "986": "wf", # Wallis-et-Futuna + "987": "pf", # Polynésie française + "988": "nc", # Nouvelle calédonie + } + country_id = self.env.ref("base.fr").id + if ( + isinstance(zipcode, str) + and len(zipcode) == 5 + and zipcode[:3] in domtom2xmlid + ): + country_xmlid = f"base.{domtom2xmlid[zipcode[:3]]}" + country_id = self.env.ref(country_xmlid).id + return country_id + + @api.model + def _siren2vat_vies(self, siren, raise_if_fail=False): + vat = f"FR{siren_to_vat(siren)}" + logger.info("VIES check of VAT %s", vat) + vies_res = False + res = False + try: + vies_res = check_vies(vat, timeout=TIMEOUT) + logger.debug("VIES answer vies_res.valid=%s", vies_res.valid) + except Exception as e: + logger.error("VIES query failed: %s", e) + if raise_if_fail: + raise UserError( + _("Failed to query VIES.\nTechnical error: %s.") % e + ) from e + return None + if vies_res and vies_res.valid: + res = vat + return res + + @api.model + def _opendatasoft_get_first_result( + self, query, raise_if_fail=False, vat_vies_query=True + ): + res_json = self._opendatasoft_get_raw_data(query, raise_if_fail=raise_if_fail) + if res_json and "records" in res_json: + if len(res_json["records"]) > 0: + raw_record = res_json["records"][0].get("fields") + if raw_record: + return self._opendatasoft_parse_record( + raw_record, vat_vies_query=vat_vies_query + ) + else: + logger.warning("The query on opendatasoft.com returned 0 records") + return False + + @api.model + def _opendatasoft_get_from_siren(self, siren, vat_vies_query=True): + if siren and siren_is_valid(siren): + vals = self._opendatasoft_get_first_result( + f"siren:{siren} AND etablissementsiege:oui", + vat_vies_query=vat_vies_query, + ) + if vals and vals.get("siren") == siren: + return vals + return False + + @api.model + def _opendatasoft_get_from_siret(self, siret, vat_vies_query=True): + if siret and siret_is_valid(siret): + vals = self._opendatasoft_get_first_result( + f"siret:{siret}", vat_vies_query=vat_vies_query + ) + if vals and vals.get("siren") and vals.get("nic"): + vals_siret = vals["siren"] + vals["nic"] + if vals_siret == siret: + return vals + return False + + @api.onchange("siren") + def siren_onchange(self): + if ( + self.siren + and siren_is_valid(self.siren) + and not self.name + and self.is_company + and not self.parent_id + ): + if self.nic: + # We only execute the query if the full SIRET is OK + vals = False + if siret_is_valid(self.siren + self.nic): + siret = self.siren + self.nic + vals = self._opendatasoft_get_from_siret(siret) + else: + vals = self._opendatasoft_get_from_siren(self.siren) + if vals: + self.update(vals) + + @api.onchange("siret") + def siret_onchange(self): + if ( + self.siret + and siret_is_valid(self.siret) + and not self.name + and self.is_company + and not self.parent_id + ): + vals = self._opendatasoft_get_from_siret(self.siret) + if vals: + self.update(vals) + + @api.onchange("vat") + def vat_onchange(self): + if ( + self.vat + and not self.name + and not self.siren + and not self.siret + and self.is_company + and not self.parent_id + ): + vat = self.vat.replace(" ", "").upper() + if vat and vat.startswith("FR") and len(vat) == 13: + siren = vat[4:] + if siren_is_valid(siren): + vals = self._opendatasoft_get_from_siren(siren) + if vals: + self.update(vals) + + @api.onchange("name") + def siren_siret_vat_in_name_onchange(self): + if ( + self.name + and self.is_company + and not self.parent_id + and not self.siren + and not self.nic + and not self.siret + and not self.street + and not self.city + and not self.zip + ): + name = self.name.replace(" ", "") + if name: + vals = False + if len(name) == 9 and name.isdigit() and siren_is_valid(name): + vals = self._opendatasoft_get_from_siren(name) + elif len(name) == 14 and name.isdigit() and siret_is_valid(name): + vals = self._opendatasoft_get_from_siret(name) + elif ( + len(name) == 13 + and name[:2] == "FR" + and name[2:].isdigit() + and siren_is_valid(name[4:]) + ): + vals = self._opendatasoft_get_from_siren(name[4:]) + if vals: + self.update(vals) diff --git a/l10n_fr_siret_lookup/pyproject.toml b/l10n_fr_siret_lookup/pyproject.toml new file mode 100644 index 000000000..4231d0ccc --- /dev/null +++ b/l10n_fr_siret_lookup/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["whool"] +build-backend = "whool.buildapi" diff --git a/l10n_fr_siret_lookup/readme/CONTRIBUTORS.md b/l10n_fr_siret_lookup/readme/CONTRIBUTORS.md new file mode 100644 index 000000000..70f0629de --- /dev/null +++ b/l10n_fr_siret_lookup/readme/CONTRIBUTORS.md @@ -0,0 +1,4 @@ +- Benjamin Rivier \ () +- Remi Cazenave \ () +- Alexis de Lattre \<\> +- Frederic Grall \<> diff --git a/l10n_fr_siret_lookup/readme/CREDITS.md b/l10n_fr_siret_lookup/readme/CREDITS.md new file mode 100644 index 000000000..bc221931d --- /dev/null +++ b/l10n_fr_siret_lookup/readme/CREDITS.md @@ -0,0 +1,3 @@ +The development of this module has been financially supported by: + +- Le Filament diff --git a/l10n_fr_siret_lookup/readme/DESCRIPTION.md b/l10n_fr_siret_lookup/readme/DESCRIPTION.md new file mode 100644 index 000000000..d48cb2bda --- /dev/null +++ b/l10n_fr_siret_lookup/readme/DESCRIPTION.md @@ -0,0 +1,27 @@ +This modules updates partner fields via the SIRENE database +\. It uses the dataset +*economicref-france-sirene-v3* of opendatasoft +\. +It computes a theorical VAT number from the SIREN and then checks the +validity of the VAT number on +[VIES](https://ec.europa.eu/taxation_customs/vies/) (if invalid, the VAT +number is discarded). + +The module supports 2 scenarios: + +- update of an existing partner via the menu *Action \> SIREN Lookup*, +- creation of a new partner: start by setting the VAT number field, the + SIREN field or SIRET field and Odoo will set the other fields. For + usability purposes, it also work when you write the VAT number, SIREN + or SIRET in the company name field. + +In the 2 scenarios, it will update the following fields: + +- Company Name +- Street +- Postal Code +- City +- Country +- SIREN and NIC (i.e. SIRET) +- VAT Number +- Language (creation scenario only) diff --git a/l10n_fr_siret_lookup/readme/USAGE.md b/l10n_fr_siret_lookup/readme/USAGE.md new file mode 100644 index 000000000..7ff37f38d --- /dev/null +++ b/l10n_fr_siret_lookup/readme/USAGE.md @@ -0,0 +1,11 @@ +To update an existing parter, go to the partner form view and click on +*Action \> SIREN Lookup*. + +By default, the search field is filled with Company name. To get more +accurate results, you may want to add the City name where the company is +registered. Then click on *Lookup*. + +A list of companies is displayed. You may want to click on one in order to +see corresponding information or directly select company from list +view. Once a company is selected, the partner information is updated and +a message is logged in the chatter. diff --git a/l10n_fr_siret_lookup/security/ir.model.access.csv b/l10n_fr_siret_lookup/security/ir.model.access.csv new file mode 100644 index 000000000..2a47e4486 --- /dev/null +++ b/l10n_fr_siret_lookup/security/ir.model.access.csv @@ -0,0 +1,3 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_fr_siret_lookup,Full access on fr.siret.lookup to partner manager,model_fr_siret_lookup,base.group_partner_manager,1,1,1,1 +access_fr_siret_lookup_line,Full access on fr.siret.lookup.line to partner manager,model_fr_siret_lookup_line,base.group_partner_manager,1,1,1,1 diff --git a/l10n_fr_siret_lookup/static/description/icon.png b/l10n_fr_siret_lookup/static/description/icon.png new file mode 100644 index 000000000..3a0328b51 Binary files /dev/null and b/l10n_fr_siret_lookup/static/description/icon.png differ diff --git a/l10n_fr_siret_lookup/static/description/index.html b/l10n_fr_siret_lookup/static/description/index.html new file mode 100644 index 000000000..cd6426101 --- /dev/null +++ b/l10n_fr_siret_lookup/static/description/index.html @@ -0,0 +1,476 @@ + + + + + +SIRET Lookup + + + +
+

SIRET Lookup

+ + +

Beta License: AGPL-3 OCA/l10n-france Translate me on Weblate Try me on Runboat

+

This modules updates partner fields via the SIRENE database +<https://data.opendatasoft.com>. It uses the dataset +economicref-france-sirene-v3 of opendatasoft +<https://public.opendatasoft.com/explore/dataset/economicref-france-sirene-v3/information/>. +It computes a theorical VAT number from the SIREN and then checks the +validity of the VAT number on +VIES (if invalid, the +VAT number is discarded).

+

The module supports 2 scenarios:

+
    +
  • update of an existing partner via the menu Action > SIREN Lookup,
  • +
  • creation of a new partner: start by setting the VAT number field, the +SIREN field or SIRET field and Odoo will set the other fields. For +usability purposes, it also work when you write the VAT number, SIREN +or SIRET in the company name field.
  • +
+

In the 2 scenarios, it will update the following fields:

+
    +
  • Company Name
  • +
  • Street
  • +
  • Postal Code
  • +
  • City
  • +
  • Country
  • +
  • SIREN and NIC (i.e. SIRET)
  • +
  • VAT Number
  • +
  • Language (creation scenario only)
  • +
+

Table of contents

+ +
+

Usage

+

To update an existing parter, go to the partner form view and click on +Action > SIREN Lookup.

+

By default, the search field is filled with Company name. To get more +accurate results, you may want to add the City name where the company is +registered. Then click on Lookup.

+

A list of company is displayed. You may want to click on one in order to +see corresponding information or directly selecting company from tree +view. Once a company is selected, the partner information is updated and +a message is logged in the chatter.

+
+
+

Bug Tracker

+

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 to smash it by providing a detailed and welcomed +feedback.

+

Do not contact contributors directly about support or help with technical issues.

+
+
+

Credits

+
+

Authors

+
    +
  • Le Filament
  • +
  • Akretion
  • +
+
+
+

Contributors

+ +
+
+

Other credits

+

The development of this module has been financially supported by:

+
    +
  • Le Filament
  • +
+
+
+

Maintainers

+

This module is maintained by the OCA.

+ +Odoo Community Association + +

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 maintainers:

+

remi-filament alexis-via

+

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_siret_lookup/views/res_partner.xml b/l10n_fr_siret_lookup/views/res_partner.xml new file mode 100644 index 000000000..ba1cd8219 --- /dev/null +++ b/l10n_fr_siret_lookup/views/res_partner.xml @@ -0,0 +1,12 @@ + + + + SIREN Lookup + fr.siret.lookup + form + new + + + form + + diff --git a/l10n_fr_siret_lookup/wizard/__init__.py b/l10n_fr_siret_lookup/wizard/__init__.py new file mode 100644 index 000000000..af1ed13a3 --- /dev/null +++ b/l10n_fr_siret_lookup/wizard/__init__.py @@ -0,0 +1 @@ +from . import fr_siret_lookup diff --git a/l10n_fr_siret_lookup/wizard/fr_siret_lookup.py b/l10n_fr_siret_lookup/wizard/fr_siret_lookup.py new file mode 100644 index 000000000..63508aff5 --- /dev/null +++ b/l10n_fr_siret_lookup/wizard/fr_siret_lookup.py @@ -0,0 +1,129 @@ +# Copyright 2018-2022 Le Filament () +# Copyright 2021-2022 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 import _, api, fields, models +from odoo.exceptions import UserError + + +class FrSiretLookup(models.TransientModel): + _name = "fr.siret.lookup" + _description = "Get values from companies" + + name = fields.Char(string="Name to Search", required=True) + line_ids = fields.One2many( + "fr.siret.lookup.line", "wizard_id", string="Results", readonly=True + ) + partner_id = fields.Many2one("res.partner", readonly=True, required=True) + + @api.model + def default_get(self, fields_list): + res = super().default_get(fields_list) + if ( + self.env.context.get("active_id") + and self.env.context.get("active_model") == "res.partner" + ): + partner = self.env["res.partner"].browse(self.env.context["active_id"]) + if not partner.is_company: + raise UserError( + _("Partner '%s' is not a company. This action is not relevant.") + % partner.display_name + ) + res.update( + { + "name": partner.name, + "partner_id": partner.id, + } + ) + return res + + # Action + @api.model + def _prepare_partner_from_data(self, data): + country_id = zipcode = False + zipcode = data.get("codepostaletablissement") + if isinstance(zipcode, int): + zipcode = str(zipcode) + if zipcode: + zipcode = zipcode.zfill(5) + country_id = self.env["res.partner"]._opendatasoft_compute_country(zipcode) + return { + "name": data.get("denominationunitelegale") + or data.get("l1_adressage_unitelegale"), + "street": data.get("adresseetablissement"), + "zip": zipcode, + "city": data.get("libellecommuneetablissement"), + "country_id": country_id, + "siren": data.get("siren") and str(data["siren"]) or False, + "siret": data.get("siret") and str(data["siret"]) or False, + "category": data.get("categorieentreprise"), + "creation_date": data.get("datecreationunitelegale"), + "ape": data.get("activiteprincipaleunitelegale"), + "ape_label": data.get("divisionunitelegale"), + "legal_type": data.get("naturejuridiqueunitelegale"), + "staff": data.get("trancheeffectifsunitelegale", 0), + } + + def get_lines(self): + self.ensure_one() + self.line_ids.unlink() + # Get request + res_json = self.env["res.partner"]._opendatasoft_get_raw_data( + self.name, raise_if_fail=True, rows=30 + ) + # Fill new company lines + companies_vals = [] + for company in res_json["records"]: + res = self._prepare_partner_from_data(company["fields"]) + companies_vals.append((0, 0, res)) + self.line_ids = companies_vals + return { + "context": self.env.context, + "view_mode": "form", + "res_model": self._name, + "res_id": self.id, + "view_id": False, + "type": "ir.actions.act_window", + "target": "new", + } + + +class FrSiretLookupLine(models.TransientModel): + _name = "fr.siret.lookup.line" + _description = "Company Selection" + + wizard_id = fields.Many2one("fr.siret.lookup", string="Wizard", ondelete="cascade") + name = fields.Char() + street = fields.Char() + zip = fields.Char() + city = fields.Char() + country_id = fields.Many2one("res.country", string="Country") + legal_type = fields.Char() + siren = fields.Char("SIREN") + siret = fields.Char("SIRET") + ape = fields.Char("APE Code") + ape_label = fields.Char("APE Label") + creation_date = fields.Date() + staff = fields.Char("# Staff") + category = fields.Char() + + def _prepare_partner_values(self): + self.ensure_one() + vat = self.env["res.partner"]._siren2vat_vies(self.siren, raise_if_fail=True) + vals = { + "name": self.name, + "street": self.street, + "zip": self.zip, + "city": self.city, + "country_id": self.country_id.id or False, + "siret": self.siret, + "vat": vat, + } + return vals + + def update_partner(self): + self.ensure_one() + partner = self.wizard_id.partner_id + partner.write(self._prepare_partner_values()) + partner.message_post(body=_("Partner updated via the opendatasoft.com API.")) diff --git a/l10n_fr_siret_lookup/wizard/fr_siret_lookup_view.xml b/l10n_fr_siret_lookup/wizard/fr_siret_lookup_view.xml new file mode 100644 index 000000000..60cda6e83 --- /dev/null +++ b/l10n_fr_siret_lookup/wizard/fr_siret_lookup_view.xml @@ -0,0 +1,99 @@ + + + + + fr.siret.lookup + +
+ + + +