mirror of
https://github.com/OCA/account-reconcile.git
synced 2025-01-20 12:27:39 +02:00
Pass Black on the files + pylint
Move test data to tests/data
This commit is contained in:
committed by
Florian da Costa
parent
5c8a0962da
commit
5bb8d7caa4
@@ -12,63 +12,67 @@ from odoo.exceptions import UserError, ValidationError
|
|||||||
|
|
||||||
|
|
||||||
class AccountJournal(models.Model):
|
class AccountJournal(models.Model):
|
||||||
_name = 'account.journal'
|
_name = "account.journal"
|
||||||
_inherit = ['account.journal', 'mail.thread']
|
_inherit = ["account.journal", "mail.thread"]
|
||||||
_order = 'sequence'
|
_order = "sequence"
|
||||||
|
|
||||||
used_for_import = fields.Boolean(
|
used_for_import = fields.Boolean(string="Journal used for import")
|
||||||
string="Journal used for import")
|
|
||||||
|
|
||||||
commission_account_id = fields.Many2one(
|
commission_account_id = fields.Many2one(
|
||||||
comodel_name='account.account',
|
comodel_name="account.account", string="Commission account"
|
||||||
string='Commission account')
|
)
|
||||||
|
|
||||||
import_type = fields.Selection(
|
import_type = fields.Selection(
|
||||||
[('generic_csvxls_so', 'Generic .csv/.xls based on SO Name')],
|
[("generic_csvxls_so", "Generic .csv/.xls based on SO Name")],
|
||||||
string='Type of import',
|
string="Type of import",
|
||||||
default='generic_csvxls_so',
|
default="generic_csvxls_so",
|
||||||
required=True,
|
required=True,
|
||||||
help="Choose here the method by which you want to import account "
|
help="Choose here the method by which you want to import account "
|
||||||
"moves for this journal.")
|
"moves for this journal.",
|
||||||
|
)
|
||||||
|
|
||||||
last_import_date = fields.Datetime(
|
last_import_date = fields.Datetime(string="Last Import Date")
|
||||||
string="Last Import Date")
|
|
||||||
|
|
||||||
partner_id = fields.Many2one(
|
partner_id = fields.Many2one(
|
||||||
comodel_name='res.partner',
|
comodel_name="res.partner",
|
||||||
string='Bank/Payment Office partner',
|
string="Bank/Payment Office partner",
|
||||||
help="Put a partner if you want to have it on the commission move "
|
help="Put a partner if you want to have it on the commission move "
|
||||||
"(and optionaly on the counterpart of the intermediate/"
|
"(and optionaly on the counterpart of the intermediate/"
|
||||||
"banking move if you tick the corresponding checkbox).")
|
"banking move if you tick the corresponding checkbox).",
|
||||||
|
)
|
||||||
|
|
||||||
receivable_account_id = fields.Many2one(
|
receivable_account_id = fields.Many2one(
|
||||||
comodel_name='account.account',
|
comodel_name="account.account",
|
||||||
string='Receivable/Payable Account',
|
string="Receivable/Payable Account",
|
||||||
help="Choose a receivable/payable account to use as the default "
|
help="Choose a receivable/payable account to use as the default "
|
||||||
"debit/credit account.")
|
"debit/credit account.",
|
||||||
|
)
|
||||||
|
|
||||||
used_for_completion = fields.Boolean(
|
used_for_completion = fields.Boolean(string="Journal used for completion")
|
||||||
string="Journal used for completion")
|
|
||||||
|
|
||||||
rule_ids = fields.Many2many(
|
rule_ids = fields.Many2many(
|
||||||
comodel_name='account.move.completion.rule',
|
comodel_name="account.move.completion.rule",
|
||||||
string='Auto-completion rules',
|
string="Auto-completion rules",
|
||||||
relation='account_journal_completion_rule_rel')
|
relation="account_journal_completion_rule_rel",
|
||||||
|
)
|
||||||
|
|
||||||
launch_import_completion = fields.Boolean(
|
launch_import_completion = fields.Boolean(
|
||||||
string="Launch completion after import",
|
string="Launch completion after import",
|
||||||
help="Tic that box to automatically launch the completion "
|
help="Tic that box to automatically launch the completion "
|
||||||
"on each imported file using this journal.")
|
"on each imported file using this journal.",
|
||||||
|
)
|
||||||
|
|
||||||
create_counterpart = fields.Boolean(
|
create_counterpart = fields.Boolean(
|
||||||
string="Create Counterpart",
|
string="Create Counterpart",
|
||||||
help="Tick that box to automatically create the move counterpart",
|
help="Tick that box to automatically create the move counterpart",
|
||||||
default=True)
|
default=True,
|
||||||
|
)
|
||||||
|
|
||||||
split_counterpart = fields.Boolean(
|
split_counterpart = fields.Boolean(
|
||||||
string="Split Counterpart",
|
string="Split Counterpart",
|
||||||
help="Two counterparts will be automatically created : one for "
|
help="Two counterparts will be automatically created : one for "
|
||||||
"the refunds and one for the payments")
|
"the refunds and one for the payments",
|
||||||
|
)
|
||||||
|
|
||||||
@api.multi
|
@api.multi
|
||||||
def _prepare_counterpart_line(self, move, amount, date):
|
def _prepare_counterpart_line(self, move, amount, date):
|
||||||
@@ -81,24 +85,24 @@ class AccountJournal(models.Model):
|
|||||||
credit = -amount
|
credit = -amount
|
||||||
debit = 0.0
|
debit = 0.0
|
||||||
counterpart_values = {
|
counterpart_values = {
|
||||||
'date_maturity': date,
|
"date_maturity": date,
|
||||||
'credit': credit,
|
"credit": credit,
|
||||||
'debit': debit,
|
"debit": debit,
|
||||||
'partner_id': self.partner_id.id,
|
"partner_id": self.partner_id.id,
|
||||||
'move_id': move.id,
|
"move_id": move.id,
|
||||||
'account_id': account_id,
|
"account_id": account_id,
|
||||||
'already_completed': True,
|
"already_completed": True,
|
||||||
'journal_id': self.id,
|
"journal_id": self.id,
|
||||||
'company_id': self.company_id.id,
|
"company_id": self.company_id.id,
|
||||||
'currency_id': self.currency_id.id,
|
"currency_id": self.currency_id.id,
|
||||||
'company_currency_id': self.company_id.currency_id.id,
|
"company_currency_id": self.company_id.currency_id.id,
|
||||||
'amount_residual': amount,
|
"amount_residual": amount,
|
||||||
}
|
}
|
||||||
return counterpart_values
|
return counterpart_values
|
||||||
|
|
||||||
@api.multi
|
@api.multi
|
||||||
def _create_counterpart(self, parser, move):
|
def _create_counterpart(self, parser, move):
|
||||||
move_line_obj = self.env['account.move.line']
|
move_line_obj = self.env["account.move.line"]
|
||||||
refund = 0.0
|
refund = 0.0
|
||||||
payment = 0.0
|
payment = 0.0
|
||||||
transfer_lines = []
|
transfer_lines = []
|
||||||
@@ -114,16 +118,18 @@ class AccountJournal(models.Model):
|
|||||||
total_amount = refund + payment
|
total_amount = refund + payment
|
||||||
if total_amount:
|
if total_amount:
|
||||||
transfer_lines.append(total_amount)
|
transfer_lines.append(total_amount)
|
||||||
counterpart_date = parser.get_move_vals().get('date') or \
|
counterpart_date = (
|
||||||
fields.Date.today()
|
parser.get_move_vals().get("date") or fields.Date.today()
|
||||||
|
)
|
||||||
transfer_line_count = len(transfer_lines)
|
transfer_line_count = len(transfer_lines)
|
||||||
check_move_validity = False
|
check_move_validity = False
|
||||||
for amount in transfer_lines:
|
for amount in transfer_lines:
|
||||||
transfer_line_count -= 1
|
transfer_line_count -= 1
|
||||||
if not transfer_line_count:
|
if not transfer_line_count:
|
||||||
check_move_validity = True
|
check_move_validity = True
|
||||||
vals = self._prepare_counterpart_line(move, amount,
|
vals = self._prepare_counterpart_line(
|
||||||
counterpart_date)
|
move, amount, counterpart_date
|
||||||
|
)
|
||||||
move_line_obj.with_context(
|
move_line_obj.with_context(
|
||||||
check_move_validity=check_move_validity
|
check_move_validity=check_move_validity
|
||||||
).create(vals)
|
).create(vals)
|
||||||
@@ -142,48 +148,53 @@ class AccountJournal(models.Model):
|
|||||||
statement ID
|
statement ID
|
||||||
:param: context: global context
|
:param: context: global context
|
||||||
"""
|
"""
|
||||||
move_line_obj = self.env['account.move.line']
|
move_line_obj = self.env["account.move.line"]
|
||||||
global_commission_amount = 0
|
global_commission_amount = 0
|
||||||
for row in parser.result_row_list:
|
for row in parser.result_row_list:
|
||||||
global_commission_amount += float(
|
global_commission_amount += float(
|
||||||
row.get('commission_amount', '0.0'))
|
row.get("commission_amount", "0.0")
|
||||||
|
)
|
||||||
partner_id = self.partner_id.id
|
partner_id = self.partner_id.id
|
||||||
# Commission line
|
# Commission line
|
||||||
if global_commission_amount > 0.0:
|
if global_commission_amount > 0.0:
|
||||||
raise UserError(_('Commission amount should not be positive.'))
|
raise UserError(_("Commission amount should not be positive."))
|
||||||
elif global_commission_amount < 0.0:
|
elif global_commission_amount < 0.0:
|
||||||
if not self.commission_account_id:
|
if not self.commission_account_id:
|
||||||
raise UserError(
|
raise UserError(
|
||||||
_('No commission account is set on the journal.'))
|
_("No commission account is set on the journal.")
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
commission_account_id = self.commission_account_id.id
|
commission_account_id = self.commission_account_id.id
|
||||||
comm_values = {
|
comm_values = {
|
||||||
'name': _('Commission line'),
|
"name": _("Commission line"),
|
||||||
'date_maturity': parser.get_move_vals().get('date') or
|
"date_maturity": (
|
||||||
fields.Date.today(),
|
parser.get_move_vals().get("date")
|
||||||
'debit': -global_commission_amount,
|
or fields.Date.today()
|
||||||
'partner_id': partner_id,
|
),
|
||||||
'move_id': move.id,
|
"debit": -global_commission_amount,
|
||||||
'account_id': commission_account_id,
|
"partner_id": partner_id,
|
||||||
'already_completed': True,
|
"move_id": move.id,
|
||||||
|
"account_id": commission_account_id,
|
||||||
|
"already_completed": True,
|
||||||
}
|
}
|
||||||
if (self.currency_id and
|
if (
|
||||||
self.currency_id != self.company_id.currency_id):
|
self.currency_id
|
||||||
|
and self.currency_id != self.company_id.currency_id
|
||||||
|
):
|
||||||
# the commission we are reading is in the currency of the
|
# the commission we are reading is in the currency of the
|
||||||
# journal: use the amount in the amount_currency field, and
|
# journal: use the amount in the amount_currency field, and
|
||||||
# set credit / debit to the value in company currency at
|
# set credit / debit to the value in company currency at
|
||||||
# the date of the move.
|
# the date of the move.
|
||||||
currency = self.currency_id.with_context(date=move.date)
|
currency = self.currency_id.with_context(date=move.date)
|
||||||
company_currency = self.company_id.currency_id
|
company_currency = self.company_id.currency_id
|
||||||
comm_values['amount_currency'] = comm_values['debit']
|
comm_values["amount_currency"] = comm_values["debit"]
|
||||||
comm_values['debit'] = currency.compute(
|
comm_values["debit"] = currency.compute(
|
||||||
comm_values['debit'],
|
comm_values["debit"], company_currency
|
||||||
company_currency
|
|
||||||
)
|
)
|
||||||
comm_values['currency_id'] = currency.id
|
comm_values["currency_id"] = currency.id
|
||||||
move_line_obj.with_context(
|
move_line_obj.with_context(check_move_validity=False).create(
|
||||||
check_move_validity=False
|
comm_values
|
||||||
).create(comm_values)
|
)
|
||||||
|
|
||||||
@api.multi
|
@api.multi
|
||||||
def write_logs_after_import(self, move, num_lines):
|
def write_logs_after_import(self, move, num_lines):
|
||||||
@@ -195,8 +206,9 @@ class AccountJournal(models.Model):
|
|||||||
:return: True
|
:return: True
|
||||||
"""
|
"""
|
||||||
self.message_post(
|
self.message_post(
|
||||||
body=_('Move %s have been imported with %s '
|
body=_("Move %s have been imported with %s " "lines.")
|
||||||
'lines.') % (move.name, num_lines))
|
% (move.name, num_lines)
|
||||||
|
)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def prepare_move_line_vals(self, parser_vals, move):
|
def prepare_move_line_vals(self, parser_vals, move):
|
||||||
@@ -211,40 +223,46 @@ class AccountJournal(models.Model):
|
|||||||
:return: dict of vals that will be passed to create method of
|
:return: dict of vals that will be passed to create method of
|
||||||
statement line.
|
statement line.
|
||||||
"""
|
"""
|
||||||
move_line_obj = self.env['account.move.line']
|
move_line_obj = self.env["account.move.line"]
|
||||||
values = parser_vals
|
values = parser_vals
|
||||||
if not values.get('account_id', False):
|
if not values.get("account_id", False):
|
||||||
values['account_id'] = self.receivable_account_id.id
|
values["account_id"] = self.receivable_account_id.id
|
||||||
account = self.env['account.account'].browse(values['account_id'])
|
account = self.env["account.account"].browse(values["account_id"])
|
||||||
if (self.currency_id and
|
if (
|
||||||
self.currency_id != self.company_id.currency_id):
|
self.currency_id
|
||||||
|
and self.currency_id != self.company_id.currency_id
|
||||||
|
):
|
||||||
# the debit and credit we are reading are in the currency of the
|
# the debit and credit we are reading are in the currency of the
|
||||||
# journal: use the amount in the amount_currency field, and set
|
# journal: use the amount in the amount_currency field, and set
|
||||||
# credit / debit to the value in company currency at the date of
|
# credit / debit to the value in company currency at the date of
|
||||||
# the move.
|
# the move.
|
||||||
currency = self.currency_id.with_context(date=move.date)
|
currency = self.currency_id.with_context(date=move.date)
|
||||||
company_currency = self.company_id.currency_id
|
company_currency = self.company_id.currency_id
|
||||||
values['amount_currency'] = values['debit'] - values['credit']
|
values["amount_currency"] = values["debit"] - values["credit"]
|
||||||
values['debit'] = currency.compute(values['debit'],
|
values["debit"] = currency.compute(
|
||||||
company_currency)
|
values["debit"], company_currency
|
||||||
values['credit'] = currency.compute(values['credit'],
|
)
|
||||||
company_currency)
|
values["credit"] = currency.compute(
|
||||||
|
values["credit"], company_currency
|
||||||
|
)
|
||||||
if account.reconcile:
|
if account.reconcile:
|
||||||
values['amount_residual'] = values['debit'] - values['credit']
|
values["amount_residual"] = values["debit"] - values["credit"]
|
||||||
else:
|
else:
|
||||||
values['amount_residual'] = 0
|
values["amount_residual"] = 0
|
||||||
values.update({
|
values.update(
|
||||||
'company_id': self.company_id.id,
|
{
|
||||||
'currency_id': self.currency_id.id,
|
"company_id": self.company_id.id,
|
||||||
'company_currency_id': self.company_id.currency_id.id,
|
"currency_id": self.currency_id.id,
|
||||||
'journal_id': self.id,
|
"company_currency_id": self.company_id.currency_id.id,
|
||||||
'move_id': move.id,
|
"journal_id": self.id,
|
||||||
'date': move.date,
|
"move_id": move.id,
|
||||||
'balance': values['debit'] - values['credit'],
|
"date": move.date,
|
||||||
'amount_residual_currency': 0,
|
"balance": values["debit"] - values["credit"],
|
||||||
'user_type_id': account.user_type_id.id,
|
"amount_residual_currency": 0,
|
||||||
'reconciled': False,
|
"user_type_id": account.user_type_id.id,
|
||||||
})
|
"reconciled": False,
|
||||||
|
}
|
||||||
|
)
|
||||||
values = move_line_obj._add_missing_default_values(values)
|
values = move_line_obj._add_missing_default_values(values)
|
||||||
return values
|
return values
|
||||||
|
|
||||||
@@ -252,9 +270,11 @@ class AccountJournal(models.Model):
|
|||||||
"""Hook to build the values of the statement from the parser and
|
"""Hook to build the values of the statement from the parser and
|
||||||
the profile.
|
the profile.
|
||||||
"""
|
"""
|
||||||
vals = {'journal_id': self.id,
|
vals = {
|
||||||
'currency_id': self.currency_id.id,
|
"journal_id": self.id,
|
||||||
'import_partner_id': self.partner_id.id}
|
"currency_id": self.currency_id.id,
|
||||||
|
"import_partner_id": self.partner_id.id,
|
||||||
|
}
|
||||||
vals.update(parser.get_move_vals())
|
vals.update(parser.get_move_vals())
|
||||||
return vals
|
return vals
|
||||||
|
|
||||||
@@ -267,23 +287,23 @@ class AccountJournal(models.Model):
|
|||||||
:param char: ftype represent the file extension (csv by default)
|
:param char: ftype represent the file extension (csv by default)
|
||||||
:return: list: list of ids of the created account.bank.statement
|
:return: list: list of ids of the created account.bank.statement
|
||||||
"""
|
"""
|
||||||
filename = self._context.get('file_name', None)
|
filename = self._context.get("file_name", None)
|
||||||
if filename:
|
if filename:
|
||||||
(filename, __) = os.path.splitext(filename)
|
(filename, __) = os.path.splitext(filename)
|
||||||
parser = new_move_parser(self, ftype=ftype, move_ref=filename)
|
parser = new_move_parser(self, ftype=ftype, move_ref=filename)
|
||||||
res = self.env['account.move']
|
res = self.env["account.move"]
|
||||||
for result_row_list in parser.parse(file_stream):
|
for result_row_list in parser.parse(file_stream):
|
||||||
move = self._move_import(
|
move = self._move_import(
|
||||||
parser, file_stream,
|
parser,
|
||||||
|
file_stream,
|
||||||
result_row_list=result_row_list,
|
result_row_list=result_row_list,
|
||||||
ftype=ftype
|
ftype=ftype,
|
||||||
)
|
)
|
||||||
res |= move
|
res |= move
|
||||||
return res
|
return res
|
||||||
|
|
||||||
def _move_import(
|
def _move_import(
|
||||||
self, parser, file_stream, result_row_list=None, ftype="csv"
|
self, parser, file_stream, result_row_list=None, ftype="csv"):
|
||||||
):
|
|
||||||
"""Create a bank statement with the given profile and parser. It will
|
"""Create a bank statement with the given profile and parser. It will
|
||||||
fulfill the bank statement with the values of the file provided, but
|
fulfill the bank statement with the values of the file provided, but
|
||||||
will not complete data (like finding the partner, or the right
|
will not complete data (like finding the partner, or the right
|
||||||
@@ -295,23 +315,26 @@ class AccountJournal(models.Model):
|
|||||||
:param char: ftype represent the file extension (csv by default)
|
:param char: ftype represent the file extension (csv by default)
|
||||||
:return: ID of the created account.bank.statement
|
:return: ID of the created account.bank.statement
|
||||||
"""
|
"""
|
||||||
move_obj = self.env['account.move']
|
move_obj = self.env["account.move"]
|
||||||
move_line_obj = self.env['account.move.line']
|
move_line_obj = self.env["account.move.line"]
|
||||||
attachment_obj = self.env['ir.attachment']
|
attachment_obj = self.env["ir.attachment"]
|
||||||
if result_row_list is None:
|
if result_row_list is None:
|
||||||
result_row_list = parser.result_row_list
|
result_row_list = parser.result_row_list
|
||||||
# Check all key are present in account.bank.statement.line!!
|
# Check all key are present in account.bank.statement.line!!
|
||||||
if not result_row_list:
|
if not result_row_list:
|
||||||
raise UserError(_("Nothing to import: "
|
raise UserError(_("Nothing to import: " "The file is empty"))
|
||||||
"The file is empty"))
|
|
||||||
parsed_cols = list(
|
parsed_cols = list(
|
||||||
parser.get_move_line_vals(result_row_list[0]).keys()
|
parser.get_move_line_vals(result_row_list[0]).keys()
|
||||||
)
|
)
|
||||||
for col in parsed_cols:
|
for col in parsed_cols:
|
||||||
if col not in move_line_obj._fields:
|
if col not in move_line_obj._fields:
|
||||||
raise UserError(
|
raise UserError(
|
||||||
_("Missing column! Column %s you try to import is not "
|
_(
|
||||||
"present in the move line!") % col)
|
"Missing column! Column %s you try to import is not "
|
||||||
|
"present in the move line!"
|
||||||
|
)
|
||||||
|
% col
|
||||||
|
)
|
||||||
move_vals = self.prepare_move_vals(result_row_list, parser)
|
move_vals = self.prepare_move_vals(result_row_list, parser)
|
||||||
move = move_obj.create(move_vals)
|
move = move_obj.create(move_vals)
|
||||||
try:
|
try:
|
||||||
@@ -333,11 +356,11 @@ class AccountJournal(models.Model):
|
|||||||
move._amount_compute()
|
move._amount_compute()
|
||||||
# Attach data to the move
|
# Attach data to the move
|
||||||
attachment_data = {
|
attachment_data = {
|
||||||
'name': 'statement file',
|
"name": "statement file",
|
||||||
'datas': file_stream,
|
"datas": file_stream,
|
||||||
'datas_fname': "%s.%s" % (fields.Date.today(), ftype),
|
"datas_fname": "%s.%s" % (fields.Date.today(), ftype),
|
||||||
'res_model': 'account.move',
|
"res_model": "account.move",
|
||||||
'res_id': move.id,
|
"res_id": move.id,
|
||||||
}
|
}
|
||||||
attachment_obj.create(attachment_data)
|
attachment_obj.create(attachment_data)
|
||||||
# If user ask to launch completion at end of import, do it!
|
# If user ask to launch completion at end of import, do it!
|
||||||
@@ -351,9 +374,15 @@ class AccountJournal(models.Model):
|
|||||||
except Exception:
|
except Exception:
|
||||||
error_type, error_value, trbk = sys.exc_info()
|
error_type, error_value, trbk = sys.exc_info()
|
||||||
st = "Error: %s\nDescription: %s\nTraceback:" % (
|
st = "Error: %s\nDescription: %s\nTraceback:" % (
|
||||||
error_type.__name__, error_value)
|
error_type.__name__,
|
||||||
st += ''.join(traceback.format_tb(trbk, 30))
|
error_value,
|
||||||
|
)
|
||||||
|
st += "".join(traceback.format_tb(trbk, 30))
|
||||||
raise ValidationError(
|
raise ValidationError(
|
||||||
_("Statement import error "
|
_(
|
||||||
"The statement cannot be created: %s") % st)
|
"Statement import error "
|
||||||
|
"The statement cannot be created: %s"
|
||||||
|
)
|
||||||
|
% st
|
||||||
|
)
|
||||||
return move
|
return move
|
||||||
|
|||||||
@@ -32,8 +32,15 @@ class FileParser(AccountMoveImportParser):
|
|||||||
format.
|
format.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, journal, ftype='csv', extra_fields=None, header=None,
|
def __init__(
|
||||||
dialect=None, move_ref=None, **kwargs):
|
self,
|
||||||
|
journal,
|
||||||
|
ftype="csv",
|
||||||
|
extra_fields=None,
|
||||||
|
header=None,
|
||||||
|
dialect=None,
|
||||||
|
move_ref=None,
|
||||||
|
**kwargs):
|
||||||
"""
|
"""
|
||||||
:param char: parse_name: The name of the parser
|
:param char: parse_name: The name of the parser
|
||||||
:param char: ftype: extension of the file (could be csv, xls or
|
:param char: ftype: extension of the file (could be csv, xls or
|
||||||
@@ -44,11 +51,12 @@ class FileParser(AccountMoveImportParser):
|
|||||||
header
|
header
|
||||||
"""
|
"""
|
||||||
super().__init__(journal, **kwargs)
|
super().__init__(journal, **kwargs)
|
||||||
if ftype in ('csv', 'xls', 'xlsx'):
|
if ftype in ("csv", "xls", "xlsx"):
|
||||||
self.ftype = ftype[0:3]
|
self.ftype = ftype[0:3]
|
||||||
else:
|
else:
|
||||||
raise UserError(
|
raise UserError(
|
||||||
_('Invalid file type %s. Please use csv, xls or xlsx') % ftype)
|
_("Invalid file type %s. Please use csv, xls or xlsx") % ftype
|
||||||
|
)
|
||||||
self.conversion_dict = extra_fields
|
self.conversion_dict = extra_fields
|
||||||
self.keys_to_validate = list(self.conversion_dict.keys())
|
self.keys_to_validate = list(self.conversion_dict.keys())
|
||||||
self.fieldnames = header
|
self.fieldnames = header
|
||||||
@@ -73,7 +81,7 @@ class FileParser(AccountMoveImportParser):
|
|||||||
given ftype
|
given ftype
|
||||||
"""
|
"""
|
||||||
if self.parsed_file is None:
|
if self.parsed_file is None:
|
||||||
if self.ftype == 'csv':
|
if self.ftype == "csv":
|
||||||
self.parsed_file = self._parse_csv()
|
self.parsed_file = self._parse_csv()
|
||||||
else:
|
else:
|
||||||
self.parsed_file = self._parse_xls()
|
self.parsed_file = self._parse_xls()
|
||||||
@@ -81,9 +89,8 @@ class FileParser(AccountMoveImportParser):
|
|||||||
if len(self.parsed_file) <= self.current_line:
|
if len(self.parsed_file) <= self.current_line:
|
||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
print(self.current_line)
|
|
||||||
self.result_row_list = self.parsed_file[
|
self.result_row_list = self.parsed_file[
|
||||||
self.current_line:self.current_line + 1
|
self.current_line: self.current_line + 1
|
||||||
]
|
]
|
||||||
self.current_line += 1
|
self.current_line += 1
|
||||||
return True
|
return True
|
||||||
@@ -101,7 +108,7 @@ class FileParser(AccountMoveImportParser):
|
|||||||
parsed_cols = list(self.result_row_list[0].keys())
|
parsed_cols = list(self.result_row_list[0].keys())
|
||||||
for col in self.keys_to_validate:
|
for col in self.keys_to_validate:
|
||||||
if col not in parsed_cols:
|
if col not in parsed_cols:
|
||||||
raise UserError(_('Column %s not present in file') % col)
|
raise UserError(_("Column %s not present in file") % col)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def _post(self, *args, **kwargs):
|
def _post(self, *args, **kwargs):
|
||||||
@@ -115,9 +122,10 @@ class FileParser(AccountMoveImportParser):
|
|||||||
csv_file = tempfile.NamedTemporaryFile()
|
csv_file = tempfile.NamedTemporaryFile()
|
||||||
csv_file.write(self.filebuffer)
|
csv_file.write(self.filebuffer)
|
||||||
csv_file.flush()
|
csv_file.flush()
|
||||||
with open(csv_file.name, 'rU') as fobj:
|
with open(csv_file.name, "rU") as fobj:
|
||||||
reader = UnicodeDictReader(fobj, fieldnames=self.fieldnames,
|
reader = UnicodeDictReader(
|
||||||
dialect=self.dialect)
|
fobj, fieldnames=self.fieldnames, dialect=self.dialect
|
||||||
|
)
|
||||||
return list(reader)
|
return list(reader)
|
||||||
|
|
||||||
def _parse_xls(self):
|
def _parse_xls(self):
|
||||||
@@ -143,26 +151,41 @@ class FileParser(AccountMoveImportParser):
|
|||||||
for rule in conversion_rules:
|
for rule in conversion_rules:
|
||||||
if conversion_rules[rule] == datetime.datetime:
|
if conversion_rules[rule] == datetime.datetime:
|
||||||
try:
|
try:
|
||||||
date_string = line[rule].split(' ')[0]
|
date_string = line[rule].split(" ")[0]
|
||||||
line[rule] = datetime.datetime.strptime(date_string,
|
line[rule] = datetime.datetime.strptime(
|
||||||
'%Y-%m-%d')
|
date_string, "%Y-%m-%d"
|
||||||
|
)
|
||||||
except ValueError as err:
|
except ValueError as err:
|
||||||
raise UserError(
|
raise UserError(
|
||||||
_("Date format is not valid."
|
_(
|
||||||
" It should be YYYY-MM-DD for column: %s"
|
"Date format is not valid."
|
||||||
" value: %s \n \n \n Please check the line with "
|
" It should be YYYY-MM-DD for column: %s"
|
||||||
"ref: %s \n \n Detail: %s") %
|
" value: %s \n \n \n Please check"
|
||||||
(rule, line.get(rule, _('Missing')),
|
" the line with ref: %s \n \n Detail: %s"
|
||||||
line.get('ref', line), repr(err)))
|
)
|
||||||
|
% (
|
||||||
|
rule,
|
||||||
|
line.get(rule, _("Missing")),
|
||||||
|
line.get("ref", line),
|
||||||
|
repr(err),
|
||||||
|
)
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
line[rule] = conversion_rules[rule](line[rule])
|
line[rule] = conversion_rules[rule](line[rule])
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
raise UserError(
|
raise UserError(
|
||||||
_("Value %s of column %s is not valid.\n Please "
|
_(
|
||||||
"check the line with ref %s:\n \n Detail: %s") %
|
"Value %s of column %s is not valid.\n Please "
|
||||||
(line.get(rule, _('Missing')), rule,
|
"check the line with ref %s:\n \n Detail: %s"
|
||||||
line.get('ref', line), repr(err)))
|
)
|
||||||
|
% (
|
||||||
|
line.get(rule, _("Missing")),
|
||||||
|
rule,
|
||||||
|
line.get("ref", line),
|
||||||
|
repr(err),
|
||||||
|
)
|
||||||
|
)
|
||||||
return result_set
|
return result_set
|
||||||
|
|
||||||
def _from_xls(self, result_set, conversion_rules):
|
def _from_xls(self, result_set, conversion_rules):
|
||||||
@@ -173,26 +196,41 @@ class FileParser(AccountMoveImportParser):
|
|||||||
for rule in conversion_rules:
|
for rule in conversion_rules:
|
||||||
if conversion_rules[rule] == datetime.datetime:
|
if conversion_rules[rule] == datetime.datetime:
|
||||||
try:
|
try:
|
||||||
t_tuple = xlrd.xldate_as_tuple(line[rule],
|
t_tuple = xlrd.xldate_as_tuple(
|
||||||
self._datemode)
|
line[rule], self._datemode
|
||||||
|
)
|
||||||
line[rule] = datetime.datetime(*t_tuple)
|
line[rule] = datetime.datetime(*t_tuple)
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
raise UserError(
|
raise UserError(
|
||||||
_("Date format is not valid. "
|
_(
|
||||||
"Please modify the cell formatting to date "
|
"Date format is not valid. "
|
||||||
"format for column: %s value: %s\n Please check "
|
"Please modify the cell formatting to date "
|
||||||
"the line with ref: %s\n \n Detail: %s") %
|
"format for column: %s value: %s\n Please"
|
||||||
(rule, line.get(rule, _('Missing')),
|
" check the line with ref: %s\n \n Detail: %s"
|
||||||
line.get('ref', line), repr(err)))
|
)
|
||||||
|
% (
|
||||||
|
rule,
|
||||||
|
line.get(rule, _("Missing")),
|
||||||
|
line.get("ref", line),
|
||||||
|
repr(err),
|
||||||
|
)
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
line[rule] = conversion_rules[rule](line[rule])
|
line[rule] = conversion_rules[rule](line[rule])
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
raise UserError(
|
raise UserError(
|
||||||
_("Value %s of column %s is not valid.\n Please "
|
_(
|
||||||
"check the line with ref %s:\n \n Detail: %s") %
|
"Value %s of column %s is not valid.\n Please "
|
||||||
(line.get(rule, _('Missing')), rule,
|
"check the line with ref %s:\n \n Detail: %s"
|
||||||
line.get('ref', line), repr(err)))
|
)
|
||||||
|
% (
|
||||||
|
line.get(rule, _("Missing")),
|
||||||
|
rule,
|
||||||
|
line.get("ref", line),
|
||||||
|
repr(err),
|
||||||
|
)
|
||||||
|
)
|
||||||
return result_set
|
return result_set
|
||||||
|
|
||||||
def _cast_rows(self, *args, **kwargs):
|
def _cast_rows(self, *args, **kwargs):
|
||||||
@@ -200,6 +238,6 @@ class FileParser(AccountMoveImportParser):
|
|||||||
providen. We call here _from_xls or _from_csv depending on the
|
providen. We call here _from_xls or _from_csv depending on the
|
||||||
self.ftype variable.
|
self.ftype variable.
|
||||||
"""
|
"""
|
||||||
func = getattr(self, '_from_%s' % self.ftype)
|
func = getattr(self, "_from_%s" % self.ftype)
|
||||||
res = func(self.result_row_list, self.conversion_dict)
|
res = func(self.result_row_list, self.conversion_dict)
|
||||||
return res
|
return res
|
||||||
|
|||||||
@@ -53,7 +53,10 @@ class TestCodaImport(common.TransactionCase):
|
|||||||
"""Test import from xls
|
"""Test import from xls
|
||||||
"""
|
"""
|
||||||
file_name = get_resource_path(
|
file_name = get_resource_path(
|
||||||
'account_move_base_import', 'demo', 'statement.xls'
|
'account_move_base_import',
|
||||||
|
'tests',
|
||||||
|
'data',
|
||||||
|
'statement.xls'
|
||||||
)
|
)
|
||||||
move = self._import_file(file_name)
|
move = self._import_file(file_name)
|
||||||
self._validate_imported_move(move)
|
self._validate_imported_move(move)
|
||||||
@@ -62,7 +65,10 @@ class TestCodaImport(common.TransactionCase):
|
|||||||
"""Test import from csv
|
"""Test import from csv
|
||||||
"""
|
"""
|
||||||
file_name = get_resource_path(
|
file_name = get_resource_path(
|
||||||
'account_move_base_import', 'demo', 'statement.csv'
|
'account_move_base_import',
|
||||||
|
'tests',
|
||||||
|
'data',
|
||||||
|
'statement.csv'
|
||||||
)
|
)
|
||||||
move = self._import_file(file_name)
|
move = self._import_file(file_name)
|
||||||
self._validate_imported_move(move)
|
self._validate_imported_move(move)
|
||||||
|
|||||||
Reference in New Issue
Block a user