[IMP] account_move_base_import: black, isort, prettier

This commit is contained in:
Damien Crier
2020-07-15 11:43:01 +02:00
committed by Florian da Costa
parent e81b55d0a8
commit 68fc7849f3
16 changed files with 653 additions and 571 deletions

View File

@@ -4,13 +4,13 @@
# Copyright 2014 ACSONE SA/NV
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)
{
'name': "Journal Entry base import",
'version': '12.0.2.0.0',
'author': "Akretion,Camptocamp,Odoo Community Association (OCA)",
'category': 'Finance',
'depends': ['account'],
'website': 'http://www.camptocamp.com',
'data': [
"name": "Journal Entry base import",
"version": "13.0.1.0.0",
"author": "Akretion,Camptocamp,Odoo Community Association (OCA)",
"category": "Finance",
"depends": ["account"],
"website": "http://www.camptocamp.com",
"data": [
"security/ir.model.access.csv",
"data/completion_rule_data.xml",
"wizard/import_statement_view.xml",
@@ -18,9 +18,7 @@
"views/journal_view.xml",
"views/partner_view.xml",
],
'external_dependencies': {
'python': ['xlrd'],
},
'installable': True,
'license': 'AGPL-3',
"external_dependencies": {"python": ["xlrd"]},
"installable": True,
"license": "AGPL-3",
}

View File

@@ -1,28 +1,27 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo noupdate="1">
<record id="bank_statement_completion_rule_2" model="account.move.completion.rule">
<field name="name">Match from line label (based on partner field 'Bank Statement Label')</field>
<field
name="name"
>Match from line label (based on partner field 'Bank Statement Label')</field>
<field name="sequence">60</field>
<field name="function_to_call">get_from_name_and_partner_field</field>
</record>
<record id="bank_statement_completion_rule_3" model="account.move.completion.rule">
<field name="name">Match from line label (based on partner name)</field>
<field name="sequence">70</field>
<field name="function_to_call">get_from_name_and_partner_name</field>
</record>
<record id="bank_statement_completion_rule_4" model="account.move.completion.rule">
<field name="name">Match from line label (based on Invoice number)</field>
<field name="sequence">40</field>
<field name="function_to_call">get_from_name_and_invoice</field>
</record>
<record id="bank_statement_completion_rule_5" model="account.move.completion.rule">
<field name="name">Match from line label (based on Invoice Supplier number)</field>
<field
name="name"
>Match from line label (based on Invoice Supplier number)</field>
<field name="sequence">45</field>
<field name="function_to_call">get_from_name_and_supplier_invoice</field>
</record>
</odoo>

View File

@@ -3,13 +3,15 @@
# Copyright 2013 Savoir-faire Linux
# Copyright 2014 ACSONE SA/NV
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)
import os
import sys
import traceback
import os
from odoo import _, api, fields, models
from ..parser.parser import new_move_parser
from odoo.exceptions import UserError, ValidationError
from ..parser.parser import new_move_parser
class AccountJournal(models.Model):
_name = "account.journal"
@@ -118,21 +120,17 @@ class AccountJournal(models.Model):
total_amount = refund + payment
if total_amount:
transfer_lines.append(total_amount)
counterpart_date = (
parser.get_move_vals().get("date") or fields.Date.today()
)
counterpart_date = parser.get_move_vals().get("date") or fields.Date.today()
transfer_line_count = len(transfer_lines)
check_move_validity = False
for amount in transfer_lines:
transfer_line_count -= 1
if not transfer_line_count:
check_move_validity = True
vals = self._prepare_counterpart_line(
move, amount, counterpart_date
vals = self._prepare_counterpart_line(move, amount, counterpart_date)
move_line_obj.with_context(check_move_validity=check_move_validity).create(
vals
)
move_line_obj.with_context(
check_move_validity=check_move_validity
).create(vals)
@api.multi
def _write_extra_move_lines(self, parser, move):
@@ -151,25 +149,20 @@ class AccountJournal(models.Model):
move_line_obj = self.env["account.move.line"]
global_commission_amount = 0
for row in parser.result_row_list:
global_commission_amount += float(
row.get("commission_amount", "0.0")
)
global_commission_amount += float(row.get("commission_amount", "0.0"))
partner_id = self.partner_id.id
# Commission line
if global_commission_amount > 0.0:
raise UserError(_("Commission amount should not be positive."))
elif global_commission_amount < 0.0:
if not self.commission_account_id:
raise UserError(
_("No commission account is set on the journal.")
)
raise UserError(_("No commission account is set on the journal."))
else:
commission_account_id = self.commission_account_id.id
comm_values = {
"name": _("Commission line"),
"date_maturity": (
parser.get_move_vals().get("date")
or fields.Date.today()
parser.get_move_vals().get("date") or fields.Date.today()
),
"debit": -global_commission_amount,
"partner_id": partner_id,
@@ -177,10 +170,7 @@ class AccountJournal(models.Model):
"account_id": commission_account_id,
"already_completed": True,
}
if (
self.currency_id
and self.currency_id != self.company_id.currency_id
):
if self.currency_id and self.currency_id != self.company_id.currency_id:
# the commission we are reading is in the currency of the
# journal: use the amount in the amount_currency field, and
# set credit / debit to the value in company currency at
@@ -228,10 +218,7 @@ class AccountJournal(models.Model):
if not values.get("account_id", False):
values["account_id"] = self.receivable_account_id.id
account = self.env["account.account"].browse(values["account_id"])
if (
self.currency_id
and self.currency_id != self.company_id.currency_id
):
if 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
# journal: use the amount in the amount_currency field, and set
# credit / debit to the value in company currency at the date of
@@ -239,12 +226,8 @@ class AccountJournal(models.Model):
currency = self.currency_id.with_context(date=move.date)
company_currency = self.company_id.currency_id
values["amount_currency"] = values["debit"] - values["credit"]
values["debit"] = currency.compute(
values["debit"], company_currency
)
values["credit"] = currency.compute(
values["credit"], company_currency
)
values["debit"] = currency.compute(values["debit"], company_currency)
values["credit"] = currency.compute(values["credit"], company_currency)
if account.reconcile:
values["amount_residual"] = values["debit"] - values["credit"]
else:
@@ -294,16 +277,12 @@ class AccountJournal(models.Model):
res = self.env["account.move"]
for result_row_list in parser.parse(file_stream):
move = self._move_import(
parser,
file_stream,
result_row_list=result_row_list,
ftype=ftype,
parser, file_stream, result_row_list=result_row_list, ftype=ftype,
)
res |= move
return res
def _move_import(
self, parser, file_stream, result_row_list=None, ftype="csv"):
def _move_import(self, parser, file_stream, result_row_list=None, ftype="csv"):
"""Create a bank statement with the given profile and parser. It will
fulfill the bank statement with the values of the file provided, but
will not complete data (like finding the partner, or the right
@@ -323,9 +302,7 @@ class AccountJournal(models.Model):
# Check all key are present in account.bank.statement.line!!
if not result_row_list:
raise UserError(_("Nothing to import: " "The file is empty"))
parsed_cols = list(
parser.get_move_line_vals(result_row_list[0]).keys()
)
parsed_cols = list(parser.get_move_line_vals(result_row_list[0]).keys())
for col in parsed_cols:
if col not in move_line_obj._fields:
raise UserError(
@@ -344,9 +321,7 @@ class AccountJournal(models.Model):
parser_vals = parser.get_move_line_vals(line)
values = self.prepare_move_line_vals(parser_vals, move)
move_store.append(values)
move_line_obj.with_context(check_move_validity=False).create(
move_store
)
move_line_obj.with_context(check_move_validity=False).create(move_store)
self._write_extra_move_lines(parser, move)
if self.create_counterpart:
self._create_counterpart(parser, move)
@@ -358,7 +333,7 @@ class AccountJournal(models.Model):
attachment_data = {
"name": "statement file",
"datas": file_stream,
"datas_fname": "%s.%s" % (fields.Date.today(), ftype),
"datas_fname": "{}.{}".format(fields.Date.today(), ftype),
"res_model": "account.move",
"res_id": move.id,
}
@@ -373,16 +348,11 @@ class AccountJournal(models.Model):
raise
except Exception:
error_type, error_value, trbk = sys.exc_info()
st = "Error: %s\nDescription: %s\nTraceback:" % (
error_type.__name__,
error_value,
st = "Error: {}\nDescription: {}\nTraceback:".format(
error_type.__name__, error_value,
)
st += "".join(traceback.format_tb(trbk, 30))
raise ValidationError(
_(
"Statement import error "
"The statement cannot be created: %s"
)
% st
_("Statement import error " "The statement cannot be created: %s") % st
)
return move

View File

@@ -3,14 +3,13 @@
# Copyright 2013 Savoir-faire Linux
# Copyright 2014 ACSONE SA/NV
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)
import traceback
import sys
import logging
import sys
import traceback
from odoo import _, api, fields, models
from odoo.exceptions import ValidationError
_logger = logging.getLogger(__name__)
@@ -38,68 +37,81 @@ class AccountMoveCompletionRule(models.Model):
process. The reference should contain the invoice number or the SO number
or any reference that will be matched by the invoice accounting move.
"""
_name = "account.move.completion.rule"
_order = "sequence asc"
_description = "Account move completion method"
sequence = fields.Integer(
string='Sequence',
help="Lower means parsed first.")
name = fields.Char(
string='Name')
sequence = fields.Integer(string="Sequence", help="Lower means parsed first.")
name = fields.Char(string="Name")
journal_ids = fields.Many2many(
comodel_name='account.journal',
relation='account_journal_completion_rule_rel',
string='Related journals')
function_to_call = fields.Selection([
('get_from_name_and_invoice',
'From line name (based on customer invoice number)'),
('get_from_name_and_supplier_invoice',
'From line name (based on supplier invoice number)'),
('get_from_name_and_partner_field',
'From line name (based on partner field)'),
('get_from_name_and_partner_name',
'From line name (based on partner name)')
], string='Method'
comodel_name="account.journal",
relation="account_journal_completion_rule_rel",
string="Related journals",
)
function_to_call = fields.Selection(
[
(
"get_from_name_and_invoice",
"From line name (based on customer invoice number)",
),
(
"get_from_name_and_supplier_invoice",
"From line name (based on supplier invoice number)",
),
(
"get_from_name_and_partner_field",
"From line name (based on partner field)",
),
(
"get_from_name_and_partner_name",
"From line name (based on partner name)",
),
],
string="Method",
)
def _find_invoice(self, line, inv_type):
"""Find invoice related to statement line"""
inv_obj = self.env['account.invoice']
if inv_type == 'supplier':
type_domain = ('in_invoice', 'in_refund')
number_field = 'reference'
elif inv_type == 'customer':
type_domain = ('out_invoice', 'out_refund')
number_field = 'number'
inv_obj = self.env["account.invoice"]
if inv_type == "supplier":
type_domain = ("in_invoice", "in_refund")
number_field = "reference"
elif inv_type == "customer":
type_domain = ("out_invoice", "out_refund")
number_field = "number"
else:
raise ValidationError(
_('Invalid invoice type for completion: %s') % inv_type)
_("Invalid invoice type for completion: %s") % inv_type
)
invoices = inv_obj.search([(number_field, '=', line.name.strip()),
('type', 'in', type_domain)])
invoices = inv_obj.search(
[(number_field, "=", line.name.strip()), ("type", "in", type_domain)]
)
if invoices:
if len(invoices) == 1:
return invoices
else:
raise ErrorTooManyPartner(
_('Line named "%s" was matched by more than one '
'partner while looking on %s invoices') %
(line.name, inv_type))
_(
'Line named "%s" was matched by more than one '
"partner while looking on %s invoices"
)
% (line.name, inv_type)
)
return False
def _from_invoice(self, line, inv_type):
"""Populate statement line values"""
if inv_type not in ('supplier', 'customer'):
if inv_type not in ("supplier", "customer"):
raise ValidationError(
_('Invalid invoice type for completion: %s') %
inv_type)
_("Invalid invoice type for completion: %s") % inv_type
)
res = {}
invoice = self._find_invoice(line, inv_type)
if invoice:
partner_id = invoice.commercial_partner_id.id
res = {'partner_id': partner_id,
'account_id': invoice.account_id.id}
res = {"partner_id": partner_id, "account_id": invoice.account_id.id}
return res
# Should be private but data are initialised with no update XML
@@ -117,7 +129,7 @@ class AccountMoveCompletionRule(models.Model):
'account_id': value,
...}
"""
return self._from_invoice(line, 'supplier')
return self._from_invoice(line, "supplier")
# Should be private but data are initialised with no update XML
def get_from_name_and_invoice(self, line):
@@ -134,7 +146,7 @@ class AccountMoveCompletionRule(models.Model):
'account_id': value,
...}
"""
return self._from_invoice(line, 'customer')
return self._from_invoice(line, "customer")
# Should be private but data are initialised with no update XML
def get_from_name_and_partner_field(self, line):
@@ -155,21 +167,20 @@ class AccountMoveCompletionRule(models.Model):
...}
"""
res = {}
partner_obj = self.env['res.partner']
partner_obj = self.env["res.partner"]
or_regex = ".*;? *%s *;?.*" % line.name
sql = ("SELECT id from res_partner"
" WHERE bank_statement_label ~* %s")
sql = "SELECT id from res_partner" " WHERE bank_statement_label ~* %s"
self.env.cr.execute(sql, (or_regex,))
partner_ids = self.env.cr.fetchall()
partners = partner_obj.browse([x[0] for x in partner_ids])
if partners:
if len(partners) > 1:
msg = (_('Line named "%s" was matched by more than '
'one partner while looking on partner label: %s') %
(line.name,
','.join([x.name for x in partners])))
msg = _(
'Line named "%s" was matched by more than '
"one partner while looking on partner label: %s"
) % (line.name, ",".join([x.name for x in partners]))
raise ErrorTooManyPartner(msg)
res['partner_id'] = partners[0].id
res["partner_id"] = partners[0].id
return res
def get_from_name_and_partner_name(self, line):
@@ -210,10 +221,13 @@ class AccountMoveCompletionRule(models.Model):
if result:
if len(result) > 1:
raise ErrorTooManyPartner(
_('Line named "%s" was matched by more than one '
'partner while looking on partner by name') %
line.name)
res['partner_id'] = result[0][0]
_(
'Line named "%s" was matched by more than one '
"partner while looking on partner by name"
)
% line.name
)
res["partner_id"] = result[0][0]
return res
@@ -227,6 +241,7 @@ class AccountMoveLine(models.Model):
Have a look in account_move_base_import module to see how we've done
it.
"""
_inherit = "account.move.line"
_order = "already_completed desc, date asc"
@@ -234,7 +249,8 @@ class AccountMoveLine(models.Model):
string="Auto-Completed",
default=False,
help="When this checkbox is ticked, the auto-completion "
"process/button will ignore this line.")
"process/button will ignore this line.",
)
def _get_line_values_from_rules(self):
"""We'll try to find out the values related to the line based on rules
@@ -268,12 +284,11 @@ class AccountMoveLine(models.Model):
rules = self.journal_id.rule_ids
for rule in rules:
method_to_call = getattr(
self.env['account.move.completion.rule'],
rule.function_to_call
self.env["account.move.completion.rule"], rule.function_to_call
)
result = method_to_call(self)
if result:
result['already_completed'] = True
result["already_completed"] = True
return result
return None
@@ -282,17 +297,17 @@ class AccountMove(models.Model):
"""We add a basic button and stuff to support the auto-completion
of the bank statement once line have been imported or manually fulfill.
"""
_name = 'account.move'
_inherit = ['account.move', 'mail.thread']
_name = "account.move"
_inherit = ["account.move", "mail.thread"]
used_for_completion = fields.Boolean(
related='journal_id.used_for_completion',
readonly=True)
completion_logs = fields.Text(string='Completion Log', readonly=True)
import_partner_id = fields.Many2one('res.partner',
string="Partner from import")
related="journal_id.used_for_completion", readonly=True
)
completion_logs = fields.Text(string="Completion Log", readonly=True)
import_partner_id = fields.Many2one("res.partner", string="Partner from import")
@api.depends('line_ids.partner_id', 'import_partner_id')
@api.depends("line_ids.partner_id", "import_partner_id")
def _compute_partner_id(self):
for move in self:
if move.import_partner_id:
@@ -314,14 +329,25 @@ class AccountMove(models.Model):
number_line = len(self.line_ids)
log = self.completion_logs or ""
completion_date = fields.Datetime.now()
message = (_("%s Account Move %s has %s/%s lines completed by "
"%s \n%s\n%s\n") % (completion_date, self.name,
number_imported, number_line,
user_name, error_msg, log))
self.write({'completion_logs': message})
message = _(
"%s Account Move %s has %s/%s lines completed by " "%s \n%s\n%s\n"
) % (
completion_date,
self.name,
number_imported,
number_line,
user_name,
error_msg,
log,
)
self.write({"completion_logs": message})
body = (_('Statement ID %s auto-completed for %s/%s lines completed') %
(self.name, number_imported, number_line)),
body = (
(
_("Statement ID %s auto-completed for %s/%s lines completed")
% (self.name, number_imported, number_line)
),
)
self.message_post(body=body)
return True
@@ -345,9 +371,10 @@ class AccountMove(models.Model):
except Exception as exc:
msg_lines.append(repr(exc))
error_type, error_value, trbk = sys.exc_info()
st = "Error: %s\nDescription: %s\nTraceback:" % (
error_type.__name__, error_value)
st += ''.join(traceback.format_tb(trbk, 30))
st = "Error: {}\nDescription: {}\nTraceback:".format(
error_type.__name__, error_value,
)
st += "".join(traceback.format_tb(trbk, 30))
_logger.error(st)
if res:
try:
@@ -355,10 +382,11 @@ class AccountMove(models.Model):
except Exception as exc:
msg_lines.append(repr(exc))
error_type, error_value, trbk = sys.exc_info()
st = "Error: %s\nDescription: %s\nTraceback:" % (
error_type.__name__, error_value)
st += ''.join(traceback.format_tb(trbk, 30))
st = "Error: {}\nDescription: {}\nTraceback:".format(
error_type.__name__, error_value,
)
st += "".join(traceback.format_tb(trbk, 30))
_logger.error(st)
msg = '\n'.join(msg_lines)
msg = "\n".join(msg_lines)
self.write_completion_log(msg, compl_lines)
return True

View File

@@ -10,12 +10,14 @@ class ResPartner(models.Model):
"""Add a bank label on the partner so that we can use it to match
this partner when we found this in a statement line.
"""
_inherit = 'res.partner'
_inherit = "res.partner"
bank_statement_label = fields.Char(
string='Bank Statement Label',
string="Bank Statement Label",
help="Enter the various label found on your bank statement "
"separated by a ; If one of this label is include in the "
"bank statement line, the partner will be automatically "
"filled (as long as you use this method/rules in your "
"statement profile).")
"statement profile).",
)

View File

@@ -4,8 +4,8 @@
# Copyright 2014 ACSONE SA/NV
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)
import datetime
import tempfile
import logging
import tempfile
from odoo import _
from odoo.exceptions import UserError
@@ -40,7 +40,8 @@ class FileParser(AccountMoveImportParser):
header=None,
dialect=None,
move_ref=None,
**kwargs):
**kwargs
):
"""
:param char: parse_name: The name of the parser
:param char: ftype: extension of the file (could be csv, xls or
@@ -152,9 +153,7 @@ class FileParser(AccountMoveImportParser):
if conversion_rules[rule] == datetime.datetime:
try:
date_string = line[rule].split(" ")[0]
line[rule] = datetime.datetime.strptime(
date_string, "%Y-%m-%d"
)
line[rule] = datetime.datetime.strptime(date_string, "%Y-%m-%d")
except ValueError as err:
raise UserError(
_(
@@ -196,9 +195,7 @@ class FileParser(AccountMoveImportParser):
for rule in conversion_rules:
if conversion_rules[rule] == datetime.datetime:
try:
t_tuple = xlrd.xldate_as_tuple(
line[rule], self._datemode
)
t_tuple = xlrd.xldate_as_tuple(line[rule], self._datemode)
line[rule] = datetime.datetime(*t_tuple)
except Exception as err:
raise UserError(

View File

@@ -4,9 +4,11 @@
# Copyright 2014 ACSONE SA/NV
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)
import datetime
from .file_parser import FileParser, float_or_zero
from odoo.tools import ustr
from .file_parser import FileParser, float_or_zero
class GenericFileParser(FileParser):
"""Standard parser that use a define format in csv or xls to import into a
@@ -15,25 +17,22 @@ class GenericFileParser(FileParser):
file.
"""
def __init__(self, journal, ftype='csv', **kwargs):
def __init__(self, journal, ftype="csv", **kwargs):
conversion_dict = {
'label': ustr,
'date': datetime.datetime,
'amount': float_or_zero,
"label": ustr,
"date": datetime.datetime,
"amount": float_or_zero,
}
# set self.env for later ORM searches
self.env = journal.env
super().__init__(
journal, ftype=ftype,
extra_fields=conversion_dict,
**kwargs)
super().__init__(journal, ftype=ftype, extra_fields=conversion_dict, **kwargs)
@classmethod
def parser_for(cls, parser_name):
"""Used by the new_bank_statement_parser class factory. Return true if
the providen name is generic_csvxls_so
"""
return parser_name == 'generic_csvxls_so'
return parser_name == "generic_csvxls_so"
def get_move_line_vals(self, line, *args, **kwargs):
"""
@@ -52,27 +51,27 @@ class GenericFileParser(FileParser):
'debit':value
}
"""
account_obj = self.env['account.account']
partner_obj = self.env['res.partner']
account_obj = self.env["account.account"]
partner_obj = self.env["res.partner"]
account_id = False
partner_id = False
if line.get('account'):
accounts = account_obj.search([('code', '=', line['account'])])
if line.get("account"):
accounts = account_obj.search([("code", "=", line["account"])])
if len(accounts) == 1:
account_id = accounts[0].id
if line.get('partner'):
partners = partner_obj.search([('name', '=', line['partner'])])
if line.get("partner"):
partners = partner_obj.search([("name", "=", line["partner"])])
if len(partners) == 1:
partner_id = partners[0].id
amount = line.get('amount', 0.0)
amount = line.get("amount", 0.0)
return {
'name': line.get('label', '/'),
'date_maturity': line.get('date', datetime.datetime.now().date()),
'credit': amount > 0.0 and amount or 0.0,
'debit': amount < 0.0 and -amount or 0.0,
'account_id': account_id,
'partner_id': partner_id,
"name": line.get("label", "/"),
"date_maturity": line.get("date", datetime.datetime.now().date()),
"credit": amount > 0.0 and amount or 0.0,
"debit": amount < 0.0 and -amount or 0.0,
"account_id": account_id,
"partner_id": partner_id,
}

View File

@@ -5,6 +5,7 @@
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)
import base64
import csv
from openerp import _, fields
@@ -13,16 +14,14 @@ def UnicodeDictReader(utf8_data, **kwargs):
pos = utf8_data.tell()
sample_data = utf8_data.read(2048)
utf8_data.seek(pos)
if not kwargs.get('dialect'):
dialect = sniffer.sniff(sample_data, delimiters=',;\t')
del kwargs['dialect']
if not kwargs.get("dialect"):
dialect = sniffer.sniff(sample_data, delimiters=",;\t")
del kwargs["dialect"]
else:
dialect = kwargs.pop('dialect')
dialect = kwargs.pop("dialect")
csv_reader = csv.DictReader(utf8_data, dialect=dialect, **kwargs)
for row in csv_reader:
yield dict([(str(key or ''),
str(value or ''))
for key, value in row.items()])
yield {str(key or ""): str(value or "") for key, value in row.items()}
class AccountMoveImportParser(object):
@@ -108,9 +107,9 @@ class AccountMoveImportParser(object):
:return: dict of vals that represent additional infos for the statement
"""
return {
'name': self.move_name or '/',
'date': self.move_date or fields.Datetime.now(),
'ref': self.move_ref or '/'
"name": self.move_name or "/",
"date": self.move_date or fields.Datetime.now(),
"ref": self.move_ref or "/",
}
def get_move_line_vals(self, line, *args, **kwargs):
@@ -144,7 +143,7 @@ class AccountMoveImportParser(object):
if filebuffer:
self.filebuffer = filebuffer
else:
raise Exception(_('No buffer file given.'))
raise Exception(_("No buffer file given."))
self._format(*args, **kwargs)
self._pre(*args, **kwargs)
if self.support_multi_moves:
@@ -184,8 +183,9 @@ def itersubclasses(cls, _seen=None):
['type', ...'tuple', ...]
"""
if not isinstance(cls, type):
raise TypeError('itersubclasses must be called with '
'new-style classes, not %.100r' % cls)
raise TypeError(
"itersubclasses must be called with " "new-style classes, not %.100r" % cls
)
if _seen is None:
_seen = set()
try:

View File

@@ -3,13 +3,15 @@
# Copyright 2013 Savoir-faire Linux
# Copyright 2014 ACSONE SA/NV
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)
from collections import namedtuple
from odoo import fields, tools
from odoo.modules import get_resource_path
from odoo.tests import common
from collections import namedtuple
name_completion_case = namedtuple(
"name_completion_case", ["partner_name", "line_label", "should_match"])
"name_completion_case", ["partner_name", "line_label", "should_match"]
)
NAMES_COMPLETION_CASES = [
name_completion_case("Acsone", "Line for Acsone SA", True),
name_completion_case("Acsone", "Line for Acsone", True),
@@ -21,29 +23,37 @@ NAMES_COMPLETION_CASES = [
name_completion_case("Acsone", "A..one for line", False),
name_completion_case("A.one SA", "A.one SA for line", True),
name_completion_case(
"Acsone SA", "Line for Acsone ([^a-zA-Z0-9 -]) SA test", False),
"Acsone SA", "Line for Acsone ([^a-zA-Z0-9 -]) SA test", False
),
name_completion_case(
"Acsone ([^a-zA-Z0-9 -]) SA", "Line for Acsone ([^a-zA-Z0-9 -]) SA "
"test", True),
"Acsone ([^a-zA-Z0-9 -]) SA",
"Line for Acsone ([^a-zA-Z0-9 -]) SA " "test",
True,
),
name_completion_case(
r"Acsone (.^$*+?()[{\| -]\) SA", r"Line for Acsone (.^$*+?()[{\| -]\) "
r"SA test", True),
r"Acsone (.^$*+?()[{\| -]\) SA",
r"Line for Acsone (.^$*+?()[{\| -]\) " r"SA test",
True,
),
name_completion_case("Acšone SA", "Line for Acšone SA test", True),
]
class BaseCompletion(common.TransactionCase):
def setUp(self):
super().setUp()
tools.convert_file(self.cr, 'account',
get_resource_path('account', 'test',
'account_minimal_test.xml'),
{}, 'init', False, 'test')
tools.convert_file(
self.cr,
"account",
get_resource_path("account", "test", "account_minimal_test.xml"),
{},
"init",
False,
"test",
)
self.account_move_obj = self.env["account.move"]
self.account_move_line_obj = \
self.env["account.move.line"]
self.company_a = self.browse_ref('base.main_company')
self.account_move_line_obj = self.env["account.move.line"]
self.company_a = self.browse_ref("base.main_company")
self.journal = self.browse_ref("account.bank_journal")
self.partner = self.browse_ref("base.res_partner_12")
self.account_id = self.ref("account.a_recv")
@@ -54,41 +64,49 @@ class BaseCompletion(common.TransactionCase):
the partner appears in the statement line label
"""
self.completion_rule_id = self.ref(
'account_move_base_import.bank_statement_completion_rule_3')
"account_move_base_import.bank_statement_completion_rule_3"
)
# Create the profile
self.journal.write({
'used_for_completion': True,
'rule_ids': [(6, 0, [self.completion_rule_id])]
})
self.journal.write(
{
"used_for_completion": True,
"rule_ids": [(6, 0, [self.completion_rule_id])],
}
)
# Create a bank statement
self.move = self.account_move_obj.create({
"date": fields.Date.today(),
"journal_id": self.journal.id
})
self.move = self.account_move_obj.create(
{"date": fields.Date.today(), "journal_id": self.journal.id}
)
for case in NAMES_COMPLETION_CASES:
self.partner.write({'name': case.partner_name})
self.partner.write({"name": case.partner_name})
self.move_line = self.account_move_line_obj.with_context(
check_move_validity=False
).create({
'account_id': self.account_id,
'credit': 1000.0,
'name': case.line_label,
'move_id': self.move.id,
})
).create(
{
"account_id": self.account_id,
"credit": 1000.0,
"name": case.line_label,
"move_id": self.move.id,
}
)
self.assertFalse(
self.move_line.partner_id,
"Partner_id must be blank before completion")
self.move_line.partner_id, "Partner_id must be blank before completion"
)
self.move.button_auto_completion()
if case.should_match:
self.assertEqual(
self.partner, self.move_line.partner_id,
self.partner,
self.move_line.partner_id,
"Missing expected partner id after completion "
"(partner_name: %s, line_name: %s)" %
(case.partner_name, case.line_label))
"(partner_name: %s, line_name: %s)"
% (case.partner_name, case.line_label),
)
else:
self.assertNotEqual(
self.partner, self.move_line.partner_id,
self.partner,
self.move_line.partner_id,
"Partner id should be empty after completion "
"(partner_name: %s, line_name: %s)"
% (case.partner_name, case.line_label))
% (case.partner_name, case.line_label),
)

View File

@@ -6,57 +6,63 @@
import base64
import os
from operator import attrgetter
from odoo.tests import common
from odoo import tools, fields
from odoo import fields, tools
from odoo.modules import get_resource_path
from odoo.tests import common
class TestCodaImport(common.TransactionCase):
def setUp(self):
super().setUp()
self.company_a = self.browse_ref('base.main_company')
tools.convert_file(self.cr, 'account',
get_resource_path('account', 'test',
'account_minimal_test.xml'),
{}, 'init', False, 'test')
self.company_a = self.browse_ref("base.main_company")
tools.convert_file(
self.cr,
"account",
get_resource_path("account", "test", "account_minimal_test.xml"),
{},
"init",
False,
"test",
)
self.account_move_obj = self.env["account.move"]
self.account_move_line_obj = self.env["account.move.line"]
self.account_id = self.ref("account.a_recv")
self.journal = self.browse_ref("account.bank_journal")
self.import_wizard_obj = self.env['credit.statement.import']
self.import_wizard_obj = self.env["credit.statement.import"]
self.partner = self.browse_ref("base.res_partner_12")
self.journal.write({
'used_for_import': True,
self.journal.write(
{
"used_for_import": True,
"import_type": "generic_csvxls_so",
'partner_id': self.partner.id,
'commission_account_id': self.account_id,
'receivable_account_id': self.account_id,
'create_counterpart': True,
})
"partner_id": self.partner.id,
"commission_account_id": self.account_id,
"receivable_account_id": self.account_id,
"create_counterpart": True,
}
)
def _import_file(self, file_name):
""" import a file using the wizard
return the create account.bank.statement object
"""
with open(file_name, 'rb') as f:
with open(file_name, "rb") as f:
content = f.read()
self.wizard = self.import_wizard_obj.create({
self.wizard = self.import_wizard_obj.create(
{
"journal_id": self.journal.id,
'input_statement': base64.b64encode(content),
'file_name': os.path.basename(file_name),
})
"input_statement": base64.b64encode(content),
"file_name": os.path.basename(file_name),
}
)
res = self.wizard.import_statement()
return self.account_move_obj.browse(res['res_id'])
return self.account_move_obj.browse(res["res_id"])
def test_simple_xls(self):
"""Test import from xls
"""
file_name = get_resource_path(
'account_move_base_import',
'tests',
'data',
'statement.xls'
"account_move_base_import", "tests", "data", "statement.xls"
)
move = self._import_file(file_name)
self._validate_imported_move(move)
@@ -65,10 +71,7 @@ class TestCodaImport(common.TransactionCase):
"""Test import from csv
"""
file_name = get_resource_path(
'account_move_base_import',
'tests',
'data',
'statement.csv'
"account_move_base_import", "tests", "data", "statement.csv"
)
move = self._import_file(file_name)
self._validate_imported_move(move)
@@ -76,11 +79,8 @@ class TestCodaImport(common.TransactionCase):
def _validate_imported_move(self, move):
self.assertEqual("/", move.name)
self.assertEqual(5, len(move.line_ids))
move_line = sorted(move.line_ids,
key=attrgetter('date_maturity'))[2]
move_line = sorted(move.line_ids, key=attrgetter("date_maturity"))[2]
# common infos
self.assertEqual(
move_line.date_maturity, fields.Date.from_string('2011-03-07')
)
self.assertEqual(move_line.date_maturity, fields.Date.from_string("2011-03-07"))
self.assertEqual(move_line.credit, 118.4)
self.assertEqual(move_line.name, "label a")

View File

@@ -7,143 +7,168 @@ from odoo.tools import convert_file
class TestInvoice(SingleTransactionCase):
def setUp(self):
super().setUp()
self.account_move_obj = self.env["account.move"]
self.account_move_line_obj = \
self.env["account.move.line"]
self.company_a = self.env.ref('base.main_company')
self.account_move_line_obj = self.env["account.move.line"]
self.company_a = self.env.ref("base.main_company")
self.partner = self.env.ref("base.res_partner_12")
def test_01_partner(self):
# I fill in the field Bank Statement Label in a Partner
self.partner_4 = self.env.ref('base.res_partner_4')
self.partner_4.bank_statement_label = 'XXX66Z'
self.assertEqual(self.partner_4.bank_statement_label, 'XXX66Z')
self.partner_4 = self.env.ref("base.res_partner_4")
self.partner_4.bank_statement_label = "XXX66Z"
self.assertEqual(self.partner_4.bank_statement_label, "XXX66Z")
def test_02_invoice(self):
convert_file(
self.cr, 'account', get_resource_path(
'account', 'test', 'account_minimal_test.xml'
), {}, 'init', False, 'test'
self.cr,
"account",
get_resource_path("account", "test", "account_minimal_test.xml"),
{},
"init",
False,
"test",
)
self.journal = self.env.ref("account.bank_journal")
self.account_id = self.env.ref("account.a_recv")
# I create a customer Invoice to be found by the completion.
product_3 = self.env.ref('product.product_product_3')
self.invoice_for_completion_1 = self.env['account.invoice'].create({
'currency_id': self.env.ref('base.EUR').id,
'invoice_line_ids': [(0, 0, {
'name': '[PCSC234] PC Assemble SC234',
'product_id': product_3.id,
'price_unit': 210.0,
'quantity': 1.0,
'uom_id': self.env.ref('uom.product_uom_unit').id,
'account_id': self.env.ref('account.a_sale').id,
})],
'journal_id': self.journal.id,
'partner_id': self.partner.id,
'account_id': self.env.ref('account.a_recv').id,
})
product_3 = self.env.ref("product.product_product_3")
self.invoice_for_completion_1 = self.env["account.invoice"].create(
{
"currency_id": self.env.ref("base.EUR").id,
"invoice_line_ids": [
(
0,
0,
{
"name": "[PCSC234] PC Assemble SC234",
"product_id": product_3.id,
"price_unit": 210.0,
"quantity": 1.0,
"uom_id": self.env.ref("uom.product_uom_unit").id,
"account_id": self.env.ref("account.a_sale").id,
},
)
],
"journal_id": self.journal.id,
"partner_id": self.partner.id,
"account_id": self.env.ref("account.a_recv").id,
}
)
# I confirm the Invoice
self.invoice_for_completion_1.action_invoice_open()
# I check that the invoice state is "Open"
self.assertEqual(self.invoice_for_completion_1.state, 'open')
self.assertEqual(self.invoice_for_completion_1.state, "open")
# I check that it is given the number "TBNK/%Y/0001"
self.assertEqual(
self.invoice_for_completion_1.number,
fields.Date.today().strftime('TBNK/%Y/0001')
fields.Date.today().strftime("TBNK/%Y/0001"),
)
def test_03_supplier_invoice(self):
# I create a demo invoice
product_delivery = self.env.ref('product.product_delivery_01')
product_order = self.env.ref('product.product_order_01')
exp_account = self.env.ref('account.a_expense')
rec_account = self.env.ref('account.a_recv')
demo_invoice_0 = self.env['account.invoice'].create({
'partner_id': self.partner.id,
'payment_term_id': self.env.ref('account.account_payment_term').id,
'type': 'in_invoice',
'date_invoice': fields.Date.today().replace(day=1),
'account_id': rec_account.id,
'invoice_line_ids': [
(0, 0, {
'price_unit': 10.0,
'quantity': 1.0,
'product_id': product_delivery.id,
'name': product_delivery.name,
'uom_id': self.env.ref('uom.product_uom_unit').id,
'account_id': exp_account.id,
}), (0, 0, {
'price_unit': 4.0,
'quantity': 1.0,
'product_id': product_order.id,
'name': product_order.name,
'uom_id': self.env.ref('uom.product_uom_unit').id,
'account_id': exp_account.id,
})
product_delivery = self.env.ref("product.product_delivery_01")
product_order = self.env.ref("product.product_order_01")
exp_account = self.env.ref("account.a_expense")
rec_account = self.env.ref("account.a_recv")
demo_invoice_0 = self.env["account.invoice"].create(
{
"partner_id": self.partner.id,
"payment_term_id": self.env.ref("account.account_payment_term").id,
"type": "in_invoice",
"date_invoice": fields.Date.today().replace(day=1),
"account_id": rec_account.id,
"invoice_line_ids": [
(
0,
0,
{
"price_unit": 10.0,
"quantity": 1.0,
"product_id": product_delivery.id,
"name": product_delivery.name,
"uom_id": self.env.ref("uom.product_uom_unit").id,
"account_id": exp_account.id,
},
),
(
0,
0,
{
"price_unit": 4.0,
"quantity": 1.0,
"product_id": product_order.id,
"name": product_order.name,
"uom_id": self.env.ref("uom.product_uom_unit").id,
"account_id": exp_account.id,
},
),
],
})
}
)
# I check that my invoice is a supplier invoice
self.assertEqual(
demo_invoice_0.type, 'in_invoice', msg="Check invoice type"
)
self.assertEqual(demo_invoice_0.type, "in_invoice", msg="Check invoice type")
# I add a reference to an existing supplier invoice
demo_invoice_0.write({'reference': 'T2S12345'})
demo_invoice_0.write({"reference": "T2S12345"})
# I check a second time that my invoice is still a supplier invoice
self.assertEqual(
demo_invoice_0.type, 'in_invoice', msg="Check invoice type 2"
)
self.assertEqual(demo_invoice_0.type, "in_invoice", msg="Check invoice type 2")
# Now I confirm it
demo_invoice_0.action_invoice_open()
# I check that the supplier number is there
self.assertEqual(
demo_invoice_0.reference, 'T2S12345', msg="Check supplier number"
demo_invoice_0.reference, "T2S12345", msg="Check supplier number"
)
# I check a third time that my invoice is still a supplier invoice
self.assertEqual(
demo_invoice_0.type, 'in_invoice', msg="Check invoice type 3"
)
self.assertEqual(demo_invoice_0.type, "in_invoice", msg="Check invoice type 3")
def test_04_refund(self):
# I create a "child" partner, to use in the invoice
# (and have a different commercial_partner_id than itself)
res_partner_12_child = self.env['res.partner'].create({
'name': 'Child Partner',
'supplier': False,
'customer': True,
'is_company': False,
'parent_id': self.partner.id,
})
res_partner_12_child = self.env["res.partner"].create(
{
"name": "Child Partner",
"supplier": False,
"customer": True,
"is_company": False,
"parent_id": self.partner.id,
}
)
# I create a customer refund to be found by the completion.
product_3 = self.env.ref('product.product_product_3')
self.refund_for_completion_1 = self.env['account.invoice'].create({
'currency_id': self.env.ref('base.EUR').id,
'invoice_line_ids': [(0, 0, {
'name': '[PCSC234] PC Assemble SC234',
'product_id': product_3.id,
'price_unit': 210.0,
'quantity': 1.0,
'uom_id': self.env.ref('uom.product_uom_unit').id,
'account_id': self.env.ref('account.a_sale').id,
})],
'journal_id': self.env.ref('account.expenses_journal').id,
'partner_id': res_partner_12_child.id,
'type': 'out_refund',
'account_id': self.env.ref('account.a_recv').id,
})
product_3 = self.env.ref("product.product_product_3")
self.refund_for_completion_1 = self.env["account.invoice"].create(
{
"currency_id": self.env.ref("base.EUR").id,
"invoice_line_ids": [
(
0,
0,
{
"name": "[PCSC234] PC Assemble SC234",
"product_id": product_3.id,
"price_unit": 210.0,
"quantity": 1.0,
"uom_id": self.env.ref("uom.product_uom_unit").id,
"account_id": self.env.ref("account.a_sale").id,
},
)
],
"journal_id": self.env.ref("account.expenses_journal").id,
"partner_id": res_partner_12_child.id,
"type": "out_refund",
"account_id": self.env.ref("account.a_recv").id,
}
)
# I confirm the refund
self.refund_for_completion_1.action_invoice_open()
# I check that the refund state is "Open"
self.assertEqual(self.refund_for_completion_1.state, 'open')
self.assertEqual(self.refund_for_completion_1.state, "open")
# I check that it is given the number "RTEXJ/%Y/0001"
self.assertEqual(
self.refund_for_completion_1.number,
fields.Date.today().strftime('RTEXJ/%Y/0001')
fields.Date.today().strftime("RTEXJ/%Y/0001"),
)
def test_05_completion(self):
@@ -151,92 +176,102 @@ class TestInvoice(SingleTransactionCase):
# journal
self.journal = self.env.ref("account.bank_journal")
completion_rule_4 = self.env.ref(
'account_move_base_import.bank_statement_completion_rule_4'
"account_move_base_import.bank_statement_completion_rule_4"
)
completion_rule_2 = self.env.ref(
'account_move_base_import.bank_statement_completion_rule_2'
"account_move_base_import.bank_statement_completion_rule_2"
)
completion_rule_3 = self.env.ref(
'account_move_base_import.bank_statement_completion_rule_3'
"account_move_base_import.bank_statement_completion_rule_3"
)
completion_rule_5 = self.env.ref(
'account_move_base_import.bank_statement_completion_rule_5'
"account_move_base_import.bank_statement_completion_rule_5"
)
completion_rules = (
completion_rule_2 | completion_rule_3 | completion_rule_4
completion_rule_2
| completion_rule_3
| completion_rule_4
| completion_rule_5
)
self.journal.write({
'used_for_completion': True,
'rule_ids': [
self.journal.write(
{
"used_for_completion": True,
"rule_ids": [
(4, comp_rule.id, False) for comp_rule in completion_rules
]
})
],
}
)
# Now I create a statement. I create statment lines separately because
# I need to find each one by XML id
move_test1 = self.env['account.move'].create({
'name': 'Move 2',
'journal_id': self.journal.id,
})
move_test1 = self.env["account.move"].create(
{"name": "Move 2", "journal_id": self.journal.id}
)
# I create a move line for a CI
move_line_ci = self.env['account.move.line'].create({
'name': '\\',
'account_id': self.env.ref('account.a_sale').id,
'move_id': move_test1.id,
'date_maturity': fields.Date.from_string('2013-12-20'),
'credit': 0.0,
})
move_line_ci = self.env["account.move.line"].create(
{
"name": "\\",
"account_id": self.env.ref("account.a_sale").id,
"move_id": move_test1.id,
"date_maturity": fields.Date.from_string("2013-12-20"),
"credit": 0.0,
}
)
# I create a move line for a SI
move_line_si = self.env['account.move.line'].create({
'name': '\\',
'account_id': self.env.ref('account.a_expense').id,
'move_id': move_test1.id,
'date_maturity': fields.Date.from_string('2013-12-19'),
'debit': 0.0,
})
move_line_si = self.env["account.move.line"].create(
{
"name": "\\",
"account_id": self.env.ref("account.a_expense").id,
"move_id": move_test1.id,
"date_maturity": fields.Date.from_string("2013-12-19"),
"debit": 0.0,
}
)
# I create a move line for a CR
move_line_cr = self.env['account.move.line'].create({
'name': '\\',
'account_id': self.env.ref('account.a_expense').id,
'move_id': move_test1.id,
'date_maturity': fields.Date.from_string('2013-12-19'),
'debit': 0.0,
})
move_line_cr = self.env["account.move.line"].create(
{
"name": "\\",
"account_id": self.env.ref("account.a_expense").id,
"move_id": move_test1.id,
"date_maturity": fields.Date.from_string("2013-12-19"),
"debit": 0.0,
}
)
# I create a move line for the Partner Name
move_line_partner_name = self.env['account.move.line'].create({
'name': 'Test autocompletion based on Partner Name Azure Interior',
'account_id': self.env.ref('account.a_sale').id,
'move_id': move_test1.id,
'date_maturity': fields.Date.from_string('2013-12-17'),
'credit': 0.0,
})
move_line_partner_name = self.env["account.move.line"].create(
{
"name": "Test autocompletion based on Partner Name Azure Interior",
"account_id": self.env.ref("account.a_sale").id,
"move_id": move_test1.id,
"date_maturity": fields.Date.from_string("2013-12-17"),
"credit": 0.0,
}
)
# I create a move line for the Partner Label
move_line_partner_label = self.env['account.move.line'].create({
'name': 'XXX66Z',
'account_id': self.env.ref('account.a_sale').id,
'move_id': move_test1.id,
'date_maturity': '2013-12-24',
'debit': 0.0,
})
move_line_partner_label = self.env["account.move.line"].create(
{
"name": "XXX66Z",
"account_id": self.env.ref("account.a_sale").id,
"move_id": move_test1.id,
"date_maturity": "2013-12-24",
"debit": 0.0,
}
)
# and add the correct name
move_line_ci.with_context(check_move_validity=False).write({
'name': fields.Date.today().strftime('TBNK/%Y/0001'),
'credit': 210.0,
})
move_line_si.with_context(check_move_validity=False).write({
'name': 'T2S12345',
'debit': 65.0,
})
move_line_cr.with_context(check_move_validity=False).write({
'name': fields.Date.today().strftime('RTEXJ/%Y/0001'),
'debit': 210.0,
})
move_line_partner_name.with_context(check_move_validity=False).write({
'credit': 600.0,
})
move_line_partner_label.with_context(check_move_validity=False).write({
'debit': 932.4,
})
move_line_ci.with_context(check_move_validity=False).write(
{"name": fields.Date.today().strftime("TBNK/%Y/0001"), "credit": 210.0}
)
move_line_si.with_context(check_move_validity=False).write(
{"name": "T2S12345", "debit": 65.0}
)
move_line_cr.with_context(check_move_validity=False).write(
{"name": fields.Date.today().strftime("RTEXJ/%Y/0001"), "debit": 210.0}
)
move_line_partner_name.with_context(check_move_validity=False).write(
{"credit": 600.0}
)
move_line_partner_label.with_context(check_move_validity=False).write(
{"debit": 932.4}
)
# I run the auto complete
move_test1.button_auto_completion()
# Now I can check that all is nice and shiny, line 1. I expect the
@@ -244,31 +279,31 @@ class TestInvoice(SingleTransactionCase):
# I Use _ref, because ref conflicts with the field ref of the
# statement line
self.assertEqual(
move_line_ci.partner_id, self.partner,
msg="Check completion by CI number"
move_line_ci.partner_id, self.partner, msg="Check completion by CI number"
)
# Line 2. I expect the Supplier invoice number to be recognised. The
# supplier invoice was created by the account module demo data, and we
# confirmed it here.
self.assertEqual(
move_line_si.partner_id, self.partner,
msg="Check completion by SI number"
move_line_si.partner_id, self.partner, msg="Check completion by SI number"
)
# Line 3. I expect the Customer refund number to be recognised. It
# should be the commercial partner, and not the regular partner.
self.assertEqual(
move_line_cr.partner_id, self.partner,
msg="Check completion by CR number and commercial partner"
move_line_cr.partner_id,
self.partner,
msg="Check completion by CR number and commercial partner",
)
# Line 4. I check that the partner name has been recognised.
self.assertEqual(
move_line_partner_name.partner_id.name, 'Azure Interior',
msg="Check completion by partner name"
move_line_partner_name.partner_id.name,
"Azure Interior",
msg="Check completion by partner name",
)
# Line 5. I check that the partner special label has been recognised.
self.partner_4 = self.env.ref('base.res_partner_4')
self.partner_4 = self.env.ref("base.res_partner_4")
self.assertEqual(
move_line_partner_label.partner_id,
self.partner_4,
msg="Check completion by partner label"
msg="Check completion by partner label",
)

View File

@@ -9,24 +9,31 @@
<field name="used_for_completion" invisible="1" />
</field>
<button name="action_duplicate" position="after">
<button name="button_auto_completion"
<button
name="button_auto_completion"
string="Auto Completion"
type="object"
class="oe_highlight"
groups="account.group_account_invoice"
attrs="{'invisible': ['|', ('used_for_completion','=',False), ('state','not in', ['draft'])]}"/>
attrs="{'invisible': ['|', ('used_for_completion','=',False), ('state','not in', ['draft'])]}"
/>
</button>
<xpath expr="//field[@name='line_ids']/tree/field[@name='credit']" position="after">
<xpath
expr="//field[@name='line_ids']/tree/field[@name='credit']"
position="after"
>
<field name="already_completed" />
</xpath>
<xpath expr="/form/sheet/notebook" position="inside">
<page string="Completion Logs" attrs="{'invisible':[('completion_logs','=',False)]}">
<page
string="Completion Logs"
attrs="{'invisible':[('completion_logs','=',False)]}"
>
<field name="completion_logs" colspan="4" nolabel="1" />
</page>
</xpath>
</field>
</record>
<record id="move_completion_rule_view_form" model="ir.ui.view">
<field name="name">account.move.completion.rule.view</field>
<field name="model">account.move.completion.rule</field>
@@ -42,7 +49,6 @@
</form>
</field>
</record>
<record id="move_completion_rule_view_tree" model="ir.ui.view">
<field name="name">account.move.completion.rule.view</field>
<field name="model">account.move.completion.rule</field>
@@ -55,31 +61,33 @@
</tree>
</field>
</record>
<record id="action_move_completion_rule_tree" model="ir.actions.act_window">
<field name="name">Move Completion Rules</field>
<field name="res_model">account.move.completion.rule</field>
<field name="view_mode">tree,form</field>
</record>
<menuitem string="Move Completion Rule" action="action_move_completion_rule_tree"
id="menu_action_move_completion_rule_tree_menu" parent="account.account_management_menu"/>
<menuitem
string="Move Completion Rule"
action="action_move_completion_rule_tree"
id="menu_action_move_completion_rule_tree_menu"
parent="account.account_management_menu"
/>
<record id="view_account_move_filter" model="ir.ui.view">
<field name="model">account.move</field>
<field name="inherit_id" ref="account.view_account_move_filter" />
<field name="arch" type="xml">
<separator position="after">
<filter name="to_complete"
<filter
name="to_complete"
string="To Complete"
domain="[
('state','!=','posted'),
('journal_id.used_for_completion', '=', True),
('line_ids.already_completed', '=', False)]"
help="Account move that should be completed manually"/>
help="Account move that should be completed manually"
/>
<separator />
</separator>
</field>
</record>
</odoo>

View File

@@ -10,29 +10,49 @@
<field name="used_for_completion" />
</field>
<notebook position="inside">
<page string="Import related infos" attrs="{'invisible': [('used_for_import', '=', False)]}">
<page
string="Import related infos"
attrs="{'invisible': [('used_for_import', '=', False)]}"
>
<group>
<field name="launch_import_completion" attrs="{'invisible': ['|',
<field
name="launch_import_completion"
attrs="{'invisible': ['|',
('used_for_import', '=', False),
('used_for_completion', '=', False)]}"/>
('used_for_completion', '=', False)]}"
/>
<field name="last_import_date" readonly="1" />
<field name="import_type" attrs="{'required': [('used_for_import', '=', True)]}"/>
<field
name="import_type"
attrs="{'required': [('used_for_import', '=', True)]}"
/>
</group>
<group>
<field name="commission_account_id" />
<field name="receivable_account_id" attrs="{'required': [('used_for_import', '=', True)]}"/>
<field
name="receivable_account_id"
attrs="{'required': [('used_for_import', '=', True)]}"
/>
<field name="partner_id" />
<field name="create_counterpart" />
<field name="split_counterpart" attrs="{'invisible': [('create_counterpart', '=', False)]}"/>
<field
name="split_counterpart"
attrs="{'invisible': [('create_counterpart', '=', False)]}"
/>
</group>
<group>
<button name="%(account_move_base_import.move_importer_action)d"
<button
name="%(account_move_base_import.move_importer_action)d"
string="Import batch file"
type="action"
colspan = "2"/>
colspan="2"
/>
</group>
</page>
<page string="Auto-Completion related infos" attrs="{'invisible': [('used_for_completion', '=', False)]}">
<page
string="Auto-Completion related infos"
attrs="{'invisible': [('used_for_completion', '=', False)]}"
>
<group string="Auto-Completion Rules" name="completion_rules">
<field name="rule_ids" colspan="2" nolabel="1" />
</group>

View File

@@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<record id="bk_view_partner_form" model="ir.ui.view">
<field name="name">account_bank_statement_import.view.partner.form</field>
<field name="model">res.partner</field>
@@ -11,5 +10,4 @@
</field>
</field>
</record>
</odoo>

View File

@@ -7,72 +7,71 @@
Wizard to import financial institute date in bank statement
"""
import os
from odoo import _, api, fields, models
from odoo.exceptions import UserError
import os
class CreditPartnerStatementImporter(models.TransientModel):
_name = "credit.statement.import"
_description = 'Import Batch File wizard'
_description = "Import Batch File wizard"
@api.model
def default_get(self, fields):
res = super().default_get(fields)
ctx = self.env.context
if (
ctx.get('active_model') == 'account.journal' and
ctx.get('active_ids')):
ids = ctx['active_ids']
assert len(ids) == 1, \
'You cannot use this on more than one journal !'
res['journal_id'] = ids[0]
if ctx.get("active_model") == "account.journal" and ctx.get("active_ids"):
ids = ctx["active_ids"]
assert len(ids) == 1, "You cannot use this on more than one journal !"
res["journal_id"] = ids[0]
return res
journal_id = fields.Many2one(
comodel_name='account.journal',
string='Import configuration parameter',
required=True)
input_statement = fields.Binary(
string='Statement file',
required=True)
comodel_name="account.journal",
string="Import configuration parameter",
required=True,
)
input_statement = fields.Binary(string="Statement file", required=True)
partner_id = fields.Many2one(
comodel_name='res.partner',
related='journal_id.partner_id', readonly=True)
comodel_name="res.partner", related="journal_id.partner_id", readonly=True
)
file_name = fields.Char()
receivable_account_id = fields.Many2one(
comodel_name='account.account',
related='journal_id.receivable_account_id', readonly=True)
comodel_name="account.account",
related="journal_id.receivable_account_id",
readonly=True,
)
commission_account_id = fields.Many2one(
comodel_name='account.account',
related='journal_id.commission_account_id', readonly=True)
comodel_name="account.account",
related="journal_id.commission_account_id",
readonly=True,
)
@api.multi
def _check_extension(self):
self.ensure_one()
(__, ftype) = os.path.splitext(self.file_name)
if not ftype:
raise UserError(_('Please use a file with an extension'))
raise UserError(_("Please use a file with an extension"))
return ftype
@api.multi
def import_statement(self):
"""This Function import credit card agency statement"""
moves = self.env['account.move']
moves = self.env["account.move"]
for importer in self:
journal = importer.journal_id
ftype = importer._check_extension()
moves |= journal.with_context(
file_name=importer.file_name).multi_move_import(
importer.input_statement,
ftype.replace('.', '')
)
xmlid = ('account', 'action_move_journal_line')
action = self.env['ir.actions.act_window'].for_xml_id(*xmlid)
file_name=importer.file_name
).multi_move_import(importer.input_statement, ftype.replace(".", ""))
xmlid = ("account", "action_move_journal_line")
action = self.env["ir.actions.act_window"].for_xml_id(*xmlid)
if len(moves) > 1:
action['domain'] = [('id', 'in', moves.ids)]
action["domain"] = [("id", "in", moves.ids)]
else:
ref = self.env.ref('account.view_move_form')
action['views'] = [(ref.id, 'form')]
action['res_id'] = moves.id if moves else False
ref = self.env.ref("account.view_move_form")
action["views"] = [(ref.id, "form")]
action["res_id"] = moves.id if moves else False
return action

View File

@@ -6,7 +6,10 @@
<field name="arch" type="xml">
<form string="Import move">
<group name="main">
<field name="journal_id" domain="[('used_for_import', '=', True)]"/>
<field
name="journal_id"
domain="[('used_for_import', '=', True)]"
/>
<field name="input_statement" filename="file_name" />
<field name="file_name" invisible="1" />
</group>
@@ -16,19 +19,27 @@
<field name="commission_account_id" />
</group>
<footer>
<button name="import_statement" string="Import file" type="object" class="oe_highlight"/>
<button
name="import_statement"
string="Import file"
type="object"
class="oe_highlight"
/>
<button special="cancel" string="Cancel" class="oe_link" />
</footer>
</form>
</field>
</record>
<record id="move_importer_action" model="ir.actions.act_window">
<field name="name">Import Batch File</field>
<field name="res_model">credit.statement.import</field>
<field name="view_mode">form</field>
<field name="target">new</field>
</record>
<menuitem id="move_importer_menu" name="Import Batch File" action="move_importer_action" parent="account.menu_finance_entries"/>
<menuitem
id="move_importer_menu"
name="Import Batch File"
action="move_importer_action"
parent="account.menu_finance_entries"
/>
</odoo>