[14.0]add account_ebics_batch

This commit is contained in:
Luc De Meyer 2022-05-07 18:42:03 +02:00
parent 554801c652
commit 3a11f73daa
10 changed files with 415 additions and 0 deletions

View File

@ -0,0 +1,50 @@
.. image:: https://img.shields.io/badge/license-AGPL--3-blue.png
:target: https://www.gnu.org/licenses/agpl
:alt: License: AGPL-3
============================================
Module to enable batch import of EBICS files
============================================
This module adds a cron job for the automated import of EBICS files.
|
A Log is created during the import in order to document import errors.
If errors have been detected, the Batch Import Log state is set to 'error'.
When all EBICS Files have been imported correctly, the Batch Import Log state is set to 'done'.
|
The user can reprocess the imported EBICS files in status 'draft' via the Log object 'REPROCESS' button until all errors have been cleared.
As an alternative, the user can force the Batch Import Log state to 'done'
(e.g. when the errors have been circumvented via manual encoding or the reprocessing of a single EBICS file).
|
Configuration
=============
Adapt the 'EBICS Batch Import' ir.cron job created during the module installation.
The cron job calls the following python method:
|
.. code-block:: python
_batch_import()
The EBICS download will be performed on all confirmed EBICS connections.
You can limit the automated operation to a subset of your EBICS connections via the ebics_config_ids parameter, e.g.
|
.. code-block:: python
_batch_import(ebics_config_ids=[1,3])

View File

@ -0,0 +1 @@
from . import models

View File

@ -0,0 +1,20 @@
# Copyright 2009-2022 Noviat.
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
{
"name": "EBICS Files batch import",
"version": "14.0.1.0.0",
"license": "AGPL-3",
"author": "Noviat",
"website": "http://www.noviat.com",
"category": "Accounting & Finance",
"summary": "EBICS Files automated import and processing",
"depends": ["account_ebics"],
"data": [
"security/ir.model.access.csv",
"data/ir_cron_data.xml",
"views/ebics_batch_log_views.xml",
"views/menu.xml",
],
"installable": True,
}

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo noupdate="1">
<record id="ir_cron_ebics_batch_import" model="ir.cron">
<field name="name">EBICS Batch Import</field>
<field name="model_id" ref="model_ebics_batch_log" />
<field name="state">code</field>
<field name="code">model._batch_import()</field>
<field name="user_id" ref="base.user_root" />
<field name="interval_number">1</field>
<field name="interval_type">days</field>
<field name="numbercall">-1</field>
<field name="active" eval="True" />
<field name="doall" eval="False" />
</record>
</odoo>

View File

@ -0,0 +1 @@
from . import ebics_batch_log

View File

@ -0,0 +1,193 @@
# Copyright 2009-2022 Noviat.
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from sys import exc_info
from traceback import format_exception
from odoo import _, api, fields, models
from odoo.exceptions import UserError
class EbicsBatchLog(models.Model):
_name = "ebics.batch.log"
_description = "Object to store EBICS Batch Import Logs"
_order = "create_date desc"
date_from = fields.Date()
date_to = fields.Date()
ebics_config_ids = fields.Many2many(
comodel_name="ebics.config", string="EBICS Configurations"
)
log_ids = fields.One2many(
comodel_name="ebics.batch.log.item",
inverse_name="log_id",
string="Batch Import Log Items",
readonly=True,
)
file_ids = fields.Many2many(
comodel_name="ebics.file",
string="Batch Import EBICS Files",
readonly=True,
)
file_count = fields.Integer(
string="EBICS Files Count", compute="_compute_ebics_files_fields", readonly=True
)
has_draft_files = fields.Boolean(compute="_compute_ebics_files_fields")
state = fields.Selection(
selection=[("draft", "Draft"), ("error", "Error"), ("done", "Done")],
string="State",
required=True,
readonly=True,
default="draft",
)
@api.depends("file_ids")
def _compute_ebics_files_fields(self):
for rec in self:
rec.has_draft_files = "draft" in rec.file_ids.mapped("state")
rec.file_count = len(rec.file_ids)
def unlink(self):
for log in self:
if log.state != "draft":
raise UserError(_("Only log objects in state 'draft' can be deleted !"))
return super().unlink()
def button_draft(self):
self.state = "draft"
def button_done(self):
self.state = "done"
def reprocess(self):
import_dict = {"errors": []}
self._ebics_process(import_dict)
self._finalise_processing(import_dict)
def view_ebics_files(self):
action = self.env["ir.actions.actions"]._for_xml_id(
"account_ebics.ebics_file_action_download"
)
action["domain"] = [("id", "in", self.file_ids.ids)]
return action
def _batch_import(self, ebics_config_ids=None, date_from=None, date_to=None):
"""
Call this method from a cron job to automate the EBICS import.
"""
log_model = self.env["ebics.batch.log"]
import_dict = {"errors": []}
configs = self.env["ebics.config"].browse(ebics_config_ids) or self.env[
"ebics.config"
].search(
[
("company_ids", "in", self.env.user.company_ids.ids),
("state", "=", "confirm"),
]
)
log = log_model.create(
{
"ebics_config_ids": [(6, 0, configs.ids)],
"date_from": date_from,
"date_to": date_to,
}
)
ebics_file_ids = []
for config in configs:
err_msg = (
_("Error while processing EBICS connection '%s' :\n") % config.name
)
if config.state == "draft":
import_dict["errors"].append(
err_msg
+ _(
"Please set state to 'Confirm' and "
"Reprocess this EBICS Import Log."
)
)
continue
try:
with self.env.cr.savepoint():
ebics_file_ids += self._ebics_import(
config, date_from, date_to, import_dict
)
except UserError as e:
import_dict["errors"].append(err_msg + " ".join(e.args))
except Exception:
tb = "".join(format_exception(*exc_info()))
import_dict["errors"].append(err_msg + tb)
log.file_ids = [(6, 0, ebics_file_ids)]
try:
with self.env.cr.savepoint():
log._ebics_process(import_dict)
except UserError as e:
import_dict["errors"].append(err_msg + " ".join(e.args))
except Exception:
tb = "".join(format_exception(*exc_info()))
import_dict["errors"].append(err_msg + tb)
log._finalise_processing(import_dict)
def _finalise_processing(self, import_dict):
log_item_model = self.env["ebics.batch.log.item"]
state = self.has_draft_files and "draft" or "done"
note = ""
error_count = 0
if import_dict["errors"]:
state = "error"
note = "\n\n".join(import_dict["errors"])
error_count = len(import_dict["errors"])
log_item_model.create(
{
"log_id": self.id,
"state": state,
"note": note,
"error_count": error_count,
}
)
self.state = state
def _ebics_import(self, config, date_from, date_to, import_dict):
ctx = dict(self.env.context, ebics_download=True)
xfer_wiz = (
self.env["ebics.xfer"]
.with_context(ctx)
.create(
{
"ebics_config_id": config.id,
"date_from": date_from,
"date_to": date_to,
}
)
)
xfer_wiz._onchange_ebics_config_id()
res = xfer_wiz.ebics_download()
file_ids = res["context"].get("ebics_file_ids")
if res["context"]["err_cnt"]:
import_dict["errors"].append(xfer_wiz.note)
return file_ids
def _ebics_process(self, import_dict):
to_process = self.file_ids.filtered(lambda r: r.state == "draft")
for ebics_file in to_process:
ebics_file.process()
class EbicsBatchLogItem(models.Model):
_name = "ebics.batch.log.item"
_description = "Object to store EBICS Batch Import Log Items"
_order = "create_date desc"
log_id = fields.Many2one(
comodel_name="ebics.batch.log",
string="Batch Object",
ondelete="cascade",
readonly=True,
)
state = fields.Selection(
selection=[("draft", "Draft"), ("error", "Error"), ("done", "Done")],
string="State",
required=True,
readonly=True,
)
note = fields.Text(string="Batch Import Log", readonly=True)
error_count = fields.Integer(string="Number of Errors", required=True, default=0)

View File

@ -0,0 +1,3 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_ebics_batch_log,ebics.batch.log,model_ebics_batch_log,account.group_account_invoice,1,1,1,1
access_ebics_batch_log_item,ebics.batch.log.item,model_ebics_batch_log_item,account.group_account_invoice,1,1,1,1
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_ebics_batch_log ebics.batch.log model_ebics_batch_log account.group_account_invoice 1 1 1 1
3 access_ebics_batch_log_item ebics.batch.log.item model_ebics_batch_log_item account.group_account_invoice 1 1 1 1

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

View File

@ -0,0 +1,118 @@
<?xml version="1.0" ?>
<odoo>
<record id="ebics_batch_log_view_search" model="ir.ui.view">
<field name="name">ebics.batch.log.search</field>
<field name="model">ebics.batch.log</field>
<field name="arch" type="xml">
<search string="Search EBICS Batch Import Log Files">
<group col="10" colspan="4">
<field name="create_date" />
<field name="state" />
</group>
<newline />
<group expand="0" string="Group By">
<filter name="group_by_state" string="State" context="{'group_by':'state'}" />
</group>
</search>
</field>
</record>
<record id="ebics_batch_log_view_tree" model="ir.ui.view">
<field name="name">ebics.batch.log.tree</field>
<field name="model">ebics.batch.log</field>
<field name="arch" type="xml">
<tree string="EBICS Batch Import Logs" create="false">
<field name="create_date" />
<field name="file_count" />
<field name="state" />
</tree>
</field>
</record>
<record id="ebics_batch_log_view_form" model="ir.ui.view">
<field name="name">ebics.batch.log.form</field>
<field name="model">ebics.batch.log</field>
<field name="arch" type="xml">
<form string="EBICS Batch Import Log" create="false">
<header>
<button
name="button_draft"
states="done,error"
string="Set to Draft"
type="object"
/>
<button
name="reprocess"
string="Reprocess"
help="Reprocess 'draft' EBICS Files"
type="object"
class="oe_highlight"
attrs="{'invisible': ['|', ('state', '=', 'done'),('has_draft_files', '=', False)]}"
/>
<button
name="button_done"
states="draft,error"
string="Mark Done"
type="object"
/>
<field
name="state"
widget="statusbar"
statusbar_visible="draft,done"
statusbar_colors="{'error':'red'}"
/>
</header>
<sheet>
<div class="oe_button_box" name="button_box">
<button
name="view_ebics_files"
type="object"
class="oe_stat_button"
icon="fa-pencil-square-o"
attrs="{'invisible': [('file_count', '=', 0)]}"
>
<field name="file_count" widget="statinfo" string="EBICS Files" />
</button>
</div>
<group colspan="4" col="4">
<field name="create_date" />
<field name="ebics_config_ids" widget="many2many_tags" />
<field name="has_draft_files" invisible="1" />
</group>
<notebook colspan="4">
<page string="Batch Import Logs">
<field name="log_ids" nolabel="1">
<tree string="Log entries">
<field name="create_date" />
<field name="state" />
<field name="error_count" />
</tree>
<form string="Batch Import Log">
<group colspan="4" col="6">
<field name="create_date" />
<field name="error_count" />
</group>
<group attrs="{'invisible':[('note', '=', False)]}">
<separator colspan="4" />
<field name="note" nolabel="1" colspan="4" height="360" />
</group>
</form>
</field>
</page>
</notebook>
</sheet>
</form>
</field>
</record>
<record id="ebics_batch_log_action" model="ir.actions.act_window">
<field name="name">EBICS Batch Import Logs</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">ebics.batch.log</field>
<field name="view_mode">tree,form</field>
<field name="view_id" ref="ebics_batch_log_view_tree" />
<field name="search_view_id" ref="ebics_batch_log_view_search" />
</record>
</odoo>

View File

@ -0,0 +1,12 @@
<?xml version="1.0" ?>
<odoo>
<menuitem
id="ebics_batch_log_menu"
name="EBICS Batch Import Logs"
parent="account_ebics.ebics_processing_menu"
action="ebics_batch_log_action"
sequence="100"
/>
</odoo>