diff --git a/account_statement_import_online_ponto/README.rst b/account_statement_import_online_ponto/README.rst new file mode 100644 index 000000000..ed94c3447 --- /dev/null +++ b/account_statement_import_online_ponto/README.rst @@ -0,0 +1,130 @@ +=================================== +Online Bank Statements: MyPonto.com +=================================== + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:4761a86432e267dd6dc91976fd25d4ea5ae91d06c8f1bf8a50c24c1916268d8e + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |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%2Fbank--statement--import-lightgray.png?logo=github + :target: https://github.com/OCA/bank-statement-import/tree/17.0/account_statement_import_online_ponto + :alt: OCA/bank-statement-import +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/bank-statement-import-17-0/bank-statement-import-17-0-account_statement_import_online_ponto + :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/bank-statement-import&target_branch=17.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +This module provides online bank statements from MyPonto.com. + +**Table of contents** + +.. contents:: + :local: + +Configuration +============= + +To configure online bank statements provider: + +1. Go to *Invoicing > Configuration > Bank Accounts* +2. Open bank account to configure and edit it +3. Set *Bank Feeds* to *Online* +4. Select *MyPonto.com* as online bank statements provider in *Online + Bank Statements (OCA)* section +5. Save the bank account +6. Click on provider and configure provider-specific settings. + +or, alternatively: + +1. Go to *Invoicing > Overview* +2. Open settings of the corresponding journal account +3. Switch to *Bank Account* tab +4. Set *Bank Feeds* to *Online* +5. Select *MyPonto.com* as online bank statements provider in *Online + Bank Statements (OCA)* section +6. Save the bank account +7. Click on provider and configure provider-specific settings. + +To obtain *Login* and *Key*: + +1. Open `MyPonto.com `__. + +Check also ``account_bank_statement_import_online`` configuration +instructions for more information. + +Usage +===== + +To pull historical bank statements: + +1. Go to *Invoicing > Configuration > Bank Accounts* +2. Select specific bank accounts +3. Launch *Actions > Online Bank Statements Pull Wizard* +4. Configure date interval and click *Pull* + +If historical data is not needed, then just simply wait for the +scheduled activity "Pull Online Bank Statements" to be executed for +getting new transactions. + +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 +------- + +* Florent de Labarre +* Therp BV + +Contributors +------------ + +- Florent de Labarre +- `Tecnativa `__: + + - Pedro M. Baeza + - João Marques + +- `Therp BV `__: + + - Ronald Portier + +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. + +This module is part of the `OCA/bank-statement-import `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/account_statement_import_online_ponto/__init__.py b/account_statement_import_online_ponto/__init__.py new file mode 100644 index 000000000..31660d6a9 --- /dev/null +++ b/account_statement_import_online_ponto/__init__.py @@ -0,0 +1,3 @@ +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from . import models diff --git a/account_statement_import_online_ponto/__manifest__.py b/account_statement_import_online_ponto/__manifest__.py new file mode 100644 index 000000000..ed8f080f7 --- /dev/null +++ b/account_statement_import_online_ponto/__manifest__.py @@ -0,0 +1,17 @@ +# Copyright 2020 Florent de Labarre. +# Copyright 2020 Tecnativa - João Marques. +# Copyright 2022-2023 Therp BV . +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). +{ + "name": "Online Bank Statements: MyPonto.com", + "version": "17.0.1.0.0", + "category": "Account", + "website": "https://github.com/OCA/bank-statement-import", + "author": "Florent de Labarre, Therp BV, Odoo Community Association (OCA)", + "license": "AGPL-3", + "installable": True, + "depends": ["account_statement_import_online"], + "data": [ + "views/online_bank_statement_provider.xml", + ], +} diff --git a/account_statement_import_online_ponto/i18n/account_statement_import_online_ponto.pot b/account_statement_import_online_ponto/i18n/account_statement_import_online_ponto.pot new file mode 100644 index 000000000..6cedfe3c8 --- /dev/null +++ b/account_statement_import_online_ponto/i18n/account_statement_import_online_ponto.pot @@ -0,0 +1,166 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * account_statement_import_online_ponto +# +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: account_statement_import_online_ponto +#. odoo-python +#: code:addons/account_statement_import_online_ponto/models/ponto_interface.py:0 +#, python-format +msgid "%d transactions present in response data" +msgstr "" + +#. module: account_statement_import_online_ponto +#: model:ir.model.fields.selection,name:account_statement_import_online_ponto.selection__online_bank_statement_provider__ponto_date_field__execution_date +msgid "Execution Date" +msgstr "" + +#. module: account_statement_import_online_ponto +#. odoo-python +#: code:addons/account_statement_import_online_ponto/models/ponto_interface.py:0 +#, python-format +msgid "GET request on %(url)s" +msgstr "" + +#. module: account_statement_import_online_ponto +#. odoo-python +#: code:addons/account_statement_import_online_ponto/models/ponto_interface.py:0 +#, python-format +msgid "GET request to %(url)s with headers %(headers)s and params %(params)s" +msgstr "" + +#. module: account_statement_import_online_ponto +#. odoo-python +#: code:addons/account_statement_import_online_ponto/models/ponto_interface.py:0 +#, python-format +msgid "HTTP answer code %(response_code)s from Ponto" +msgstr "" + +#. module: account_statement_import_online_ponto +#: model:ir.model,name:account_statement_import_online_ponto.model_ponto_interface +msgid "Interface to all interactions with Ponto API" +msgstr "" + +#. module: account_statement_import_online_ponto +#: model_terms:ir.ui.view,arch_db:account_statement_import_online_ponto.online_bank_statement_provider_form +msgid "Login" +msgstr "" + +#. module: account_statement_import_online_ponto +#. odoo-python +#: code:addons/account_statement_import_online_ponto/models/online_bank_statement_provider_ponto.py:0 +#, python-format +msgid "No lines were retrieved from Ponto" +msgstr "" + +#. module: account_statement_import_online_ponto +#. odoo-python +#: code:addons/account_statement_import_online_ponto/models/ponto_interface.py:0 +#, python-format +msgid "No transactions where found in data %(data)s" +msgstr "" + +#. module: account_statement_import_online_ponto +#: model:ir.model,name:account_statement_import_online_ponto.model_online_bank_statement_provider +msgid "Online Bank Statement Provider" +msgstr "" + +#. module: account_statement_import_online_ponto +#. odoo-python +#: code:addons/account_statement_import_online_ponto/models/ponto_interface.py:0 +#, python-format +msgid "POST request on %(url)s" +msgstr "" + +#. module: account_statement_import_online_ponto +#. odoo-python +#: code:addons/account_statement_import_online_ponto/models/ponto_interface.py:0 +#, python-format +msgid "Please fill login and key." +msgstr "" + +#. module: account_statement_import_online_ponto +#. odoo-python +#: code:addons/account_statement_import_online_ponto/models/ponto_interface.py:0 +#, python-format +msgid "Ponto : no token" +msgstr "" + +#. module: account_statement_import_online_ponto +#. odoo-python +#: code:addons/account_statement_import_online_ponto/models/ponto_interface.py:0 +#, python-format +msgid "Ponto : wrong configuration, account {account} not found in {data}" +msgstr "" + +#. module: account_statement_import_online_ponto +#: model_terms:ir.ui.view,arch_db:account_statement_import_online_ponto.online_bank_statement_provider_form +msgid "Ponto Config" +msgstr "" + +#. module: account_statement_import_online_ponto +#: model:ir.model.fields,field_description:account_statement_import_online_ponto.field_online_bank_statement_provider__ponto_date_field +msgid "Ponto Date Field" +msgstr "" + +#. module: account_statement_import_online_ponto +#: model:ir.model.fields,field_description:account_statement_import_online_ponto.field_online_bank_statement_provider__ponto_last_identifier +msgid "Ponto Last Identifier" +msgstr "" + +#. module: account_statement_import_online_ponto +#. odoo-python +#: code:addons/account_statement_import_online_ponto/models/online_bank_statement_provider_ponto.py:0 +#, python-format +msgid "Ponto obtain all new statement data for journal %s" +msgstr "" + +#. module: account_statement_import_online_ponto +#. odoo-python +#: code:addons/account_statement_import_online_ponto/models/online_bank_statement_provider_ponto.py:0 +#, python-format +msgid "" +"Ponto obtain statement data for journal %(journal)s from %(date_since)s to " +"%(date_until)s" +msgstr "" + +#. module: account_statement_import_online_ponto +#: model_terms:ir.ui.view,arch_db:account_statement_import_online_ponto.online_bank_statement_provider_form +msgid "Secret Key" +msgstr "" + +#. module: account_statement_import_online_ponto +#: model:ir.model.fields,help:account_statement_import_online_ponto.field_online_bank_statement_provider__ponto_date_field +msgid "" +"Select the Ponto date field that will be used for the Odoo bank statement " +"line date." +msgstr "" + +#. module: account_statement_import_online_ponto +#. odoo-python +#: code:addons/account_statement_import_online_ponto/models/ponto_interface.py:0 +#, python-format +msgid "Server returned status code {response_code}: {response_text}" +msgstr "" + +#. module: account_statement_import_online_ponto +#. odoo-python +#: code:addons/account_statement_import_online_ponto/tests/test_account_statement_import_online_ponto.py:0 +#, python-format +msgid "Statement contains transactions: %s" +msgstr "" + +#. module: account_statement_import_online_ponto +#: model:ir.model.fields.selection,name:account_statement_import_online_ponto.selection__online_bank_statement_provider__ponto_date_field__value_date +msgid "Value Date" +msgstr "" diff --git a/account_statement_import_online_ponto/i18n/ca.po b/account_statement_import_online_ponto/i18n/ca.po new file mode 100644 index 000000000..c61f45ec8 --- /dev/null +++ b/account_statement_import_online_ponto/i18n/ca.po @@ -0,0 +1,126 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * account_statement_import_online_ponto +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 14.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2022-01-26 18:52+0000\n" +"Last-Translator: Jaume Planas \n" +"Language-Team: none\n" +"Language: ca\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: account_statement_import_online_ponto +#: code:addons/account_statement_import_online_ponto/models/online_bank_statement_provider_ponto.py:0 +#: code:addons/account_statement_import_online_ponto/models/online_bank_statement_provider_ponto.py:0 +#, python-format +msgid "" +"%s \n" +"\n" +" %s" +msgstr "" +"%s \n" +"\n" +" %s" + +#. module: account_statement_import_online_ponto +#: model:ir.model.fields,field_description:account_statement_import_online_ponto.field_online_bank_statement_provider__display_name +msgid "Display Name" +msgstr "Nom" + +#. module: account_statement_import_online_ponto +#: code:addons/account_statement_import_online_ponto/models/online_bank_statement_provider_ponto.py:0 +#, python-format +msgid "" +"Error during Create Synchronisation %s \n" +"\n" +" %s" +msgstr "" +"Error al crear sincronització %s \n" +"\n" +" %s" + +#. module: account_statement_import_online_ponto +#: code:addons/account_statement_import_online_ponto/models/online_bank_statement_provider_ponto.py:0 +#, python-format +msgid "" +"Error during get transaction.\n" +"\n" +"%s \n" +"\n" +" %s" +msgstr "" +"Error durant la transacció GET.\n" +"\n" +"%s \n" +"\n" +" %s" + +#. module: account_statement_import_online_ponto +#: model:ir.model.fields,field_description:account_statement_import_online_ponto.field_online_bank_statement_provider__id +msgid "ID" +msgstr "ID" + +#. module: account_statement_import_online_ponto +#: model:ir.model.fields,field_description:account_statement_import_online_ponto.field_online_bank_statement_provider____last_update +msgid "Last Modified on" +msgstr "Última modificació el" + +#. module: account_statement_import_online_ponto +#: model_terms:ir.ui.view,arch_db:account_statement_import_online_ponto.online_bank_statement_provider_form +msgid "Login" +msgstr "Inicia sessió" + +#. module: account_statement_import_online_ponto +#: model:ir.model,name:account_statement_import_online_ponto.model_online_bank_statement_provider +msgid "Online Bank Statement Provider" +msgstr "Proveïdor en línia d'extractes bancaris" + +#. module: account_statement_import_online_ponto +#: code:addons/account_statement_import_online_ponto/models/online_bank_statement_provider_ponto.py:0 +#, python-format +msgid "Please fill login and key." +msgstr "Ompliu l'inici de sessió i la clau." + +#. module: account_statement_import_online_ponto +#: code:addons/account_statement_import_online_ponto/models/online_bank_statement_provider_ponto.py:0 +#, python-format +msgid "Ponto : no token" +msgstr "Ponto: cap token" + +#. module: account_statement_import_online_ponto +#: code:addons/account_statement_import_online_ponto/models/online_bank_statement_provider_ponto.py:0 +#, python-format +msgid "Ponto : wrong configuration, unknow account %s" +msgstr "Ponto: configuració errònia, compte %s desconegut" + +#. module: account_statement_import_online_ponto +#: model:ir.model.fields,field_description:account_statement_import_online_ponto.field_online_bank_statement_provider__ponto_last_identifier +msgid "Ponto Last Identifier" +msgstr "Ponto Últim identificador" + +#. module: account_statement_import_online_ponto +#: model:ir.model.fields,field_description:account_statement_import_online_ponto.field_online_bank_statement_provider__ponto_token +msgid "Ponto Token" +msgstr "Token Ponto" + +#. module: account_statement_import_online_ponto +#: model:ir.model.fields,field_description:account_statement_import_online_ponto.field_online_bank_statement_provider__ponto_token_expiration +msgid "Ponto Token Expiration" +msgstr "Caducitat token Ponto" + +#. module: account_statement_import_online_ponto +#: model_terms:ir.ui.view,arch_db:account_statement_import_online_ponto.online_bank_statement_provider_form +msgid "Reset Last identifier." +msgstr "Restabliment últim identificador." + +#. module: account_statement_import_online_ponto +#: model_terms:ir.ui.view,arch_db:account_statement_import_online_ponto.online_bank_statement_provider_form +msgid "Secret Key" +msgstr "Clau secreta" diff --git a/account_statement_import_online_ponto/i18n/es.po b/account_statement_import_online_ponto/i18n/es.po new file mode 100644 index 000000000..d3d667ff7 --- /dev/null +++ b/account_statement_import_online_ponto/i18n/es.po @@ -0,0 +1,175 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * account_statement_import_online_ponto +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 16.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2023-11-01 21:38+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: account_statement_import_online_ponto +#. odoo-python +#: code:addons/account_statement_import_online_ponto/models/ponto_interface.py:0 +#, python-format +msgid "%d transactions present in response data" +msgstr "%d transacciones presentes en los datos de respuesta" + +#. module: account_statement_import_online_ponto +#: model:ir.model.fields.selection,name:account_statement_import_online_ponto.selection__online_bank_statement_provider__ponto_date_field__execution_date +msgid "Execution Date" +msgstr "Fecha de Ejecución" + +#. module: account_statement_import_online_ponto +#. odoo-python +#: code:addons/account_statement_import_online_ponto/models/ponto_interface.py:0 +#, python-format +msgid "GET request on %(url)s" +msgstr "Solicitud GET en %(url)s" + +#. module: account_statement_import_online_ponto +#. odoo-python +#: code:addons/account_statement_import_online_ponto/models/ponto_interface.py:0 +#, python-format +msgid "GET request to %(url)s with headers %(headers)s and params %(params)s" +msgstr "" +"Solicitud GET a %(url)s con cabeceras %(headers)s y parámetros %(params)s" + +#. module: account_statement_import_online_ponto +#. odoo-python +#: code:addons/account_statement_import_online_ponto/models/ponto_interface.py:0 +#, python-format +msgid "HTTP answer code %(response_code)s from Ponto" +msgstr "Código de respuesta HTTP %(response_code)s de Ponto" + +#. module: account_statement_import_online_ponto +#: model:ir.model,name:account_statement_import_online_ponto.model_ponto_interface +msgid "Interface to all interactions with Ponto API" +msgstr "Interfaz para todas las interacciones con la API Ponto" + +#. module: account_statement_import_online_ponto +#: model_terms:ir.ui.view,arch_db:account_statement_import_online_ponto.online_bank_statement_provider_form +msgid "Login" +msgstr "Inicio de sesión" + +#. module: account_statement_import_online_ponto +#. odoo-python +#: code:addons/account_statement_import_online_ponto/models/online_bank_statement_provider_ponto.py:0 +#, python-format +msgid "No lines were retrieved from Ponto" +msgstr "No se recuperaron líneas del Ponto" + +#. module: account_statement_import_online_ponto +#. odoo-python +#: code:addons/account_statement_import_online_ponto/models/ponto_interface.py:0 +#, python-format +msgid "No transactions where found in data %(data)s" +msgstr "No se han encontrado transacciones en los datos %(data)s" + +#. module: account_statement_import_online_ponto +#: model:ir.model,name:account_statement_import_online_ponto.model_online_bank_statement_provider +msgid "Online Bank Statement Provider" +msgstr "Proveedor de Extractos Bancarios en Línea" + +#. module: account_statement_import_online_ponto +#. odoo-python +#: code:addons/account_statement_import_online_ponto/models/ponto_interface.py:0 +#, python-format +msgid "POST request on %(url)s" +msgstr "Petición POST en %(url)s" + +#. module: account_statement_import_online_ponto +#. odoo-python +#: code:addons/account_statement_import_online_ponto/models/ponto_interface.py:0 +#, python-format +msgid "Please fill login and key." +msgstr "Por favor, rellene login y clave." + +#. module: account_statement_import_online_ponto +#. odoo-python +#: code:addons/account_statement_import_online_ponto/models/ponto_interface.py:0 +#, python-format +msgid "Ponto : no token" +msgstr "Ponto: sin ficha" + +#. module: account_statement_import_online_ponto +#. odoo-python +#: code:addons/account_statement_import_online_ponto/models/ponto_interface.py:0 +#, python-format +msgid "Ponto : wrong configuration, account {account} not found in {data}" +msgstr "Ponto : configuración errónea, cuenta {account} no encontrada en {data}" + +#. module: account_statement_import_online_ponto +#: model_terms:ir.ui.view,arch_db:account_statement_import_online_ponto.online_bank_statement_provider_form +msgid "Ponto Config" +msgstr "Config Ponto" + +#. module: account_statement_import_online_ponto +#: model:ir.model.fields,field_description:account_statement_import_online_ponto.field_online_bank_statement_provider__ponto_date_field +msgid "Ponto Date Field" +msgstr "Ponto Fecha Campo" + +#. module: account_statement_import_online_ponto +#: model:ir.model.fields,field_description:account_statement_import_online_ponto.field_online_bank_statement_provider__ponto_last_identifier +msgid "Ponto Last Identifier" +msgstr "Ponto Último Identificador" + +#. module: account_statement_import_online_ponto +#. odoo-python +#: code:addons/account_statement_import_online_ponto/models/online_bank_statement_provider_ponto.py:0 +#, python-format +msgid "Ponto obtain all new statement data for journal %s" +msgstr "Ponto obtener todos los datos de los nuevos extractos para el diario %s" + +#. module: account_statement_import_online_ponto +#. odoo-python +#: code:addons/account_statement_import_online_ponto/models/online_bank_statement_provider_ponto.py:0 +#, python-format +msgid "" +"Ponto obtain statement data for journal %(journal)s from %(date_since)s to " +"%(date_until)s" +msgstr "" +"Ponto obtiene los datos del extracto del diario %(journal)s desde " +"%(date_since)s hasta %(date_until)s" + +#. module: account_statement_import_online_ponto +#: model_terms:ir.ui.view,arch_db:account_statement_import_online_ponto.online_bank_statement_provider_form +msgid "Secret Key" +msgstr "Clave Secreta" + +#. module: account_statement_import_online_ponto +#: model:ir.model.fields,help:account_statement_import_online_ponto.field_online_bank_statement_provider__ponto_date_field +msgid "" +"Select the Ponto date field that will be used for the Odoo bank statement " +"line date." +msgstr "" +"Seleccione el campo de fecha Ponto que se utilizará para la fecha de la " +"línea del extracto bancario de Odoo." + +#. module: account_statement_import_online_ponto +#. odoo-python +#: code:addons/account_statement_import_online_ponto/models/ponto_interface.py:0 +#, python-format +msgid "Server returned status code {response_code}: {response_text}" +msgstr "" +"El servidor ha devuelto el código de estado {response_code}: {response_text}" + +#. module: account_statement_import_online_ponto +#. odoo-python +#: code:addons/account_statement_import_online_ponto/tests/test_account_statement_import_online_ponto.py:0 +#, python-format +msgid "Statement contains transactions: %s" +msgstr "El extracto contiene transacciones: %s" + +#. module: account_statement_import_online_ponto +#: model:ir.model.fields.selection,name:account_statement_import_online_ponto.selection__online_bank_statement_provider__ponto_date_field__value_date +msgid "Value Date" +msgstr "Fecha Valor" diff --git a/account_statement_import_online_ponto/i18n/it.po b/account_statement_import_online_ponto/i18n/it.po new file mode 100644 index 000000000..94eb7cba5 --- /dev/null +++ b/account_statement_import_online_ponto/i18n/it.po @@ -0,0 +1,126 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * account_statement_import_online_ponto +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 14.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2024-05-03 16:35+0000\n" +"Last-Translator: mymage \n" +"Language-Team: none\n" +"Language: it\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: account_statement_import_online_ponto +#: code:addons/account_statement_import_online_ponto/models/online_bank_statement_provider_ponto.py:0 +#: code:addons/account_statement_import_online_ponto/models/online_bank_statement_provider_ponto.py:0 +#, python-format +msgid "" +"%s \n" +"\n" +" %s" +msgstr "" +"%s \n" +"\n" +" %s" + +#. module: account_statement_import_online_ponto +#: model:ir.model.fields,field_description:account_statement_import_online_ponto.field_online_bank_statement_provider__display_name +msgid "Display Name" +msgstr "Nome visualizzato" + +#. module: account_statement_import_online_ponto +#: code:addons/account_statement_import_online_ponto/models/online_bank_statement_provider_ponto.py:0 +#, python-format +msgid "" +"Error during Create Synchronisation %s \n" +"\n" +" %s" +msgstr "" +"Errore nella creazione della sincronizzazione %s \n" +"\n" +" %s" + +#. module: account_statement_import_online_ponto +#: code:addons/account_statement_import_online_ponto/models/online_bank_statement_provider_ponto.py:0 +#, python-format +msgid "" +"Error during get transaction.\n" +"\n" +"%s \n" +"\n" +" %s" +msgstr "" +"Errore nell'ottenere la transizione.\n" +"\n" +"%s \n" +"\n" +" %s" + +#. module: account_statement_import_online_ponto +#: model:ir.model.fields,field_description:account_statement_import_online_ponto.field_online_bank_statement_provider__id +msgid "ID" +msgstr "ID" + +#. module: account_statement_import_online_ponto +#: model:ir.model.fields,field_description:account_statement_import_online_ponto.field_online_bank_statement_provider____last_update +msgid "Last Modified on" +msgstr "Ultima modifica il" + +#. module: account_statement_import_online_ponto +#: model_terms:ir.ui.view,arch_db:account_statement_import_online_ponto.online_bank_statement_provider_form +msgid "Login" +msgstr "Login" + +#. module: account_statement_import_online_ponto +#: model:ir.model,name:account_statement_import_online_ponto.model_online_bank_statement_provider +msgid "Online Bank Statement Provider" +msgstr "Fornitore estratto conto bancario online" + +#. module: account_statement_import_online_ponto +#: code:addons/account_statement_import_online_ponto/models/online_bank_statement_provider_ponto.py:0 +#, python-format +msgid "Please fill login and key." +msgstr "Fornire login e chiave." + +#. module: account_statement_import_online_ponto +#: code:addons/account_statement_import_online_ponto/models/online_bank_statement_provider_ponto.py:0 +#, python-format +msgid "Ponto : no token" +msgstr "Ponto : nessun token" + +#. module: account_statement_import_online_ponto +#: code:addons/account_statement_import_online_ponto/models/online_bank_statement_provider_ponto.py:0 +#, python-format +msgid "Ponto : wrong configuration, unknow account %s" +msgstr "Ponto: configurazione errata, account %s sconosciuto" + +#. module: account_statement_import_online_ponto +#: model:ir.model.fields,field_description:account_statement_import_online_ponto.field_online_bank_statement_provider__ponto_last_identifier +msgid "Ponto Last Identifier" +msgstr "Ultimo identificatore Ponto" + +#. module: account_statement_import_online_ponto +#: model:ir.model.fields,field_description:account_statement_import_online_ponto.field_online_bank_statement_provider__ponto_token +msgid "Ponto Token" +msgstr "Token Ponto" + +#. module: account_statement_import_online_ponto +#: model:ir.model.fields,field_description:account_statement_import_online_ponto.field_online_bank_statement_provider__ponto_token_expiration +msgid "Ponto Token Expiration" +msgstr "Scadenza token Ponto" + +#. module: account_statement_import_online_ponto +#: model_terms:ir.ui.view,arch_db:account_statement_import_online_ponto.online_bank_statement_provider_form +msgid "Reset Last identifier." +msgstr "Resetta ultimo identificatore." + +#. module: account_statement_import_online_ponto +#: model_terms:ir.ui.view,arch_db:account_statement_import_online_ponto.online_bank_statement_provider_form +msgid "Secret Key" +msgstr "Chiave segreta" diff --git a/account_statement_import_online_ponto/i18n/nl.po b/account_statement_import_online_ponto/i18n/nl.po new file mode 100644 index 000000000..8299ac32a --- /dev/null +++ b/account_statement_import_online_ponto/i18n/nl.po @@ -0,0 +1,175 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * account_statement_import_online_ponto +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 16.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2023-11-14 15:13+0000\n" +"Last-Translator: Thijs van Oers \n" +"Language-Team: none\n" +"Language: nl\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: account_statement_import_online_ponto +#. odoo-python +#: code:addons/account_statement_import_online_ponto/models/ponto_interface.py:0 +#, python-format +msgid "%d transactions present in response data" +msgstr "%d transacties aanwezig in response data" + +#. module: account_statement_import_online_ponto +#: model:ir.model.fields.selection,name:account_statement_import_online_ponto.selection__online_bank_statement_provider__ponto_date_field__execution_date +msgid "Execution Date" +msgstr "datum uitvoering" + +#. module: account_statement_import_online_ponto +#. odoo-python +#: code:addons/account_statement_import_online_ponto/models/ponto_interface.py:0 +#, python-format +msgid "GET request on %(url)s" +msgstr "Vraag request aan %(url)s" + +#. module: account_statement_import_online_ponto +#. odoo-python +#: code:addons/account_statement_import_online_ponto/models/ponto_interface.py:0 +#, python-format +msgid "GET request to %(url)s with headers %(headers)s and params %(params)s" +msgstr "" + +#. module: account_statement_import_online_ponto +#. odoo-python +#: code:addons/account_statement_import_online_ponto/models/ponto_interface.py:0 +#, python-format +msgid "HTTP answer code %(response_code)s from Ponto" +msgstr "HTTP antwoord code %(response_code)s vanuit Ponto" + +#. module: account_statement_import_online_ponto +#: model:ir.model,name:account_statement_import_online_ponto.model_ponto_interface +msgid "Interface to all interactions with Ponto API" +msgstr "Interface naar alle interacties met de Ponto API" + +#. module: account_statement_import_online_ponto +#: model_terms:ir.ui.view,arch_db:account_statement_import_online_ponto.online_bank_statement_provider_form +msgid "Login" +msgstr "Inlog" + +#. module: account_statement_import_online_ponto +#. odoo-python +#: code:addons/account_statement_import_online_ponto/models/online_bank_statement_provider_ponto.py:0 +#, python-format +msgid "No lines were retrieved from Ponto" +msgstr "Er zijn geen regels opgehaald vanuit Ponto" + +#. module: account_statement_import_online_ponto +#. odoo-python +#: code:addons/account_statement_import_online_ponto/models/ponto_interface.py:0 +#, python-format +msgid "No transactions where found in data %(data)s" +msgstr "Geen transacties gevonden voor dagen %(data)s" + +#. module: account_statement_import_online_ponto +#: model:ir.model,name:account_statement_import_online_ponto.model_online_bank_statement_provider +msgid "Online Bank Statement Provider" +msgstr "Online aanbieder bankafschriften" + +#. module: account_statement_import_online_ponto +#. odoo-python +#: code:addons/account_statement_import_online_ponto/models/ponto_interface.py:0 +#, python-format +msgid "POST request on %(url)s" +msgstr "POST request op %(url)s" + +#. module: account_statement_import_online_ponto +#. odoo-python +#: code:addons/account_statement_import_online_ponto/models/ponto_interface.py:0 +#, python-format +msgid "Please fill login and key." +msgstr "Vul uw login en key in." + +#. module: account_statement_import_online_ponto +#. odoo-python +#: code:addons/account_statement_import_online_ponto/models/ponto_interface.py:0 +#, python-format +msgid "Ponto : no token" +msgstr "Ponto: geen token" + +#. module: account_statement_import_online_ponto +#. odoo-python +#: code:addons/account_statement_import_online_ponto/models/ponto_interface.py:0 +#, python-format +msgid "Ponto : wrong configuration, account {account} not found in {data}" +msgstr "" +"Ponto : verkeerde configuratie, rekening {account} niet gevonden in {data}" + +#. module: account_statement_import_online_ponto +#: model_terms:ir.ui.view,arch_db:account_statement_import_online_ponto.online_bank_statement_provider_form +msgid "Ponto Config" +msgstr "Ponto configuratie" + +#. module: account_statement_import_online_ponto +#: model:ir.model.fields,field_description:account_statement_import_online_ponto.field_online_bank_statement_provider__ponto_date_field +msgid "Ponto Date Field" +msgstr "Ponto datumveld" + +#. module: account_statement_import_online_ponto +#: model:ir.model.fields,field_description:account_statement_import_online_ponto.field_online_bank_statement_provider__ponto_last_identifier +msgid "Ponto Last Identifier" +msgstr "Laatste identifier Ponto" + +#. module: account_statement_import_online_ponto +#. odoo-python +#: code:addons/account_statement_import_online_ponto/models/online_bank_statement_provider_ponto.py:0 +#, python-format +msgid "Ponto obtain all new statement data for journal %s" +msgstr "Ponto verkrijgt alle nieuwe afschrift informatie voor dagboek %s" + +#. module: account_statement_import_online_ponto +#. odoo-python +#: code:addons/account_statement_import_online_ponto/models/online_bank_statement_provider_ponto.py:0 +#, python-format +msgid "" +"Ponto obtain statement data for journal %(journal)s from %(date_since)s to " +"%(date_until)s" +msgstr "" +"Ponto verkrijgt afschrift informatie voor dagboek %(journal)s vanaf " +"%(date_since)s tot %(date_until)s" + +#. module: account_statement_import_online_ponto +#: model_terms:ir.ui.view,arch_db:account_statement_import_online_ponto.online_bank_statement_provider_form +msgid "Secret Key" +msgstr "" + +#. module: account_statement_import_online_ponto +#: model:ir.model.fields,help:account_statement_import_online_ponto.field_online_bank_statement_provider__ponto_date_field +msgid "" +"Select the Ponto date field that will be used for the Odoo bank statement " +"line date." +msgstr "" +"Selecteer het Ponto datumveld dat zal worden gebruikt voor de Odoo " +"bankafschriftregel datum." + +#. module: account_statement_import_online_ponto +#. odoo-python +#: code:addons/account_statement_import_online_ponto/models/ponto_interface.py:0 +#, python-format +msgid "Server returned status code {response_code}: {response_text}" +msgstr "" +"De server gaf de volgende status code terug {response_code}: {response_text}" + +#. module: account_statement_import_online_ponto +#. odoo-python +#: code:addons/account_statement_import_online_ponto/tests/test_account_statement_import_online_ponto.py:0 +#, python-format +msgid "Statement contains transactions: %s" +msgstr "Afschrift bevat transacties: %s" + +#. module: account_statement_import_online_ponto +#: model:ir.model.fields.selection,name:account_statement_import_online_ponto.selection__online_bank_statement_provider__ponto_date_field__value_date +msgid "Value Date" +msgstr "Datum waarde" diff --git a/account_statement_import_online_ponto/models/__init__.py b/account_statement_import_online_ponto/models/__init__.py new file mode 100644 index 000000000..d21cc89ed --- /dev/null +++ b/account_statement_import_online_ponto/models/__init__.py @@ -0,0 +1,3 @@ +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). +from . import ponto_interface +from . import online_bank_statement_provider_ponto diff --git a/account_statement_import_online_ponto/models/online_bank_statement_provider_ponto.py b/account_statement_import_online_ponto/models/online_bank_statement_provider_ponto.py new file mode 100644 index 000000000..da525d992 --- /dev/null +++ b/account_statement_import_online_ponto/models/online_bank_statement_provider_ponto.py @@ -0,0 +1,225 @@ +# Copyright 2020 Florent de Labarre +# Copyright 2022-2023 Therp BV . +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). +import json +import logging +import re +from datetime import datetime, timedelta +from operator import itemgetter + +import pytz + +from odoo import _, api, fields, models + +_logger = logging.getLogger(__name__) + + +class OnlineBankStatementProvider(models.Model): + _inherit = "online.bank.statement.provider" + + ponto_last_identifier = fields.Char(readonly=True) + ponto_date_field = fields.Selection( + [ + ("execution_date", "Execution Date"), + ("value_date", "Value Date"), + ], + default="execution_date", + help="Select the Ponto date field that will be used for " + "the Odoo bank statement line date.", + ) + + @api.model + def _get_available_services(self): + """Each provider model must register its service.""" + return super()._get_available_services() + [ + ("ponto", "MyPonto.com"), + ] + + def _pull(self, date_since, date_until): + """For Ponto the pulling of data will not be grouped by statement. + + Instead we will pull data from the last available backwards. + + For a scheduled pull we will continue until we get to data + already retrieved or there is no more data available. + + For a wizard pull we will discard data after date_until and + stop retrieving when either we get before date_since or there is + no more data available. + """ + # pylint: disable=missing-return + ponto_providers = self.filtered(lambda provider: provider.service == "ponto") + debug = self.env.context.get("account_statement_online_import_debug") + debug_data = [] + data = super(OnlineBankStatementProvider, self - ponto_providers)._pull( + date_since, date_until + ) + if debug: + debug_data += data + for provider in ponto_providers: + data = provider._ponto_pull(date_since, date_until) + if debug: + debug_data += data + return debug_data + + def _ponto_pull(self, date_since, date_until): + """Translate information from Ponto to Odoo bank statement lines.""" + self.ensure_one() + is_scheduled = self.env.context.get("scheduled", False) + if is_scheduled: + _logger.debug( + _( + "Ponto obtain statement data for journal %(journal)s" + " from %(date_since)s to %(date_until)s" + ), + dict( + journal=self.journal_id.name, + date_since=date_since, + date_until=date_until, + ), + ) + else: + _logger.debug( + _("Ponto obtain all new statement data for journal %s"), + self.journal_id.name, + ) + lines = self._ponto_retrieve_data(date_since, date_until) + if not lines: + _logger.info(_("No lines were retrieved from Ponto")) + else: + # For scheduled runs, store latest identifier. + if is_scheduled: + self.ponto_last_identifier = lines[0].get("id") + self._ponto_store_lines(lines) + return lines + + def _ponto_retrieve_data(self, date_since, date_until): + """Fill buffer with data from Ponto. + + We will retrieve data from the latest transactions present in Ponto + backwards, until we find data that has an execution date before date_since, + or until we get to a transaction that we already have. + + Note: when reading data they are likely to be in descending order of + execution_date (not seen a guarantee for this in Ponto API). When using + value date, they may well be out of order. So we cannot simply stop + when we have found a transaction date before the date_since. + + We will not read transactions more then a week before before date_since. + """ + date_stop = date_since - timedelta(days=7) + is_scheduled = self.env.context.get("scheduled", False) + lines = [] + interface_model = self.env["ponto.interface"] + access_data = interface_model._login(self.username, self.password) + interface_model._set_access_account(access_data, self.account_number) + latest_identifier = False + transactions = interface_model._get_transactions(access_data, latest_identifier) + while transactions: + for line in transactions: + identifier = line.get("id") + transaction_datetime = self._ponto_get_transaction_datetime(line) + if is_scheduled: + # Handle all stop conditions for scheduled runs. + if identifier == self.ponto_last_identifier or ( + not self.ponto_last_identifier + and transaction_datetime < date_stop + ): + return lines + else: + # Handle stop conditions for non scheduled runs. + if transaction_datetime < date_stop: + return lines + if ( + transaction_datetime < date_since + or transaction_datetime > date_until + ): + continue + line["transaction_datetime"] = transaction_datetime + lines.append(line) + latest_identifier = transactions[-1].get("id") + transactions = interface_model._get_transactions( + access_data, latest_identifier + ) + # We get here if we found no transactions before date_since, + # or not equal to stored last identifier. + return lines + + def _ponto_store_lines(self, lines): + """Store transactions retrieved from Ponto in statements.""" + lines = sorted(lines, key=itemgetter("transaction_datetime")) + + # Group statement lines by date per period (date range) + grouped_periods = {} + for line in lines: + date_since = line["transaction_datetime"] + statement_date_since = self._get_statement_date_since(date_since) + statement_date_until = ( + statement_date_since + self._get_statement_date_step() + ) + if (statement_date_since, statement_date_until) not in grouped_periods: + grouped_periods[(statement_date_since, statement_date_until)] = [] + + line.pop("transaction_datetime") + vals_line = self._ponto_get_transaction_vals(line) + grouped_periods[(statement_date_since, statement_date_until)].append( + vals_line + ) + + # For each period, create or update statement lines + for period, statement_lines in grouped_periods.items(): + (date_since, date_until) = period + self._create_or_update_statement( + (statement_lines, {}), date_since, date_until + ) + + def _ponto_get_transaction_vals(self, transaction): + """Translate information from Ponto to statement line vals.""" + attributes = transaction.get("attributes", {}) + ref_list = [ + attributes.get(x) + for x in { + "description", + "counterpartName", + "counterpartReference", + } + if attributes.get(x) + ] + ref = " ".join(ref_list) + date = self._ponto_get_transaction_datetime(transaction) + vals_line = { + "sequence": 1, # Sequence is not meaningfull for Ponto. + "date": date, + "ref": re.sub(" +", " ", ref) or "/", + "payment_ref": attributes.get("remittanceInformation", ref), + "unique_import_id": transaction["id"], + "amount": attributes["amount"], + "raw_data": json.dumps(transaction), + } + if attributes.get("counterpartReference"): + vals_line["account_number"] = attributes["counterpartReference"] + if attributes.get("counterpartName"): + vals_line["partner_name"] = attributes["counterpartName"] + return vals_line + + def _ponto_get_transaction_datetime(self, transaction): + """Get execution datetime for a transaction. + + Odoo often names variables containing date and time just xxx_date or + date_xxx. We try to avoid this misleading naming by using datetime as + much for variables and fields of type datetime. + """ + attributes = transaction.get("attributes", {}) + if self.ponto_date_field == "value_date": + datetime_str = attributes.get("valueDate") + else: + datetime_str = attributes.get("executionDate") + return self._ponto_datetime_from_string(datetime_str) + + def _ponto_datetime_from_string(self, datetime_str): + """Dates in Ponto are expressed in UTC, so we need to convert them + to supplied tz for proper classification. + """ + dt = datetime.strptime(datetime_str, "%Y-%m-%dT%H:%M:%S.%fZ") + dt = dt.replace(tzinfo=pytz.utc).astimezone(pytz.timezone(self.tz or "utc")) + return dt.replace(tzinfo=None) diff --git a/account_statement_import_online_ponto/models/ponto_interface.py b/account_statement_import_online_ponto/models/ponto_interface.py new file mode 100644 index 000000000..8c52e0204 --- /dev/null +++ b/account_statement_import_online_ponto/models/ponto_interface.py @@ -0,0 +1,166 @@ +# Copyright 2020 Florent de Labarre +# Copyright 2022 Therp BV . +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +import base64 +import json +import logging + +import requests +from dateutil.relativedelta import relativedelta + +from odoo import _, fields, models +from odoo.exceptions import UserError + +from odoo.addons.base.models.res_bank import sanitize_account_number + +_logger = logging.getLogger(__name__) + +PONTO_ENDPOINT = "https://api.myponto.com" + + +class PontoInterface(models.AbstractModel): + _name = "ponto.interface" + _description = "Interface to all interactions with Ponto API" + + def _login(self, username, password): + """Ponto login returns an access dictionary for further requests.""" + url = PONTO_ENDPOINT + "/oauth2/token" + if not (username and password): + raise UserError(_("Please fill login and key.")) + login = ":".join([username, password]) + login = base64.b64encode(login.encode("UTF-8")).decode("UTF-8") + login_headers = { + "Content-Type": "application/x-www-form-urlencoded", + "Accept": "application/json", + "Authorization": f"Basic {login}", + } + _logger.debug(_("POST request on %(url)s"), dict(url=url)) + response = requests.post( + url, + params={"grant_type": "client_credentials"}, + headers=login_headers, + timeout=60, + ) + data = self._get_response_data(response) + access_token = data.get("access_token", False) + if not access_token: + raise UserError(_("Ponto : no token")) + token_expiration = fields.Datetime.now() + relativedelta( + seconds=data.get("expires_in", False) + ) + return { + "username": username, + "password": password, + "access_token": access_token, + "token_expiration": token_expiration, + } + + def _get_request_headers(self, access_data): + """Get headers with authorization for further ponto requests.""" + if access_data["token_expiration"] <= fields.Datetime.now(): + updated_data = self._login(access_data["username"], access_data["password"]) + access_data.update(updated_data) + return { + "Accept": "application/json", + "Authorization": "Bearer {access_token}".format( + access_token=access_data["access_token"] + ), + } + + def _set_access_account(self, access_data, account_number): + """Set ponto account for bank account in access_data.""" + url = PONTO_ENDPOINT + "/accounts" + _logger.debug(_("GET request on %(url)s"), dict(url=url)) + response = requests.get( + url, + params={"limit": 100}, + headers=self._get_request_headers(access_data), + timeout=60, + ) + data = self._get_response_data(response) + for ponto_account in data.get("data", []): + ponto_iban = sanitize_account_number( + ponto_account.get("attributes", {}).get("reference", "") + ) + if ponto_iban == account_number: + access_data["ponto_account"] = ponto_account.get("id") + return + # If we get here, we did not find Ponto account for bank account. + raise UserError( + _( + "Ponto : wrong configuration, account {account} not found in {data}" + ).format(account=account_number, data=data) + ) + + def _get_transactions(self, access_data, last_identifier): + """Get transactions from ponto, using last_identifier as pointer. + + Note that Ponto has the transactions in descending order. The first + transaction, retrieved by not passing an identifier, is the latest + present in Ponto. If you read transactions 'after' a certain identifier + (Ponto id), you will get transactions with an earlier date. + """ + url = ( + PONTO_ENDPOINT + + "/accounts/" + + access_data["ponto_account"] + + "/transactions" + ) + params = {"limit": 100} + if last_identifier: + params["after"] = last_identifier + data = self._get_request(access_data, url, params) + transactions = self._get_transactions_from_data(data) + return transactions + + def _get_transactions_from_data(self, data): + """Get all transactions that are in the ponto response data.""" + transactions = data.get("data", []) + if not transactions: + _logger.debug( + _("No transactions where found in data %(data)s"), + dict(data=data), + ) + else: + _logger.debug( + _("%d transactions present in response data"), + len(transactions), + ) + return transactions + + def _get_request(self, access_data, url, params): + """Interact with Ponto to get next page of data.""" + headers = self._get_request_headers(access_data) + _logger.debug( + _("GET request to %(url)s with headers %(headers)s and params %(params)s"), + dict( + url=url, + headers=headers, + params=params, + ), + ) + response = requests.get( + url, + params=params, + headers=headers, + timeout=(60, 300), + ) + return self._get_response_data(response) + + def _get_response_data(self, response): + """Get response data for GET or POST request.""" + _logger.debug( + _("HTTP answer code %(response_code)s from Ponto"), + dict(response_code=response.status_code), + ) + if response.status_code not in (200, 201): + raise UserError( + _( + "Server returned status code {response_code}: {response_text}" + ).format( + response_code=response.status_code, + response_text=response.text, + ) + ) + return json.loads(response.text) diff --git a/account_statement_import_online_ponto/pyproject.toml b/account_statement_import_online_ponto/pyproject.toml new file mode 100644 index 000000000..4231d0ccc --- /dev/null +++ b/account_statement_import_online_ponto/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["whool"] +build-backend = "whool.buildapi" diff --git a/account_statement_import_online_ponto/readme/CONFIGURE.md b/account_statement_import_online_ponto/readme/CONFIGURE.md new file mode 100644 index 000000000..605b13c17 --- /dev/null +++ b/account_statement_import_online_ponto/readme/CONFIGURE.md @@ -0,0 +1,27 @@ +To configure online bank statements provider: + +1. Go to *Invoicing \> Configuration \> Bank Accounts* +2. Open bank account to configure and edit it +3. Set *Bank Feeds* to *Online* +4. Select *MyPonto.com* as online bank statements provider in *Online + Bank Statements (OCA)* section +5. Save the bank account +6. Click on provider and configure provider-specific settings. + +or, alternatively: + +1. Go to *Invoicing \> Overview* +2. Open settings of the corresponding journal account +3. Switch to *Bank Account* tab +4. Set *Bank Feeds* to *Online* +5. Select *MyPonto.com* as online bank statements provider in *Online + Bank Statements (OCA)* section +6. Save the bank account +7. Click on provider and configure provider-specific settings. + +To obtain *Login* and *Key*: + +1. Open [MyPonto.com](https://myponto.com/). + +Check also `account_bank_statement_import_online` configuration +instructions for more information. diff --git a/account_statement_import_online_ponto/readme/CONTRIBUTORS.md b/account_statement_import_online_ponto/readme/CONTRIBUTORS.md new file mode 100644 index 000000000..cb97ddef3 --- /dev/null +++ b/account_statement_import_online_ponto/readme/CONTRIBUTORS.md @@ -0,0 +1,6 @@ +- Florent de Labarre +- [Tecnativa](https://www.tecnativa.com): + - Pedro M. Baeza + - João Marques +- [Therp BV](https://therp.nl): + - Ronald Portier \<\> diff --git a/account_statement_import_online_ponto/readme/DESCRIPTION.md b/account_statement_import_online_ponto/readme/DESCRIPTION.md new file mode 100644 index 000000000..28193a894 --- /dev/null +++ b/account_statement_import_online_ponto/readme/DESCRIPTION.md @@ -0,0 +1 @@ +This module provides online bank statements from MyPonto.com. diff --git a/account_statement_import_online_ponto/readme/USAGE.md b/account_statement_import_online_ponto/readme/USAGE.md new file mode 100644 index 000000000..4a80ed2ef --- /dev/null +++ b/account_statement_import_online_ponto/readme/USAGE.md @@ -0,0 +1,10 @@ +To pull historical bank statements: + +1. Go to *Invoicing \> Configuration \> Bank Accounts* +2. Select specific bank accounts +3. Launch *Actions \> Online Bank Statements Pull Wizard* +4. Configure date interval and click *Pull* + +If historical data is not needed, then just simply wait for the +scheduled activity "Pull Online Bank Statements" to be executed for +getting new transactions. diff --git a/account_statement_import_online_ponto/static/description/icon.png b/account_statement_import_online_ponto/static/description/icon.png new file mode 100644 index 000000000..09847ed76 Binary files /dev/null and b/account_statement_import_online_ponto/static/description/icon.png differ diff --git a/account_statement_import_online_ponto/static/description/index.html b/account_statement_import_online_ponto/static/description/index.html new file mode 100644 index 000000000..4247230ca --- /dev/null +++ b/account_statement_import_online_ponto/static/description/index.html @@ -0,0 +1,478 @@ + + + + + +Online Bank Statements: MyPonto.com + + + +
+

Online Bank Statements: MyPonto.com

+ + +

Beta License: AGPL-3 OCA/bank-statement-import Translate me on Weblate Try me on Runboat

+

This module provides online bank statements from MyPonto.com.

+

Table of contents

+ +
+

Configuration

+

To configure online bank statements provider:

+
    +
  1. Go to Invoicing > Configuration > Bank Accounts
  2. +
  3. Open bank account to configure and edit it
  4. +
  5. Set Bank Feeds to Online
  6. +
  7. Select MyPonto.com as online bank statements provider in Online +Bank Statements (OCA) section
  8. +
  9. Save the bank account
  10. +
  11. Click on provider and configure provider-specific settings.
  12. +
+

or, alternatively:

+
    +
  1. Go to Invoicing > Overview
  2. +
  3. Open settings of the corresponding journal account
  4. +
  5. Switch to Bank Account tab
  6. +
  7. Set Bank Feeds to Online
  8. +
  9. Select MyPonto.com as online bank statements provider in Online +Bank Statements (OCA) section
  10. +
  11. Save the bank account
  12. +
  13. Click on provider and configure provider-specific settings.
  14. +
+

To obtain Login and Key:

+
    +
  1. Open MyPonto.com.
  2. +
+

Check also account_bank_statement_import_online configuration +instructions for more information.

+
+
+

Usage

+

To pull historical bank statements:

+
    +
  1. Go to Invoicing > Configuration > Bank Accounts
  2. +
  3. Select specific bank accounts
  4. +
  5. Launch Actions > Online Bank Statements Pull Wizard
  6. +
  7. Configure date interval and click Pull
  8. +
+

If historical data is not needed, then just simply wait for the +scheduled activity “Pull Online Bank Statements” to be executed for +getting new transactions.

+
+
+

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

+
    +
  • Florent de Labarre
  • +
  • Therp BV
  • +
+
+
+

Contributors

+ +
+
+

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.

+

This module is part of the OCA/bank-statement-import project on GitHub.

+

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

+
+
+
+ + diff --git a/account_statement_import_online_ponto/tests/__init__.py b/account_statement_import_online_ponto/tests/__init__.py new file mode 100644 index 000000000..7f0830753 --- /dev/null +++ b/account_statement_import_online_ponto/tests/__init__.py @@ -0,0 +1,4 @@ +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from . import test_ponto_interface +from . import test_account_statement_import_online_ponto diff --git a/account_statement_import_online_ponto/tests/test_account_statement_import_online_ponto.py b/account_statement_import_online_ponto/tests/test_account_statement_import_online_ponto.py new file mode 100644 index 000000000..1624c9b63 --- /dev/null +++ b/account_statement_import_online_ponto/tests/test_account_statement_import_online_ponto.py @@ -0,0 +1,431 @@ +# Copyright 2020 Florent de Labarre +# Copyright 2022 Therp BV . +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). +import logging +from datetime import datetime +from unittest import mock + +from odoo import _, fields +from odoo.tests import tagged + +from odoo.addons.base.tests.common import BaseCommon + +_logger = logging.getLogger(__name__) + +_module_ns = "odoo.addons.account_statement_import_online_ponto" +_interface_class = _module_ns + ".models.ponto_interface" + ".PontoInterface" + + +# Transactions should be ordered by descending executionDate. +FOUR_TRANSACTIONS = [ + # First transaction will be after date_until. + { + "type": "transaction", + "relationships": { + "account": { + "links": {"related": "https://api.myponto.com/accounts/"}, + "data": { + "type": "account", + "id": "fd3d5b1d-fca9-4310-a5c8-76f2a9dc7c75", + }, + } + }, + "id": "1552c32f-e63f-4ce6-a974-f270e6cd53a9", + "attributes": { + "valueDate": "2019-12-04T12:30:00.000Z", + "remittanceInformationType": "unstructured", + "remittanceInformation": "Arresto Momentum", + "executionDate": "2019-12-04T10:25:00.000Z", + "description": "Wire transfer after execution", + "currency": "EUR", + "counterpartReference": "BE10325927501996", + "counterpartName": "Some other customer", + "amount": 8.95, + }, + }, + # Next transaction has valueDate before, executionDate after date_until. + { + "type": "transaction", + "relationships": { + "account": { + "links": {"related": "https://api.myponto.com/accounts/"}, + "data": { + "type": "account", + "id": "fd3d5b1d-fca9-4310-a5c8-76f2a9dc7c75", + }, + } + }, + "id": "701ab965-21c4-46ca-b157-306c0646e0e2", + "attributes": { + "valueDate": "2019-11-18T00:00:00.000Z", + "remittanceInformationType": "unstructured", + "remittanceInformation": "Minima vitae totam!", + "executionDate": "2019-11-20T00:00:00.000Z", + "description": "Wire transfer", + "currency": "EUR", + "counterpartReference": "BE26089479973169", + "counterpartName": "Osinski Group", + "amount": 6.08, + }, + }, + { + "type": "transaction", + "relationships": { + "account": { + "links": {"related": "https://api.myponto.com/accounts/"}, + "data": { + "type": "account", + "id": "fd3d5b1d-fca9-4310-a5c8-76f2a9dc7c75", + }, + } + }, + "id": "9ac50483-16dc-4a82-aa60-df56077405cd", + "attributes": { + "valueDate": "2019-11-04T00:00:00.000Z", + "remittanceInformationType": "unstructured", + "remittanceInformation": "Quia voluptatem blanditiis.", + "executionDate": "2019-11-06T00:00:00.000Z", + "description": "Wire transfer", + "currency": "EUR", + "counterpartReference": "BE97201830401438", + "counterpartName": "Stokes-Miller", + "amount": 5.48, + }, + }, + { + "type": "transaction", + "relationships": { + "account": { + "links": {"related": "https://api.myponto.com/accounts/"}, + "data": { + "type": "account", + "id": "fd3d5b1d-fca9-4310-a5c8-76f2a9dc7c75", + }, + } + }, + "id": "b21a6c65-1c52-4ba6-8cbc-127d2b2d85ff", + "attributes": { + "valueDate": "2019-11-04T00:00:00.000Z", + "remittanceInformationType": "unstructured", + "remittanceInformation": "Laboriosam repelo?", + "executionDate": "2019-11-04T00:00:00.000Z", + "description": "Wire transfer", + "currency": "EUR", + "counterpartReference": "BE10325927501996", + "counterpartName": "Strosin-Veum", + "amount": 5.83, + }, + }, +] + +EMPTY_TRANSACTIONS = [] + +EARLY_TRANSACTIONS = [ + # First transaction in october 2019, month before other transactions. + { + "type": "transaction", + "relationships": { + "account": { + "links": {"related": "https://api.myponto.com/accounts/"}, + "data": { + "type": "account", + "id": "fd3d5b1d-fca9-4310-a5c8-76f2a9dc7c75", + }, + } + }, + "id": "1552c32f-e63f-4ce6-a974-f270e6cd5301", + "attributes": { + "valueDate": "2019-10-04T12:29:00.000Z", + "remittanceInformationType": "unstructured", + "remittanceInformation": "Arresto Momentum", + "executionDate": "2019-10-04T10:24:00.000Z", + "description": "Wire transfer after execution", + "currency": "EUR", + "counterpartReference": "BE10325927501996", + "counterpartName": "Some other customer", + "amount": 4.25, + }, + }, + # Second transaction in september 2019. + { + "type": "transaction", + "relationships": { + "account": { + "links": {"related": "https://api.myponto.com/accounts/"}, + "data": { + "type": "account", + "id": "fd3d5b1d-fca9-4310-a5c8-76f2a9dc7c75", + }, + } + }, + "id": "701ab965-21c4-46ca-b157-306c0646e002", + "attributes": { + "valueDate": "2019-09-18T01:00:00.000Z", + "remittanceInformationType": "unstructured", + "remittanceInformation": "Minima vitae totam!", + "executionDate": "2019-09-20T01:00:00.000Z", + "description": "Wire transfer", + "currency": "EUR", + "counterpartReference": "BE26089479973169", + "counterpartName": "Osinski Group", + "amount": 4.08, + }, + }, +] + +transaction_amounts = [5.48, 5.83, 6.08, 8.95] + + +@tagged("post_install", "-at_install") +class TestAccountStatementImportOnlinePonto(BaseCommon): + def setUp(self): + super().setUp() + + self.now = fields.Datetime.now() + self.currency_eur = self.env.ref("base.EUR") + self.currency_usd = self.env.ref("base.USD") + self.AccountJournal = self.env["account.journal"] + self.ResPartnerBank = self.env["res.partner.bank"] + self.OnlineBankStatementProvider = self.env["online.bank.statement.provider"] + self.AccountBankStatement = self.env["account.bank.statement"] + self.AccountBankStatementLine = self.env["account.bank.statement.line"] + self.AccountStatementPull = self.env["online.bank.statement.pull.wizard"] + + self.currency_eur.write({"active": True}) + + self.bank_account = self.ResPartnerBank.create( + { + "acc_number": "FR0214508000302245362775K46", + "partner_id": self.env.user.company_id.partner_id.id, + } + ) + self.journal = self.AccountJournal.create( + { + "name": "Bank", + "type": "bank", + "code": "BANK", + "currency_id": self.currency_eur.id, + "bank_statements_source": "online", + "bank_account_id": self.bank_account.id, + } + ) + self.provider = self.OnlineBankStatementProvider.create( + { + "name": "Ponto Provider", + "service": "ponto", + "journal_id": self.journal.id, + # To get all the moves in a month at once + "statement_creation_mode": "monthly", + } + ) + + self.mock_login = lambda: mock.patch( + _interface_class + "._login", + return_value={ + "username": "test_user", + "password": "very_secret", + "access_token": "abcd1234", + "token_expiration": datetime(2099, 12, 31, 23, 59, 59), + }, + ) + self.mock_set_access_account = lambda: mock.patch( + _interface_class + "._set_access_account", + return_value=None, + ) + # return list of transactions on first call, empty list on second call. + self.mock_get_transactions = lambda: mock.patch( + _interface_class + "._get_transactions", + side_effect=[ + FOUR_TRANSACTIONS, + EMPTY_TRANSACTIONS, + ], + ) + # return two times list of transactions, empty list on third call. + self.mock_get_transactions_multi = lambda: mock.patch( + _interface_class + "._get_transactions", + side_effect=[ + FOUR_TRANSACTIONS, + EARLY_TRANSACTIONS, + EMPTY_TRANSACTIONS, + ], + ) + + def test_balance_start(self): + """Test wether end balance of last statement, taken as start balance of new.""" + statement_date = datetime(2019, 11, 1) + data = self._get_statement_line_data(statement_date) + self.provider.statement_creation_mode = "daily" + self.provider._create_or_update_statement( + data, statement_date, datetime(2019, 11, 2) + ) + with self.mock_login(), self.mock_set_access_account(), self.mock_get_transactions(): # noqa: E501 + vals = { + "date_since": datetime(2019, 11, 4), + "date_until": datetime(2019, 11, 5), + } + wizard = self.AccountStatementPull.with_context( + active_model=self.provider._name, + active_id=self.provider.id, + ).create(vals) + wizard.action_pull() + statements = self.AccountBankStatement.search( + [("journal_id", "=", self.journal.id)], order="name" + ) + self.assertEqual(len(statements), 2) + new_statement = statements[1] + self.assertEqual(len(new_statement.line_ids), 1) + self.assertEqual(new_statement.balance_start, 100) + self.assertEqual(new_statement.balance_end, 105.83) + + def test_ponto_execution_date(self): + with self.mock_login(), self.mock_set_access_account(), self.mock_get_transactions(): # noqa: E501 + # First base selection on execution date. + self.provider.ponto_date_field = "execution_date" + statement = self._get_statements_from_wizard() # Will get 1 statement + self._check_line_count(statement.line_ids, expected_count=2) + self._check_statement_amounts(statement, transaction_amounts[:2]) + + def test_ponto_value_date(self): + with self.mock_login(), self.mock_set_access_account(), self.mock_get_transactions(): # noqa: E501 + # First base selection on execution date. + self.provider.ponto_date_field = "value_date" + statement = self._get_statements_from_wizard() # Will get 1 statement + self._check_line_count(statement.line_ids, expected_count=3) + self._check_statement_amounts(statement, transaction_amounts[:3]) + + def test_ponto_get_transactions_multi(self): + with self.mock_login(), self.mock_set_access_account(), self.mock_get_transactions_multi(): # noqa: E501 + # First base selection on execution date. + self.provider.ponto_date_field = "execution_date" + # Expect statements for october and november. + statements = self._get_statements_from_wizard( + expected_statement_count=2, date_since=datetime(2019, 9, 25) + ) + self._check_line_count(statements[0].line_ids, expected_count=1) # october + self._check_line_count(statements[1].line_ids, expected_count=2) # november + self._check_statement_amounts(statements[0], [4.25]) + self._check_statement_amounts( + statements[1], + transaction_amounts[:2], + expected_balance_end=15.56, # Includes 4.25 from statement before. + ) + + def test_ponto_scheduled(self): + with self.mock_login(), self.mock_set_access_account(), self.mock_get_transactions(): # noqa: E501 + # Scheduled should get all transaction, ignoring date_until. + self.provider.ponto_last_identifier = False + date_since = datetime(2019, 11, 3) + date_until = datetime(2019, 11, 18) + self.provider.with_context(scheduled=True)._pull(date_since, date_until) + statements = self._get_statements_from_journal(expected_count=2) + self._check_line_count(statements[0].line_ids, expected_count=3) + self._check_statement_amounts(statements[0], transaction_amounts[:3]) + self._check_line_count(statements[1].line_ids, expected_count=1) + # Expected balance_end will include amounts of previous statement. + self._check_statement_amounts( + statements[1], transaction_amounts[3:], expected_balance_end=26.34 + ) + + def test_ponto_scheduled_from_identifier(self): + with self.mock_login(), self.mock_set_access_account(), self.mock_get_transactions(): # noqa: E501 + # Scheduled should get all transactions after last identifier. + self.provider.ponto_last_identifier = "9ac50483-16dc-4a82-aa60-df56077405cd" + date_since = datetime(2019, 11, 3) + date_until = datetime(2019, 11, 18) + self.provider.with_context(scheduled=True)._pull(date_since, date_until) + # First two transactions for statement 0 should have been ignored. + statements = self._get_statements_from_journal(expected_count=2) + self._check_line_count(statements[0].line_ids, expected_count=1) + self._check_statement_amounts(statements[0], transaction_amounts[2:3]) + self._check_line_count(statements[1].line_ids, expected_count=1) + # Expected balance_end will include amounts of previous statement. + self._check_statement_amounts( + statements[1], transaction_amounts[3:], expected_balance_end=15.03 + ) + + def _get_statements_from_wizard(self, expected_statement_count=1, date_since=None): + """Run wizard to pull data and return statement.""" + date_since = date_since if date_since else datetime(2019, 11, 3) + vals = { + "date_since": date_since, + "date_until": datetime(2019, 11, 18), + } + wizard = self.AccountStatementPull.with_context( + active_model=self.provider._name, + active_id=self.provider.id, + ).create(vals) + wizard.action_pull() + return self._get_statements_from_journal( + expected_count=expected_statement_count + ) + + def _get_statements_from_journal(self, expected_count=0): + """We only expect statements created by our tests.""" + statements = self.AccountBankStatement.search( + [("journal_id", "=", self.journal.id)], + order="date asc", + ) + self.assertEqual(len(statements), expected_count) + return statements + + def _check_line_count(self, lines, expected_count=0): + """Check wether lines contain expected number of transactions. + + If count differs, show the unique id's of lines that are present. + """ + # If we do not get all lines, show lines we did get: + line_count = len(lines) + if line_count != expected_count: + _logger.info( + _("Statement contains transactions: %s"), + " ".join(lines.mapped("unique_import_id")), + ) + self.assertEqual(line_count, expected_count) + + def _check_statement_amounts( + self, statement, expected_amounts, expected_balance_end=0.0 + ): + """Check wether amount in lines and end_balance as expected.""" + sorted_amounts = sorted([round(line.amount, 2) for line in statement.line_ids]) + sorted_expected_amounts = sorted( + [round(amount, 2) for amount in expected_amounts] + ) + self.assertEqual(sorted_amounts, sorted_expected_amounts) + if not expected_balance_end: + expected_balance_end = sum(expected_amounts) + self.assertEqual( + round(statement.balance_end, 2), round(expected_balance_end, 2) + ) + + def _get_statement_line_data(self, statement_date): + return [ + { + "payment_ref": "payment", + "amount": 100, + "date": statement_date, + "unique_import_id": str(statement_date), + "partner_name": "John Doe", + "account_number": "XX00 0000 0000 0000", + } + ], {} + + def test_wizard_action_debug(self): + """Debug data is returned properly.""" + statement_date = datetime(2019, 11, 1) + data = self._get_statement_line_data(statement_date) + self.provider.statement_creation_mode = "daily" + self.provider._create_or_update_statement( + data, statement_date, datetime(2019, 11, 2) + ) + with self.mock_login(), self.mock_set_access_account(), self.mock_get_transactions(): # noqa: E501 + vals = { + "date_since": datetime(2019, 11, 4), + "date_until": datetime(2019, 11, 5), + } + wizard = self.AccountStatementPull.with_context( + active_model=self.provider._name, + active_id=self.provider.id, + ).create(vals) + action = wizard.action_debug() + debug_wizard = self.env[action["res_model"]].browse(action["res_id"]) + self.assertIn("Laboriosam repelo", debug_wizard.data) diff --git a/account_statement_import_online_ponto/tests/test_ponto_interface.py b/account_statement_import_online_ponto/tests/test_ponto_interface.py new file mode 100644 index 000000000..cbaf2268b --- /dev/null +++ b/account_statement_import_online_ponto/tests/test_ponto_interface.py @@ -0,0 +1,99 @@ +# Copyright 2022 Therp BV . +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). +import json +from unittest.mock import MagicMock, patch + +from dateutil.relativedelta import relativedelta + +from odoo import fields +from odoo.tests import tagged + +from odoo.addons.base.tests.common import BaseCommon + +from .test_account_statement_import_online_ponto import FOUR_TRANSACTIONS + + +@tagged("post_install", "-at_install") +class TestPontoInterface(BaseCommon): + @patch("requests.post") + def test_login(self, requests_post): + """Check Ponto API login.""" + mock_response = MagicMock() + mock_response.status_code = 200 + mock_response.text = json.dumps( + { + "access_token": "live_the_token", + "expires_in": 1799, + "scope": "ai", + "token_type": "bearer", + } + ) + requests_post.return_value = mock_response + interface_model = self.env["ponto.interface"] + access_data = interface_model._login("uncle_john", "secret") + self.assertEqual(access_data["access_token"], "live_the_token") + self.assertIn("token_expiration", access_data) + + @patch("requests.get") + def test_set_access_account(self, requests_get): + """Test getting account data for Ponto access.""" + mock_response = MagicMock() + mock_response.status_code = 200 + mock_response.text = json.dumps( + { + "data": [ + { + "id": "wrong_id", + "attributes": { + "reference": "NL66ABNA123456789", + }, + }, + { + "id": "2ad3df83-be01-47cf-a6be-cf0de5cb4c99", + "attributes": { + "reference": "NL66RABO123456789", + }, + }, + ], + } + ) + requests_get.return_value = mock_response + # Start of actual test. + access_data = self._get_access_dict(include_account=False) + interface_model = self.env["ponto.interface"] + interface_model._set_access_account(access_data, "NL66RABO123456789") + self.assertIn("ponto_account", access_data) + self.assertEqual( + access_data["ponto_account"], "2ad3df83-be01-47cf-a6be-cf0de5cb4c99" + ) + + @patch("requests.get") + def test_get_transactions(self, requests_get): + """Test getting transactions from Ponto.""" + mock_response = MagicMock() + mock_response.status_code = 200 + # Key "data" will contain a list of transactions. + mock_response.text = json.dumps({"data": FOUR_TRANSACTIONS}) + requests_get.return_value = mock_response + # Start of actual test. + access_data = self._get_access_dict() + interface_model = self.env["ponto.interface"] + transactions = interface_model._get_transactions(access_data, False) + self.assertEqual(len(transactions), 4) + self.assertEqual(transactions[3]["id"], "b21a6c65-1c52-4ba6-8cbc-127d2b2d85ff") + self.assertEqual( + transactions[3]["attributes"]["counterpartReference"], "BE10325927501996" + ) + + def _get_access_dict(self, include_account=True): + """Get access dict that caches login/account information.""" + token_expiration = fields.Datetime.now() + relativedelta(seconds=1800) + access_data = { + "username": "uncle_john", + "password": "secret", + "access_token": "live_the_token", + "token_expiration": token_expiration, + } + if include_account: + access_data["ponto_account"] = "2ad3df83-be01-47cf-a6be-cf0de5cb4c99" + return access_data diff --git a/account_statement_import_online_ponto/views/online_bank_statement_provider.xml b/account_statement_import_online_ponto/views/online_bank_statement_provider.xml new file mode 100644 index 000000000..267dc370a --- /dev/null +++ b/account_statement_import_online_ponto/views/online_bank_statement_provider.xml @@ -0,0 +1,21 @@ + + + + online.bank.statement.provider.form + online.bank.statement.provider + + + + + + + + + + + + +