Merge PR #740 into 16.0

Signed-off-by pedrobaeza
This commit is contained in:
OCA-git-bot
2024-11-26 07:05:27 +00:00
9 changed files with 137 additions and 7 deletions

View File

@@ -103,6 +103,8 @@ Contributors
* Alexey Pelykh <alexey.pelykh@corphub.eu>
* Sebastiano Picchi <sebastiano.picchi@pytech.it>
Maintainers
~~~~~~~~~~~

View File

@@ -173,6 +173,14 @@ class AccountStatementImportSheetMapping(models.Model):
help="Set the Header lines number.",
default="0",
)
skip_empty_lines = fields.Boolean(
default=False,
help="Allows to skip empty lines",
)
offset_column = fields.Integer(
default=0,
help="Horizontal spaces to ignore before starting to parse",
)
@api.constrains(
"amount_type",
@@ -217,6 +225,12 @@ class AccountStatementImportSheetMapping(models.Model):
elif "comma" == self.float_thousands_sep == self.float_decimal_sep:
self.float_thousands_sep = "dot"
@api.constrains("offset_column")
def _check_columns(self):
for mapping in self:
if mapping.offset_column < 0:
raise ValidationError(_("Offsets cannot be negative"))
def _get_float_separators(self):
self.ensure_one()
separators = {

View File

@@ -188,6 +188,8 @@ class AccountStatementImportSheetParser(models.TransientModel):
else:
[next(csv_or_xlsx) for _i in range(header_line)]
header = [value.strip() for value in next(csv_or_xlsx)]
if mapping.offset_column:
header = header[mapping.offset_column :]
# NOTE no seria necesario debit_column y credit_column ya que tenemos los
# respectivos campos related
@@ -226,7 +228,7 @@ class AccountStatementImportSheetParser(models.TransientModel):
footer_line = numrows - mapping.footer_lines_skip_count
if isinstance(csv_or_xlsx, tuple):
rows = range(mapping.header_lines_skip_count, footer_line)
rows = range(label_line, footer_line)
else:
rows = csv_or_xlsx
@@ -236,7 +238,7 @@ class AccountStatementImportSheetParser(models.TransientModel):
book = csv_or_xlsx[0]
sheet = csv_or_xlsx[1]
values = []
for col_index in range(0, sheet.row_len(row)):
for col_index in range(mapping.offset_column, sheet.row_len(row)):
cell_type = sheet.cell_type(row, col_index)
cell_value = sheet.cell_value(row, col_index)
if cell_type == xlrd.XL_CELL_DATE:
@@ -246,6 +248,8 @@ class AccountStatementImportSheetParser(models.TransientModel):
if index >= footer_line:
continue
values = list(row)
if mapping.skip_empty_lines and not any(values):
continue
timestamp = self._get_values_from_column(
values, columns, "timestamp_column"
@@ -375,6 +379,8 @@ class AccountStatementImportSheetParser(models.TransientModel):
line["bank_name"] = bank_name
if bank_account is not None:
line["bank_account"] = bank_account
if line:
lines.append(line)
return lines

View File

@@ -15,3 +15,5 @@
* `CorporateHub <https://corporatehub.eu/>`__
* Alexey Pelykh <alexey.pelykh@corphub.eu>
* Sebastiano Picchi <sebastiano.picchi@pytech.it>

View File

@@ -8,10 +8,11 @@
/*
:Author: David Goodger (goodger@python.org)
:Id: $Id: html4css1.css 8954 2022-01-20 10:10:25Z milde $
:Id: $Id: html4css1.css 9511 2024-01-13 09:50:07Z milde $
:Copyright: This stylesheet has been placed in the public domain.
Default cascading style sheet for the HTML output of Docutils.
Despite the name, some widely supported CSS2 features are used.
See https://docutils.sourceforge.io/docs/howto/html-stylesheets.html for how to
customize this style sheet.
@@ -274,7 +275,7 @@ pre.literal-block, pre.doctest-block, pre.math, pre.code {
margin-left: 2em ;
margin-right: 2em }
pre.code .ln { color: grey; } /* line numbers */
pre.code .ln { color: gray; } /* line numbers */
pre.code, code { background-color: #eeeeee }
pre.code .comment, code .comment { color: #5C6576 }
pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold }
@@ -300,7 +301,7 @@ span.option {
span.pre {
white-space: pre }
span.problematic {
span.problematic, pre.problematic {
color: red }
span.section-subtitle {
@@ -455,12 +456,15 @@ If you spotted it first, help us to smash it by providing a detailed and welcome
<li>Alexey Pelykh &lt;<a class="reference external" href="mailto:alexey.pelykh&#64;corphub.eu">alexey.pelykh&#64;corphub.eu</a>&gt;</li>
</ul>
</li>
<li>Sebastiano Picchi &lt;<a class="reference external" href="mailto:sebastiano.picchi&#64;pytech.it">sebastiano.picchi&#64;pytech.it</a>&gt;</li>
</ul>
</div>
<div class="section" id="maintainers">
<h2><a class="toc-backref" href="#toc-entry-9">Maintainers</a></h2>
<p>This module is maintained by the OCA.</p>
<a class="reference external image-reference" href="https://odoo-community.org"><img alt="Odoo Community Association" src="https://odoo-community.org/logo.png" /></a>
<a class="reference external image-reference" href="https://odoo-community.org">
<img alt="Odoo Community Association" src="https://odoo-community.org/logo.png" />
</a>
<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>

View File

@@ -0,0 +1,5 @@
"Date","Label","Currency","Amount","Amount Currency","Partner Name","Bank Account"
"02/25/2018","AAAOOO 1","EUR","-33.50","0.0","John Doe","123456789"
"02/26/2018","AAAOOO 2","EUR","1,525.00","1,000.00","Azure Interior",""
,,,,,,
"02/27/2018","AAAOOO 3","EUR","800.00","800.00","Azure Interior","123456789"
1 Date Label Currency Amount Amount Currency Partner Name Bank Account
2 02/25/2018 AAAOOO 1 EUR -33.50 0.0 John Doe 123456789
3 02/26/2018 AAAOOO 2 EUR 1,525.00 1,000.00 Azure Interior
4
5 02/27/2018 AAAOOO 3 EUR 800.00 800.00 Azure Interior 123456789

View File

@@ -678,3 +678,95 @@ class TestAccountStatementImportSheetFile(common.TransactionCase):
self.parser._parse_decimal(Decimal("1234.56"), self.mock_mapping_comma_dot),
1234.56,
)
def test_offsets(self):
journal = self.AccountJournal.create(
{
"name": "Bank",
"type": "bank",
"code": "BANK",
"currency_id": self.currency_usd.id,
"suspense_account_id": self.suspense_account.id,
}
)
file_name = "fixtures/sample_statement_offsets.xlsx"
data = self._data_file(file_name)
wizard = self.AccountStatementImport.with_context(journal_id=journal.id).create(
{
"statement_filename": file_name,
"statement_file": data,
"sheet_mapping_id": self.sample_statement_map.id,
}
)
with self.assertRaises(UserError):
wizard.with_context(
account_statement_import_txt_xlsx_test=True
).import_file_button()
statement_map_offsets = self.sample_statement_map.copy(
{
"offset_column": 1,
"header_lines_skip_count": 3,
}
)
wizard = self.AccountStatementImport.with_context(journal_id=journal.id).create(
{
"statement_filename": file_name,
"statement_file": data,
"sheet_mapping_id": statement_map_offsets.id,
}
)
wizard.with_context(
account_statement_import_txt_xlsx_test=True
).import_file_button()
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, 0.0)
self.assertEqual(statement.balance_end_real, 1491.5)
self.assertEqual(statement.balance_end, 1491.5)
def test_skip_empty_lines(self):
journal = self.AccountJournal.create(
{
"name": "Bank",
"type": "bank",
"code": "BANK",
"currency_id": self.currency_usd.id,
"suspense_account_id": self.suspense_account.id,
}
)
file_name = "fixtures/empty_lines_statement.csv"
data = self._data_file(file_name, "utf-8")
wizard = self.AccountStatementImport.with_context(journal_id=journal.id).create(
{
"statement_filename": file_name,
"statement_file": data,
"sheet_mapping_id": self.sample_statement_map.id,
}
)
with self.assertRaises(UserError):
wizard.with_context(
account_statement_import_txt_xlsx_test=True
).import_file_button()
statement_map_empty_line = self.sample_statement_map.copy(
{
"skip_empty_lines": True,
}
)
wizard = self.AccountStatementImport.with_context(journal_id=journal.id).create(
{
"statement_filename": file_name,
"statement_file": data,
"sheet_mapping_id": statement_map_empty_line.id,
}
)
wizard.with_context(
account_statement_import_txt_xlsx_test=True
).import_file_button()
statement = self.AccountBankStatement.search([("journal_id", "=", journal.id)])
self.assertEqual(len(statement), 1)
self.assertEqual(len(statement.line_ids), 3)
self.assertEqual(statement.balance_start, 0.0)
self.assertEqual(statement.balance_end_real, 2291.5)
self.assertEqual(statement.balance_end, 2291.5)

View File

@@ -64,8 +64,13 @@
/>
</group>
<group>
<field name="skip_empty_lines" />
<field name="header_lines_skip_count" />
<field name="footer_lines_skip_count" />
<field
name="offset_column"
attrs="{'invisible': [('no_header', '=', True)]}"
/>
</group>
</group>
<group string="Columns">