mirror of
https://github.com/OCA/account-reconcile.git
synced 2025-01-20 12:27:39 +02:00
[IMP] account_move_base_import: black, isort, prettier
This commit is contained in:
committed by
Florian da Costa
parent
e81b55d0a8
commit
68fc7849f3
@@ -4,13 +4,13 @@
|
|||||||
# Copyright 2014 ACSONE SA/NV
|
# Copyright 2014 ACSONE SA/NV
|
||||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)
|
||||||
{
|
{
|
||||||
'name': "Journal Entry base import",
|
"name": "Journal Entry base import",
|
||||||
'version': '12.0.2.0.0',
|
"version": "13.0.1.0.0",
|
||||||
'author': "Akretion,Camptocamp,Odoo Community Association (OCA)",
|
"author": "Akretion,Camptocamp,Odoo Community Association (OCA)",
|
||||||
'category': 'Finance',
|
"category": "Finance",
|
||||||
'depends': ['account'],
|
"depends": ["account"],
|
||||||
'website': 'http://www.camptocamp.com',
|
"website": "http://www.camptocamp.com",
|
||||||
'data': [
|
"data": [
|
||||||
"security/ir.model.access.csv",
|
"security/ir.model.access.csv",
|
||||||
"data/completion_rule_data.xml",
|
"data/completion_rule_data.xml",
|
||||||
"wizard/import_statement_view.xml",
|
"wizard/import_statement_view.xml",
|
||||||
@@ -18,9 +18,7 @@
|
|||||||
"views/journal_view.xml",
|
"views/journal_view.xml",
|
||||||
"views/partner_view.xml",
|
"views/partner_view.xml",
|
||||||
],
|
],
|
||||||
'external_dependencies': {
|
"external_dependencies": {"python": ["xlrd"]},
|
||||||
'python': ['xlrd'],
|
"installable": True,
|
||||||
},
|
"license": "AGPL-3",
|
||||||
'installable': True,
|
|
||||||
'license': 'AGPL-3',
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,28 +1,27 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
<odoo noupdate="1">
|
<odoo noupdate="1">
|
||||||
|
<record id="bank_statement_completion_rule_2" model="account.move.completion.rule">
|
||||||
<record id="bank_statement_completion_rule_2" model="account.move.completion.rule">
|
<field
|
||||||
<field name="name">Match from line label (based on partner field 'Bank Statement Label')</field>
|
name="name"
|
||||||
<field name="sequence">60</field>
|
>Match from line label (based on partner field 'Bank Statement Label')</field>
|
||||||
<field name="function_to_call">get_from_name_and_partner_field</field>
|
<field name="sequence">60</field>
|
||||||
</record>
|
<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">
|
<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="name">Match from line label (based on partner name)</field>
|
||||||
<field name="sequence">70</field>
|
<field name="sequence">70</field>
|
||||||
<field name="function_to_call">get_from_name_and_partner_name</field>
|
<field name="function_to_call">get_from_name_and_partner_name</field>
|
||||||
</record>
|
</record>
|
||||||
|
<record id="bank_statement_completion_rule_4" model="account.move.completion.rule">
|
||||||
<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="name">Match from line label (based on Invoice number)</field>
|
<field name="sequence">40</field>
|
||||||
<field name="sequence">40</field>
|
<field name="function_to_call">get_from_name_and_invoice</field>
|
||||||
<field name="function_to_call">get_from_name_and_invoice</field>
|
</record>
|
||||||
</record>
|
<record id="bank_statement_completion_rule_5" model="account.move.completion.rule">
|
||||||
|
<field
|
||||||
<record id="bank_statement_completion_rule_5" model="account.move.completion.rule">
|
name="name"
|
||||||
<field name="name">Match from line label (based on Invoice Supplier number)</field>
|
>Match from line label (based on Invoice Supplier number)</field>
|
||||||
<field name="sequence">45</field>
|
<field name="sequence">45</field>
|
||||||
<field name="function_to_call">get_from_name_and_supplier_invoice</field>
|
<field name="function_to_call">get_from_name_and_supplier_invoice</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
</odoo>
|
</odoo>
|
||||||
|
|||||||
@@ -3,13 +3,15 @@
|
|||||||
# Copyright 2013 Savoir-faire Linux
|
# Copyright 2013 Savoir-faire Linux
|
||||||
# Copyright 2014 ACSONE SA/NV
|
# Copyright 2014 ACSONE SA/NV
|
||||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)
|
||||||
|
import os
|
||||||
import sys
|
import sys
|
||||||
import traceback
|
import traceback
|
||||||
import os
|
|
||||||
from odoo import _, api, fields, models
|
from odoo import _, api, fields, models
|
||||||
from ..parser.parser import new_move_parser
|
|
||||||
from odoo.exceptions import UserError, ValidationError
|
from odoo.exceptions import UserError, ValidationError
|
||||||
|
|
||||||
|
from ..parser.parser import new_move_parser
|
||||||
|
|
||||||
|
|
||||||
class AccountJournal(models.Model):
|
class AccountJournal(models.Model):
|
||||||
_name = "account.journal"
|
_name = "account.journal"
|
||||||
@@ -118,21 +120,17 @@ 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 = (
|
counterpart_date = parser.get_move_vals().get("date") or 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(
|
vals = self._prepare_counterpart_line(move, amount, counterpart_date)
|
||||||
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
|
@api.multi
|
||||||
def _write_extra_move_lines(self, parser, move):
|
def _write_extra_move_lines(self, parser, move):
|
||||||
@@ -151,25 +149,20 @@ class AccountJournal(models.Model):
|
|||||||
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": (
|
"date_maturity": (
|
||||||
parser.get_move_vals().get("date")
|
parser.get_move_vals().get("date") or fields.Date.today()
|
||||||
or fields.Date.today()
|
|
||||||
),
|
),
|
||||||
"debit": -global_commission_amount,
|
"debit": -global_commission_amount,
|
||||||
"partner_id": partner_id,
|
"partner_id": partner_id,
|
||||||
@@ -177,10 +170,7 @@ class AccountJournal(models.Model):
|
|||||||
"account_id": commission_account_id,
|
"account_id": commission_account_id,
|
||||||
"already_completed": True,
|
"already_completed": True,
|
||||||
}
|
}
|
||||||
if (
|
if self.currency_id and 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
|
||||||
@@ -228,10 +218,7 @@ class AccountJournal(models.Model):
|
|||||||
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 (
|
if self.currency_id and 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
|
||||||
@@ -239,12 +226,8 @@ class AccountJournal(models.Model):
|
|||||||
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"] = currency.compute(values["debit"], 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:
|
||||||
@@ -294,16 +277,12 @@ class AccountJournal(models.Model):
|
|||||||
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,
|
parser, file_stream, result_row_list=result_row_list, ftype=ftype,
|
||||||
file_stream,
|
|
||||||
result_row_list=result_row_list,
|
|
||||||
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
|
||||||
@@ -323,9 +302,7 @@ class AccountJournal(models.Model):
|
|||||||
# 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: " "The file is empty"))
|
raise UserError(_("Nothing to import: " "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(
|
||||||
@@ -344,9 +321,7 @@ class AccountJournal(models.Model):
|
|||||||
parser_vals = parser.get_move_line_vals(line)
|
parser_vals = parser.get_move_line_vals(line)
|
||||||
values = self.prepare_move_line_vals(parser_vals, move)
|
values = self.prepare_move_line_vals(parser_vals, move)
|
||||||
move_store.append(values)
|
move_store.append(values)
|
||||||
move_line_obj.with_context(check_move_validity=False).create(
|
move_line_obj.with_context(check_move_validity=False).create(move_store)
|
||||||
move_store
|
|
||||||
)
|
|
||||||
self._write_extra_move_lines(parser, move)
|
self._write_extra_move_lines(parser, move)
|
||||||
if self.create_counterpart:
|
if self.create_counterpart:
|
||||||
self._create_counterpart(parser, move)
|
self._create_counterpart(parser, move)
|
||||||
@@ -358,7 +333,7 @@ class AccountJournal(models.Model):
|
|||||||
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": "{}.{}".format(fields.Date.today(), ftype),
|
||||||
"res_model": "account.move",
|
"res_model": "account.move",
|
||||||
"res_id": move.id,
|
"res_id": move.id,
|
||||||
}
|
}
|
||||||
@@ -373,16 +348,11 @@ class AccountJournal(models.Model):
|
|||||||
raise
|
raise
|
||||||
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: {}\nDescription: {}\nTraceback:".format(
|
||||||
error_type.__name__,
|
error_type.__name__, error_value,
|
||||||
error_value,
|
|
||||||
)
|
)
|
||||||
st += "".join(traceback.format_tb(trbk, 30))
|
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
|
||||||
|
|||||||
@@ -3,14 +3,13 @@
|
|||||||
# Copyright 2013 Savoir-faire Linux
|
# Copyright 2013 Savoir-faire Linux
|
||||||
# Copyright 2014 ACSONE SA/NV
|
# Copyright 2014 ACSONE SA/NV
|
||||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)
|
||||||
import traceback
|
|
||||||
import sys
|
|
||||||
import logging
|
import logging
|
||||||
|
import sys
|
||||||
|
import traceback
|
||||||
|
|
||||||
from odoo import _, api, fields, models
|
from odoo import _, api, fields, models
|
||||||
from odoo.exceptions import ValidationError
|
from odoo.exceptions import ValidationError
|
||||||
|
|
||||||
|
|
||||||
_logger = logging.getLogger(__name__)
|
_logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
@@ -38,68 +37,81 @@ class AccountMoveCompletionRule(models.Model):
|
|||||||
process. The reference should contain the invoice number or the SO number
|
process. The reference should contain the invoice number or the SO number
|
||||||
or any reference that will be matched by the invoice accounting move.
|
or any reference that will be matched by the invoice accounting move.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
_name = "account.move.completion.rule"
|
_name = "account.move.completion.rule"
|
||||||
_order = "sequence asc"
|
_order = "sequence asc"
|
||||||
_description = "Account move completion method"
|
_description = "Account move completion method"
|
||||||
|
|
||||||
sequence = fields.Integer(
|
sequence = fields.Integer(string="Sequence", help="Lower means parsed first.")
|
||||||
string='Sequence',
|
name = fields.Char(string="Name")
|
||||||
help="Lower means parsed first.")
|
|
||||||
name = fields.Char(
|
|
||||||
string='Name')
|
|
||||||
journal_ids = fields.Many2many(
|
journal_ids = fields.Many2many(
|
||||||
comodel_name='account.journal',
|
comodel_name="account.journal",
|
||||||
relation='account_journal_completion_rule_rel',
|
relation="account_journal_completion_rule_rel",
|
||||||
string='Related journals')
|
string="Related journals",
|
||||||
function_to_call = fields.Selection([
|
)
|
||||||
('get_from_name_and_invoice',
|
function_to_call = fields.Selection(
|
||||||
'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_invoice",
|
||||||
('get_from_name_and_partner_field',
|
"From line name (based on customer invoice number)",
|
||||||
'From line name (based on partner field)'),
|
),
|
||||||
('get_from_name_and_partner_name',
|
(
|
||||||
'From line name (based on partner name)')
|
"get_from_name_and_supplier_invoice",
|
||||||
], string='Method'
|
"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):
|
def _find_invoice(self, line, inv_type):
|
||||||
"""Find invoice related to statement line"""
|
"""Find invoice related to statement line"""
|
||||||
inv_obj = self.env['account.invoice']
|
inv_obj = self.env["account.invoice"]
|
||||||
if inv_type == 'supplier':
|
if inv_type == "supplier":
|
||||||
type_domain = ('in_invoice', 'in_refund')
|
type_domain = ("in_invoice", "in_refund")
|
||||||
number_field = 'reference'
|
number_field = "reference"
|
||||||
elif inv_type == 'customer':
|
elif inv_type == "customer":
|
||||||
type_domain = ('out_invoice', 'out_refund')
|
type_domain = ("out_invoice", "out_refund")
|
||||||
number_field = 'number'
|
number_field = "number"
|
||||||
else:
|
else:
|
||||||
raise ValidationError(
|
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()),
|
invoices = inv_obj.search(
|
||||||
('type', 'in', type_domain)])
|
[(number_field, "=", line.name.strip()), ("type", "in", type_domain)]
|
||||||
|
)
|
||||||
if invoices:
|
if invoices:
|
||||||
if len(invoices) == 1:
|
if len(invoices) == 1:
|
||||||
return invoices
|
return invoices
|
||||||
else:
|
else:
|
||||||
raise ErrorTooManyPartner(
|
raise ErrorTooManyPartner(
|
||||||
_('Line named "%s" was matched by more than one '
|
_(
|
||||||
'partner while looking on %s invoices') %
|
'Line named "%s" was matched by more than one '
|
||||||
(line.name, inv_type))
|
"partner while looking on %s invoices"
|
||||||
|
)
|
||||||
|
% (line.name, inv_type)
|
||||||
|
)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def _from_invoice(self, line, inv_type):
|
def _from_invoice(self, line, inv_type):
|
||||||
"""Populate statement line values"""
|
"""Populate statement line values"""
|
||||||
if inv_type not in ('supplier', 'customer'):
|
if inv_type not in ("supplier", "customer"):
|
||||||
raise ValidationError(
|
raise ValidationError(
|
||||||
_('Invalid invoice type for completion: %s') %
|
_("Invalid invoice type for completion: %s") % inv_type
|
||||||
inv_type)
|
)
|
||||||
res = {}
|
res = {}
|
||||||
invoice = self._find_invoice(line, inv_type)
|
invoice = self._find_invoice(line, inv_type)
|
||||||
if invoice:
|
if invoice:
|
||||||
partner_id = invoice.commercial_partner_id.id
|
partner_id = invoice.commercial_partner_id.id
|
||||||
res = {'partner_id': partner_id,
|
res = {"partner_id": partner_id, "account_id": invoice.account_id.id}
|
||||||
'account_id': invoice.account_id.id}
|
|
||||||
return res
|
return res
|
||||||
|
|
||||||
# Should be private but data are initialised with no update XML
|
# Should be private but data are initialised with no update XML
|
||||||
@@ -117,7 +129,7 @@ class AccountMoveCompletionRule(models.Model):
|
|||||||
'account_id': value,
|
'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
|
# Should be private but data are initialised with no update XML
|
||||||
def get_from_name_and_invoice(self, line):
|
def get_from_name_and_invoice(self, line):
|
||||||
@@ -134,7 +146,7 @@ class AccountMoveCompletionRule(models.Model):
|
|||||||
'account_id': value,
|
'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
|
# Should be private but data are initialised with no update XML
|
||||||
def get_from_name_and_partner_field(self, line):
|
def get_from_name_and_partner_field(self, line):
|
||||||
@@ -155,21 +167,20 @@ class AccountMoveCompletionRule(models.Model):
|
|||||||
...}
|
...}
|
||||||
"""
|
"""
|
||||||
res = {}
|
res = {}
|
||||||
partner_obj = self.env['res.partner']
|
partner_obj = self.env["res.partner"]
|
||||||
or_regex = ".*;? *%s *;?.*" % line.name
|
or_regex = ".*;? *%s *;?.*" % line.name
|
||||||
sql = ("SELECT id from res_partner"
|
sql = "SELECT id from res_partner" " WHERE bank_statement_label ~* %s"
|
||||||
" WHERE bank_statement_label ~* %s")
|
self.env.cr.execute(sql, (or_regex,))
|
||||||
self.env.cr.execute(sql, (or_regex, ))
|
|
||||||
partner_ids = self.env.cr.fetchall()
|
partner_ids = self.env.cr.fetchall()
|
||||||
partners = partner_obj.browse([x[0] for x in partner_ids])
|
partners = partner_obj.browse([x[0] for x in partner_ids])
|
||||||
if partners:
|
if partners:
|
||||||
if len(partners) > 1:
|
if len(partners) > 1:
|
||||||
msg = (_('Line named "%s" was matched by more than '
|
msg = _(
|
||||||
'one partner while looking on partner label: %s') %
|
'Line named "%s" was matched by more than '
|
||||||
(line.name,
|
"one partner while looking on partner label: %s"
|
||||||
','.join([x.name for x in partners])))
|
) % (line.name, ",".join([x.name for x in partners]))
|
||||||
raise ErrorTooManyPartner(msg)
|
raise ErrorTooManyPartner(msg)
|
||||||
res['partner_id'] = partners[0].id
|
res["partner_id"] = partners[0].id
|
||||||
return res
|
return res
|
||||||
|
|
||||||
def get_from_name_and_partner_name(self, line):
|
def get_from_name_and_partner_name(self, line):
|
||||||
@@ -210,10 +221,13 @@ class AccountMoveCompletionRule(models.Model):
|
|||||||
if result:
|
if result:
|
||||||
if len(result) > 1:
|
if len(result) > 1:
|
||||||
raise ErrorTooManyPartner(
|
raise ErrorTooManyPartner(
|
||||||
_('Line named "%s" was matched by more than one '
|
_(
|
||||||
'partner while looking on partner by name') %
|
'Line named "%s" was matched by more than one '
|
||||||
line.name)
|
"partner while looking on partner by name"
|
||||||
res['partner_id'] = result[0][0]
|
)
|
||||||
|
% line.name
|
||||||
|
)
|
||||||
|
res["partner_id"] = result[0][0]
|
||||||
return res
|
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
|
Have a look in account_move_base_import module to see how we've done
|
||||||
it.
|
it.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
_inherit = "account.move.line"
|
_inherit = "account.move.line"
|
||||||
_order = "already_completed desc, date asc"
|
_order = "already_completed desc, date asc"
|
||||||
|
|
||||||
@@ -234,7 +249,8 @@ class AccountMoveLine(models.Model):
|
|||||||
string="Auto-Completed",
|
string="Auto-Completed",
|
||||||
default=False,
|
default=False,
|
||||||
help="When this checkbox is ticked, the auto-completion "
|
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):
|
def _get_line_values_from_rules(self):
|
||||||
"""We'll try to find out the values related to the line based on rules
|
"""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
|
rules = self.journal_id.rule_ids
|
||||||
for rule in rules:
|
for rule in rules:
|
||||||
method_to_call = getattr(
|
method_to_call = getattr(
|
||||||
self.env['account.move.completion.rule'],
|
self.env["account.move.completion.rule"], rule.function_to_call
|
||||||
rule.function_to_call
|
|
||||||
)
|
)
|
||||||
result = method_to_call(self)
|
result = method_to_call(self)
|
||||||
if result:
|
if result:
|
||||||
result['already_completed'] = True
|
result["already_completed"] = True
|
||||||
return result
|
return result
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@@ -282,17 +297,17 @@ class AccountMove(models.Model):
|
|||||||
"""We add a basic button and stuff to support the auto-completion
|
"""We add a basic button and stuff to support the auto-completion
|
||||||
of the bank statement once line have been imported or manually fulfill.
|
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(
|
used_for_completion = fields.Boolean(
|
||||||
related='journal_id.used_for_completion',
|
related="journal_id.used_for_completion", readonly=True
|
||||||
readonly=True)
|
)
|
||||||
completion_logs = fields.Text(string='Completion Log', readonly=True)
|
completion_logs = fields.Text(string="Completion Log", readonly=True)
|
||||||
import_partner_id = fields.Many2one('res.partner',
|
import_partner_id = fields.Many2one("res.partner", string="Partner from import")
|
||||||
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):
|
def _compute_partner_id(self):
|
||||||
for move in self:
|
for move in self:
|
||||||
if move.import_partner_id:
|
if move.import_partner_id:
|
||||||
@@ -314,14 +329,25 @@ class AccountMove(models.Model):
|
|||||||
number_line = len(self.line_ids)
|
number_line = len(self.line_ids)
|
||||||
log = self.completion_logs or ""
|
log = self.completion_logs or ""
|
||||||
completion_date = fields.Datetime.now()
|
completion_date = fields.Datetime.now()
|
||||||
message = (_("%s Account Move %s has %s/%s lines completed by "
|
message = _(
|
||||||
"%s \n%s\n%s\n") % (completion_date, self.name,
|
"%s Account Move %s has %s/%s lines completed by " "%s \n%s\n%s\n"
|
||||||
number_imported, number_line,
|
) % (
|
||||||
user_name, error_msg, log))
|
completion_date,
|
||||||
self.write({'completion_logs': message})
|
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') %
|
body = (
|
||||||
(self.name, number_imported, number_line)),
|
(
|
||||||
|
_("Statement ID %s auto-completed for %s/%s lines completed")
|
||||||
|
% (self.name, number_imported, number_line)
|
||||||
|
),
|
||||||
|
)
|
||||||
self.message_post(body=body)
|
self.message_post(body=body)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@@ -345,9 +371,10 @@ class AccountMove(models.Model):
|
|||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
msg_lines.append(repr(exc))
|
msg_lines.append(repr(exc))
|
||||||
error_type, error_value, trbk = sys.exc_info()
|
error_type, error_value, trbk = sys.exc_info()
|
||||||
st = "Error: %s\nDescription: %s\nTraceback:" % (
|
st = "Error: {}\nDescription: {}\nTraceback:".format(
|
||||||
error_type.__name__, error_value)
|
error_type.__name__, error_value,
|
||||||
st += ''.join(traceback.format_tb(trbk, 30))
|
)
|
||||||
|
st += "".join(traceback.format_tb(trbk, 30))
|
||||||
_logger.error(st)
|
_logger.error(st)
|
||||||
if res:
|
if res:
|
||||||
try:
|
try:
|
||||||
@@ -355,10 +382,11 @@ class AccountMove(models.Model):
|
|||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
msg_lines.append(repr(exc))
|
msg_lines.append(repr(exc))
|
||||||
error_type, error_value, trbk = sys.exc_info()
|
error_type, error_value, trbk = sys.exc_info()
|
||||||
st = "Error: %s\nDescription: %s\nTraceback:" % (
|
st = "Error: {}\nDescription: {}\nTraceback:".format(
|
||||||
error_type.__name__, error_value)
|
error_type.__name__, error_value,
|
||||||
st += ''.join(traceback.format_tb(trbk, 30))
|
)
|
||||||
|
st += "".join(traceback.format_tb(trbk, 30))
|
||||||
_logger.error(st)
|
_logger.error(st)
|
||||||
msg = '\n'.join(msg_lines)
|
msg = "\n".join(msg_lines)
|
||||||
self.write_completion_log(msg, compl_lines)
|
self.write_completion_log(msg, compl_lines)
|
||||||
return True
|
return True
|
||||||
|
|||||||
@@ -10,12 +10,14 @@ class ResPartner(models.Model):
|
|||||||
"""Add a bank label on the partner so that we can use it to match
|
"""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.
|
this partner when we found this in a statement line.
|
||||||
"""
|
"""
|
||||||
_inherit = 'res.partner'
|
|
||||||
|
_inherit = "res.partner"
|
||||||
|
|
||||||
bank_statement_label = fields.Char(
|
bank_statement_label = fields.Char(
|
||||||
string='Bank Statement Label',
|
string="Bank Statement Label",
|
||||||
help="Enter the various label found on your bank statement "
|
help="Enter the various label found on your bank statement "
|
||||||
"separated by a ; If one of this label is include in the "
|
"separated by a ; If one of this label is include in the "
|
||||||
"bank statement line, the partner will be automatically "
|
"bank statement line, the partner will be automatically "
|
||||||
"filled (as long as you use this method/rules in your "
|
"filled (as long as you use this method/rules in your "
|
||||||
"statement profile).")
|
"statement profile).",
|
||||||
|
)
|
||||||
|
|||||||
@@ -4,8 +4,8 @@
|
|||||||
# Copyright 2014 ACSONE SA/NV
|
# Copyright 2014 ACSONE SA/NV
|
||||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)
|
||||||
import datetime
|
import datetime
|
||||||
import tempfile
|
|
||||||
import logging
|
import logging
|
||||||
|
import tempfile
|
||||||
|
|
||||||
from odoo import _
|
from odoo import _
|
||||||
from odoo.exceptions import UserError
|
from odoo.exceptions import UserError
|
||||||
@@ -33,14 +33,15 @@ class FileParser(AccountMoveImportParser):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
journal,
|
journal,
|
||||||
ftype="csv",
|
ftype="csv",
|
||||||
extra_fields=None,
|
extra_fields=None,
|
||||||
header=None,
|
header=None,
|
||||||
dialect=None,
|
dialect=None,
|
||||||
move_ref=None,
|
move_ref=None,
|
||||||
**kwargs):
|
**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
|
||||||
@@ -90,7 +91,7 @@ class FileParser(AccountMoveImportParser):
|
|||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
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
|
||||||
@@ -152,9 +153,7 @@ class FileParser(AccountMoveImportParser):
|
|||||||
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(
|
line[rule] = datetime.datetime.strptime(date_string, "%Y-%m-%d")
|
||||||
date_string, "%Y-%m-%d"
|
|
||||||
)
|
|
||||||
except ValueError as err:
|
except ValueError as err:
|
||||||
raise UserError(
|
raise UserError(
|
||||||
_(
|
_(
|
||||||
@@ -196,9 +195,7 @@ 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(
|
t_tuple = xlrd.xldate_as_tuple(line[rule], 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(
|
||||||
|
|||||||
@@ -4,9 +4,11 @@
|
|||||||
# Copyright 2014 ACSONE SA/NV
|
# Copyright 2014 ACSONE SA/NV
|
||||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)
|
||||||
import datetime
|
import datetime
|
||||||
from .file_parser import FileParser, float_or_zero
|
|
||||||
from odoo.tools import ustr
|
from odoo.tools import ustr
|
||||||
|
|
||||||
|
from .file_parser import FileParser, float_or_zero
|
||||||
|
|
||||||
|
|
||||||
class GenericFileParser(FileParser):
|
class GenericFileParser(FileParser):
|
||||||
"""Standard parser that use a define format in csv or xls to import into a
|
"""Standard parser that use a define format in csv or xls to import into a
|
||||||
@@ -15,25 +17,22 @@ class GenericFileParser(FileParser):
|
|||||||
file.
|
file.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, journal, ftype='csv', **kwargs):
|
def __init__(self, journal, ftype="csv", **kwargs):
|
||||||
conversion_dict = {
|
conversion_dict = {
|
||||||
'label': ustr,
|
"label": ustr,
|
||||||
'date': datetime.datetime,
|
"date": datetime.datetime,
|
||||||
'amount': float_or_zero,
|
"amount": float_or_zero,
|
||||||
}
|
}
|
||||||
# set self.env for later ORM searches
|
# set self.env for later ORM searches
|
||||||
self.env = journal.env
|
self.env = journal.env
|
||||||
super().__init__(
|
super().__init__(journal, ftype=ftype, extra_fields=conversion_dict, **kwargs)
|
||||||
journal, ftype=ftype,
|
|
||||||
extra_fields=conversion_dict,
|
|
||||||
**kwargs)
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def parser_for(cls, parser_name):
|
def parser_for(cls, parser_name):
|
||||||
"""Used by the new_bank_statement_parser class factory. Return true if
|
"""Used by the new_bank_statement_parser class factory. Return true if
|
||||||
the providen name is generic_csvxls_so
|
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):
|
def get_move_line_vals(self, line, *args, **kwargs):
|
||||||
"""
|
"""
|
||||||
@@ -52,27 +51,27 @@ class GenericFileParser(FileParser):
|
|||||||
'debit':value
|
'debit':value
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
account_obj = self.env['account.account']
|
account_obj = self.env["account.account"]
|
||||||
partner_obj = self.env['res.partner']
|
partner_obj = self.env["res.partner"]
|
||||||
account_id = False
|
account_id = False
|
||||||
partner_id = False
|
partner_id = False
|
||||||
|
|
||||||
if line.get('account'):
|
if line.get("account"):
|
||||||
accounts = account_obj.search([('code', '=', line['account'])])
|
accounts = account_obj.search([("code", "=", line["account"])])
|
||||||
if len(accounts) == 1:
|
if len(accounts) == 1:
|
||||||
account_id = accounts[0].id
|
account_id = accounts[0].id
|
||||||
|
|
||||||
if line.get('partner'):
|
if line.get("partner"):
|
||||||
partners = partner_obj.search([('name', '=', line['partner'])])
|
partners = partner_obj.search([("name", "=", line["partner"])])
|
||||||
if len(partners) == 1:
|
if len(partners) == 1:
|
||||||
partner_id = partners[0].id
|
partner_id = partners[0].id
|
||||||
|
|
||||||
amount = line.get('amount', 0.0)
|
amount = line.get("amount", 0.0)
|
||||||
return {
|
return {
|
||||||
'name': line.get('label', '/'),
|
"name": line.get("label", "/"),
|
||||||
'date_maturity': line.get('date', datetime.datetime.now().date()),
|
"date_maturity": line.get("date", datetime.datetime.now().date()),
|
||||||
'credit': amount > 0.0 and amount or 0.0,
|
"credit": amount > 0.0 and amount or 0.0,
|
||||||
'debit': amount < 0.0 and -amount or 0.0,
|
"debit": amount < 0.0 and -amount or 0.0,
|
||||||
'account_id': account_id,
|
"account_id": account_id,
|
||||||
'partner_id': partner_id,
|
"partner_id": partner_id,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)
|
||||||
import base64
|
import base64
|
||||||
import csv
|
import csv
|
||||||
|
|
||||||
from openerp import _, fields
|
from openerp import _, fields
|
||||||
|
|
||||||
|
|
||||||
@@ -13,16 +14,14 @@ def UnicodeDictReader(utf8_data, **kwargs):
|
|||||||
pos = utf8_data.tell()
|
pos = utf8_data.tell()
|
||||||
sample_data = utf8_data.read(2048)
|
sample_data = utf8_data.read(2048)
|
||||||
utf8_data.seek(pos)
|
utf8_data.seek(pos)
|
||||||
if not kwargs.get('dialect'):
|
if not kwargs.get("dialect"):
|
||||||
dialect = sniffer.sniff(sample_data, delimiters=',;\t')
|
dialect = sniffer.sniff(sample_data, delimiters=",;\t")
|
||||||
del kwargs['dialect']
|
del kwargs["dialect"]
|
||||||
else:
|
else:
|
||||||
dialect = kwargs.pop('dialect')
|
dialect = kwargs.pop("dialect")
|
||||||
csv_reader = csv.DictReader(utf8_data, dialect=dialect, **kwargs)
|
csv_reader = csv.DictReader(utf8_data, dialect=dialect, **kwargs)
|
||||||
for row in csv_reader:
|
for row in csv_reader:
|
||||||
yield dict([(str(key or ''),
|
yield {str(key or ""): str(value or "") for key, value in row.items()}
|
||||||
str(value or ''))
|
|
||||||
for key, value in row.items()])
|
|
||||||
|
|
||||||
|
|
||||||
class AccountMoveImportParser(object):
|
class AccountMoveImportParser(object):
|
||||||
@@ -108,9 +107,9 @@ class AccountMoveImportParser(object):
|
|||||||
:return: dict of vals that represent additional infos for the statement
|
:return: dict of vals that represent additional infos for the statement
|
||||||
"""
|
"""
|
||||||
return {
|
return {
|
||||||
'name': self.move_name or '/',
|
"name": self.move_name or "/",
|
||||||
'date': self.move_date or fields.Datetime.now(),
|
"date": self.move_date or fields.Datetime.now(),
|
||||||
'ref': self.move_ref or '/'
|
"ref": self.move_ref or "/",
|
||||||
}
|
}
|
||||||
|
|
||||||
def get_move_line_vals(self, line, *args, **kwargs):
|
def get_move_line_vals(self, line, *args, **kwargs):
|
||||||
@@ -144,7 +143,7 @@ class AccountMoveImportParser(object):
|
|||||||
if filebuffer:
|
if filebuffer:
|
||||||
self.filebuffer = filebuffer
|
self.filebuffer = filebuffer
|
||||||
else:
|
else:
|
||||||
raise Exception(_('No buffer file given.'))
|
raise Exception(_("No buffer file given."))
|
||||||
self._format(*args, **kwargs)
|
self._format(*args, **kwargs)
|
||||||
self._pre(*args, **kwargs)
|
self._pre(*args, **kwargs)
|
||||||
if self.support_multi_moves:
|
if self.support_multi_moves:
|
||||||
@@ -184,8 +183,9 @@ def itersubclasses(cls, _seen=None):
|
|||||||
['type', ...'tuple', ...]
|
['type', ...'tuple', ...]
|
||||||
"""
|
"""
|
||||||
if not isinstance(cls, type):
|
if not isinstance(cls, type):
|
||||||
raise TypeError('itersubclasses must be called with '
|
raise TypeError(
|
||||||
'new-style classes, not %.100r' % cls)
|
"itersubclasses must be called with " "new-style classes, not %.100r" % cls
|
||||||
|
)
|
||||||
if _seen is None:
|
if _seen is None:
|
||||||
_seen = set()
|
_seen = set()
|
||||||
try:
|
try:
|
||||||
|
|||||||
@@ -3,13 +3,15 @@
|
|||||||
# Copyright 2013 Savoir-faire Linux
|
# Copyright 2013 Savoir-faire Linux
|
||||||
# Copyright 2014 ACSONE SA/NV
|
# Copyright 2014 ACSONE SA/NV
|
||||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)
|
||||||
|
from collections import namedtuple
|
||||||
|
|
||||||
from odoo import fields, tools
|
from odoo import fields, tools
|
||||||
from odoo.modules import get_resource_path
|
from odoo.modules import get_resource_path
|
||||||
from odoo.tests import common
|
from odoo.tests import common
|
||||||
from collections import namedtuple
|
|
||||||
|
|
||||||
name_completion_case = 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 = [
|
NAMES_COMPLETION_CASES = [
|
||||||
name_completion_case("Acsone", "Line for Acsone SA", True),
|
name_completion_case("Acsone", "Line for Acsone SA", True),
|
||||||
name_completion_case("Acsone", "Line for Acsone", 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("Acsone", "A..one for line", False),
|
||||||
name_completion_case("A.one SA", "A.one SA for line", True),
|
name_completion_case("A.one SA", "A.one SA for line", True),
|
||||||
name_completion_case(
|
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(
|
name_completion_case(
|
||||||
"Acsone ([^a-zA-Z0-9 -]) SA", "Line for Acsone ([^a-zA-Z0-9 -]) SA "
|
"Acsone ([^a-zA-Z0-9 -]) SA",
|
||||||
"test", True),
|
"Line for Acsone ([^a-zA-Z0-9 -]) SA " "test",
|
||||||
|
True,
|
||||||
|
),
|
||||||
name_completion_case(
|
name_completion_case(
|
||||||
r"Acsone (.^$*+?()[{\| -]\) SA", r"Line for Acsone (.^$*+?()[{\| -]\) "
|
r"Acsone (.^$*+?()[{\| -]\) SA",
|
||||||
r"SA test", True),
|
r"Line for Acsone (.^$*+?()[{\| -]\) " r"SA test",
|
||||||
|
True,
|
||||||
|
),
|
||||||
name_completion_case("Acšone SA", "Line for Acšone SA test", True),
|
name_completion_case("Acšone SA", "Line for Acšone SA test", True),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
class BaseCompletion(common.TransactionCase):
|
class BaseCompletion(common.TransactionCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super().setUp()
|
super().setUp()
|
||||||
tools.convert_file(self.cr, 'account',
|
tools.convert_file(
|
||||||
get_resource_path('account', 'test',
|
self.cr,
|
||||||
'account_minimal_test.xml'),
|
"account",
|
||||||
{}, 'init', False, 'test')
|
get_resource_path("account", "test", "account_minimal_test.xml"),
|
||||||
|
{},
|
||||||
|
"init",
|
||||||
|
False,
|
||||||
|
"test",
|
||||||
|
)
|
||||||
self.account_move_obj = self.env["account.move"]
|
self.account_move_obj = self.env["account.move"]
|
||||||
self.account_move_line_obj = \
|
self.account_move_line_obj = self.env["account.move.line"]
|
||||||
self.env["account.move.line"]
|
self.company_a = self.browse_ref("base.main_company")
|
||||||
self.company_a = self.browse_ref('base.main_company')
|
|
||||||
self.journal = self.browse_ref("account.bank_journal")
|
self.journal = self.browse_ref("account.bank_journal")
|
||||||
self.partner = self.browse_ref("base.res_partner_12")
|
self.partner = self.browse_ref("base.res_partner_12")
|
||||||
self.account_id = self.ref("account.a_recv")
|
self.account_id = self.ref("account.a_recv")
|
||||||
@@ -54,41 +64,49 @@ class BaseCompletion(common.TransactionCase):
|
|||||||
the partner appears in the statement line label
|
the partner appears in the statement line label
|
||||||
"""
|
"""
|
||||||
self.completion_rule_id = self.ref(
|
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
|
# Create the profile
|
||||||
self.journal.write({
|
self.journal.write(
|
||||||
'used_for_completion': True,
|
{
|
||||||
'rule_ids': [(6, 0, [self.completion_rule_id])]
|
"used_for_completion": True,
|
||||||
})
|
"rule_ids": [(6, 0, [self.completion_rule_id])],
|
||||||
|
}
|
||||||
|
)
|
||||||
# Create a bank statement
|
# Create a bank statement
|
||||||
self.move = self.account_move_obj.create({
|
self.move = self.account_move_obj.create(
|
||||||
"date": fields.Date.today(),
|
{"date": fields.Date.today(), "journal_id": self.journal.id}
|
||||||
"journal_id": self.journal.id
|
)
|
||||||
})
|
|
||||||
|
|
||||||
for case in NAMES_COMPLETION_CASES:
|
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(
|
self.move_line = self.account_move_line_obj.with_context(
|
||||||
check_move_validity=False
|
check_move_validity=False
|
||||||
).create({
|
).create(
|
||||||
'account_id': self.account_id,
|
{
|
||||||
'credit': 1000.0,
|
"account_id": self.account_id,
|
||||||
'name': case.line_label,
|
"credit": 1000.0,
|
||||||
'move_id': self.move.id,
|
"name": case.line_label,
|
||||||
})
|
"move_id": self.move.id,
|
||||||
|
}
|
||||||
|
)
|
||||||
self.assertFalse(
|
self.assertFalse(
|
||||||
self.move_line.partner_id,
|
self.move_line.partner_id, "Partner_id must be blank before completion"
|
||||||
"Partner_id must be blank before completion")
|
)
|
||||||
self.move.button_auto_completion()
|
self.move.button_auto_completion()
|
||||||
if case.should_match:
|
if case.should_match:
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
self.partner, self.move_line.partner_id,
|
self.partner,
|
||||||
|
self.move_line.partner_id,
|
||||||
"Missing expected partner id after completion "
|
"Missing expected partner id after completion "
|
||||||
"(partner_name: %s, line_name: %s)" %
|
"(partner_name: %s, line_name: %s)"
|
||||||
(case.partner_name, case.line_label))
|
% (case.partner_name, case.line_label),
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
self.assertNotEqual(
|
self.assertNotEqual(
|
||||||
self.partner, self.move_line.partner_id,
|
self.partner,
|
||||||
|
self.move_line.partner_id,
|
||||||
"Partner id should be empty after completion "
|
"Partner id should be empty after completion "
|
||||||
"(partner_name: %s, line_name: %s)"
|
"(partner_name: %s, line_name: %s)"
|
||||||
% (case.partner_name, case.line_label))
|
% (case.partner_name, case.line_label),
|
||||||
|
)
|
||||||
|
|||||||
@@ -6,57 +6,63 @@
|
|||||||
import base64
|
import base64
|
||||||
import os
|
import os
|
||||||
from operator import attrgetter
|
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.modules import get_resource_path
|
||||||
|
from odoo.tests import common
|
||||||
|
|
||||||
|
|
||||||
class TestCodaImport(common.TransactionCase):
|
class TestCodaImport(common.TransactionCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super().setUp()
|
super().setUp()
|
||||||
self.company_a = self.browse_ref('base.main_company')
|
self.company_a = self.browse_ref("base.main_company")
|
||||||
tools.convert_file(self.cr, 'account',
|
tools.convert_file(
|
||||||
get_resource_path('account', 'test',
|
self.cr,
|
||||||
'account_minimal_test.xml'),
|
"account",
|
||||||
{}, 'init', False, 'test')
|
get_resource_path("account", "test", "account_minimal_test.xml"),
|
||||||
|
{},
|
||||||
|
"init",
|
||||||
|
False,
|
||||||
|
"test",
|
||||||
|
)
|
||||||
self.account_move_obj = self.env["account.move"]
|
self.account_move_obj = self.env["account.move"]
|
||||||
self.account_move_line_obj = self.env["account.move.line"]
|
self.account_move_line_obj = self.env["account.move.line"]
|
||||||
self.account_id = self.ref("account.a_recv")
|
self.account_id = self.ref("account.a_recv")
|
||||||
self.journal = self.browse_ref("account.bank_journal")
|
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.partner = self.browse_ref("base.res_partner_12")
|
||||||
self.journal.write({
|
self.journal.write(
|
||||||
'used_for_import': True,
|
{
|
||||||
"import_type": "generic_csvxls_so",
|
"used_for_import": True,
|
||||||
'partner_id': self.partner.id,
|
"import_type": "generic_csvxls_so",
|
||||||
'commission_account_id': self.account_id,
|
"partner_id": self.partner.id,
|
||||||
'receivable_account_id': self.account_id,
|
"commission_account_id": self.account_id,
|
||||||
'create_counterpart': True,
|
"receivable_account_id": self.account_id,
|
||||||
})
|
"create_counterpart": True,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
def _import_file(self, file_name):
|
def _import_file(self, file_name):
|
||||||
""" import a file using the wizard
|
""" import a file using the wizard
|
||||||
return the create account.bank.statement object
|
return the create account.bank.statement object
|
||||||
"""
|
"""
|
||||||
with open(file_name, 'rb') as f:
|
with open(file_name, "rb") as f:
|
||||||
content = f.read()
|
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),
|
"journal_id": self.journal.id,
|
||||||
'file_name': os.path.basename(file_name),
|
"input_statement": base64.b64encode(content),
|
||||||
})
|
"file_name": os.path.basename(file_name),
|
||||||
|
}
|
||||||
|
)
|
||||||
res = self.wizard.import_statement()
|
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):
|
def test_simple_xls(self):
|
||||||
"""Test import from xls
|
"""Test import from xls
|
||||||
"""
|
"""
|
||||||
file_name = get_resource_path(
|
file_name = get_resource_path(
|
||||||
'account_move_base_import',
|
"account_move_base_import", "tests", "data", "statement.xls"
|
||||||
'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)
|
||||||
@@ -65,10 +71,7 @@ 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',
|
"account_move_base_import", "tests", "data", "statement.csv"
|
||||||
'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)
|
||||||
@@ -76,11 +79,8 @@ class TestCodaImport(common.TransactionCase):
|
|||||||
def _validate_imported_move(self, move):
|
def _validate_imported_move(self, move):
|
||||||
self.assertEqual("/", move.name)
|
self.assertEqual("/", move.name)
|
||||||
self.assertEqual(5, len(move.line_ids))
|
self.assertEqual(5, len(move.line_ids))
|
||||||
move_line = sorted(move.line_ids,
|
move_line = sorted(move.line_ids, key=attrgetter("date_maturity"))[2]
|
||||||
key=attrgetter('date_maturity'))[2]
|
|
||||||
# common infos
|
# common infos
|
||||||
self.assertEqual(
|
self.assertEqual(move_line.date_maturity, fields.Date.from_string("2011-03-07"))
|
||||||
move_line.date_maturity, fields.Date.from_string('2011-03-07')
|
|
||||||
)
|
|
||||||
self.assertEqual(move_line.credit, 118.4)
|
self.assertEqual(move_line.credit, 118.4)
|
||||||
self.assertEqual(move_line.name, "label a")
|
self.assertEqual(move_line.name, "label a")
|
||||||
|
|||||||
@@ -7,143 +7,168 @@ from odoo.tools import convert_file
|
|||||||
|
|
||||||
|
|
||||||
class TestInvoice(SingleTransactionCase):
|
class TestInvoice(SingleTransactionCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super().setUp()
|
super().setUp()
|
||||||
self.account_move_obj = self.env["account.move"]
|
self.account_move_obj = self.env["account.move"]
|
||||||
self.account_move_line_obj = \
|
self.account_move_line_obj = self.env["account.move.line"]
|
||||||
self.env["account.move.line"]
|
self.company_a = self.env.ref("base.main_company")
|
||||||
self.company_a = self.env.ref('base.main_company')
|
|
||||||
self.partner = self.env.ref("base.res_partner_12")
|
self.partner = self.env.ref("base.res_partner_12")
|
||||||
|
|
||||||
def test_01_partner(self):
|
def test_01_partner(self):
|
||||||
# I fill in the field Bank Statement Label in a Partner
|
# I fill in the field Bank Statement Label in a Partner
|
||||||
self.partner_4 = self.env.ref('base.res_partner_4')
|
self.partner_4 = self.env.ref("base.res_partner_4")
|
||||||
self.partner_4.bank_statement_label = 'XXX66Z'
|
self.partner_4.bank_statement_label = "XXX66Z"
|
||||||
self.assertEqual(self.partner_4.bank_statement_label, 'XXX66Z')
|
self.assertEqual(self.partner_4.bank_statement_label, "XXX66Z")
|
||||||
|
|
||||||
def test_02_invoice(self):
|
def test_02_invoice(self):
|
||||||
convert_file(
|
convert_file(
|
||||||
self.cr, 'account', get_resource_path(
|
self.cr,
|
||||||
'account', 'test', 'account_minimal_test.xml'
|
"account",
|
||||||
), {}, 'init', False, 'test'
|
get_resource_path("account", "test", "account_minimal_test.xml"),
|
||||||
|
{},
|
||||||
|
"init",
|
||||||
|
False,
|
||||||
|
"test",
|
||||||
)
|
)
|
||||||
self.journal = self.env.ref("account.bank_journal")
|
self.journal = self.env.ref("account.bank_journal")
|
||||||
self.account_id = self.env.ref("account.a_recv")
|
self.account_id = self.env.ref("account.a_recv")
|
||||||
# I create a customer Invoice to be found by the completion.
|
# I create a customer Invoice to be found by the completion.
|
||||||
product_3 = self.env.ref('product.product_product_3')
|
product_3 = self.env.ref("product.product_product_3")
|
||||||
self.invoice_for_completion_1 = self.env['account.invoice'].create({
|
self.invoice_for_completion_1 = self.env["account.invoice"].create(
|
||||||
'currency_id': self.env.ref('base.EUR').id,
|
{
|
||||||
'invoice_line_ids': [(0, 0, {
|
"currency_id": self.env.ref("base.EUR").id,
|
||||||
'name': '[PCSC234] PC Assemble SC234',
|
"invoice_line_ids": [
|
||||||
'product_id': product_3.id,
|
(
|
||||||
'price_unit': 210.0,
|
0,
|
||||||
'quantity': 1.0,
|
0,
|
||||||
'uom_id': self.env.ref('uom.product_uom_unit').id,
|
{
|
||||||
'account_id': self.env.ref('account.a_sale').id,
|
"name": "[PCSC234] PC Assemble SC234",
|
||||||
})],
|
"product_id": product_3.id,
|
||||||
'journal_id': self.journal.id,
|
"price_unit": 210.0,
|
||||||
'partner_id': self.partner.id,
|
"quantity": 1.0,
|
||||||
'account_id': self.env.ref('account.a_recv').id,
|
"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
|
# I confirm the Invoice
|
||||||
self.invoice_for_completion_1.action_invoice_open()
|
self.invoice_for_completion_1.action_invoice_open()
|
||||||
# I check that the invoice state is "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"
|
# I check that it is given the number "TBNK/%Y/0001"
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
self.invoice_for_completion_1.number,
|
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):
|
def test_03_supplier_invoice(self):
|
||||||
# I create a demo invoice
|
# I create a demo invoice
|
||||||
product_delivery = self.env.ref('product.product_delivery_01')
|
product_delivery = self.env.ref("product.product_delivery_01")
|
||||||
product_order = self.env.ref('product.product_order_01')
|
product_order = self.env.ref("product.product_order_01")
|
||||||
exp_account = self.env.ref('account.a_expense')
|
exp_account = self.env.ref("account.a_expense")
|
||||||
rec_account = self.env.ref('account.a_recv')
|
rec_account = self.env.ref("account.a_recv")
|
||||||
demo_invoice_0 = self.env['account.invoice'].create({
|
demo_invoice_0 = self.env["account.invoice"].create(
|
||||||
'partner_id': self.partner.id,
|
{
|
||||||
'payment_term_id': self.env.ref('account.account_payment_term').id,
|
"partner_id": self.partner.id,
|
||||||
'type': 'in_invoice',
|
"payment_term_id": self.env.ref("account.account_payment_term").id,
|
||||||
'date_invoice': fields.Date.today().replace(day=1),
|
"type": "in_invoice",
|
||||||
'account_id': rec_account.id,
|
"date_invoice": fields.Date.today().replace(day=1),
|
||||||
'invoice_line_ids': [
|
"account_id": rec_account.id,
|
||||||
(0, 0, {
|
"invoice_line_ids": [
|
||||||
'price_unit': 10.0,
|
(
|
||||||
'quantity': 1.0,
|
0,
|
||||||
'product_id': product_delivery.id,
|
0,
|
||||||
'name': product_delivery.name,
|
{
|
||||||
'uom_id': self.env.ref('uom.product_uom_unit').id,
|
"price_unit": 10.0,
|
||||||
'account_id': exp_account.id,
|
"quantity": 1.0,
|
||||||
}), (0, 0, {
|
"product_id": product_delivery.id,
|
||||||
'price_unit': 4.0,
|
"name": product_delivery.name,
|
||||||
'quantity': 1.0,
|
"uom_id": self.env.ref("uom.product_uom_unit").id,
|
||||||
'product_id': product_order.id,
|
"account_id": exp_account.id,
|
||||||
'name': product_order.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
|
# I check that my invoice is a supplier invoice
|
||||||
self.assertEqual(
|
self.assertEqual(demo_invoice_0.type, "in_invoice", msg="Check invoice type")
|
||||||
demo_invoice_0.type, 'in_invoice', msg="Check invoice type"
|
|
||||||
)
|
|
||||||
# I add a reference to an existing supplier invoice
|
# 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
|
# I check a second time that my invoice is still a supplier invoice
|
||||||
self.assertEqual(
|
self.assertEqual(demo_invoice_0.type, "in_invoice", msg="Check invoice type 2")
|
||||||
demo_invoice_0.type, 'in_invoice', msg="Check invoice type 2"
|
|
||||||
)
|
|
||||||
# Now I confirm it
|
# Now I confirm it
|
||||||
demo_invoice_0.action_invoice_open()
|
demo_invoice_0.action_invoice_open()
|
||||||
# I check that the supplier number is there
|
# I check that the supplier number is there
|
||||||
self.assertEqual(
|
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
|
# I check a third time that my invoice is still a supplier invoice
|
||||||
self.assertEqual(
|
self.assertEqual(demo_invoice_0.type, "in_invoice", msg="Check invoice type 3")
|
||||||
demo_invoice_0.type, 'in_invoice', msg="Check invoice type 3"
|
|
||||||
)
|
|
||||||
|
|
||||||
def test_04_refund(self):
|
def test_04_refund(self):
|
||||||
# I create a "child" partner, to use in the invoice
|
# I create a "child" partner, to use in the invoice
|
||||||
# (and have a different commercial_partner_id than itself)
|
# (and have a different commercial_partner_id than itself)
|
||||||
res_partner_12_child = self.env['res.partner'].create({
|
res_partner_12_child = self.env["res.partner"].create(
|
||||||
'name': 'Child Partner',
|
{
|
||||||
'supplier': False,
|
"name": "Child Partner",
|
||||||
'customer': True,
|
"supplier": False,
|
||||||
'is_company': False,
|
"customer": True,
|
||||||
'parent_id': self.partner.id,
|
"is_company": False,
|
||||||
})
|
"parent_id": self.partner.id,
|
||||||
|
}
|
||||||
|
)
|
||||||
# I create a customer refund to be found by the completion.
|
# I create a customer refund to be found by the completion.
|
||||||
product_3 = self.env.ref('product.product_product_3')
|
product_3 = self.env.ref("product.product_product_3")
|
||||||
self.refund_for_completion_1 = self.env['account.invoice'].create({
|
self.refund_for_completion_1 = self.env["account.invoice"].create(
|
||||||
'currency_id': self.env.ref('base.EUR').id,
|
{
|
||||||
'invoice_line_ids': [(0, 0, {
|
"currency_id": self.env.ref("base.EUR").id,
|
||||||
'name': '[PCSC234] PC Assemble SC234',
|
"invoice_line_ids": [
|
||||||
'product_id': product_3.id,
|
(
|
||||||
'price_unit': 210.0,
|
0,
|
||||||
'quantity': 1.0,
|
0,
|
||||||
'uom_id': self.env.ref('uom.product_uom_unit').id,
|
{
|
||||||
'account_id': self.env.ref('account.a_sale').id,
|
"name": "[PCSC234] PC Assemble SC234",
|
||||||
})],
|
"product_id": product_3.id,
|
||||||
'journal_id': self.env.ref('account.expenses_journal').id,
|
"price_unit": 210.0,
|
||||||
'partner_id': res_partner_12_child.id,
|
"quantity": 1.0,
|
||||||
'type': 'out_refund',
|
"uom_id": self.env.ref("uom.product_uom_unit").id,
|
||||||
'account_id': self.env.ref('account.a_recv').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
|
# I confirm the refund
|
||||||
self.refund_for_completion_1.action_invoice_open()
|
self.refund_for_completion_1.action_invoice_open()
|
||||||
|
|
||||||
# I check that the refund state is "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"
|
# I check that it is given the number "RTEXJ/%Y/0001"
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
self.refund_for_completion_1.number,
|
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):
|
def test_05_completion(self):
|
||||||
@@ -151,92 +176,102 @@ class TestInvoice(SingleTransactionCase):
|
|||||||
# journal
|
# journal
|
||||||
self.journal = self.env.ref("account.bank_journal")
|
self.journal = self.env.ref("account.bank_journal")
|
||||||
completion_rule_4 = self.env.ref(
|
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(
|
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(
|
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(
|
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_rules = (
|
||||||
completion_rule_2 | completion_rule_3 | completion_rule_4
|
completion_rule_2
|
||||||
|
| completion_rule_3
|
||||||
|
| completion_rule_4
|
||||||
| completion_rule_5
|
| completion_rule_5
|
||||||
)
|
)
|
||||||
self.journal.write({
|
self.journal.write(
|
||||||
'used_for_completion': True,
|
{
|
||||||
'rule_ids': [
|
"used_for_completion": True,
|
||||||
(4, comp_rule.id, False) for comp_rule in completion_rules
|
"rule_ids": [
|
||||||
]
|
(4, comp_rule.id, False) for comp_rule in completion_rules
|
||||||
})
|
],
|
||||||
|
}
|
||||||
|
)
|
||||||
# Now I create a statement. I create statment lines separately because
|
# Now I create a statement. I create statment lines separately because
|
||||||
# I need to find each one by XML id
|
# I need to find each one by XML id
|
||||||
move_test1 = self.env['account.move'].create({
|
move_test1 = self.env["account.move"].create(
|
||||||
'name': 'Move 2',
|
{"name": "Move 2", "journal_id": self.journal.id}
|
||||||
'journal_id': self.journal.id,
|
)
|
||||||
})
|
|
||||||
# I create a move line for a CI
|
# I create a move line for a CI
|
||||||
move_line_ci = self.env['account.move.line'].create({
|
move_line_ci = self.env["account.move.line"].create(
|
||||||
'name': '\\',
|
{
|
||||||
'account_id': self.env.ref('account.a_sale').id,
|
"name": "\\",
|
||||||
'move_id': move_test1.id,
|
"account_id": self.env.ref("account.a_sale").id,
|
||||||
'date_maturity': fields.Date.from_string('2013-12-20'),
|
"move_id": move_test1.id,
|
||||||
'credit': 0.0,
|
"date_maturity": fields.Date.from_string("2013-12-20"),
|
||||||
})
|
"credit": 0.0,
|
||||||
|
}
|
||||||
|
)
|
||||||
# I create a move line for a SI
|
# I create a move line for a SI
|
||||||
move_line_si = self.env['account.move.line'].create({
|
move_line_si = self.env["account.move.line"].create(
|
||||||
'name': '\\',
|
{
|
||||||
'account_id': self.env.ref('account.a_expense').id,
|
"name": "\\",
|
||||||
'move_id': move_test1.id,
|
"account_id": self.env.ref("account.a_expense").id,
|
||||||
'date_maturity': fields.Date.from_string('2013-12-19'),
|
"move_id": move_test1.id,
|
||||||
'debit': 0.0,
|
"date_maturity": fields.Date.from_string("2013-12-19"),
|
||||||
})
|
"debit": 0.0,
|
||||||
|
}
|
||||||
|
)
|
||||||
# I create a move line for a CR
|
# I create a move line for a CR
|
||||||
move_line_cr = self.env['account.move.line'].create({
|
move_line_cr = self.env["account.move.line"].create(
|
||||||
'name': '\\',
|
{
|
||||||
'account_id': self.env.ref('account.a_expense').id,
|
"name": "\\",
|
||||||
'move_id': move_test1.id,
|
"account_id": self.env.ref("account.a_expense").id,
|
||||||
'date_maturity': fields.Date.from_string('2013-12-19'),
|
"move_id": move_test1.id,
|
||||||
'debit': 0.0,
|
"date_maturity": fields.Date.from_string("2013-12-19"),
|
||||||
})
|
"debit": 0.0,
|
||||||
|
}
|
||||||
|
)
|
||||||
# I create a move line for the Partner Name
|
# I create a move line for the Partner Name
|
||||||
move_line_partner_name = self.env['account.move.line'].create({
|
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,
|
"name": "Test autocompletion based on Partner Name Azure Interior",
|
||||||
'move_id': move_test1.id,
|
"account_id": self.env.ref("account.a_sale").id,
|
||||||
'date_maturity': fields.Date.from_string('2013-12-17'),
|
"move_id": move_test1.id,
|
||||||
'credit': 0.0,
|
"date_maturity": fields.Date.from_string("2013-12-17"),
|
||||||
})
|
"credit": 0.0,
|
||||||
|
}
|
||||||
|
)
|
||||||
# I create a move line for the Partner Label
|
# I create a move line for the Partner Label
|
||||||
move_line_partner_label = self.env['account.move.line'].create({
|
move_line_partner_label = self.env["account.move.line"].create(
|
||||||
'name': 'XXX66Z',
|
{
|
||||||
'account_id': self.env.ref('account.a_sale').id,
|
"name": "XXX66Z",
|
||||||
'move_id': move_test1.id,
|
"account_id": self.env.ref("account.a_sale").id,
|
||||||
'date_maturity': '2013-12-24',
|
"move_id": move_test1.id,
|
||||||
'debit': 0.0,
|
"date_maturity": "2013-12-24",
|
||||||
})
|
"debit": 0.0,
|
||||||
|
}
|
||||||
|
)
|
||||||
# and add the correct name
|
# and add the correct name
|
||||||
move_line_ci.with_context(check_move_validity=False).write({
|
move_line_ci.with_context(check_move_validity=False).write(
|
||||||
'name': fields.Date.today().strftime('TBNK/%Y/0001'),
|
{"name": fields.Date.today().strftime("TBNK/%Y/0001"), "credit": 210.0}
|
||||||
'credit': 210.0,
|
)
|
||||||
})
|
move_line_si.with_context(check_move_validity=False).write(
|
||||||
move_line_si.with_context(check_move_validity=False).write({
|
{"name": "T2S12345", "debit": 65.0}
|
||||||
'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_cr.with_context(check_move_validity=False).write({
|
)
|
||||||
'name': fields.Date.today().strftime('RTEXJ/%Y/0001'),
|
move_line_partner_name.with_context(check_move_validity=False).write(
|
||||||
'debit': 210.0,
|
{"credit": 600.0}
|
||||||
})
|
)
|
||||||
move_line_partner_name.with_context(check_move_validity=False).write({
|
move_line_partner_label.with_context(check_move_validity=False).write(
|
||||||
'credit': 600.0,
|
{"debit": 932.4}
|
||||||
})
|
)
|
||||||
move_line_partner_label.with_context(check_move_validity=False).write({
|
|
||||||
'debit': 932.4,
|
|
||||||
})
|
|
||||||
# I run the auto complete
|
# I run the auto complete
|
||||||
move_test1.button_auto_completion()
|
move_test1.button_auto_completion()
|
||||||
# Now I can check that all is nice and shiny, line 1. I expect the
|
# 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
|
# I Use _ref, because ref conflicts with the field ref of the
|
||||||
# statement line
|
# statement line
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
move_line_ci.partner_id, self.partner,
|
move_line_ci.partner_id, self.partner, msg="Check completion by CI number"
|
||||||
msg="Check completion by CI number"
|
|
||||||
)
|
)
|
||||||
# Line 2. I expect the Supplier invoice number to be recognised. The
|
# Line 2. I expect the Supplier invoice number to be recognised. The
|
||||||
# supplier invoice was created by the account module demo data, and we
|
# supplier invoice was created by the account module demo data, and we
|
||||||
# confirmed it here.
|
# confirmed it here.
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
move_line_si.partner_id, self.partner,
|
move_line_si.partner_id, self.partner, msg="Check completion by SI number"
|
||||||
msg="Check completion by SI number"
|
|
||||||
)
|
)
|
||||||
# Line 3. I expect the Customer refund number to be recognised. It
|
# Line 3. I expect the Customer refund number to be recognised. It
|
||||||
# should be the commercial partner, and not the regular partner.
|
# should be the commercial partner, and not the regular partner.
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
move_line_cr.partner_id, self.partner,
|
move_line_cr.partner_id,
|
||||||
msg="Check completion by CR number and commercial partner"
|
self.partner,
|
||||||
|
msg="Check completion by CR number and commercial partner",
|
||||||
)
|
)
|
||||||
# Line 4. I check that the partner name has been recognised.
|
# Line 4. I check that the partner name has been recognised.
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
move_line_partner_name.partner_id.name, 'Azure Interior',
|
move_line_partner_name.partner_id.name,
|
||||||
msg="Check completion by partner name"
|
"Azure Interior",
|
||||||
|
msg="Check completion by partner name",
|
||||||
)
|
)
|
||||||
# Line 5. I check that the partner special label has been recognised.
|
# 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(
|
self.assertEqual(
|
||||||
move_line_partner_label.partner_id,
|
move_line_partner_label.partner_id,
|
||||||
self.partner_4,
|
self.partner_4,
|
||||||
msg="Check completion by partner label"
|
msg="Check completion by partner label",
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,85 +1,93 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
<odoo>
|
<odoo>
|
||||||
<record id="view_move_importer_form" model="ir.ui.view">
|
<record id="view_move_importer_form" model="ir.ui.view">
|
||||||
<field name="name">account.move.view</field>
|
<field name="name">account.move.view</field>
|
||||||
<field name="model">account.move</field>
|
<field name="model">account.move</field>
|
||||||
<field name="inherit_id" ref="account.view_move_form"/>
|
<field name="inherit_id" ref="account.view_move_form" />
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<field name="journal_id" position="after">
|
<field name="journal_id" position="after">
|
||||||
<field name="used_for_completion" invisible="1"/>
|
<field name="used_for_completion" invisible="1" />
|
||||||
</field>
|
</field>
|
||||||
<button name="action_duplicate" position="after">
|
<button name="action_duplicate" position="after">
|
||||||
<button name="button_auto_completion"
|
<button
|
||||||
string="Auto Completion"
|
name="button_auto_completion"
|
||||||
type="object"
|
string="Auto Completion"
|
||||||
class="oe_highlight"
|
type="object"
|
||||||
groups="account.group_account_invoice"
|
class="oe_highlight"
|
||||||
attrs="{'invisible': ['|', ('used_for_completion','=',False), ('state','not in', ['draft'])]}"/>
|
groups="account.group_account_invoice"
|
||||||
|
attrs="{'invisible': ['|', ('used_for_completion','=',False), ('state','not in', ['draft'])]}"
|
||||||
|
/>
|
||||||
</button>
|
</button>
|
||||||
<xpath expr="//field[@name='line_ids']/tree/field[@name='credit']" position="after">
|
<xpath
|
||||||
<field name="already_completed"/>
|
expr="//field[@name='line_ids']/tree/field[@name='credit']"
|
||||||
|
position="after"
|
||||||
|
>
|
||||||
|
<field name="already_completed" />
|
||||||
</xpath>
|
</xpath>
|
||||||
<xpath expr="/form/sheet/notebook" position="inside">
|
<xpath expr="/form/sheet/notebook" position="inside">
|
||||||
<page string="Completion Logs" attrs="{'invisible':[('completion_logs','=',False)]}">
|
<page
|
||||||
<field name="completion_logs" colspan="4" nolabel="1"/>
|
string="Completion Logs"
|
||||||
|
attrs="{'invisible':[('completion_logs','=',False)]}"
|
||||||
|
>
|
||||||
|
<field name="completion_logs" colspan="4" nolabel="1" />
|
||||||
</page>
|
</page>
|
||||||
</xpath>
|
</xpath>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="move_completion_rule_view_form" model="ir.ui.view">
|
<record id="move_completion_rule_view_form" model="ir.ui.view">
|
||||||
<field name="name">account.move.completion.rule.view</field>
|
<field name="name">account.move.completion.rule.view</field>
|
||||||
<field name="model">account.move.completion.rule</field>
|
<field name="model">account.move.completion.rule</field>
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<form string="Move Completion Rule">
|
<form string="Move Completion Rule">
|
||||||
<group>
|
<group>
|
||||||
<field name="sequence"/>
|
<field name="sequence" />
|
||||||
<field name="name" select="1" />
|
<field name="name" select="1" />
|
||||||
<field name="function_to_call"/>
|
<field name="function_to_call" />
|
||||||
</group>
|
</group>
|
||||||
<separator colspan="4" string="Related Profiles"/>
|
<separator colspan="4" string="Related Profiles" />
|
||||||
<field name="journal_ids" nolabel="1" colspan="4"/>
|
<field name="journal_ids" nolabel="1" colspan="4" />
|
||||||
</form>
|
</form>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="move_completion_rule_view_tree" model="ir.ui.view">
|
<record id="move_completion_rule_view_tree" model="ir.ui.view">
|
||||||
<field name="name">account.move.completion.rule.view</field>
|
<field name="name">account.move.completion.rule.view</field>
|
||||||
<field name="model">account.move.completion.rule</field>
|
<field name="model">account.move.completion.rule</field>
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<tree string="Move Completion Rule">
|
<tree string="Move Completion Rule">
|
||||||
<field name="sequence"/>
|
<field name="sequence" />
|
||||||
<field name="name" select="1" />
|
<field name="name" select="1" />
|
||||||
<field name="journal_ids" />
|
<field name="journal_ids" />
|
||||||
<field name="function_to_call"/>
|
<field name="function_to_call" />
|
||||||
</tree>
|
</tree>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="action_move_completion_rule_tree" model="ir.actions.act_window">
|
<record id="action_move_completion_rule_tree" model="ir.actions.act_window">
|
||||||
<field name="name">Move Completion Rules</field>
|
<field name="name">Move Completion Rules</field>
|
||||||
<field name="res_model">account.move.completion.rule</field>
|
<field name="res_model">account.move.completion.rule</field>
|
||||||
<field name="view_mode">tree,form</field>
|
<field name="view_mode">tree,form</field>
|
||||||
</record>
|
</record>
|
||||||
|
<menuitem
|
||||||
<menuitem string="Move Completion Rule" action="action_move_completion_rule_tree"
|
string="Move Completion Rule"
|
||||||
id="menu_action_move_completion_rule_tree_menu" parent="account.account_management_menu"/>
|
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">
|
<record id="view_account_move_filter" model="ir.ui.view">
|
||||||
<field name="model">account.move</field>
|
<field name="model">account.move</field>
|
||||||
<field name="inherit_id" ref="account.view_account_move_filter"/>
|
<field name="inherit_id" ref="account.view_account_move_filter" />
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<separator position="after">
|
<separator position="after">
|
||||||
<filter name="to_complete"
|
<filter
|
||||||
|
name="to_complete"
|
||||||
string="To Complete"
|
string="To Complete"
|
||||||
domain="[
|
domain="[
|
||||||
('state','!=','posted'),
|
('state','!=','posted'),
|
||||||
('journal_id.used_for_completion', '=', True),
|
('journal_id.used_for_completion', '=', True),
|
||||||
('line_ids.already_completed', '=', False)]"
|
('line_ids.already_completed', '=', False)]"
|
||||||
help="Account move that should be completed manually"/>
|
help="Account move that should be completed manually"
|
||||||
<separator/>
|
/>
|
||||||
|
<separator />
|
||||||
</separator>
|
</separator>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
</odoo>
|
</odoo>
|
||||||
|
|||||||
@@ -1,40 +1,60 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
<odoo>
|
<odoo>
|
||||||
<record id="journal_importer_view_form" model="ir.ui.view">
|
<record id="journal_importer_view_form" model="ir.ui.view">
|
||||||
<field name="name">account.journal.view</field>
|
<field name="name">account.journal.view</field>
|
||||||
<field name="model">account.journal</field>
|
<field name="model">account.journal</field>
|
||||||
<field name="inherit_id" ref="account.view_account_journal_form"/>
|
<field name="inherit_id" ref="account.view_account_journal_form" />
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<field name="loss_account_id" position="after">
|
<field name="loss_account_id" position="after">
|
||||||
<field name="used_for_import"/>
|
<field name="used_for_import" />
|
||||||
<field name="used_for_completion"/>
|
<field name="used_for_completion" />
|
||||||
</field>
|
</field>
|
||||||
<notebook position="inside">
|
<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>
|
<group>
|
||||||
<field name="launch_import_completion" attrs="{'invisible': ['|',
|
<field
|
||||||
|
name="launch_import_completion"
|
||||||
|
attrs="{'invisible': ['|',
|
||||||
('used_for_import', '=', False),
|
('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="last_import_date" readonly="1" />
|
||||||
|
<field
|
||||||
|
name="import_type"
|
||||||
|
attrs="{'required': [('used_for_import', '=', True)]}"
|
||||||
|
/>
|
||||||
</group>
|
</group>
|
||||||
<group>
|
<group>
|
||||||
<field name="commission_account_id"/>
|
<field name="commission_account_id" />
|
||||||
<field name="receivable_account_id" attrs="{'required': [('used_for_import', '=', True)]}"/>
|
<field
|
||||||
<field name="partner_id"/>
|
name="receivable_account_id"
|
||||||
<field name="create_counterpart"/>
|
attrs="{'required': [('used_for_import', '=', True)]}"
|
||||||
<field name="split_counterpart" attrs="{'invisible': [('create_counterpart', '=', False)]}"/>
|
/>
|
||||||
|
<field name="partner_id" />
|
||||||
|
<field name="create_counterpart" />
|
||||||
|
<field
|
||||||
|
name="split_counterpart"
|
||||||
|
attrs="{'invisible': [('create_counterpart', '=', False)]}"
|
||||||
|
/>
|
||||||
</group>
|
</group>
|
||||||
<group>
|
<group>
|
||||||
<button name="%(account_move_base_import.move_importer_action)d"
|
<button
|
||||||
string="Import batch file"
|
name="%(account_move_base_import.move_importer_action)d"
|
||||||
type="action"
|
string="Import batch file"
|
||||||
colspan = "2"/>
|
type="action"
|
||||||
|
colspan="2"
|
||||||
|
/>
|
||||||
</group>
|
</group>
|
||||||
</page>
|
</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">
|
<group string="Auto-Completion Rules" name="completion_rules">
|
||||||
<field name="rule_ids" colspan="2" nolabel="1"/>
|
<field name="rule_ids" colspan="2" nolabel="1" />
|
||||||
</group>
|
</group>
|
||||||
</page>
|
</page>
|
||||||
</notebook>
|
</notebook>
|
||||||
|
|||||||
@@ -1,15 +1,13 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
<odoo>
|
<odoo>
|
||||||
|
|
||||||
<record id="bk_view_partner_form" model="ir.ui.view">
|
<record id="bk_view_partner_form" model="ir.ui.view">
|
||||||
<field name="name">account_bank_statement_import.view.partner.form</field>
|
<field name="name">account_bank_statement_import.view.partner.form</field>
|
||||||
<field name="model">res.partner</field>
|
<field name="model">res.partner</field>
|
||||||
<field name="inherit_id" ref="account.view_partner_property_form"/>
|
<field name="inherit_id" ref="account.view_partner_property_form" />
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<field name="property_account_payable_id" position="after">
|
<field name="property_account_payable_id" position="after">
|
||||||
<field name="bank_statement_label"/>
|
<field name="bank_statement_label" />
|
||||||
</field>
|
</field>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
</odoo>
|
</odoo>
|
||||||
|
|||||||
@@ -7,72 +7,71 @@
|
|||||||
Wizard to import financial institute date in bank statement
|
Wizard to import financial institute date in bank statement
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
from odoo import _, api, fields, models
|
from odoo import _, api, fields, models
|
||||||
from odoo.exceptions import UserError
|
from odoo.exceptions import UserError
|
||||||
import os
|
|
||||||
|
|
||||||
|
|
||||||
class CreditPartnerStatementImporter(models.TransientModel):
|
class CreditPartnerStatementImporter(models.TransientModel):
|
||||||
_name = "credit.statement.import"
|
_name = "credit.statement.import"
|
||||||
_description = 'Import Batch File wizard'
|
_description = "Import Batch File wizard"
|
||||||
|
|
||||||
@api.model
|
@api.model
|
||||||
def default_get(self, fields):
|
def default_get(self, fields):
|
||||||
res = super().default_get(fields)
|
res = super().default_get(fields)
|
||||||
ctx = self.env.context
|
ctx = self.env.context
|
||||||
if (
|
if ctx.get("active_model") == "account.journal" and ctx.get("active_ids"):
|
||||||
ctx.get('active_model') == 'account.journal' and
|
ids = ctx["active_ids"]
|
||||||
ctx.get('active_ids')):
|
assert len(ids) == 1, "You cannot use this on more than one journal !"
|
||||||
ids = ctx['active_ids']
|
res["journal_id"] = ids[0]
|
||||||
assert len(ids) == 1, \
|
|
||||||
'You cannot use this on more than one journal !'
|
|
||||||
res['journal_id'] = ids[0]
|
|
||||||
return res
|
return res
|
||||||
|
|
||||||
journal_id = fields.Many2one(
|
journal_id = fields.Many2one(
|
||||||
comodel_name='account.journal',
|
comodel_name="account.journal",
|
||||||
string='Import configuration parameter',
|
string="Import configuration parameter",
|
||||||
required=True)
|
required=True,
|
||||||
input_statement = fields.Binary(
|
)
|
||||||
string='Statement file',
|
input_statement = fields.Binary(string="Statement file", required=True)
|
||||||
required=True)
|
|
||||||
partner_id = fields.Many2one(
|
partner_id = fields.Many2one(
|
||||||
comodel_name='res.partner',
|
comodel_name="res.partner", related="journal_id.partner_id", readonly=True
|
||||||
related='journal_id.partner_id', readonly=True)
|
)
|
||||||
file_name = fields.Char()
|
file_name = fields.Char()
|
||||||
receivable_account_id = fields.Many2one(
|
receivable_account_id = fields.Many2one(
|
||||||
comodel_name='account.account',
|
comodel_name="account.account",
|
||||||
related='journal_id.receivable_account_id', readonly=True)
|
related="journal_id.receivable_account_id",
|
||||||
|
readonly=True,
|
||||||
|
)
|
||||||
commission_account_id = fields.Many2one(
|
commission_account_id = fields.Many2one(
|
||||||
comodel_name='account.account',
|
comodel_name="account.account",
|
||||||
related='journal_id.commission_account_id', readonly=True)
|
related="journal_id.commission_account_id",
|
||||||
|
readonly=True,
|
||||||
|
)
|
||||||
|
|
||||||
@api.multi
|
@api.multi
|
||||||
def _check_extension(self):
|
def _check_extension(self):
|
||||||
self.ensure_one()
|
self.ensure_one()
|
||||||
(__, ftype) = os.path.splitext(self.file_name)
|
(__, ftype) = os.path.splitext(self.file_name)
|
||||||
if not ftype:
|
if not ftype:
|
||||||
raise UserError(_('Please use a file with an extension'))
|
raise UserError(_("Please use a file with an extension"))
|
||||||
return ftype
|
return ftype
|
||||||
|
|
||||||
@api.multi
|
@api.multi
|
||||||
def import_statement(self):
|
def import_statement(self):
|
||||||
"""This Function import credit card agency statement"""
|
"""This Function import credit card agency statement"""
|
||||||
moves = self.env['account.move']
|
moves = self.env["account.move"]
|
||||||
for importer in self:
|
for importer in self:
|
||||||
journal = importer.journal_id
|
journal = importer.journal_id
|
||||||
ftype = importer._check_extension()
|
ftype = importer._check_extension()
|
||||||
moves |= journal.with_context(
|
moves |= journal.with_context(
|
||||||
file_name=importer.file_name).multi_move_import(
|
file_name=importer.file_name
|
||||||
importer.input_statement,
|
).multi_move_import(importer.input_statement, ftype.replace(".", ""))
|
||||||
ftype.replace('.', '')
|
xmlid = ("account", "action_move_journal_line")
|
||||||
)
|
action = self.env["ir.actions.act_window"].for_xml_id(*xmlid)
|
||||||
xmlid = ('account', 'action_move_journal_line')
|
|
||||||
action = self.env['ir.actions.act_window'].for_xml_id(*xmlid)
|
|
||||||
if len(moves) > 1:
|
if len(moves) > 1:
|
||||||
action['domain'] = [('id', 'in', moves.ids)]
|
action["domain"] = [("id", "in", moves.ids)]
|
||||||
else:
|
else:
|
||||||
ref = self.env.ref('account.view_move_form')
|
ref = self.env.ref("account.view_move_form")
|
||||||
action['views'] = [(ref.id, 'form')]
|
action["views"] = [(ref.id, "form")]
|
||||||
action['res_id'] = moves.id if moves else False
|
action["res_id"] = moves.id if moves else False
|
||||||
return action
|
return action
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
<odoo>
|
<odoo>
|
||||||
<record id="move_importer_view" model="ir.ui.view">
|
<record id="move_importer_view" model="ir.ui.view">
|
||||||
<field name="name">credit.statement.import.config.view</field>
|
<field name="name">credit.statement.import.config.view</field>
|
||||||
@@ -6,29 +6,40 @@
|
|||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<form string="Import move">
|
<form string="Import move">
|
||||||
<group name="main">
|
<group name="main">
|
||||||
<field name="journal_id" domain="[('used_for_import', '=', True)]"/>
|
<field
|
||||||
<field name="input_statement" filename="file_name"/>
|
name="journal_id"
|
||||||
<field name="file_name" invisible="1"/>
|
domain="[('used_for_import', '=', True)]"
|
||||||
|
/>
|
||||||
|
<field name="input_statement" filename="file_name" />
|
||||||
|
<field name="file_name" invisible="1" />
|
||||||
</group>
|
</group>
|
||||||
<group string="Import Parameters Summary" name="params">
|
<group string="Import Parameters Summary" name="params">
|
||||||
<field name="partner_id"/>
|
<field name="partner_id" />
|
||||||
<field name="receivable_account_id"/>
|
<field name="receivable_account_id" />
|
||||||
<field name="commission_account_id"/>
|
<field name="commission_account_id" />
|
||||||
</group>
|
</group>
|
||||||
<footer>
|
<footer>
|
||||||
<button name="import_statement" string="Import file" type="object" class="oe_highlight"/>
|
<button
|
||||||
<button special="cancel" string="Cancel" class="oe_link"/>
|
name="import_statement"
|
||||||
|
string="Import file"
|
||||||
|
type="object"
|
||||||
|
class="oe_highlight"
|
||||||
|
/>
|
||||||
|
<button special="cancel" string="Cancel" class="oe_link" />
|
||||||
</footer>
|
</footer>
|
||||||
</form>
|
</form>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="move_importer_action" model="ir.actions.act_window">
|
<record id="move_importer_action" model="ir.actions.act_window">
|
||||||
<field name="name">Import Batch File</field>
|
<field name="name">Import Batch File</field>
|
||||||
<field name="res_model">credit.statement.import</field>
|
<field name="res_model">credit.statement.import</field>
|
||||||
<field name="view_mode">form</field>
|
<field name="view_mode">form</field>
|
||||||
<field name="target">new</field>
|
<field name="target">new</field>
|
||||||
</record>
|
</record>
|
||||||
|
<menuitem
|
||||||
<menuitem id="move_importer_menu" name="Import Batch File" action="move_importer_action" parent="account.menu_finance_entries"/>
|
id="move_importer_menu"
|
||||||
|
name="Import Batch File"
|
||||||
|
action="move_importer_action"
|
||||||
|
parent="account.menu_finance_entries"
|
||||||
|
/>
|
||||||
</odoo>
|
</odoo>
|
||||||
|
|||||||
Reference in New Issue
Block a user