mirror of
https://github.com/OCA/bank-statement-import.git
synced 2025-01-20 12:37:43 +02:00
[MIG] account_bank_statement_import_txt_xlsx: Migration to 13.0
This commit is contained in:
committed by
Sergio Zanchetta
parent
51e4044692
commit
1e0efc397a
@@ -14,13 +14,13 @@ Account Bank Statement Import TXT XLSX
|
||||
: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/12.0/account_bank_statement_import_txt_xlsx
|
||||
:target: https://github.com/OCA/bank-statement-import/tree/13.0/account_bank_statement_import_txt_xlsx
|
||||
: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-12-0/bank-statement-import-12-0-account_bank_statement_import_txt_xlsx
|
||||
:target: https://translation.odoo-community.org/projects/bank-statement-import-13.0/bank-statement-import-13.0-account_bank_statement_import_txt_xlsx
|
||||
:alt: Translate me on Weblate
|
||||
.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png
|
||||
:target: https://runbot.odoo-community.org/runbot/174/12.0
|
||||
:target: https://runbot.odoo-community.org/runbot/174/13.0
|
||||
:alt: Try me on Runbot
|
||||
|
||||
|badge1| |badge2| |badge3| |badge4| |badge5|
|
||||
@@ -62,7 +62,7 @@ Bug Tracker
|
||||
Bugs are tracked on `GitHub Issues <https://github.com/OCA/bank-statement-import/issues>`_.
|
||||
In case of trouble, please check there if your issue has already been reported.
|
||||
If you spotted it first, help us smashing it by providing a detailed and welcomed
|
||||
`feedback <https://github.com/OCA/bank-statement-import/issues/new?body=module:%20account_bank_statement_import_txt_xlsx%0Aversion:%2012.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
|
||||
`feedback <https://github.com/OCA/bank-statement-import/issues/new?body=module:%20account_bank_statement_import_txt_xlsx%0Aversion:%2013.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
|
||||
|
||||
Do not contact contributors directly about support or help with technical issues.
|
||||
|
||||
@@ -72,7 +72,7 @@ Credits
|
||||
Authors
|
||||
~~~~~~~
|
||||
|
||||
* Eficent
|
||||
* ForgeFlow
|
||||
|
||||
Contributors
|
||||
~~~~~~~~~~~~
|
||||
@@ -82,8 +82,8 @@ Contributors
|
||||
* Tecnativa (https://www.tecnativa.com)
|
||||
* Vicent Cubells <vicent.cubells@tecnativa.com>
|
||||
* Victor M.M. Torres <victor.martin@tecnativa.com>
|
||||
* Eficent (https://www.eficent.com)
|
||||
* Jordi Ballester Alomar <jordi.ballester@eficent.com>
|
||||
* ForgeFlow (https://www.forgeflow.com)
|
||||
* Jordi Ballester Alomar <jordi.ballester@forgeflow.com>
|
||||
|
||||
Maintainers
|
||||
~~~~~~~~~~~
|
||||
@@ -98,6 +98,6 @@ 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 <https://github.com/OCA/bank-statement-import/tree/12.0/account_bank_statement_import_txt_xlsx>`_ project on GitHub.
|
||||
This module is part of the `OCA/bank-statement-import <https://github.com/OCA/bank-statement-import/tree/13.0/account_bank_statement_import_txt_xlsx>`_ project on GitHub.
|
||||
|
||||
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
|
||||
|
||||
@@ -5,10 +5,10 @@
|
||||
{
|
||||
"name": "Account Bank Statement Import TXT XLSX",
|
||||
"summary": "Import TXT/CSV or XLSX files as Bank Statements in Odoo",
|
||||
"version": "12.0.2.0.0",
|
||||
"version": "13.0.1.0.0",
|
||||
"category": "Accounting",
|
||||
"website": "https://github.com/OCA/bank-statement-import",
|
||||
"author": "ForgeFlow, " "Brainbean Apps, " "Odoo Community Association (OCA)",
|
||||
"author": "ForgeFlow, Brainbean Apps, Odoo Community Association (OCA)",
|
||||
"license": "AGPL-3",
|
||||
"installable": True,
|
||||
"depends": [
|
||||
@@ -16,7 +16,7 @@
|
||||
"multi_step_wizard",
|
||||
"web_widget_dropdown_dynamic",
|
||||
],
|
||||
"external_dependencies": {"python": ["csv", "xlrd",]},
|
||||
"external_dependencies": {"python": ["csv", "xlrd"]},
|
||||
"data": [
|
||||
"security/ir.model.access.csv",
|
||||
"data/map_data.xml",
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Odoo Server 12.0\n"
|
||||
"Project-Id-Version: Odoo Server 13.0\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"Last-Translator: <>\n"
|
||||
"Language-Team: \n"
|
||||
|
||||
@@ -1,98 +0,0 @@
|
||||
# Copyright 2020 Brainbean Apps (https://brainbeanapps.com)
|
||||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
|
||||
|
||||
from openupgradelib import openupgrade
|
||||
|
||||
|
||||
@openupgrade.migrate()
|
||||
def migrate(env, version):
|
||||
openupgrade.logged_query(
|
||||
env.cr,
|
||||
"""
|
||||
WITH _mappings AS (
|
||||
SELECT
|
||||
m.id,
|
||||
l.field_to_assign,
|
||||
l.name,
|
||||
l.date_format
|
||||
FROM
|
||||
account_bank_statement_import_map AS m
|
||||
RIGHT OUTER JOIN (
|
||||
SELECT
|
||||
*,
|
||||
ROW_NUMBER() OVER (
|
||||
PARTITION BY map_parent_id, field_to_assign
|
||||
ORDER BY id ASC
|
||||
) AS row_number
|
||||
FROM account_bank_statement_import_map_line
|
||||
WHERE field_to_assign IS NOT NULL
|
||||
) AS l ON m.id = l.map_parent_id AND l.row_number = 1
|
||||
)
|
||||
|
||||
INSERT INTO account_bank_statement_import_sheet_mapping (
|
||||
name,
|
||||
float_thousands_sep,
|
||||
float_decimal_sep,
|
||||
file_encoding,
|
||||
delimiter,
|
||||
quotechar,
|
||||
timestamp_format,
|
||||
timestamp_column,
|
||||
amount_column,
|
||||
original_currency_column,
|
||||
original_amount_column,
|
||||
description_column,
|
||||
reference_column,
|
||||
notes_column,
|
||||
partner_name_column,
|
||||
bank_account_column
|
||||
)
|
||||
SELECT
|
||||
m.name,
|
||||
m.float_thousands_sep,
|
||||
m.float_decimal_sep,
|
||||
m.file_encoding,
|
||||
(
|
||||
CASE
|
||||
WHEN m.delimiter='.' THEN 'dot'
|
||||
WHEN m.delimiter=',' THEN 'comma'
|
||||
WHEN m.delimiter=';' THEN 'semicolon'
|
||||
WHEN m.delimiter='' THEN 'n/a'
|
||||
WHEN m.delimiter='\t' THEN 'tab'
|
||||
WHEN m.delimiter=' ' THEN 'space'
|
||||
ELSE 'n/a'
|
||||
END
|
||||
) AS delimiter,
|
||||
m.quotechar,
|
||||
COALESCE(_date.date_format, '%m/%d/%Y') AS timestamp_format,
|
||||
COALESCE(_date.name, 'Date') AS timestamp_column,
|
||||
COALESCE(_amount.name, 'Amount') AS amount_column,
|
||||
_o_currency.name AS original_currency_column,
|
||||
_o_amount.name AS original_amount_column,
|
||||
_description.name AS description_column,
|
||||
_ref.name AS reference_column,
|
||||
_notes.name AS notes_column,
|
||||
_p_name.name AS partner_name_column,
|
||||
_bank_acc.name AS bank_account_column
|
||||
FROM
|
||||
account_bank_statement_import_map AS m
|
||||
LEFT JOIN _mappings AS _date
|
||||
ON m.id = _date.id AND _date.field_to_assign = 'date'
|
||||
LEFT JOIN _mappings AS _description
|
||||
ON m.id = _description.id AND _description.field_to_assign = 'name'
|
||||
LEFT JOIN _mappings AS _o_currency
|
||||
ON m.id = _o_currency.id AND _o_currency.field_to_assign = 'currency'
|
||||
LEFT JOIN _mappings AS _amount
|
||||
ON m.id = _amount.id AND _amount.field_to_assign = 'amount'
|
||||
LEFT JOIN _mappings AS _o_amount
|
||||
ON m.id = _o_amount.id AND _o_amount.field_to_assign = 'amount_currency'
|
||||
LEFT JOIN _mappings AS _ref
|
||||
ON m.id = _ref.id AND _ref.field_to_assign = 'ref'
|
||||
LEFT JOIN _mappings AS _notes
|
||||
ON m.id = _notes.id AND _notes.field_to_assign = 'note'
|
||||
LEFT JOIN _mappings AS _p_name
|
||||
ON m.id = _p_name.id AND _p_name.field_to_assign = 'partner_name'
|
||||
LEFT JOIN _mappings AS _bank_acc
|
||||
ON m.id = _bank_acc.id AND _bank_acc.field_to_assign = 'account_number';
|
||||
""",
|
||||
)
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
import logging
|
||||
|
||||
from odoo import api, fields, models
|
||||
from odoo import fields, models
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -24,13 +24,12 @@ class AccountBankStatementImport(models.TransientModel):
|
||||
default=_get_default_mapping_id,
|
||||
)
|
||||
|
||||
@api.multi
|
||||
def _parse_file(self, data_file):
|
||||
self.ensure_one()
|
||||
try:
|
||||
Parser = self.env["account.bank.statement.import.sheet.parser"]
|
||||
return Parser.parse(self.sheet_mapping_id, data_file, self.filename)
|
||||
except:
|
||||
return Parser.parse(data_file, self.sheet_mapping_id)
|
||||
except BaseException:
|
||||
if self.env.context.get("account_bank_statement_import_txt_xlsx_test"):
|
||||
raise
|
||||
_logger.warning("Sheet parser error", exc_info=True)
|
||||
|
||||
@@ -12,12 +12,12 @@ class AccountBankStatementImportSheetMapping(models.Model):
|
||||
name = fields.Char(required=True,)
|
||||
float_thousands_sep = fields.Selection(
|
||||
string="Thousands Separator",
|
||||
selection=[("dot", "dot (.)"), ("comma", "comma (,)"), ("none", "none"),],
|
||||
selection=[("dot", "dot (.)"), ("comma", "comma (,)"), ("none", "none")],
|
||||
default="dot",
|
||||
)
|
||||
float_decimal_sep = fields.Selection(
|
||||
string="Decimals Separator",
|
||||
selection=[("dot", "dot (.)"), ("comma", "comma (,)"), ("none", "none"),],
|
||||
selection=[("dot", "dot (.)"), ("comma", "comma (,)"), ("none", "none")],
|
||||
default="comma",
|
||||
)
|
||||
file_encoding = fields.Selection(
|
||||
@@ -52,9 +52,9 @@ class AccountBankStatementImportSheetMapping(models.Model):
|
||||
],
|
||||
default="comma",
|
||||
)
|
||||
quotechar = fields.Char(string="Text qualifier", size=1, default='"',)
|
||||
timestamp_format = fields.Char(string="Timestamp Format", required=True,)
|
||||
timestamp_column = fields.Char(string="Timestamp column", required=True,)
|
||||
quotechar = fields.Char(string="Text qualifier", size=1, default='"')
|
||||
timestamp_format = fields.Char(string="Timestamp Format", required=True)
|
||||
timestamp_column = fields.Char(string="Timestamp column", required=True)
|
||||
currency_column = fields.Char(
|
||||
string="Currency column",
|
||||
help=(
|
||||
@@ -127,7 +127,6 @@ class AccountBankStatementImportSheetMapping(models.Model):
|
||||
elif "comma" == self.float_thousands_sep == self.float_decimal_sep:
|
||||
self.float_thousands_sep = "dot"
|
||||
|
||||
@api.multi
|
||||
def _get_float_separators(self):
|
||||
self.ensure_one()
|
||||
separators = {
|
||||
@@ -143,9 +142,8 @@ class AccountBankStatementImportSheetMapping(models.Model):
|
||||
@api.model
|
||||
def _decode_column_delimiter_character(self, delimiter):
|
||||
return (
|
||||
{"dot": ".", "comma": ",", "semicolon": ";", "tab": "\t", "space": " ",}
|
||||
{"dot": ".", "comma": ",", "semicolon": ";", "tab": "\t", "space": " "}
|
||||
).get(delimiter)
|
||||
|
||||
@api.multi
|
||||
def _get_column_delimiter_character(self):
|
||||
return self._decode_column_delimiter_character(self.delimiter)
|
||||
|
||||
@@ -7,7 +7,6 @@ import logging
|
||||
from datetime import datetime
|
||||
from decimal import Decimal
|
||||
from io import StringIO
|
||||
from os import path
|
||||
|
||||
from odoo import _, api, models
|
||||
|
||||
@@ -43,21 +42,19 @@ class AccountBankStatementImportSheetParser(models.TransientModel):
|
||||
return list(next(csv_data))
|
||||
|
||||
@api.model
|
||||
def parse(self, mapping, data_file, filename):
|
||||
def parse(self, data_file, mapping):
|
||||
journal = self.env["account.journal"].browse(self.env.context.get("journal_id"))
|
||||
currency_code = (journal.currency_id or journal.company_id.currency_id).name
|
||||
account_number = journal.bank_account_id.acc_number
|
||||
|
||||
name = _("%s: %s") % (journal.code, path.basename(filename),)
|
||||
lines = self._parse_lines(mapping, data_file, currency_code)
|
||||
if not lines:
|
||||
return currency_code, account_number, [{"name": name, "transactions": [],}]
|
||||
return currency_code, account_number, [{"transactions": []}]
|
||||
|
||||
lines = list(sorted(lines, key=lambda line: line["timestamp"]))
|
||||
first_line = lines[0]
|
||||
last_line = lines[-1]
|
||||
data = {
|
||||
"name": name,
|
||||
"date": first_line["timestamp"].date(),
|
||||
}
|
||||
|
||||
@@ -77,13 +74,12 @@ class AccountBankStatementImportSheetParser(models.TransientModel):
|
||||
map(lambda line: self._convert_line_to_transactions(line), lines)
|
||||
)
|
||||
)
|
||||
data.update(
|
||||
{"transactions": transactions,}
|
||||
)
|
||||
data.update({"transactions": transactions})
|
||||
|
||||
return currency_code, account_number, [data]
|
||||
|
||||
def _parse_lines(self, mapping, data_file, currency_code):
|
||||
columns = dict()
|
||||
try:
|
||||
workbook = xlrd.open_workbook(
|
||||
file_contents=data_file,
|
||||
@@ -111,59 +107,61 @@ class AccountBankStatementImportSheetParser(models.TransientModel):
|
||||
header = [str(value) for value in csv_or_xlsx[1].row_values(0)]
|
||||
else:
|
||||
header = [value.strip() for value in next(csv_or_xlsx)]
|
||||
timestamp_column = header.index(mapping.timestamp_column)
|
||||
currency_column = (
|
||||
columns["timestamp_column"] = header.index(mapping.timestamp_column)
|
||||
columns["currency_column"] = (
|
||||
header.index(mapping.currency_column) if mapping.currency_column else None
|
||||
)
|
||||
amount_column = header.index(mapping.amount_column)
|
||||
balance_column = (
|
||||
columns["amount_column"] = header.index(mapping.amount_column)
|
||||
columns["balance_column"] = (
|
||||
header.index(mapping.balance_column) if mapping.balance_column else None
|
||||
)
|
||||
original_currency_column = (
|
||||
columns["original_currency_column"] = (
|
||||
header.index(mapping.original_currency_column)
|
||||
if mapping.original_currency_column
|
||||
else None
|
||||
)
|
||||
original_amount_column = (
|
||||
columns["original_amount_column"] = (
|
||||
header.index(mapping.original_amount_column)
|
||||
if mapping.original_amount_column
|
||||
else None
|
||||
)
|
||||
debit_credit_column = (
|
||||
columns["debit_credit_column"] = (
|
||||
header.index(mapping.debit_credit_column)
|
||||
if mapping.debit_credit_column
|
||||
else None
|
||||
)
|
||||
transaction_id_column = (
|
||||
columns["transaction_id_column"] = (
|
||||
header.index(mapping.transaction_id_column)
|
||||
if mapping.transaction_id_column
|
||||
else None
|
||||
)
|
||||
description_column = (
|
||||
columns["description_column"] = (
|
||||
header.index(mapping.description_column)
|
||||
if mapping.description_column
|
||||
else None
|
||||
)
|
||||
notes_column = (
|
||||
columns["notes_column"] = (
|
||||
header.index(mapping.notes_column) if mapping.notes_column else None
|
||||
)
|
||||
reference_column = (
|
||||
columns["reference_column"] = (
|
||||
header.index(mapping.reference_column) if mapping.reference_column else None
|
||||
)
|
||||
partner_name_column = (
|
||||
columns["partner_name_column"] = (
|
||||
header.index(mapping.partner_name_column)
|
||||
if mapping.partner_name_column
|
||||
else None
|
||||
)
|
||||
bank_name_column = (
|
||||
columns["bank_name_column"] = (
|
||||
header.index(mapping.bank_name_column) if mapping.bank_name_column else None
|
||||
)
|
||||
bank_account_column = (
|
||||
columns["bank_account_column"] = (
|
||||
header.index(mapping.bank_account_column)
|
||||
if mapping.bank_account_column
|
||||
else None
|
||||
)
|
||||
return self._parse_rows(mapping, currency_code, csv_or_xlsx, columns)
|
||||
|
||||
def _parse_rows(self, mapping, currency_code, csv_or_xlsx, columns): # noqa: C901
|
||||
if isinstance(csv_or_xlsx, tuple):
|
||||
rows = range(1, csv_or_xlsx[1].nrows)
|
||||
else:
|
||||
@@ -184,47 +182,67 @@ class AccountBankStatementImportSheetParser(models.TransientModel):
|
||||
else:
|
||||
values = list(row)
|
||||
|
||||
timestamp = values[timestamp_column]
|
||||
timestamp = values[columns["timestamp_column"]]
|
||||
currency = (
|
||||
values[currency_column]
|
||||
if currency_column is not None
|
||||
values[columns["currency_column"]]
|
||||
if columns["currency_column"] is not None
|
||||
else currency_code
|
||||
)
|
||||
amount = values[amount_column]
|
||||
balance = values[balance_column] if balance_column is not None else None
|
||||
amount = values[columns["amount_column"]]
|
||||
balance = (
|
||||
values[columns["balance_column"]]
|
||||
if columns["balance_column"] is not None
|
||||
else None
|
||||
)
|
||||
original_currency = (
|
||||
values[original_currency_column]
|
||||
if original_currency_column is not None
|
||||
values[columns["original_currency_column"]]
|
||||
if columns["original_currency_column"] is not None
|
||||
else None
|
||||
)
|
||||
original_amount = (
|
||||
values[original_amount_column]
|
||||
if original_amount_column is not None
|
||||
values[columns["original_amount_column"]]
|
||||
if columns["original_amount_column"] is not None
|
||||
else None
|
||||
)
|
||||
debit_credit = (
|
||||
values[debit_credit_column] if debit_credit_column is not None else None
|
||||
values[columns["debit_credit_column"]]
|
||||
if columns["debit_credit_column"] is not None
|
||||
else None
|
||||
)
|
||||
transaction_id = (
|
||||
values[transaction_id_column]
|
||||
if transaction_id_column is not None
|
||||
values[columns["transaction_id_column"]]
|
||||
if columns["transaction_id_column"] is not None
|
||||
else None
|
||||
)
|
||||
description = (
|
||||
values[description_column] if description_column is not None else None
|
||||
values[columns["description_column"]]
|
||||
if columns["description_column"] is not None
|
||||
else None
|
||||
)
|
||||
notes = (
|
||||
values[columns["notes_column"]]
|
||||
if columns["notes_column"] is not None
|
||||
else None
|
||||
)
|
||||
notes = values[notes_column] if notes_column is not None else None
|
||||
reference = (
|
||||
values[reference_column] if reference_column is not None else None
|
||||
values[columns["reference_column"]]
|
||||
if columns["reference_column"] is not None
|
||||
else None
|
||||
)
|
||||
partner_name = (
|
||||
values[partner_name_column] if partner_name_column is not None else None
|
||||
values[columns["partner_name_column"]]
|
||||
if columns["partner_name_column"] is not None
|
||||
else None
|
||||
)
|
||||
bank_name = (
|
||||
values[bank_name_column] if bank_name_column is not None else None
|
||||
values[columns["bank_name_column"]]
|
||||
if columns["bank_name_column"] is not None
|
||||
else None
|
||||
)
|
||||
bank_account = (
|
||||
values[bank_account_column] if bank_account_column is not None else None
|
||||
values[columns["bank_account_column"]]
|
||||
if columns["bank_account_column"] is not None
|
||||
else None
|
||||
)
|
||||
|
||||
if currency != currency_code:
|
||||
@@ -310,8 +328,7 @@ class AccountBankStatementImportSheetParser(models.TransientModel):
|
||||
|
||||
if transaction_id:
|
||||
transaction["unique_import_id"] = "{}-{}".format(
|
||||
transaction_id,
|
||||
int(timestamp.timestamp()),
|
||||
transaction_id, int(timestamp.timestamp()),
|
||||
)
|
||||
|
||||
transaction["name"] = description or _("N/A")
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* Tecnativa (https://www.tecnativa.com)
|
||||
* Vicent Cubells <vicent.cubells@tecnativa.com>
|
||||
* Victor M.M. Torres <victor.martin@tecnativa.com>
|
||||
* Eficent (https://www.eficent.com)
|
||||
* Jordi Ballester Alomar <jordi.ballester@eficent.com>
|
||||
* ForgeFlow (https://www.forgeflow.com)
|
||||
* Jordi Ballester Alomar <jordi.ballester@forgeflow.com>
|
||||
* Miquel Raïch Regué <miquel.raich@forgeflow.com>
|
||||
* Alexey Pelykh <alexey.pelykh@brainbeanapps.com>
|
||||
|
||||
@@ -367,7 +367,7 @@ ul.auto-toc {
|
||||
!! This file is generated by oca-gen-addon-readme !!
|
||||
!! changes will be overwritten. !!
|
||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
|
||||
<p><a class="reference external" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external" href="https://github.com/OCA/bank-statement-import/tree/12.0/account_bank_statement_import_txt_xlsx"><img alt="OCA/bank-statement-import" src="https://img.shields.io/badge/github-OCA%2Fbank--statement--import-lightgray.png?logo=github" /></a> <a class="reference external" href="https://translation.odoo-community.org/projects/bank-statement-import-12-0/bank-statement-import-12-0-account_bank_statement_import_txt_xlsx"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external" href="https://runbot.odoo-community.org/runbot/174/12.0"><img alt="Try me on Runbot" src="https://img.shields.io/badge/runbot-Try%20me-875A7B.png" /></a></p>
|
||||
<p><a class="reference external" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external" href="https://github.com/OCA/bank-statement-import/tree/13.0/account_bank_statement_import_txt_xlsx"><img alt="OCA/bank-statement-import" src="https://img.shields.io/badge/github-OCA%2Fbank--statement--import-lightgray.png?logo=github" /></a> <a class="reference external" href="https://translation.odoo-community.org/projects/bank-statement-import-13.0/bank-statement-import-13.0-account_bank_statement_import_txt_xlsx"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external" href="https://runbot.odoo-community.org/runbot/174/13.0"><img alt="Try me on Runbot" src="https://img.shields.io/badge/runbot-Try%20me-875A7B.png" /></a></p>
|
||||
<p>This module allows you to import the any TXT/CSV or XLSX file in Odoo as bank
|
||||
statements.</p>
|
||||
<p><strong>Table of contents</strong></p>
|
||||
@@ -410,7 +410,7 @@ Lines</strong> and set every line with which field of statement have to match.</
|
||||
<p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/bank-statement-import/issues">GitHub Issues</a>.
|
||||
In case of trouble, please check there if your issue has already been reported.
|
||||
If you spotted it first, help us smashing it by providing a detailed and welcomed
|
||||
<a class="reference external" href="https://github.com/OCA/bank-statement-import/issues/new?body=module:%20account_bank_statement_import_txt_xlsx%0Aversion:%2012.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
|
||||
<a class="reference external" href="https://github.com/OCA/bank-statement-import/issues/new?body=module:%20account_bank_statement_import_txt_xlsx%0Aversion:%2013.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
|
||||
<p>Do not contact contributors directly about support or help with technical issues.</p>
|
||||
</div>
|
||||
<div class="section" id="credits">
|
||||
@@ -418,7 +418,7 @@ If you spotted it first, help us smashing it by providing a detailed and welcome
|
||||
<div class="section" id="authors">
|
||||
<h2><a class="toc-backref" href="#id5">Authors</a></h2>
|
||||
<ul class="simple">
|
||||
<li>Eficent</li>
|
||||
<li>ForgeFlow</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="contributors">
|
||||
@@ -429,8 +429,8 @@ If you spotted it first, help us smashing it by providing a detailed and welcome
|
||||
<li>Tecnativa (<a class="reference external" href="https://www.tecnativa.com">https://www.tecnativa.com</a>)
|
||||
* Vicent Cubells <<a class="reference external" href="mailto:vicent.cubells@tecnativa.com">vicent.cubells@tecnativa.com</a>>
|
||||
* Victor M.M. Torres <<a class="reference external" href="mailto:victor.martin@tecnativa.com">victor.martin@tecnativa.com</a>></li>
|
||||
<li>Eficent (<a class="reference external" href="https://www.eficent.com">https://www.eficent.com</a>)
|
||||
* Jordi Ballester Alomar <<a class="reference external" href="mailto:jordi.ballester@eficent.com">jordi.ballester@eficent.com</a>></li>
|
||||
<li>ForgeFlow (<a class="reference external" href="https://www.forgeflow.com">https://www.forgeflow.com</a>)
|
||||
* Jordi Ballester Alomar <<a class="reference external" href="mailto:jordi.ballester@forgeflow.com">jordi.ballester@forgeflow.com</a>></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="maintainers">
|
||||
@@ -440,7 +440,7 @@ If you spotted it first, help us smashing it by providing a detailed and welcome
|
||||
<p>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.</p>
|
||||
<p>This module is part of the <a class="reference external" href="https://github.com/OCA/bank-statement-import/tree/12.0/account_bank_statement_import_txt_xlsx">OCA/bank-statement-import</a> project on GitHub.</p>
|
||||
<p>This module is part of the <a class="reference external" href="https://github.com/OCA/bank-statement-import/tree/13.0/account_bank_statement_import_txt_xlsx">OCA/bank-statement-import</a> project on GitHub.</p>
|
||||
<p>You are welcome to contribute. To learn how please visit <a class="reference external" href="https://odoo-community.org/page/Contribute">https://odoo-community.org/page/Contribute</a>.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -47,24 +47,21 @@ class TestAccountBankStatementImportTxtXlsx(common.TransactionCase):
|
||||
"currency_id": self.currency_usd.id,
|
||||
}
|
||||
)
|
||||
data = self._data_file("fixtures/sample_statement_en.csv", "utf-8")
|
||||
wizard = self.AccountBankStatementImport.with_context(
|
||||
{"journal_id": journal.id,}
|
||||
journal_id=journal.id
|
||||
).create(
|
||||
{
|
||||
"filename": "fixtures/sample_statement_en.csv",
|
||||
"data_file": self._data_file(
|
||||
"fixtures/sample_statement_en.csv", "utf-8"
|
||||
),
|
||||
"attachment_ids": [
|
||||
(0, 0, {"name": "fixtures/sample_statement_en.csv", "datas": data})
|
||||
],
|
||||
"sheet_mapping_id": self.sample_statement_map.id,
|
||||
}
|
||||
)
|
||||
wizard.with_context(
|
||||
{
|
||||
"journal_id": journal.id,
|
||||
"account_bank_statement_import_txt_xlsx_test": True,
|
||||
}
|
||||
account_bank_statement_import_txt_xlsx_test=True
|
||||
).import_file()
|
||||
statement = self.AccountBankStatement.search([("journal_id", "=", journal.id),])
|
||||
statement = self.AccountBankStatement.search([("journal_id", "=", journal.id)])
|
||||
self.assertEqual(len(statement), 1)
|
||||
self.assertEqual(len(statement.line_ids), 2)
|
||||
|
||||
@@ -77,25 +74,22 @@ class TestAccountBankStatementImportTxtXlsx(common.TransactionCase):
|
||||
"currency_id": self.currency_usd.id,
|
||||
}
|
||||
)
|
||||
data = self._data_file("fixtures/empty_statement_en.csv", "utf-8")
|
||||
wizard = self.AccountBankStatementImport.with_context(
|
||||
{"journal_id": journal.id,}
|
||||
journal_id=journal.id
|
||||
).create(
|
||||
{
|
||||
"filename": "fixtures/empty_statement_en.csv",
|
||||
"data_file": self._data_file(
|
||||
"fixtures/empty_statement_en.csv", "utf-8"
|
||||
),
|
||||
"attachment_ids": [
|
||||
(0, 0, {"name": "fixtures/empty_statement_en.csv", "datas": data})
|
||||
],
|
||||
"sheet_mapping_id": self.sample_statement_map.id,
|
||||
}
|
||||
)
|
||||
with self.assertRaises(UserError):
|
||||
wizard.with_context(
|
||||
{
|
||||
"journal_id": journal.id,
|
||||
"account_bank_statement_import_txt_xlsx_test": True,
|
||||
}
|
||||
account_bank_statement_import_txt_xlsx_test=True
|
||||
).import_file()
|
||||
statement = self.AccountBankStatement.search([("journal_id", "=", journal.id),])
|
||||
statement = self.AccountBankStatement.search([("journal_id", "=", journal.id)])
|
||||
self.assertEqual(len(statement), 0)
|
||||
|
||||
def test_import_xlsx_file(self):
|
||||
@@ -107,22 +101,21 @@ class TestAccountBankStatementImportTxtXlsx(common.TransactionCase):
|
||||
"currency_id": self.currency_usd.id,
|
||||
}
|
||||
)
|
||||
data = self._data_file("fixtures/sample_statement_en.xlsx")
|
||||
wizard = self.AccountBankStatementImport.with_context(
|
||||
{"journal_id": journal.id,}
|
||||
journal_id=journal.id
|
||||
).create(
|
||||
{
|
||||
"filename": "fixtures/sample_statement_en.xlsx",
|
||||
"data_file": self._data_file("fixtures/sample_statement_en.xlsx"),
|
||||
"attachment_ids": [
|
||||
(0, 0, {"name": "fixtures/sample_statement_en.xlsx", "datas": data})
|
||||
],
|
||||
"sheet_mapping_id": self.sample_statement_map.id,
|
||||
}
|
||||
)
|
||||
wizard.with_context(
|
||||
{
|
||||
"journal_id": journal.id,
|
||||
"account_bank_statement_import_txt_xlsx_test": True,
|
||||
}
|
||||
account_bank_statement_import_txt_xlsx_test=True
|
||||
).import_file()
|
||||
statement = self.AccountBankStatement.search([("journal_id", "=", journal.id),])
|
||||
statement = self.AccountBankStatement.search([("journal_id", "=", journal.id)])
|
||||
self.assertEqual(len(statement), 1)
|
||||
self.assertEqual(len(statement.line_ids), 2)
|
||||
|
||||
@@ -135,29 +128,33 @@ class TestAccountBankStatementImportTxtXlsx(common.TransactionCase):
|
||||
"currency_id": self.currency_usd.id,
|
||||
}
|
||||
)
|
||||
data = self._data_file("fixtures/empty_statement_en.xlsx")
|
||||
wizard = self.AccountBankStatementImport.with_context(
|
||||
{"journal_id": journal.id,}
|
||||
journal_id=journal.id
|
||||
).create(
|
||||
{
|
||||
"filename": "fixtures/empty_statement_en.xlsx",
|
||||
"data_file": self._data_file("fixtures/empty_statement_en.xlsx"),
|
||||
"attachment_ids": [
|
||||
(0, 0, {"name": "fixtures/empty_statement_en.xlsx", "datas": data})
|
||||
],
|
||||
"sheet_mapping_id": self.sample_statement_map.id,
|
||||
}
|
||||
)
|
||||
with self.assertRaises(UserError):
|
||||
wizard.with_context(
|
||||
{
|
||||
"journal_id": journal.id,
|
||||
"account_bank_statement_import_txt_xlsx_test": True,
|
||||
}
|
||||
account_bank_statement_import_txt_xlsx_test=True
|
||||
).import_file()
|
||||
statement = self.AccountBankStatement.search([("journal_id", "=", journal.id),])
|
||||
statement = self.AccountBankStatement.search([("journal_id", "=", journal.id)])
|
||||
self.assertEqual(len(statement), 0)
|
||||
|
||||
def test_mapping_import_wizard_xlsx(self):
|
||||
with common.Form(self.AccountBankStatementImportSheetMappingWizard) as form:
|
||||
form.filename = "fixtures/empty_statement_en.xlsx"
|
||||
form.data_file = self._data_file("fixtures/empty_statement_en.xlsx")
|
||||
attachment = self.env["ir.attachment"].create(
|
||||
{
|
||||
"name": "fixtures/empty_statement_en.xlsx",
|
||||
"datas": self._data_file("fixtures/empty_statement_en.xlsx"),
|
||||
}
|
||||
)
|
||||
form.attachment_ids.add(attachment)
|
||||
self.assertEqual(len(form.header), 90)
|
||||
self.assertEqual(
|
||||
len(
|
||||
@@ -174,8 +171,13 @@ class TestAccountBankStatementImportTxtXlsx(common.TransactionCase):
|
||||
|
||||
def test_mapping_import_wizard_csv(self):
|
||||
with common.Form(self.AccountBankStatementImportSheetMappingWizard) as form:
|
||||
form.filename = "fixtures/empty_statement_en.csv"
|
||||
form.data_file = self._data_file("fixtures/empty_statement_en.csv")
|
||||
attachment = self.env["ir.attachment"].create(
|
||||
{
|
||||
"name": "fixtures/empty_statement_en.csv",
|
||||
"datas": self._data_file("fixtures/empty_statement_en.csv"),
|
||||
}
|
||||
)
|
||||
form.attachment_ids.add(attachment)
|
||||
self.assertEqual(len(form.header), 90)
|
||||
self.assertEqual(
|
||||
len(
|
||||
@@ -199,22 +201,21 @@ class TestAccountBankStatementImportTxtXlsx(common.TransactionCase):
|
||||
"currency_id": self.currency_usd.id,
|
||||
}
|
||||
)
|
||||
data = self._data_file("fixtures/original_currency.csv", "utf-8")
|
||||
wizard = self.AccountBankStatementImport.with_context(
|
||||
{"journal_id": journal.id,}
|
||||
journal_id=journal.id
|
||||
).create(
|
||||
{
|
||||
"filename": "fixtures/original_currency.csv",
|
||||
"data_file": self._data_file("fixtures/original_currency.csv", "utf-8"),
|
||||
"attachment_ids": [
|
||||
(0, 0, {"name": "fixtures/original_currency.csv", "datas": data})
|
||||
],
|
||||
"sheet_mapping_id": self.sample_statement_map.id,
|
||||
}
|
||||
)
|
||||
wizard.with_context(
|
||||
{
|
||||
"journal_id": journal.id,
|
||||
"account_bank_statement_import_txt_xlsx_test": True,
|
||||
}
|
||||
account_bank_statement_import_txt_xlsx_test=True
|
||||
).import_file()
|
||||
statement = self.AccountBankStatement.search([("journal_id", "=", journal.id),])
|
||||
statement = self.AccountBankStatement.search([("journal_id", "=", journal.id)])
|
||||
self.assertEqual(len(statement), 1)
|
||||
self.assertEqual(len(statement.line_ids), 1)
|
||||
|
||||
@@ -238,22 +239,21 @@ class TestAccountBankStatementImportTxtXlsx(common.TransactionCase):
|
||||
"original_amount_column": None,
|
||||
}
|
||||
)
|
||||
data = self._data_file("fixtures/multi_currency.csv", "utf-8")
|
||||
wizard = self.AccountBankStatementImport.with_context(
|
||||
{"journal_id": journal.id,}
|
||||
journal_id=journal.id
|
||||
).create(
|
||||
{
|
||||
"filename": "fixtures/multi_currency.csv",
|
||||
"data_file": self._data_file("fixtures/multi_currency.csv", "utf-8"),
|
||||
"attachment_ids": [
|
||||
(0, 0, {"name": "fixtures/multi_currency.csv", "datas": data})
|
||||
],
|
||||
"sheet_mapping_id": statement_map.id,
|
||||
}
|
||||
)
|
||||
wizard.with_context(
|
||||
{
|
||||
"journal_id": journal.id,
|
||||
"account_bank_statement_import_txt_xlsx_test": True,
|
||||
}
|
||||
account_bank_statement_import_txt_xlsx_test=True
|
||||
).import_file()
|
||||
statement = self.AccountBankStatement.search([("journal_id", "=", journal.id),])
|
||||
statement = self.AccountBankStatement.search([("journal_id", "=", journal.id)])
|
||||
self.assertEqual(len(statement), 1)
|
||||
self.assertEqual(len(statement.line_ids), 1)
|
||||
|
||||
@@ -277,22 +277,21 @@ class TestAccountBankStatementImportTxtXlsx(common.TransactionCase):
|
||||
"original_amount_column": None,
|
||||
}
|
||||
)
|
||||
data = self._data_file("fixtures/balance.csv", "utf-8")
|
||||
wizard = self.AccountBankStatementImport.with_context(
|
||||
{"journal_id": journal.id,}
|
||||
journal_id=journal.id
|
||||
).create(
|
||||
{
|
||||
"filename": "fixtures/balance.csv",
|
||||
"data_file": self._data_file("fixtures/balance.csv", "utf-8"),
|
||||
"attachment_ids": [
|
||||
(0, 0, {"name": "fixtures/balance.csv", "datas": data})
|
||||
],
|
||||
"sheet_mapping_id": statement_map.id,
|
||||
}
|
||||
)
|
||||
wizard.with_context(
|
||||
{
|
||||
"journal_id": journal.id,
|
||||
"account_bank_statement_import_txt_xlsx_test": True,
|
||||
}
|
||||
account_bank_statement_import_txt_xlsx_test=True
|
||||
).import_file()
|
||||
statement = self.AccountBankStatement.search([("journal_id", "=", journal.id),])
|
||||
statement = self.AccountBankStatement.search([("journal_id", "=", journal.id)])
|
||||
self.assertEqual(len(statement), 1)
|
||||
self.assertEqual(len(statement.line_ids), 2)
|
||||
self.assertEqual(statement.balance_start, 10.0)
|
||||
@@ -318,22 +317,21 @@ class TestAccountBankStatementImportTxtXlsx(common.TransactionCase):
|
||||
"credit_value": "C",
|
||||
}
|
||||
)
|
||||
data = self._data_file("fixtures/debit_credit.csv", "utf-8")
|
||||
wizard = self.AccountBankStatementImport.with_context(
|
||||
{"journal_id": journal.id,}
|
||||
journal_id=journal.id
|
||||
).create(
|
||||
{
|
||||
"filename": "fixtures/debit_credit.csv",
|
||||
"data_file": self._data_file("fixtures/debit_credit.csv", "utf-8"),
|
||||
"attachment_ids": [
|
||||
(0, 0, {"name": "fixtures/debit_credit.csv", "datas": data})
|
||||
],
|
||||
"sheet_mapping_id": statement_map.id,
|
||||
}
|
||||
)
|
||||
wizard.with_context(
|
||||
{
|
||||
"journal_id": journal.id,
|
||||
"account_bank_statement_import_txt_xlsx_test": True,
|
||||
}
|
||||
account_bank_statement_import_txt_xlsx_test=True
|
||||
).import_file()
|
||||
statement = self.AccountBankStatement.search([("journal_id", "=", journal.id),])
|
||||
statement = self.AccountBankStatement.search([("journal_id", "=", journal.id)])
|
||||
self.assertEqual(len(statement), 1)
|
||||
self.assertEqual(len(statement.line_ids), 2)
|
||||
self.assertEqual(statement.balance_start, 10.0)
|
||||
|
||||
@@ -78,7 +78,6 @@
|
||||
>
|
||||
<field name="name">Statement Sheet Mappings</field>
|
||||
<field name="res_model">account.bank.statement.import.sheet.mapping</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
</record>
|
||||
<menuitem
|
||||
|
||||
@@ -14,8 +14,12 @@ class AccountBankStatementImportSheetMappingWizard(models.TransientModel):
|
||||
_description = "Account Bank Statement Import Sheet Mapping Wizard"
|
||||
_inherit = ["multi.step.wizard.mixin"]
|
||||
|
||||
data_file = fields.Binary(string="Bank Statement File", required=True,)
|
||||
filename = fields.Char()
|
||||
attachment_ids = fields.Many2many(
|
||||
comodel_name="ir.attachment",
|
||||
string="Files",
|
||||
required=True,
|
||||
relation="account_bank_statement_import_sheet_mapping_wiz_attachment_rel",
|
||||
)
|
||||
header = fields.Char()
|
||||
file_encoding = fields.Selection(
|
||||
string="Encoding", selection=lambda self: self._selection_file_encoding(),
|
||||
@@ -97,11 +101,11 @@ class AccountBankStatementImportSheetMappingWizard(models.TransientModel):
|
||||
.selection
|
||||
)
|
||||
|
||||
@api.onchange("data_file")
|
||||
def _onchange_data_file(self):
|
||||
@api.onchange("attachment_ids")
|
||||
def _onchange_attachment_ids(self):
|
||||
Parser = self.env["account.bank.statement.import.sheet.parser"]
|
||||
Mapping = self.env["account.bank.statement.import.sheet.mapping"]
|
||||
if not self.data_file:
|
||||
if not self.attachment_ids:
|
||||
return
|
||||
csv_options = {}
|
||||
if self.delimiter:
|
||||
@@ -110,9 +114,12 @@ class AccountBankStatementImportSheetMappingWizard(models.TransientModel):
|
||||
)
|
||||
if self.quotechar:
|
||||
csv_options["quotechar"] = self.quotechar
|
||||
header = Parser.parse_header(
|
||||
b64decode(self.data_file), self.file_encoding, csv_options
|
||||
)
|
||||
header = []
|
||||
for data_file in self.attachment_ids:
|
||||
header += Parser.parse_header(
|
||||
b64decode(data_file.datas), self.file_encoding, csv_options
|
||||
)
|
||||
header = list(set(header))
|
||||
self.header = json.dumps(header)
|
||||
|
||||
@api.model
|
||||
@@ -122,12 +129,12 @@ class AccountBankStatementImportSheetMappingWizard(models.TransientModel):
|
||||
return []
|
||||
return [(x, x) for x in json.loads(header)]
|
||||
|
||||
@api.multi
|
||||
def _get_mapping_values(self):
|
||||
"""Hook for extension"""
|
||||
self.ensure_one()
|
||||
filename = "& ".join(self.attachment_ids.mapped("name"))
|
||||
return {
|
||||
"name": _("Mapping from %s") % path.basename(self.filename),
|
||||
"name": _("Mapping from %s") % path.basename(filename),
|
||||
"float_thousands_sep": "comma",
|
||||
"float_decimal_sep": "dot",
|
||||
"file_encoding": self.file_encoding,
|
||||
@@ -152,7 +159,6 @@ class AccountBankStatementImportSheetMappingWizard(models.TransientModel):
|
||||
"bank_account_column": self.bank_account_column,
|
||||
}
|
||||
|
||||
@api.multi
|
||||
def import_mapping(self):
|
||||
self.ensure_one()
|
||||
mapping = self.env["account.bank.statement.import.sheet.mapping"].create(
|
||||
|
||||
@@ -21,11 +21,12 @@
|
||||
<group name="start" attrs="{'invisible': [('state', '!=', 'start')]}">
|
||||
<group colspan="2">
|
||||
<field
|
||||
name="data_file"
|
||||
filename="filename"
|
||||
placeholder="Choose a file to import..."
|
||||
name="attachment_ids"
|
||||
widget="many2many_binary"
|
||||
colspan="2"
|
||||
string="Upload Files"
|
||||
nolabel="1"
|
||||
/>
|
||||
<field name="filename" invisible="1" />
|
||||
</group>
|
||||
<group string="Options" colspan="2">
|
||||
<field name="file_encoding" />
|
||||
@@ -157,9 +158,8 @@
|
||||
id="action_account_bank_statement_import_sheet_mapping_wizard"
|
||||
name="Import Mapping"
|
||||
res_model="account.bank.statement.import.sheet.mapping.wizard"
|
||||
src_model="account.bank.statement.import.sheet.mapping"
|
||||
binding_model="account.bank.statement.import.sheet.mapping"
|
||||
view_mode="form"
|
||||
target="new"
|
||||
key2="client_action_multi"
|
||||
/>
|
||||
</odoo>
|
||||
|
||||
Reference in New Issue
Block a user