Tower: upload at_accounting 18.0.1.7 (via marketplace)
This commit is contained in:
154
addons/at_accounting/wizard/account_bank_statement_import_csv.py
Normal file
154
addons/at_accounting/wizard/account_bank_statement_import_csv.py
Normal file
@@ -0,0 +1,154 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
import contextlib
|
||||
|
||||
import psycopg2
|
||||
|
||||
from odoo import _, api, fields, models, Command
|
||||
from odoo.exceptions import UserError, ValidationError
|
||||
from odoo.addons.base_import.models.base_import import FIELDS_RECURSION_LIMIT
|
||||
|
||||
|
||||
class AccountBankStmtImportCSV(models.TransientModel):
|
||||
|
||||
_inherit = 'base_import.import'
|
||||
|
||||
@api.model
|
||||
def get_fields_tree(self, model, depth=FIELDS_RECURSION_LIMIT):
|
||||
fields_list = super(AccountBankStmtImportCSV, self).get_fields_tree(model, depth=depth)
|
||||
if self._context.get('bank_stmt_import', False):
|
||||
add_fields = [{
|
||||
'id': 'balance',
|
||||
'name': 'balance',
|
||||
'string': 'Cumulative Balance',
|
||||
'required': False,
|
||||
'fields': [],
|
||||
'type': 'monetary',
|
||||
'model_name': model,
|
||||
}, {
|
||||
'id': 'debit',
|
||||
'name': 'debit',
|
||||
'string': 'Debit',
|
||||
'required': False,
|
||||
'fields': [],
|
||||
'type': 'monetary',
|
||||
'model_name': model,
|
||||
}, {
|
||||
'id': 'credit',
|
||||
'name': 'credit',
|
||||
'string': 'Credit',
|
||||
'required': False,
|
||||
'fields': [],
|
||||
'type': 'monetary',
|
||||
'model_name': model,
|
||||
}]
|
||||
fields_list.extend(add_fields)
|
||||
return fields_list
|
||||
|
||||
def _convert_to_float(self, value):
|
||||
return float(value) if value else 0.0
|
||||
|
||||
def _parse_import_data(self, data, import_fields, options):
|
||||
# EXTENDS base
|
||||
data = super()._parse_import_data(data, import_fields, options)
|
||||
journal_id = self._context.get('default_journal_id')
|
||||
bank_stmt_import = options.get('bank_stmt_import')
|
||||
if not journal_id or not bank_stmt_import:
|
||||
return data
|
||||
|
||||
has_amount = 'amount' in import_fields
|
||||
has_credit = 'credit' in import_fields
|
||||
has_debit = 'debit' in import_fields
|
||||
if (has_debit ^ has_credit) or not (has_amount ^ has_debit):
|
||||
raise ValidationError(_("Make sure that an Amount or Debit and Credit is in the file."))
|
||||
statement_vals = options['statement_vals'] = {}
|
||||
ret_data = []
|
||||
|
||||
import_fields.append('sequence')
|
||||
index_balance = False
|
||||
convert_to_amount = False
|
||||
|
||||
# check that the rows are sorted by date (ascending or descending) as we assume they are in the following code
|
||||
# we can't order the rows for the user as two rows could have the same date
|
||||
# and we don't have a way to know which one should be first
|
||||
if 'date' in import_fields:
|
||||
index_date = import_fields.index('date')
|
||||
dates = [fields.Date.from_string(line[index_date]) for line in data if line[index_date]]
|
||||
sorted_dates_asc = sorted(dates)
|
||||
if dates != sorted_dates_asc: # If dates are not in ascending order, check if they are in descending order
|
||||
sorted_dates_desc = sorted_dates_asc[::-1]
|
||||
if dates == sorted_dates_desc:
|
||||
data = data[::-1] # reverse data if dates are in descending order to make them ascending
|
||||
else: # If dates are not sorted at all, we throw an error
|
||||
raise UserError(_('Rows must be sorted by date.'))
|
||||
|
||||
if 'debit' in import_fields and 'credit' in import_fields:
|
||||
index_debit = import_fields.index('debit')
|
||||
index_credit = import_fields.index('credit')
|
||||
self._parse_float_from_data(data, index_debit, 'debit', options)
|
||||
self._parse_float_from_data(data, index_credit, 'credit', options)
|
||||
import_fields.append('amount')
|
||||
convert_to_amount = True
|
||||
|
||||
# add starting balance and ending balance to context
|
||||
if 'balance' in import_fields:
|
||||
index_balance = import_fields.index('balance')
|
||||
self._parse_float_from_data(data, index_balance, 'balance', options)
|
||||
statement_vals['balance_start'] = self._convert_to_float(data[0][index_balance])
|
||||
statement_vals['balance_start'] -= self._convert_to_float(data[0][import_fields.index('amount')]) \
|
||||
if not convert_to_amount \
|
||||
else abs(self._convert_to_float(data[0][index_credit]))-abs(self._convert_to_float(data[0][index_debit]))
|
||||
statement_vals['balance_end_real'] = data[len(data)-1][index_balance]
|
||||
import_fields.remove('balance')
|
||||
|
||||
if convert_to_amount:
|
||||
import_fields.remove('debit')
|
||||
import_fields.remove('credit')
|
||||
|
||||
for index, line in enumerate(data):
|
||||
line.append(index)
|
||||
remove_index = []
|
||||
if convert_to_amount:
|
||||
line.append(
|
||||
abs(self._convert_to_float(line[index_credit]))
|
||||
- abs(self._convert_to_float(line[index_debit]))
|
||||
)
|
||||
remove_index.extend([index_debit, index_credit])
|
||||
if index_balance:
|
||||
remove_index.append(index_balance)
|
||||
# Remove added field debit/credit/balance
|
||||
for index in sorted(remove_index, reverse=True):
|
||||
del line[index]
|
||||
if line[import_fields.index('amount')]:
|
||||
ret_data.append(line)
|
||||
|
||||
return ret_data
|
||||
|
||||
def parse_preview(self, options, count=10):
|
||||
if options.get('bank_stmt_import', False):
|
||||
self = self.with_context(bank_stmt_import=True)
|
||||
return super(AccountBankStmtImportCSV, self).parse_preview(options, count=count)
|
||||
|
||||
def execute_import(self, fields, columns, options, dryrun=False):
|
||||
if options.get('bank_stmt_import'):
|
||||
with self.env.cr.savepoint(flush=False) as sp:
|
||||
res = super().execute_import(fields, columns, options, dryrun=dryrun)
|
||||
|
||||
if not 'statement_id' in fields:
|
||||
statement = self.env['account.bank.statement'].create({
|
||||
'reference': self.file_name,
|
||||
'line_ids': [Command.set(res.get('ids', []))],
|
||||
**options.get('statement_vals', {}),
|
||||
})
|
||||
if not dryrun:
|
||||
res['messages'].append({
|
||||
'statement_id': statement.id,
|
||||
'type': 'bank_statement'
|
||||
})
|
||||
|
||||
with contextlib.suppress(psycopg2.InternalError):
|
||||
sp.close(rollback=dryrun)
|
||||
|
||||
return res
|
||||
else:
|
||||
return super(AccountBankStmtImportCSV, self).execute_import(fields, columns, options, dryrun=dryrun)
|
||||
Reference in New Issue
Block a user