Metadata-Version: 2.1
Name: odoo-addon-account_statement_import_online_enable_banking
Version: 16.0.1.0.1.2
Requires-Python: >=3.10
Requires-Dist: odoo-addon-account_statement_import_online>=16.0dev,<16.1dev
Requires-Dist: odoo>=16.0a,<16.1dev
Requires-Dist: pyjwt
Summary: Import bank statements through Enable Banking (PSD2)
Home-page: https://somit.coop
License: AGPL-3
Author: SomIT Cooperatiu SCCL
Classifier: Programming Language :: Python
Classifier: Framework :: Odoo
Classifier: Framework :: Odoo :: 16.0
Classifier: License :: OSI Approved :: GNU Affero General Public License v3
Description-Content-Type: text/x-rst

=======================================
Online Bank Statements: Enable Banking
=======================================

Import bank statements directly from the bank into Odoo using
`Enable Banking <https://enablebanking.com>`_, a PSD2 licensed account
information service provider (AISP).

This module extends the OCA framework module ``account_statement_import_online``
with the **Enable Banking** service, so bank journals pull their statements
from the bank through the Enable Banking REST API using a read-only account
information session (AIS) that the user authorizes with strong customer
authentication (SCA) at the bank.

Features
========

* PSD2 account information: the user authorizes read-only access to the bank
  account with the bank SCA flow; Odoo pulls the transactions afterwards,
  without the bank credentials ever touching Odoo.
* One API fetch per pull: transactions are requested once for the whole
  window and paginated with ``continuation_key``, respecting the background
  fetch limits that most banks apply.
* Statements are split according to the configured statement creation mode
  (daily, weekly or monthly), reusing the standard framework.
* Duplicate-safe: every transaction is imported once, based on its
  ``entry_reference``.
* Closing booked balance attached to the current statement when the bank
  provides it (``GET /accounts/{id}/balances``).
* Session lifecycle: the authorization expiration is stored on the provider,
  a warning is shown 15 days in advance and a **Reconnect** button renews the
  authorization; the bank account is recovered automatically by matching the
  journal IBAN.
* Rate limits (``ASPSP_RATE_LIMIT_EXCEEDED``) are logged on the provider and
  deferred to the next scheduled run instead of breaking the pull.
* Full translation support (English, Spanish, Catalan).

Configuration
=============

Requirements
------------

* The ``pyjwt`` Python library must be installed in the server (declared as
  external dependency of the module; the JWT is signed with RS256).
* A public HTTPS URL for Odoo reachable by the browser that completes the bank
  authorization. Enable Banking validates the redirect URL against the
  registered list with an exact match, so ``web.base.url`` must hold the HTTPS
  URL of the instance: Odoo rewrites that parameter with the scheme of the last
  web request, so set ``web.base.url.freeze`` when the instance runs behind an
  HTTPS proxy. When the current request is already HTTPS the module builds the
  redirect URL from the request itself and does not depend on the parameter.

Register the Enable Banking application
---------------------------------------

#. Create an account and sign in at the `Enable Banking Control Panel
   <https://enablebanking.com/cp>`_.
#. Register a new application in the desired environment (start with
   *sandbox*; *restricted production* for real bank accounts).
#. Enable Banking asks for a certificate: use the default one offered by the
   control panel or upload your own self-signed certificate.
#. The control panel shows the **Application ID** and lets you download the
   **private key (PEM)**. Keep both.
#. In the application settings, add this Odoo instance's redirect URL:
   ``https://<your-odoo-domain>/enable_banking/response`` (no trailing
   slash). The exact value is shown in the provider form (*Enable Banking
   Redirect URL* field). Enable Banking validates it against the registered
   list with an **exact match**: if the callback URL is missing, the
   authorization is rejected with ``REDIRECT_URI_NOT_ALLOWED``.

Configure the provider
----------------------

#. Open the bank journal (*Accounting > Configuration > Bank Journals*) and
   set **Bank Statements Source** to *Online*.
#. Open its online bank statement provider and choose **Enable Banking** as
   *Service*.
#. Fill in the *Enable Banking* group:

   * **Application ID**: value obtained when registering the application.
   * **Private Key**: PEM file downloaded when registering the application.
   * **ASPSP Name**: exact bank name as listed by Enable Banking
     (e.g. ``Caixa Guissona``).
   * **ASPSP Country**: two-letter country code of the bank (e.g. ``ES``).
   * **PSU Type**: *Business* for company accounts, *Personal* otherwise.

#. Click **Connect** and complete the authorization in your bank; the account
   is linked when the bank redirects the browser back to Odoo.

Scheduled pull
--------------

Banks limit how many background fetches an application can make per day (many
ASPSPs allow around 4). The pull interval defaults to **1 day**; keep a daily
(or slower) schedule. When the bank answers a rate limit error, the pull is
logged on the provider and deferred to the next scheduled run.

When the authorization is about to expire (15 days warning is displayed), use
**Reconnect** to renew it. The maximum consent validity depends on the bank
and is usually 180 days.

De-duplication
--------------

Statement lines are de-duplicated with the transaction identifier the bank
provides (``entry_reference``). Some banks do not return any identifier at all:
for those, the module builds a deterministic digest of the transaction content,
so pulling the same period twice does not duplicate the lines. Identical
operations of the same pull are kept apart with an occurrence index, so
repeated transactions are never dropped either.

Repairing a journal imported with an older version
--------------------------------------------------

A journal that already imported operations before this fallback existed keeps
lines without identifier, and usually the same operation several times. The
bundled script repairs it in place::

    EB_DEDUPE_PROVIDER_ID=<provider id> odoo shell -d <db> --no-http < scripts/dedupe_statement_lines.py

#. The first run is a **dry run**: it lists the repeated groups and how many
   lines would be deleted or identified, and it stops there.
#. Add ``EB_DEDUPE_APPLY=1`` to the same command to delete the extra copies and
   write the identifiers. The script reads the operations from Enable Banking
   through the module itself, so the identifiers it writes are exactly the ones
   the next pull expects.
#. Start one pull afterwards to refresh the statement balances.

An operation can legitimately be repeated the same day with the same amount and
reference, so a line is only deleted when the bank returns fewer copies than
the journal holds. Lines whose operation the bank no longer returns are left
untouched unless ``EB_DEDUPE_TRUST_CONTENT=1`` is passed.

What the script never touches:

* journals of other banks: only the journal of the provider passed in
  ``EB_DEDUPE_PROVIDER_ID`` is read, the rest of the database is never scanned;
* lines outside the reviewed window (``EB_DEDUPE_DAYS``, 180 days by default),
  so older statements are not affected;
* lines that already carry an identifier;
* lines created by hand: they belong to no statement and are only counted in
  the report;
* reconciled lines: they are never deleted, and when a group contains a
  reconciled copy that copy is the one kept and identified.

Usage
=====

#. Register the application and configure the provider as described above.
#. Complete the authorization with **Connect**.
#. Pull the history you need with **Pull Online Bank Statement** (banks
   usually offer up to ~90 days of history when first linking), then let the
   scheduled pull keep the journal up to date.
#. Use **Reconnect** when the authorization approaches its expiration.

Known issues / Roadmap
======================

* The first pull window depends on the history the bank makes available
  through Enable Banking (commonly up to 90 days).
* The authorization flow opens the bank in a new browser tab; make sure
  pop-up blockers do not interfere.
* Banks that do not provide transaction identifiers rely on the content digest
  for de-duplication; if such a bank also changes the transaction data between
  two retrievals, a duplicated line may have to be deleted by hand.

Credits
=======

Authors
-------

* SomIT Cooperatiu SCCL

Contributors
------------

* Nicolás Ramos <nicolas.ramos@somit.coop> (https://github.com/nicolasramos)

Maintainers
-----------

* Nicolás Ramos (https://github.com/nicolasramos)

This module is built on top of the OCA modules of the
`bank-statement-import <https://github.com/OCA/bank-statement-import>`_
project.
