2
0

[MIG] account_move_template: Migration to 15.0

This commit is contained in:
Andy Quijada [Vauxoo] 2022-06-02 19:15:16 -04:00 committed by Abraham Anes
parent 2c088bcfde
commit af14d2afb6
6 changed files with 152 additions and 58 deletions

View File

@ -5,7 +5,7 @@
{ {
"name": "Account Move Template", "name": "Account Move Template",
"version": "14.0.1.1.1", "version": "15.0.1.0.0",
"category": "Accounting", "category": "Accounting",
"summary": "Templates for recurring Journal Entries", "summary": "Templates for recurring Journal Entries",
"author": "Agile Business Group, Aurium Technologies, Vauxoo, ForgeFlow, " "author": "Agile Business Group, Aurium Technologies, Vauxoo, ForgeFlow, "

View File

@ -4,8 +4,10 @@
# #
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: Odoo Server 14.0\n" "Project-Id-Version: Odoo Server 15.0+e\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-06-03 20:52+0000\n"
"PO-Revision-Date: 2022-06-03 20:52+0000\n"
"Last-Translator: \n" "Last-Translator: \n"
"Language-Team: \n" "Language-Team: \n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
@ -200,25 +202,25 @@ msgstr ""
#: code:addons/account_move_template/models/account_move_template.py:0 #: code:addons/account_move_template/models/account_move_template.py:0
#, python-format #, python-format
msgid "" msgid ""
"Impossible to compute the formula of line with sequence %s (formula: %s). " "Impossible to compute the formula of line with sequence %(sequence)s "
"Check that the lines used in the formula really exists and have a lower " "(formula: %(code)s). Check that the lines used in the formula really exists "
"sequence than the current line." "and have a lower sequence than the current line."
msgstr "" msgstr ""
#. module: account_move_template #. module: account_move_template
#: code:addons/account_move_template/models/account_move_template.py:0 #: code:addons/account_move_template/models/account_move_template.py:0
#, python-format #, python-format
msgid "" msgid ""
"Impossible to compute the formula of line with sequence %s (formula: %s): " "Impossible to compute the formula of line with sequence %(sequence)s "
"the syntax of the formula is wrong." "(formula: %(code)s): the syntax of the formula is wrong."
msgstr "" msgstr ""
#. module: account_move_template #. module: account_move_template
#: code:addons/account_move_template/wizard/account_move_template_run.py:0 #: code:addons/account_move_template/wizard/account_move_template_run.py:0
#, python-format #, python-format
msgid "" msgid ""
"Invalid dictionary: {}\n" "Invalid dictionary: %(exception)s\n"
"{}" "%(msg)s"
msgstr "" msgstr ""
#. module: account_move_template #. module: account_move_template
@ -435,8 +437,8 @@ msgstr ""
#: code:addons/account_move_template/wizard/account_move_template_run.py:0 #: code:addons/account_move_template/wizard/account_move_template_run.py:0
#, python-format #, python-format
msgid "" msgid ""
"The selected template (%s) is not in the same company (%s) as the current " "The selected template (%(template)s) is not in the same company "
"user (%s)." "(%(company)s) as the current user (%(user_company)s)."
msgstr "" msgstr ""
#. module: account_move_template #. module: account_move_template

View File

@ -45,24 +45,26 @@ class AccountMoveTemplate(models.Model):
try: try:
val = safe_eval(line.python_code, safe_eval_dict) val = safe_eval(line.python_code, safe_eval_dict)
sequence2amount[line.sequence] = val sequence2amount[line.sequence] = val
except ValueError: except ValueError as err:
raise UserError( raise UserError(
_( _(
"Impossible to compute the formula of line with sequence %s " "Impossible to compute the formula of line with sequence %(sequence)s "
"(formula: %s). Check that the lines used in the formula " "(formula: %(code)s). Check that the lines used in the formula "
"really exists and have a lower sequence than the current " "really exists and have a lower sequence than the current "
"line." "line.",
sequence=line.sequence,
code=line.python_code,
) )
% (line.sequence, line.python_code) ) from err
) except SyntaxError as err:
except SyntaxError:
raise UserError( raise UserError(
_( _(
"Impossible to compute the formula of line with sequence %s " "Impossible to compute the formula of line with sequence %(sequence)s "
"(formula: %s): the syntax of the formula is wrong." "(formula: %(code)s): the syntax of the formula is wrong.",
sequence=line.sequence,
code=line.python_code,
) )
% (line.sequence, line.python_code) ) from err
)
def compute_lines(self, sequence2amount): def compute_lines(self, sequence2amount):
company_cur = self.company_id.currency_id company_cur = self.company_id.currency_id
@ -109,7 +111,7 @@ class AccountMoveTemplateLine(models.Model):
"account.move.template", string="Move Template", ondelete="cascade" "account.move.template", string="Move Template", ondelete="cascade"
) )
name = fields.Char(string="Label", required=True) name = fields.Char(string="Label", required=True)
sequence = fields.Integer("Sequence", required=True) sequence = fields.Integer(required=True)
account_id = fields.Many2one( account_id = fields.Many2one(
"account.account", "account.account",
string="Account", string="Account",
@ -138,11 +140,10 @@ class AccountMoveTemplateLine(models.Model):
note = fields.Char() note = fields.Char()
type = fields.Selection( type = fields.Selection(
[("computed", "Computed"), ("input", "User input")], [("computed", "Computed"), ("input", "User input")],
string="Type",
required=True, required=True,
default="input", default="input",
) )
python_code = fields.Text("Python Code") python_code = fields.Text()
move_line_type = fields.Selection( move_line_type = fields.Selection(
[("cr", "Credit"), ("dr", "Debit")], required=True, string="Direction" [("cr", "Credit"), ("dr", "Debit")], required=True, string="Direction"
) )

View File

@ -4,7 +4,7 @@ import logging
from psycopg2 import IntegrityError from psycopg2 import IntegrityError
from odoo import fields from odoo import Command, fields
from odoo.tests.common import TransactionCase from odoo.tests.common import TransactionCase
from odoo.tools import mute_logger from odoo.tools import mute_logger
@ -20,7 +20,7 @@ class TestAccountMoveTemplate(TransactionCase):
def _chart_of_accounts_create(self, company, chart): def _chart_of_accounts_create(self, company, chart):
_logger.debug("Creating chart of account") _logger.debug("Creating chart of account")
self.env.user.write( self.env.user.write(
{"company_ids": [(4, company.id)], "company_id": company.id} {"company_ids": [Command.link(company.id)], "company_id": company.id}
) )
self.with_context(company_id=company.id, force_company=company.id) self.with_context(company_id=company.id, force_company=company.id)
wizard = self.env["wizard.multi.charts.accounts"].create( wizard = self.env["wizard.multi.charts.accounts"].create(
@ -71,7 +71,7 @@ class TestAccountMoveTemplate(TransactionCase):
) )
], ],
"company_id": self.company.id, "company_id": self.company.id,
"company_ids": [(4, self.company.id)], "company_ids": [Command.link(self.company.id)],
} }
) )
) )
@ -179,7 +179,7 @@ class TestAccountMoveTemplate(TransactionCase):
"sequence": 2, "sequence": 2,
"account_id": self.account_company_1.id, "account_id": self.account_company_1.id,
"move_line_type": "cr", "move_line_type": "cr",
"tax_ids": [(4, self.tax.id)], "tax_ids": [Command.link(self.tax.id)],
"type": "input", "type": "input",
}, },
), ),

View File

@ -1,6 +1,7 @@
# Copyright 2020 Ecosoft (http://ecosoft.co.th) # Copyright 2020 Ecosoft (http://ecosoft.co.th)
# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html # License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html
from odoo.exceptions import ValidationError from odoo import Command
from odoo.exceptions import UserError, ValidationError
from odoo.tests.common import Form, TransactionCase from odoo.tests.common import Form, TransactionCase
@ -69,9 +70,9 @@ class TestAccountMoveTemplateEnhanced(TransactionCase):
"name": "Test Template", "name": "Test Template",
"journal_id": self.journal.id, "journal_id": self.journal.id,
"line_ids": [ "line_ids": [
(0, 0, ar_line), Command.create(ar_line),
(0, 0, income_line1), Command.create(income_line1),
(0, 0, income_line2), Command.create(income_line2),
], ],
} }
) )
@ -143,7 +144,8 @@ class TestAccountMoveTemplateEnhanced(TransactionCase):
} }
) )
template_run = f.save() template_run = f.save()
with self.assertRaises(ValidationError): msg_error = "overwrite are .'partner_id', 'amount', 'name', 'date_maturity'"
with self.assertRaisesRegex(ValidationError, msg_error):
template_run.load_lines() template_run.load_lines()
# Assign only on valid fields, and load_lines again # Assign only on valid fields, and load_lines again
with Form(self.env["account.move.template.run"]) as f: with Form(self.env["account.move.template.run"]) as f:
@ -159,7 +161,7 @@ class TestAccountMoveTemplateEnhanced(TransactionCase):
res = template_run.load_lines() res = template_run.load_lines()
self.assertEqual(template_run.line_ids[0].partner_id, self.partners[0]) self.assertEqual(template_run.line_ids[0].partner_id, self.partners[0])
self.assertEqual(template_run.line_ids[0].amount, 3000) self.assertEqual(template_run.line_ids[0].amount, 3000)
res = template_run.with_context(res["context"]).generate_move() res = template_run.with_context(**res["context"]).generate_move()
move = self.Move.browse(res["res_id"]) move = self.Move.browse(res["res_id"])
self.assertRecordValues( self.assertRecordValues(
move.line_ids.sorted("credit"), move.line_ids.sorted("credit"),
@ -184,3 +186,86 @@ class TestAccountMoveTemplateEnhanced(TransactionCase):
}, },
], ],
) )
def test_move_copy(self):
template_copy = self.move_template.copy()
self.assertEqual(template_copy.name, "Test Template (copy)")
def test_move_generate_from_action_button(self):
# `Generate Journal Entry` action button
res = self.move_template.generate_journal_entry()
self.assertEqual(res["name"], "Create Entry from Template")
self.assertEqual(res["res_model"], "account.move.template.run")
def test_move_template_exceptions(self):
msg_error = "Python Code must be set for computed line with sequence 1."
with self.assertRaisesRegex(ValidationError, msg_error):
self.move_template.line_ids[1].python_code = ""
self.move_template.line_ids[1].python_code = "P0*1/3"
with Form(self.env["account.move.template.run"]) as f:
f.template_id = self.move_template
template_run = f.save()
template_run.load_lines()
msg_error = "really exists and have a lower sequence than the current line."
with self.assertRaisesRegex(UserError, msg_error):
template_run.generate_move()
self.move_template.line_ids[1].python_code = "L0*"
with Form(self.env["account.move.template.run"]) as f:
f.template_id = self.move_template
template_run = f.save()
template_run.load_lines()
msg_error = "the syntax of the formula is wrong."
with self.assertRaisesRegex(UserError, msg_error):
template_run.generate_move()
self.move_template.line_ids[1].python_code = "L0*1/3"
with Form(self.env["account.move.template.run"]) as f:
f.template_id = self.move_template
template_run = f.save()
template_run.load_lines()
template_run.line_ids[0].amount = 0
msg_error = "Debit and credit of all lines are null."
with self.assertRaisesRegex(UserError, msg_error):
template_run.generate_move()
with Form(self.env["account.move.template.run"]) as f:
f.template_id = self.move_template
f.overwrite = []
template_run = f.save()
msg_error = "Overwrite value must be a valid python dict"
with self.assertRaisesRegex(ValidationError, msg_error):
template_run.load_lines()
with Form(self.env["account.move.template.run"]) as f:
f.template_id = self.move_template
f.overwrite = str({"P0": {"amount": 100}})
template_run = f.save()
msg_error = "Keys must be line sequence, i..e, L1, L2, ..."
with self.assertRaisesRegex(ValidationError, msg_error):
template_run.load_lines()
with Form(self.env["account.move.template.run"]) as f:
f.template_id = self.move_template
f.overwrite = str({"L0": []})
template_run = f.save()
msg_error = "Invalid dictionary: 'list' object has no attribute 'keys'"
with self.assertRaisesRegex(ValidationError, msg_error):
template_run.load_lines()
with Form(self.env["account.move.template.run"]) as f:
f.template_id = self.move_template
f.overwrite = str({"L0": {"test": 100}})
template_run = f.save()
msg_error = "overwrite are .'partner_id', 'amount', 'name', 'date_maturity'"
with self.assertRaisesRegex(ValidationError, msg_error):
template_run.load_lines()
with Form(self.env["account.move.template.run"]) as f:
f.template_id = self.move_template
template_run = f.save()
template_run.line_ids.unlink()
msg_error = "You deleted a line in the wizard. This is not allowed:"
with self.assertRaisesRegex(UserError, msg_error):
template_run.generate_move()

View File

@ -2,7 +2,7 @@
# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html # License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html
from ast import literal_eval from ast import literal_eval
from odoo import _, fields, models from odoo import Command, _, fields, models
from odoo.exceptions import UserError, ValidationError from odoo.exceptions import UserError, ValidationError
@ -51,9 +51,9 @@ Valid dictionary to overwrite template lines:
"partner_id": tmpl_line.partner_id.id or False, "partner_id": tmpl_line.partner_id.id or False,
"move_line_type": tmpl_line.move_line_type, "move_line_type": tmpl_line.move_line_type,
"tax_line_id": tmpl_line.tax_line_id.id, "tax_line_id": tmpl_line.tax_line_id.id,
"tax_ids": [(6, 0, tmpl_line.tax_ids.ids)], "tax_ids": [Command.set(tmpl_line.tax_ids.ids)],
"analytic_account_id": tmpl_line.analytic_account_id.id, "analytic_account_id": tmpl_line.analytic_account_id.id,
"analytic_tag_ids": [(6, 0, tmpl_line.analytic_tag_ids.ids)], "analytic_tag_ids": [Command.set(tmpl_line.analytic_tag_ids.ids)],
"note": tmpl_line.note, "note": tmpl_line.note,
"payment_term_id": tmpl_line.payment_term_id.id or False, "payment_term_id": tmpl_line.payment_term_id.id or False,
"is_refund": tmpl_line.is_refund, "is_refund": tmpl_line.is_refund,
@ -70,13 +70,11 @@ Valid dictionary to overwrite template lines:
if self.company_id != self.template_id.company_id: if self.company_id != self.template_id.company_id:
raise UserError( raise UserError(
_( _(
"The selected template (%s) is not in the same company (%s) " "The selected template (%(template)s) is not in the same company "
"as the current user (%s)." "(%(company)s) as the current user (%(user_company)s).",
) template=self.template_id.name,
% ( company=self.template_id.company_id.display_name,
self.template_id.name, user_company=self.company_id.display_name,
self.template_id.company_id.display_name,
self.company_id.display_name,
) )
) )
tmpl_lines = self.template_id.line_ids tmpl_lines = self.template_id.line_ids
@ -121,8 +119,10 @@ Valid dictionary to overwrite template lines:
try: try:
overwrite_vals = literal_eval(overwrite_vals) overwrite_vals = literal_eval(overwrite_vals)
assert isinstance(overwrite_vals, dict) assert isinstance(overwrite_vals, dict)
except (SyntaxError, ValueError, AssertionError): except (SyntaxError, ValueError, AssertionError) as err:
raise ValidationError(_("Overwrite value must be a valid python dict")) raise ValidationError(
_("Overwrite value must be a valid python dict")
) from err
# First level keys must be L1, L2, ... # First level keys must be L1, L2, ...
keys = overwrite_vals.keys() keys = overwrite_vals.keys()
if list(filter(lambda x: x[:1] != "L" or not x[1:].isdigit(), keys)): if list(filter(lambda x: x[:1] != "L" or not x[1:].isdigit(), keys)):
@ -144,7 +144,13 @@ Valid dictionary to overwrite template lines:
'L2': {'partner_id': 2, 'amount': 20}, 'L2': {'partner_id': 2, 'amount': 20},
} }
""" """
raise ValidationError(_("Invalid dictionary: {}\n{}".format(e, msg))) raise ValidationError(
_(
"Invalid dictionary: %(exception)s\n%(msg)s",
exception=e,
msg=msg,
)
) from e
return overwrite_vals return overwrite_vals
def _safe_vals(self, model, vals): def _safe_vals(self, model, vals):
@ -179,7 +185,7 @@ Valid dictionary to overwrite template lines:
amount = sequence2amount[line.sequence] amount = sequence2amount[line.sequence]
if not company_cur.is_zero(amount): if not company_cur.is_zero(amount):
move_vals["line_ids"].append( move_vals["line_ids"].append(
(0, 0, self._prepare_move_line(line, amount)) Command.create(self._prepare_move_line(line, amount))
) )
move = self.env["account.move"].create(move_vals) move = self.env["account.move"].create(move_vals)
action = self.env.ref("account.action_move_journal_line") action = self.env.ref("account.action_move_journal_line")
@ -223,9 +229,9 @@ Valid dictionary to overwrite template lines:
"tax_repartition_line_id": line.tax_repartition_line_id.id or False, "tax_repartition_line_id": line.tax_repartition_line_id.id or False,
} }
if line.analytic_tag_ids: if line.analytic_tag_ids:
values["analytic_tag_ids"] = [(6, 0, line.analytic_tag_ids.ids)] values["analytic_tag_ids"] = [Command.set(line.analytic_tag_ids.ids)]
if line.tax_ids: if line.tax_ids:
values["tax_ids"] = [(6, 0, line.tax_ids.ids)] values["tax_ids"] = [Command.set(line.tax_ids.ids)]
tax_repartition = "refund_tax_id" if line.is_refund else "invoice_tax_id" tax_repartition = "refund_tax_id" if line.is_refund else "invoice_tax_id"
atrl_ids = self.env["account.tax.repartition.line"].search( atrl_ids = self.env["account.tax.repartition.line"].search(
[ [
@ -233,9 +239,11 @@ Valid dictionary to overwrite template lines:
("repartition_type", "=", "base"), ("repartition_type", "=", "base"),
] ]
) )
values["tag_ids"] = [(6, 0, atrl_ids.mapped("tag_ids").ids)] values["tax_tag_ids"] = [Command.set(atrl_ids.mapped("tag_ids").ids)]
if line.tax_repartition_line_id: if line.tax_repartition_line_id:
values["tag_ids"] = [(6, 0, line.tax_repartition_line_id.tag_ids.ids)] values["tax_tag_ids"] = [
Command.set(line.tax_repartition_line_id.tag_ids.ids)
]
# With overwrite options # With overwrite options
overwrite = self._context.get("overwrite", {}) overwrite = self._context.get("overwrite", {})
move_line_vals = overwrite.get("L{}".format(line.sequence), {}) move_line_vals = overwrite.get("L{}".format(line.sequence), {})
@ -264,8 +272,8 @@ class AccountMoveTemplateLineRun(models.TransientModel):
company_currency_id = fields.Many2one( company_currency_id = fields.Many2one(
related="wizard_id.company_id.currency_id", string="Company Currency" related="wizard_id.company_id.currency_id", string="Company Currency"
) )
sequence = fields.Integer("Sequence", required=True) sequence = fields.Integer(required=True)
name = fields.Char("Name", readonly=True) name = fields.Char(readonly=True)
account_id = fields.Many2one("account.account", required=True, readonly=True) account_id = fields.Many2one("account.account", required=True, readonly=True)
analytic_account_id = fields.Many2one("account.analytic.account", readonly=True) analytic_account_id = fields.Many2one("account.analytic.account", readonly=True)
analytic_tag_ids = fields.Many2many( analytic_tag_ids = fields.Many2many(
@ -285,9 +293,7 @@ class AccountMoveTemplateLineRun(models.TransientModel):
readonly=True, readonly=True,
string="Direction", string="Direction",
) )
amount = fields.Monetary( amount = fields.Monetary(required=True, currency_field="company_currency_id")
"Amount", required=True, currency_field="company_currency_id"
)
note = fields.Char(readonly=True) note = fields.Char(readonly=True)
is_refund = fields.Boolean(string="Is a refund?", readonly=True) is_refund = fields.Boolean(string="Is a refund?", readonly=True)
tax_repartition_line_id = fields.Many2one( tax_repartition_line_id = fields.Many2one(