From 22e57f872ef6f9fe3552da9e8885e9c8a24b56bc Mon Sep 17 00:00:00 2001 From: Andrea Date: Mon, 7 Sep 2020 14:31:18 +0200 Subject: [PATCH] [13.0][MIG] account_spread_cost_revenue --- account_spread_cost_revenue/__manifest__.py | 8 +- .../migrations/13.0.1.0.0/post-migration.py | 26 + .../migrations/13.0.1.0.0/pre-migration.py | 7 + .../models/__init__.py | 4 +- .../models/account_invoice.py | 59 -- .../models/account_move.py | 34 ++ ...t_invoice_line.py => account_move_line.py} | 68 ++- .../models/account_spread.py | 335 +++++------- .../models/account_spread_line.py | 71 +-- .../models/account_spread_template.py | 78 +-- .../models/res_company.py | 4 +- .../readme/HISTORY.rst | 5 + .../security/account_spread_security.xml | 6 +- .../static/src/js/account_spread.js | 2 +- .../tests/test_account_invoice_auto_spread.py | 147 +---- .../tests/test_account_invoice_spread.py | 510 +++++++++--------- .../tests/test_account_spread_cost_revenue.py | 263 +++------ .../tests/test_compute_spread_board.py | 21 +- .../views/account_invoice.xml | 35 -- .../views/account_move.xml | 31 ++ .../views/account_spread.xml | 30 +- .../views/account_spread_template.xml | 3 +- .../views/res_company.xml | 2 +- ...account_spread_invoice_line_link_wizard.py | 100 ++-- ...ccount_spread_invoice_line_link_wizard.xml | 2 +- 25 files changed, 817 insertions(+), 1034 deletions(-) create mode 100644 account_spread_cost_revenue/migrations/13.0.1.0.0/post-migration.py create mode 100644 account_spread_cost_revenue/migrations/13.0.1.0.0/pre-migration.py delete mode 100644 account_spread_cost_revenue/models/account_invoice.py create mode 100644 account_spread_cost_revenue/models/account_move.py rename account_spread_cost_revenue/models/{account_invoice_line.py => account_move_line.py} (58%) delete mode 100644 account_spread_cost_revenue/views/account_invoice.xml create mode 100644 account_spread_cost_revenue/views/account_move.xml diff --git a/account_spread_cost_revenue/__manifest__.py b/account_spread_cost_revenue/__manifest__.py index b93c0f17..b04823cb 100644 --- a/account_spread_cost_revenue/__manifest__.py +++ b/account_spread_cost_revenue/__manifest__.py @@ -1,22 +1,22 @@ -# Copyright 2016-2019 Onestein () +# Copyright 2016-2020 Onestein () # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). { "name": "Cost-Revenue Spread", "summary": "Spread costs and revenues over a custom period", - "version": "12.0.1.2.0", + "version": "13.0.1.0.0", "development_status": "Beta", "author": "Onestein,Odoo Community Association (OCA)", "maintainers": ["astirpe"], "license": "AGPL-3", "website": "https://github.com/OCA/account-financial-tools/", "category": "Accounting & Finance", - "depends": ["account",], + "depends": ["account"], "data": [ "security/ir.model.access.csv", "security/account_spread_security.xml", "views/account_spread.xml", - "views/account_invoice.xml", + "views/account_move.xml", "views/res_company.xml", "views/account_spread_template.xml", "templates/assets.xml", diff --git a/account_spread_cost_revenue/migrations/13.0.1.0.0/post-migration.py b/account_spread_cost_revenue/migrations/13.0.1.0.0/post-migration.py new file mode 100644 index 00000000..8bdc596d --- /dev/null +++ b/account_spread_cost_revenue/migrations/13.0.1.0.0/post-migration.py @@ -0,0 +1,26 @@ +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from odoo import SUPERUSER_ID, api + + +def migrate(cr, version): + env = api.Environment(cr, SUPERUSER_ID, {}) + rule_name = "account_spread_cost_revenue.account_spread_multi_company_rule" + rule = env.ref(rule_name, raise_if_not_found=False) + if rule: + domain = "['|',('company_id','=',False),('company_id','in',company_ids)]" + rule.write({"domain_force": domain}) + + rule_name = "account_spread_cost_revenue.account_spread_template_multi_company_rule" + rule = env.ref(rule_name, raise_if_not_found=False) + if rule: + domain = "['|',('company_id','=',False),('company_id','in',company_ids)]" + rule.write({"domain_force": domain}) + + rule_name = ( + "account_spread_cost_revenue.account_spread_template_auto_multi_company_rule" + ) + rule = env.ref(rule_name, raise_if_not_found=False) + if rule: + domain = "['|',('company_id','=',False),('company_id','in',company_ids)]" + rule.write({"domain_force": domain}) diff --git a/account_spread_cost_revenue/migrations/13.0.1.0.0/pre-migration.py b/account_spread_cost_revenue/migrations/13.0.1.0.0/pre-migration.py new file mode 100644 index 00000000..faf0d188 --- /dev/null +++ b/account_spread_cost_revenue/migrations/13.0.1.0.0/pre-migration.py @@ -0,0 +1,7 @@ +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from odoo.tools import sql + + +def migrate(cr, version): + sql.rename_column(cr, "res_partner", "auto_archive", "auto_archive_spread") diff --git a/account_spread_cost_revenue/models/__init__.py b/account_spread_cost_revenue/models/__init__.py index e7d567cb..c37541a4 100644 --- a/account_spread_cost_revenue/models/__init__.py +++ b/account_spread_cost_revenue/models/__init__.py @@ -1,7 +1,7 @@ # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -from . import account_invoice -from . import account_invoice_line +from . import account_move +from . import account_move_line from . import account_spread_line from . import account_spread from . import account_spread_template diff --git a/account_spread_cost_revenue/models/account_invoice.py b/account_spread_cost_revenue/models/account_invoice.py deleted file mode 100644 index acfbedd1..00000000 --- a/account_spread_cost_revenue/models/account_invoice.py +++ /dev/null @@ -1,59 +0,0 @@ -# Copyright 2016-2019 Onestein () -# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). - -from odoo import api, models - - -class AccountInvoice(models.Model): - _inherit = "account.invoice" - - def action_invoice_open(self): - for invoice in self: - invoice.invoice_line_ids.create_auto_spread() - return super().action_invoice_open() - - @api.multi - def action_move_create(self): - """Invoked when validating the invoices.""" - res = super().action_move_create() - spreads = self.mapped("invoice_line_ids.spread_id") - spreads.compute_spread_board() - spreads.reconcile_spread_moves() - return res - - @api.multi - def invoice_line_move_line_get(self): - """Copying expense/revenue account from spread to move lines.""" - res = super().invoice_line_move_line_get() - for line in res: - invl_id = line.get("invl_id") - invl = self.env["account.invoice.line"].browse(invl_id) - if invl.spread_id: - if invl.invoice_id.type in ("out_invoice", "in_refund"): - account = invl.spread_id.debit_account_id - else: - account = invl.spread_id.credit_account_id - line["account_id"] = account.id - return res - - @api.multi - def action_cancel(self): - """Cancel the spread lines and their related moves when - the invoice is canceled.""" - res = super().action_cancel() - spread_lines = self.mapped("invoice_line_ids.spread_id.line_ids") - moves = spread_lines.mapped("move_id") - moves.button_cancel() - moves.unlink() - spread_lines.unlink() - return res - - @api.model - def _refund_cleanup_lines(self, lines): - result = super()._refund_cleanup_lines(lines) - for i, line in enumerate(lines): - for name in line._fields.keys(): - if name == "spread_id": - result[i][2][name] = False - break - return result diff --git a/account_spread_cost_revenue/models/account_move.py b/account_spread_cost_revenue/models/account_move.py new file mode 100644 index 00000000..2923db3d --- /dev/null +++ b/account_spread_cost_revenue/models/account_move.py @@ -0,0 +1,34 @@ +# Copyright 2016-2020 Onestein () +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from odoo import api, models + + +class AccountMove(models.Model): + _inherit = "account.move" + + def action_post(self): + """Invoked when validating the invoices.""" + self.mapped("invoice_line_ids").create_auto_spread() + res = super().action_post() + spreads = self.mapped("invoice_line_ids.spread_id") + spreads.compute_spread_board() + spreads.reconcile_spread_moves() + return res + + def button_cancel(self): + """Cancel the spread lines and their related moves when + the invoice is canceled.""" + spread_lines = self.mapped("invoice_line_ids.spread_id.line_ids") + moves = spread_lines.mapped("move_id") + moves.line_ids.remove_move_reconcile() + moves.filtered(lambda move: move.state == "posted").button_draft() + moves.with_context(force_delete=True).unlink() + spread_lines.unlink() + res = super().button_cancel() + return res + + @api.constrains("name", "journal_id", "state") + def _check_unique_sequence_number(self): + if not self.env.context.get("skip_unique_sequence_number"): + return super()._check_unique_sequence_number() diff --git a/account_spread_cost_revenue/models/account_invoice_line.py b/account_spread_cost_revenue/models/account_move_line.py similarity index 58% rename from account_spread_cost_revenue/models/account_invoice_line.py rename to account_spread_cost_revenue/models/account_move_line.py index 16595129..d349c990 100644 --- a/account_spread_cost_revenue/models/account_invoice_line.py +++ b/account_spread_cost_revenue/models/account_move_line.py @@ -1,12 +1,12 @@ -# Copyright 2016-2019 Onestein () +# Copyright 2016-2020 Onestein () # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). from odoo import _, api, fields, models -from odoo.exceptions import UserError +from odoo.exceptions import UserError, ValidationError -class AccountInvoiceLine(models.Model): - _inherit = "account.invoice.line" +class AccountMoveLine(models.Model): + _inherit = "account.move.line" spread_id = fields.Many2one("account.spread", string="Spread Board", copy=False) spread_check = fields.Selection( @@ -18,17 +18,16 @@ class AccountInvoiceLine(models.Model): compute="_compute_spread_check", ) - @api.depends("spread_id", "invoice_id.state") + @api.depends("spread_id", "move_id.state") def _compute_spread_check(self): for line in self: if line.spread_id: line.spread_check = "linked" - elif line.invoice_id.state == "draft": + elif line.move_id.state == "draft": line.spread_check = "unlinked" else: line.spread_check = "unavailable" - @api.multi def spread_details(self): """Button on the invoice lines tree view of the invoice form to show the spread form view.""" @@ -39,7 +38,6 @@ class AccountInvoiceLine(models.Model): if self.spread_id: return { "name": _("Spread Details"), - "view_type": "form", "view_mode": "form", "res_model": "account.spread", "type": "ir.actions.act_window", @@ -50,16 +48,14 @@ class AccountInvoiceLine(models.Model): # In case no spread board is linked to the invoice line # open the wizard to link them - company = self.invoice_id.company_id ctx = dict( self.env.context, default_invoice_line_id=self.id, - default_company_id=company.id, - allow_spread_planning=company.allow_spread_planning, + default_company_id=self.move_id.company_id.id, + allow_spread_planning=self.move_id.company_id.allow_spread_planning, ) return { "name": _("Link Invoice Line with Spread Board"), - "view_type": "form", "view_mode": "form", "res_model": "account.spread.invoice.line.link.wizard", "type": "ir.actions.act_window", @@ -67,6 +63,52 @@ class AccountInvoiceLine(models.Model): "context": ctx, } + @api.constrains("spread_id", "account_id") + def _check_spread_account_balance_sheet(self): + for line in self: + if not line.spread_id: + pass + elif line.move_id.type in ("out_invoice", "in_refund"): + if line.account_id != line.spread_id.debit_account_id: + raise ValidationError( + _( + "The account of the invoice line does not correspond " + "to the Balance Sheet (debit account) of the spread" + ) + ) + elif line.move_id.type in ("in_invoice", "out_refund"): + if line.account_id != line.spread_id.credit_account_id: + raise ValidationError( + _( + "The account of the invoice line does not correspond " + "to the Balance Sheet (credit account) of the spread" + ) + ) + + def write(self, vals): + if vals.get("spread_id"): + spread = self.env["account.spread"].browse(vals.get("spread_id")) + if spread.invoice_type in ["out_invoice", "in_refund"]: + vals["account_id"] = spread.debit_account_id.id + else: + vals["account_id"] = spread.credit_account_id.id + return super().write(vals) + + def _check_spread_reconcile_validity(self): + # Improve error messages of standard Odoo + reconciled_lines = self.filtered(lambda l: l.reconciled) + msg_line = _("Move line: %s (%s), account code: %s\n") + if reconciled_lines: + msg = _("Cannot reconcile entries that are already reconciled:\n") + for line in reconciled_lines: + msg += msg_line % (line.id, line.name, line.account_id.code) + raise ValidationError(msg) + if len(self.mapped("account_id").ids) > 1: + msg = _("Some entries are not from the same account:\n") + for line in self: + msg += msg_line % (line.id, line.name, line.account_id.code) + raise ValidationError(msg) + def create_auto_spread(self): """ Create auto spread table for each invoice line, when needed """ @@ -88,7 +130,7 @@ class AccountInvoiceLine(models.Model): continue spread_type = ( "sale" - if line.invoice_type in ["out_invoice", "out_refund"] + if line.move_id.type in ["out_invoice", "out_refund"] else "purchase" ) spread_auto = self.env["account.spread.template.auto"].search( diff --git a/account_spread_cost_revenue/models/account_spread.py b/account_spread_cost_revenue/models/account_spread.py index 3408b156..93aafc35 100644 --- a/account_spread_cost_revenue/models/account_spread.py +++ b/account_spread_cost_revenue/models/account_spread.py @@ -1,4 +1,4 @@ -# Copyright 2018-2019 Onestein () +# Copyright 2018-2020 Onestein () # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). import calendar @@ -10,8 +10,6 @@ from odoo import _, api, fields, models from odoo.exceptions import UserError, ValidationError from odoo.tools import float_is_zero -from odoo.addons import decimal_precision as dp - class AccountSpread(models.Model): _name = "account.spread" @@ -46,65 +44,64 @@ class AccountSpread(models.Model): help="Period length for the entries", required=True, ) - use_invoice_line_account = fields.Boolean(string="Use invoice line's account",) + use_invoice_line_account = fields.Boolean() credit_account_id = fields.Many2one( - "account.account", string="Credit Account", required=True + "account.account", + compute="_compute_credit_account_id", + readonly=False, + store=True, + required=True, ) debit_account_id = fields.Many2one( - "account.account", string="Debit Account", required=True + "account.account", + compute="_compute_debit_account_id", + readonly=False, + store=True, + required=True, ) is_credit_account_deprecated = fields.Boolean( compute="_compute_deprecated_accounts" ) is_debit_account_deprecated = fields.Boolean(compute="_compute_deprecated_accounts") - unspread_amount = fields.Float( - digits=dp.get_precision("Account"), compute="_compute_amounts" - ) - unposted_amount = fields.Float( - digits=dp.get_precision("Account"), compute="_compute_amounts" - ) - posted_amount = fields.Float( - digits=dp.get_precision("Account"), compute="_compute_amounts" - ) - total_amount = fields.Float( - digits=dp.get_precision("Account"), compute="_compute_amounts" - ) - all_posted = fields.Boolean(compute="_compute_amounts", store=True) + unspread_amount = fields.Float(digits="Account", compute="_compute_amounts",) + unposted_amount = fields.Float(digits="Account", compute="_compute_amounts",) + posted_amount = fields.Float(digits="Account", compute="_compute_amounts",) + total_amount = fields.Float(digits="Account", compute="_compute_amounts",) + all_posted = fields.Boolean(compute="_compute_all_posted", store=True) line_ids = fields.One2many( "account.spread.line", "spread_id", string="Spread Lines" ) spread_date = fields.Date( string="Start Date", default=time.strftime("%Y-01-01"), required=True ) - journal_id = fields.Many2one("account.journal", string="Journal", required=True) + journal_id = fields.Many2one( + "account.journal", + compute="_compute_journal_id", + readonly=False, + store=True, + required=True, + ) invoice_line_ids = fields.One2many( - "account.invoice.line", "spread_id", copy=False, string="Invoice Lines" + "account.move.line", "spread_id", copy=False, string="Invoice Lines" ) invoice_line_id = fields.Many2one( - "account.invoice.line", + "account.move.line", string="Invoice line", compute="_compute_invoice_line", inverse="_inverse_invoice_line", store=True, ) invoice_id = fields.Many2one( - related="invoice_line_id.invoice_id", - readonly=True, - store=True, - string="Invoice", + related="invoice_line_id.move_id", readonly=True, store=True, ) - estimated_amount = fields.Float(digits=dp.get_precision("Account")) + estimated_amount = fields.Float(digits="Account") company_id = fields.Many2one( - "res.company", - default=lambda self: self.env.user.company_id, - string="Company", - required=True, + "res.company", default=lambda self: self.env.company, required=True ) currency_id = fields.Many2one( "res.currency", - string="Currency", required=True, - default=lambda self: self.env.user.company_id.currency_id.id, + default=lambda self: self.env.company.currency_id.id, ) account_analytic_id = fields.Many2one( "account.analytic.account", string="Analytic Account" @@ -112,10 +109,10 @@ class AccountSpread(models.Model): analytic_tag_ids = fields.Many2many("account.analytic.tag", string="Analytic Tags") move_line_auto_post = fields.Boolean("Auto-post lines", default=True) display_create_all_moves = fields.Boolean( - compute="_compute_display_create_all_moves", string="Display Button All Moves" + compute="_compute_display_create_all_moves", ) display_recompute_buttons = fields.Boolean( - compute="_compute_display_recompute_buttons", string="Display Buttons Recompute" + compute="_compute_display_recompute_buttons", ) display_move_line_auto_post = fields.Boolean( compute="_compute_display_move_line_auto_post", @@ -123,18 +120,19 @@ class AccountSpread(models.Model): ) active = fields.Boolean(default=True) + @api.model + def default_journal(self, company_id): + domain = [("type", "=", "general"), ("company_id", "=", company_id)] + return self.env["account.journal"].search(domain, limit=1) + @api.model def default_get(self, fields): res = super().default_get(fields) - if "company_id" not in fields: - company_id = self.env.user.company_id.id - else: - company_id = res["company_id"] - default_journal = self.env["account.journal"].search( - [("type", "=", "general"), ("company_id", "=", company_id)], limit=1 - ) - if "journal_id" not in res and default_journal: - res["journal_id"] = default_journal.id + if "journal_id" not in res: + company_id = res.get("company_id", self.env.company.id) + default_journal = self.default_journal(company_id) + if default_journal: + res["journal_id"] = default_journal.id return res @api.depends("invoice_type") @@ -145,20 +143,16 @@ class AccountSpread(models.Model): else: spread.spread_type = "purchase" - @api.depends("invoice_line_ids", "invoice_line_ids.invoice_id") + @api.depends("invoice_line_ids", "invoice_line_ids.move_id") def _compute_invoice_line(self): for spread in self: invoice_lines = spread.invoice_line_ids - line = invoice_lines and invoice_lines[0] or False - spread.invoice_line_id = line + spread.invoice_line_id = invoice_lines and invoice_lines[0] or False - @api.multi def _inverse_invoice_line(self): for spread in self: invoice_line = spread.invoice_line_id - spread.write( - {"invoice_line_ids": [(6, 0, [invoice_line.id])],} - ) + spread.write({"invoice_line_ids": [(6, 0, [invoice_line.id])]}) @api.depends( "estimated_amount", @@ -171,38 +165,36 @@ class AccountSpread(models.Model): ) def _compute_amounts(self): for spread in self: - moves_amount = 0.0 - posted_amount = 0.0 + lines_move = spread.line_ids.filtered(lambda l: l.move_id) + moves_amount = sum(spread_line.amount for spread_line in lines_move) + lines_posted = lines_move.filtered(lambda l: l.move_id.state == "posted") + posted_amount = sum(spread_line.amount for spread_line in lines_posted) total_amount = spread.estimated_amount if spread.invoice_line_id: - invoice = spread.invoice_line_id.invoice_id total_amount = spread.invoice_line_id.currency_id._convert( - spread.invoice_line_id.price_subtotal, + spread.invoice_line_id.balance, spread.currency_id, spread.company_id, - invoice._get_currency_rate_date() or fields.Date.today(), + spread.invoice_id.date, ) - for spread_line in spread.line_ids: - if spread_line.move_id: - moves_amount += spread_line.amount - if spread_line.move_id.state == "posted": - posted_amount += spread_line.amount spread.unspread_amount = total_amount - moves_amount spread.unposted_amount = total_amount - posted_amount spread.posted_amount = posted_amount spread.total_amount = total_amount - spread.all_posted = spread.unposted_amount == 0.0 - @api.multi + @api.depends("unposted_amount") + def _compute_all_posted(self): + for spread in self: + rounding = self.currency_id.rounding + unposted = spread.unposted_amount + spread.all_posted = float_is_zero(unposted, precision_rounding=rounding) + def _compute_display_create_all_moves(self): for spread in self: - if any(not line.move_id for line in spread.line_ids): - spread.display_create_all_moves = True - else: - spread.display_create_all_moves = False + any_not_move = any(not line.move_id for line in spread.line_ids) + spread.display_create_all_moves = any_not_move - @api.multi def _compute_display_recompute_buttons(self): for spread in self: spread.display_recompute_buttons = True @@ -210,14 +202,12 @@ class AccountSpread(models.Model): if spread.invoice_id.state == "draft": spread.display_recompute_buttons = False - @api.multi + @api.depends("company_id.force_move_auto_post") def _compute_display_move_line_auto_post(self): for spread in self: - spread.display_move_line_auto_post = True - if spread.company_id.force_move_auto_post: - spread.display_move_line_auto_post = False + auto_post = spread.company_id.force_move_auto_post + spread.display_move_line_auto_post = not auto_post - @api.multi def _get_spread_entry_name(self, seq): """Use this method to customise the name of the accounting entry.""" self.ensure_one() @@ -239,66 +229,67 @@ class AccountSpread(models.Model): if self.template_id.start_date: self.spread_date = self.template_id.start_date - @api.onchange("invoice_type", "company_id") - def onchange_invoice_type(self): - company = self.company_id + @api.depends("invoice_type", "company_id") + def _compute_journal_id(self): if not self.env.context.get("default_journal_id"): - journal = company.default_spread_expense_journal_id - if self.invoice_type in ("out_invoice", "in_refund"): - journal = company.default_spread_revenue_journal_id - if journal: - self.journal_id = journal + for spread in self: + journal = spread.company_id.default_spread_expense_journal_id + if spread.invoice_type in ("out_invoice", "in_refund"): + journal = spread.company_id.default_spread_revenue_journal_id + if not journal: + journal = self.default_journal(spread.company_id.id) + spread.journal_id = journal + @api.depends("invoice_type", "company_id") + def _compute_debit_account_id(self): if not self.env.context.get("default_debit_account_id"): - if self.invoice_type in ("out_invoice", "in_refund"): - debit_account_id = company.default_spread_revenue_account_id - self.debit_account_id = debit_account_id + invoice_types = ("out_invoice", "in_refund") + for spread in self.filtered(lambda s: s.invoice_type in invoice_types): + debit_account = spread.company_id.default_spread_revenue_account_id + spread.debit_account_id = debit_account + @api.depends("invoice_type", "company_id") + def _compute_credit_account_id(self): if not self.env.context.get("default_credit_account_id"): - if self.invoice_type in ("in_invoice", "out_refund"): - credit_account_id = company.default_spread_expense_account_id - self.credit_account_id = credit_account_id + invoice_types = ("in_invoice", "out_refund") + for spread in self.filtered(lambda s: s.invoice_type in invoice_types): + credit_account = spread.company_id.default_spread_expense_account_id + spread.credit_account_id = credit_account @api.constrains("invoice_id", "invoice_type") def _check_invoice_type(self): - for spread in self: - if not spread.invoice_id: - pass - elif spread.invoice_type != spread.invoice_id.type: - raise ValidationError( - _("The Invoice Type does not correspond to the Invoice") - ) + if self.filtered( + lambda s: s.invoice_id and s.invoice_type != s.invoice_id.type + ): + raise ValidationError( + _("The Invoice Type does not correspond to the Invoice") + ) @api.constrains("journal_id") def _check_journal(self): for spread in self: moves = spread.mapped("line_ids.move_id").filtered("journal_id") if any(move.journal_id != spread.journal_id for move in moves): - raise ValidationError( - _("The Journal is not consistent with the account moves.") - ) + err_msg = _("The Journal is not consistent with the account moves.") + raise ValidationError(err_msg) @api.constrains("template_id", "invoice_type") def _check_template_invoice_type(self): - for spread in self: + for spread in self.filtered(lambda s: s.template_id.spread_type == "sale"): if spread.invoice_type in ["in_invoice", "in_refund"]: - if spread.template_id.spread_type == "sale": - raise ValidationError( - _( - "The Spread Template (Sales) is not compatible " - "with selected invoice type" - ) - ) - elif spread.invoice_type in ["out_invoice", "out_refund"]: - if spread.template_id.spread_type == "purchase": - raise ValidationError( - _( - "The Spread Template (Purchases) is not compatible " - "with selected invoice type" - ) - ) + err_msg = _( + "The Spread Template (Sales) is not compatible " + "with selected invoice type" + ) + raise ValidationError(err_msg) + for spread in self.filtered(lambda s: s.template_id.spread_type == "purchase"): + if spread.invoice_type in ["out_invoice", "out_refund"]: + err_msg = _( + "The Spread Template (Purchases) is not compatible " + "with selected invoice type" + ) + raise ValidationError(err_msg) - @api.multi def _get_spread_period_duration(self): """Converts the selected period_type to number of months.""" self.ensure_one() @@ -308,7 +299,6 @@ class AccountSpread(models.Model): return 3 return 1 - @api.multi def _init_line_date(self, posted_line_ids): """Calculates the initial spread date. This method is used by "def _compute_spread_board()" method. @@ -324,7 +314,6 @@ class AccountSpread(models.Model): spread_date = self.spread_date return spread_date - @api.multi def _next_line_date(self, month_day, date): """Calculates the next spread date. This method is used by "def _compute_spread_board()" method. @@ -338,11 +327,10 @@ class AccountSpread(models.Model): date = date.replace(day=min(max_day_in_month, month_day)) return date - @api.multi def _compute_spread_board(self): """Creates the spread lines. This method is highly inspired from method compute_depreciation_board() present in standard - "account_asset" module, developed by Odoo SA. + Odoo 11.0 "account_asset" module, developed by Odoo SA. """ self.ensure_one() @@ -391,19 +379,15 @@ class AccountSpread(models.Model): msg_body = _("Spread table '%s' created.") % invoice_type_selection self.message_post(body=msg_body) - @api.multi def _get_number_of_periods(self, month_day): """Calculates the number of spread lines.""" self.ensure_one() - if month_day != 1: - return self.period_number + 1 - return self.period_number + return self.period_number + 1 if month_day != 1 else self.period_number @staticmethod def _get_last_day_of_month(spread_date): return spread_date + relativedelta(day=31) - @api.multi def _compute_board_amount(self, sequence, amount, number_of_periods): """Calculates the amount for the spread lines.""" self.ensure_one() @@ -418,7 +402,6 @@ class AccountSpread(models.Model): amount = (amount_to_spread / period) / month_days * days return amount - @api.multi def compute_spread_board(self): """Checks whether the spread lines should be calculated. In case checks pass, invoke "def _compute_spread_board()" method. @@ -426,7 +409,6 @@ class AccountSpread(models.Model): for spread in self.filtered(lambda s: s.total_amount): spread._compute_spread_board() - @api.multi def action_recalculate_spread(self): """Recalculate spread""" self.ensure_one() @@ -435,37 +417,30 @@ class AccountSpread(models.Model): self.compute_spread_board() self.env["account.spread.line"]._create_entries() - @api.multi def action_undo_spread(self): - """Undo spreading: Remove all created moves, - restore original account on move line""" + """Undo spreading: Remove all created moves""" self.ensure_one() self.mapped("line_ids").filtered("move_id").unlink_move() self.mapped("line_ids").unlink() - @api.multi def action_unlink_invoice_line(self): """Unlink the invoice line from the spread board""" self.ensure_one() if self.invoice_id.state != "draft": - raise UserError( - _("Cannot unlink invoice lines if the invoice is validated") - ) + msg = _("Cannot unlink invoice lines if the invoice is validated") + raise UserError(msg) self._action_unlink_invoice_line() - @api.multi def _action_unlink_invoice_line(self): - spread_mls = self.mapped("line_ids.move_id.line_ids") - spread_mls.remove_move_reconcile() + self.mapped("line_ids.move_id.line_ids").remove_move_reconcile() self._message_post_unlink_invoice_line() self.write({"invoice_line_ids": [(5, 0, 0)]}) def _message_post_unlink_invoice_line(self): for spread in self: - invoice_id = spread.invoice_id.id inv_link = ( - "%s" % (invoice_id, _("Invoice")) + "%s" % (spread.invoice_id.id, _("Invoice")) ) msg_body = _("Unlinked invoice line '%s' (view %s).") % ( spread.invoice_line_id.name, @@ -482,91 +457,61 @@ class AccountSpread(models.Model): ) spread.invoice_id.message_post(body=msg_body) - @api.multi def unlink(self): if self.filtered(lambda s: s.invoice_line_id): - raise UserError( - _("Cannot delete spread(s) that are linked " "to an invoice line.") - ) + err_msg = _("Cannot delete spread(s) that are linked to an invoice line.") + raise UserError(err_msg) if self.mapped("line_ids.move_id").filtered(lambda m: m.state == "posted"): - raise ValidationError( - _("Cannot delete spread(s): there are " "posted Journal Entries.") - ) + err_msg = _("Cannot delete spread(s): there are posted Journal Entries.") + raise ValidationError(err_msg) return super().unlink() - @api.multi def reconcile_spread_moves(self): for spread in self: spread._reconcile_spread_moves() - @api.multi def _reconcile_spread_moves(self, created_moves=False): """Reconcile spread moves if possible""" self.ensure_one() - if not self.invoice_id.number: - return - spread_mls = self.line_ids.mapped("move_id.line_ids") if created_moves: spread_mls |= created_moves.mapped("line_ids") - spread_sign = True if self.total_amount >= 0.0 else False - in_invoice_or_out_refund = ("in_invoice", "out_refund") + account = self.invoice_line_id.account_id + mls_to_reconcile = spread_mls.filtered(lambda l: l.account_id == account) - if self.invoice_type in in_invoice_or_out_refund and spread_sign: - spread_mls = spread_mls.filtered(lambda x: x.credit != 0.0) - elif self.invoice_type in in_invoice_or_out_refund: - spread_mls = spread_mls.filtered(lambda x: x.debit != 0.0) - elif spread_sign: - spread_mls = spread_mls.filtered(lambda x: x.debit != 0.0) - else: - spread_mls = spread_mls.filtered(lambda x: x.credit != 0.0) - - invoice_mls = self.invoice_id.move_id.mapped("line_ids") - if self.invoice_id.type in in_invoice_or_out_refund and spread_sign: - invoice_mls = invoice_mls.filtered(lambda x: x.debit != 0.0) - elif self.invoice_id.type in in_invoice_or_out_refund: - invoice_mls = invoice_mls.filtered(lambda x: x.credit != 0.0) - elif spread_sign: - invoice_mls = invoice_mls.filtered(lambda x: x.credit != 0.0) - else: - invoice_mls = invoice_mls.filtered(lambda x: x.debit != 0.0) - - to_be_reconciled = self.env["account.move.line"] - if len(invoice_mls) > 1: - # Refine selection of move line. - # The name is formatted the same way as it is done when creating - # move lines in method "def invoice_line_move_line_get()" of - # standard account module - raw_name = self.invoice_line_id.name - formatted_name = raw_name.split("\n")[0][:64] - for move_line in invoice_mls: - if move_line.name == formatted_name: - to_be_reconciled |= move_line - else: - to_be_reconciled = invoice_mls - - if len(to_be_reconciled) == 1: - do_reconcile = spread_mls + to_be_reconciled + if mls_to_reconcile: + do_reconcile = mls_to_reconcile + self.invoice_line_id do_reconcile.remove_move_reconcile() + do_reconcile._check_spread_reconcile_validity() do_reconcile.reconcile() - @api.multi def create_all_moves(self): for line in self.mapped("line_ids").filtered(lambda l: not l.move_id): line.create_move() + def _post_spread_moves(self, moves): + self.ensure_one() + if not moves: + return + ctx = dict(self.env.context, skip_unique_sequence_number=True) + if self.company_id.force_move_auto_post or self.move_line_auto_post: + moves.with_context(ctx).post() + @api.depends("debit_account_id.deprecated", "credit_account_id.deprecated") def _compute_deprecated_accounts(self): for spread in self: - debit_deprecated = bool(spread.debit_account_id.deprecated) - credit_deprecated = bool(spread.credit_account_id.deprecated) - spread.is_debit_account_deprecated = debit_deprecated - spread.is_credit_account_deprecated = credit_deprecated + spread.is_debit_account_deprecated = spread.debit_account_id.deprecated + spread.is_credit_account_deprecated = spread.credit_account_id.deprecated - @api.multi def open_reconcile_view(self): - self.ensure_one() + action_name = "account_spread_cost_revenue.action_account_moves_all_spread" + [action] = self.env.ref(action_name).read() + action["domain"] = [("id", "in", [])] spread_mls = self.line_ids.mapped("move_id.line_ids") - return spread_mls.open_reconcile_view() + spread_mls = spread_mls.filtered(lambda m: m.reconciled) + if spread_mls: + domain = [("id", "in", spread_mls.ids + [self.invoice_line_id.id])] + action["domain"] = domain + return action diff --git a/account_spread_cost_revenue/models/account_spread_line.py b/account_spread_cost_revenue/models/account_spread_line.py index 531724e3..8054dc29 100644 --- a/account_spread_cost_revenue/models/account_spread_line.py +++ b/account_spread_cost_revenue/models/account_spread_line.py @@ -1,11 +1,9 @@ -# Copyright 2016-2019 Onestein () +# Copyright 2016-2020 Onestein () # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). from odoo import _, api, fields, models from odoo.exceptions import UserError -from odoo.addons import decimal_precision as dp - class AccountInvoiceSpreadLine(models.Model): _name = "account.spread.line" @@ -13,14 +11,11 @@ class AccountInvoiceSpreadLine(models.Model): _order = "date" name = fields.Char("Description", readonly=True) - amount = fields.Float(digits=dp.get_precision("Account"), required=True) + amount = fields.Float(digits="Account", required=True) date = fields.Date(required=True) - spread_id = fields.Many2one( - "account.spread", string="Spread Board", ondelete="cascade" - ) + spread_id = fields.Many2one("account.spread", ondelete="cascade") move_id = fields.Many2one("account.move", string="Journal Entry", readonly=True) - @api.multi def create_and_reconcile_moves(self): grouped_lines = {} for spread_line in self: @@ -40,27 +35,15 @@ class AccountInvoiceSpreadLine(models.Model): for move in created_moves ) spread.message_post(body=post_msg) + if spread.invoice_id.state == "posted": + spread._reconcile_spread_moves(created_moves) + spread._post_spread_moves(created_moves) - spread._reconcile_spread_moves(created_moves) - self._post_spread_moves(spread, created_moves) - - @api.model - def _post_spread_moves(self, spread, moves): - if not moves: - return - if spread.company_id.force_move_auto_post: - moves.post() - elif spread.move_line_auto_post: - moves.post() - - @api.multi def create_move(self): - """Button to manually create a move from a spread line entry. - """ + """Button to manually create a move from a spread line entry.""" self.ensure_one() self.create_and_reconcile_moves() - @api.multi def _create_moves(self): if self.filtered(lambda l: l.move_id): raise UserError( @@ -74,19 +57,21 @@ class AccountInvoiceSpreadLine(models.Model): for line in self: move_vals = line._prepare_move() move = self.env["account.move"].create(move_vals) - - line.write({"move_id": move.id}) + line.move_id = move created_moves += move return created_moves - @api.multi def _prepare_move(self): self.ensure_one() spread_date = self.env.context.get("spread_date") or self.date spread = self.spread_id analytic = spread.account_analytic_id - analytic_tags = [(4, tag.id, None) for tag in spread.analytic_tag_ids] + analytic_tags = [] + if self.env["account.analytic.tag"].check_access_rights( + "read", raise_exception=False + ): + analytic_tags = [(6, 0, spread.analytic_tag_ids.ids)] company_currency = spread.company_id.currency_id current_currency = spread.currency_id @@ -95,13 +80,17 @@ class AccountInvoiceSpreadLine(models.Model): self.amount, company_currency, spread.company_id, spread_date ) + debit_credit = spread.invoice_type in ["in_invoice", "out_refund"] + line_ids = [ ( 0, 0, { - "name": spread.name.split("\n")[0][:64], - "account_id": spread.debit_account_id.id, + "name": spread.name, + "account_id": spread.debit_account_id.id + if debit_credit + else spread.credit_account_id.id, "debit": amount if amount > 0.0 else 0.0, "credit": -amount if amount < 0.0 else 0.0, "partner_id": self.spread_id.invoice_id.partner_id.id, @@ -115,8 +104,10 @@ class AccountInvoiceSpreadLine(models.Model): 0, 0, { - "name": spread.name.split("\n")[0][:64], - "account_id": spread.credit_account_id.id, + "name": spread.name, + "account_id": spread.credit_account_id.id + if debit_credit + else spread.debit_account_id.id, "credit": amount if amount > 0.0 else 0.0, "debit": -amount if amount < 0.0 else 0.0, "partner_id": self.spread_id.invoice_id.partner_id.id, @@ -135,17 +126,14 @@ class AccountInvoiceSpreadLine(models.Model): "journal_id": spread.journal_id.id, "line_ids": line_ids, "company_id": spread.company_id.id, + "partner_id": spread.invoice_id.partner_id.id, } - @api.multi def open_move(self): - """Used by a button to manually view a move from a - spread line entry. - """ + """Used by a button to manually view a move from a spread line entry.""" self.ensure_one() return { "name": _("Journal Entry"), - "view_type": "form", "view_mode": "form", "res_model": "account.move", "view_id": False, @@ -153,18 +141,15 @@ class AccountInvoiceSpreadLine(models.Model): "res_id": self.move_id.id, } - @api.multi def unlink_move(self): - """Used by a button to manually unlink a move - from a spread line entry. - """ + """Used by a button to manually unlink a move from a spread line entry.""" for line in self: move = line.move_id if move.state == "posted": move.button_cancel() move.line_ids.remove_move_reconcile() post_msg = _("Deleted move %s") % line.move_id.id - move.unlink() + move.with_context(force_delete=True).unlink() line.move_id = False line.spread_id.message_post(body=post_msg) @@ -188,6 +173,6 @@ class AccountInvoiceSpreadLine(models.Model): spreads_to_archive = ( self.env["account.spread"] .search([("all_posted", "=", True)]) - .filtered(lambda s: s.company_id.auto_archive) + .filtered(lambda s: s.company_id.auto_archive_spread) ) spreads_to_archive.write({"active": False}) diff --git a/account_spread_cost_revenue/models/account_spread_template.py b/account_spread_cost_revenue/models/account_spread_template.py index b35f064c..0f3e3859 100644 --- a/account_spread_cost_revenue/models/account_spread_template.py +++ b/account_spread_cost_revenue/models/account_spread_template.py @@ -1,4 +1,4 @@ -# Copyright 2018-2019 Onestein () +# Copyright 2018-2020 Onestein () # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). from odoo import _, api, fields, models @@ -14,13 +14,15 @@ class AccountSpreadTemplate(models.Model): [("sale", "Customer"), ("purchase", "Supplier")], default="sale", required=True ) company_id = fields.Many2one( - "res.company", - default=lambda self: self.env.user.company_id, - string="Company", - required=True, + "res.company", default=lambda self: self.env.company, required=True ) spread_journal_id = fields.Many2one( - "account.journal", string="Journal", required=True + "account.journal", + string="Journal", + compute="_compute_spread_journal", + readonly=False, + store=True, + required=True, ) use_invoice_line_account = fields.Boolean( string="Invoice account as spread account", @@ -28,12 +30,17 @@ class AccountSpreadTemplate(models.Model): "In this case, user need to select expense/revenue account too.", ) spread_account_id = fields.Many2one( - "account.account", string="Spread Balance Sheet Account", required=False + "account.account", + string="Spread Balance Sheet Account", + compute="_compute_spread_account", + readonly=False, + store=True, + required=False, ) exp_rev_account_id = fields.Many2one( "account.account", string="Expense/Revenue Account", - help="Optional account to overwrite the existing expense/revenue " "account", + help="Optional account to overwrite the existing expense/revenue account", ) period_number = fields.Integer( string="Number of Repetitions", help="Define the number of spread lines" @@ -57,15 +64,14 @@ class AccountSpreadTemplate(models.Model): @api.model def default_get(self, fields): res = super().default_get(fields) - if "company_id" not in fields: - company_id = self.env.user.company_id.id - else: - company_id = res["company_id"] - default_journal = self.env["account.journal"].search( - [("type", "=", "general"), ("company_id", "=", company_id)], limit=1 - ) - if "spread_journal_id" not in res and default_journal: - res["spread_journal_id"] = default_journal.id + if not res.get("company_id"): + res["company_id"] = self.env.company.id + if "spread_journal_id" not in res: + default_journal = self.env["account.spread"].default_journal( + res["company_id"] + ) + if default_journal: + res["spread_journal_id"] = default_journal.id return res @api.constrains("auto_spread", "auto_spread_ids") @@ -80,19 +86,27 @@ class AccountSpreadTemplate(models.Model): ) ) - @api.onchange("spread_type", "company_id") - def onchange_spread_type(self): - company = self.company_id - if self.spread_type == "sale": - account = company.default_spread_revenue_account_id - journal = company.default_spread_revenue_journal_id - else: - account = company.default_spread_expense_account_id - journal = company.default_spread_expense_journal_id - if account: - self.spread_account_id = account - if journal: - self.spread_journal_id = journal + @api.depends("spread_type", "company_id") + def _compute_spread_journal(self): + for spread in self: + company = spread.company_id + if spread.spread_type == "sale": + journal = company.default_spread_revenue_journal_id + else: + journal = company.default_spread_expense_journal_id + if journal: + spread.spread_journal_id = journal + + @api.depends("spread_type", "company_id") + def _compute_spread_account(self): + for spread in self: + company = spread.company_id + if spread.spread_type == "sale": + account = company.default_spread_revenue_account_id + else: + account = company.default_spread_expense_account_id + if account: + spread.spread_account_id = account @api.onchange("use_invoice_line_account") def _onchange_user_invoice_line_account(self): @@ -144,7 +158,9 @@ class AccountSpreadTemplate(models.Model): product = self.env["product.product"].browse(res[0]) account = self.env["account.account"].browse(res[1]) analytic = self.env["account.analytic.account"].browse(res[2]) - results.append("{} / {} / {}".format(product.name, account.name, analytic.name)) + results.append( + "{} / {} / {}".format(product.name, account.name, analytic.name) + ) if results: raise UserError( _("Followings are duplicated combinations,\n\n%s" % "\n".join(results)) diff --git a/account_spread_cost_revenue/models/res_company.py b/account_spread_cost_revenue/models/res_company.py index afddf497..a9f46092 100644 --- a/account_spread_cost_revenue/models/res_company.py +++ b/account_spread_cost_revenue/models/res_company.py @@ -1,4 +1,4 @@ -# Copyright 2018-2019 Onestein () +# Copyright 2018-2020 Onestein () # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). from odoo import fields, models @@ -33,7 +33,7 @@ class ResCompany(models.Model): help="Enable this option if you want to post automatically the " "accounting moves of all the spreads.", ) - auto_archive = fields.Boolean( + auto_archive_spread = fields.Boolean( "Auto-archive spread", help="Enable this option if you want the cron job to automatically " "archive the spreads when all lines are posted.", diff --git a/account_spread_cost_revenue/readme/HISTORY.rst b/account_spread_cost_revenue/readme/HISTORY.rst index 66ca64b7..0f78ecec 100644 --- a/account_spread_cost_revenue/readme/HISTORY.rst +++ b/account_spread_cost_revenue/readme/HISTORY.rst @@ -1,3 +1,8 @@ +13.0.1.0.0 +~~~~~~~~~~ + +* [MIG] Port account_spread_cost_revenue to V13. + 12.0.2.0.0 ~~~~~~~~~~ diff --git a/account_spread_cost_revenue/security/account_spread_security.xml b/account_spread_cost_revenue/security/account_spread_security.xml index 1e72ba70..99df6699 100644 --- a/account_spread_cost_revenue/security/account_spread_security.xml +++ b/account_spread_cost_revenue/security/account_spread_security.xml @@ -7,7 +7,7 @@ ['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])] + >['|',('company_id','=',False),('company_id', 'in', company_ids)] Account Spread Template multi-company @@ -15,7 +15,7 @@ ['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])] + >['|',('company_id','=',False),('company_id', 'in', company_ids)] Account Spread Tempalte Auto multi-company @@ -23,7 +23,7 @@ ['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])] + >['|',('company_id','=',False),('company_id', 'in', company_ids)] diff --git a/account_spread_cost_revenue/static/src/js/account_spread.js b/account_spread_cost_revenue/static/src/js/account_spread.js index c3fdde5b..70fb91d9 100644 --- a/account_spread_cost_revenue/static/src/js/account_spread.js +++ b/account_spread_cost_revenue/static/src/js/account_spread.js @@ -11,7 +11,7 @@ odoo.define("account_spread_cost_revenue.widget", function(require) { events: _.extend({}, AbstractField.prototype.events, { click: "_onClick", }), - description: "", + noLabel: true, /** * @override diff --git a/account_spread_cost_revenue/tests/test_account_invoice_auto_spread.py b/account_spread_cost_revenue/tests/test_account_invoice_auto_spread.py index e5a5f8f1..4526f79c 100644 --- a/account_spread_cost_revenue/tests/test_account_invoice_auto_spread.py +++ b/account_spread_cost_revenue/tests/test_account_invoice_auto_spread.py @@ -2,110 +2,13 @@ # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). from odoo.exceptions import UserError -from odoo.modules.module import get_resource_path -from odoo.tests import common -from odoo.tools import convert_file + +from odoo.addons.account_spread_cost_revenue.tests.test_account_invoice_spread import ( + TestAccountInvoiceSpread, +) -class TestAccountInvoiceSpread(common.TransactionCase): - def _load(self, module, *args): - convert_file( - self.cr, - "account_spread_cost_revenue", - get_resource_path(module, *args), - {}, - "init", - False, - "test", - self.registry._assertion_report, - ) - - def setUp(self): - super().setUp() - self._load("account", "test", "account_minimal_test.xml") - - type_receivable = self.env.ref("account.data_account_type_receivable") - type_payable = self.env.ref("account.data_account_type_payable") - type_revenue = self.env.ref("account.data_account_type_revenue") - - self.invoice_account = self.env["account.account"].create( - { - "name": "test_account_receivable", - "code": "123", - "user_type_id": type_receivable.id, - "reconcile": True, - } - ) - - self.account_payable = self.env["account.account"].create( - { - "name": "test_account_payable", - "code": "321", - "user_type_id": type_payable.id, - "reconcile": True, - } - ) - - self.account_revenue = self.env["account.account"].create( - { - "name": "test_account_revenue", - "code": "864", - "user_type_id": type_revenue.id, - "reconcile": True, - } - ) - - self.invoice_line_account = self.account_payable - - self.spread_account = self.env["account.account"].create( - { - "name": "test spread account_payable", - "code": "765", - "user_type_id": type_payable.id, - "reconcile": True, - } - ) - - partner = self.env["res.partner"].create( - {"name": "Partner Name", "supplier": True,} - ) - - # Purchase Invoice - self.invoice = self.env["account.invoice"].create( - { - "partner_id": partner.id, - "account_id": self.invoice_account.id, - "type": "in_invoice", - } - ) - self.invoice_line = self.env["account.invoice.line"].create( - { - "quantity": 1.0, - "price_unit": 1000.0, - "invoice_id": self.invoice.id, - "name": "product that cost 1000", - "account_id": self.invoice_account.id, - } - ) - - # Sales Invoice - self.invoice_2 = self.env["account.invoice"].create( - { - "partner_id": partner.id, - "account_id": self.invoice_account.id, - "type": "out_invoice", - } - ) - self.invoice_line_2 = self.env["account.invoice.line"].create( - { - "quantity": 1.0, - "price_unit": 1000.0, - "invoice_id": self.invoice_2.id, - "name": "product that cost 1000", - "account_id": self.invoice_line_account.id, - } - ) - +class TestAccountInvoiceAutoSpread(TestAccountInvoiceSpread): def test_01_no_auto_spread_sheet(self): self.env["account.spread.template"].create( @@ -119,13 +22,15 @@ class TestAccountInvoiceSpread(common.TransactionCase): "account_spread_cost_revenue.expenses_journal" ), "auto_spread": False, # Auto Spread = False - "auto_spread_ids": [(0, 0, {"account_id": self.invoice_account.id})], + "auto_spread_ids": [ + (0, 0, {"account_id": self.vendor_bill_line.account_id.id}) + ], } ) - self.assertFalse(self.invoice_line.spread_id) - self.invoice.action_invoice_open() - self.assertFalse(self.invoice_line.spread_id) + self.assertFalse(self.vendor_bill_line.spread_id) + self.vendor_bill.action_post() + self.assertFalse(self.vendor_bill_line.spread_id) def test_02_new_auto_spread_sheet_purchase(self): @@ -140,7 +45,9 @@ class TestAccountInvoiceSpread(common.TransactionCase): "account_spread_cost_revenue.expenses_journal" ), "auto_spread": True, # Auto Spread - "auto_spread_ids": [(0, 0, {"account_id": self.invoice_account.id})], + "auto_spread_ids": [ + (0, 0, {"account_id": self.vendor_bill_line.account_id.id}) + ], } ) template2 = self.env["account.spread.template"].create( @@ -154,20 +61,22 @@ class TestAccountInvoiceSpread(common.TransactionCase): "account_spread_cost_revenue.expenses_journal" ), "auto_spread": True, # Auto Spread - "auto_spread_ids": [(0, 0, {"account_id": self.invoice_account.id})], + "auto_spread_ids": [ + (0, 0, {"account_id": self.vendor_bill_line.account_id.id}) + ], } ) template2._check_auto_spread_ids_unique() - self.assertFalse(self.invoice_line.spread_id) + self.assertFalse(self.vendor_bill_line.spread_id) with self.assertRaises(UserError): # too many auto_spread_ids matched - self.invoice.action_invoice_open() + self.vendor_bill.action_post() template2.auto_spread = False # Do not use this template - self.invoice.action_invoice_open() - self.assertTrue(self.invoice_line.spread_id) + self.vendor_bill.action_post() + self.assertTrue(self.vendor_bill_line.spread_id) - spread_lines = self.invoice_line.spread_id.line_ids + spread_lines = self.vendor_bill_line.spread_id.line_ids self.assertTrue(spread_lines) for line in spread_lines: @@ -182,22 +91,22 @@ class TestAccountInvoiceSpread(common.TransactionCase): "spread_type": "sale", "period_number": 5, "period_type": "month", - "spread_account_id": self.account_revenue.id, + "spread_account_id": self.account_receivable.id, "spread_journal_id": self.ref( "account_spread_cost_revenue.sales_journal" ), "auto_spread": True, # Auto Spread "auto_spread_ids": [ - (0, 0, {"account_id": self.invoice_line_account.id}) + (0, 0, {"account_id": self.invoice_line.account_id.id}) ], } ) - self.assertFalse(self.invoice_line_2.spread_id) - self.invoice_2.action_invoice_open() - self.assertTrue(self.invoice_line_2.spread_id) + self.assertFalse(self.invoice_line.spread_id) + self.sale_invoice.action_post() + self.assertTrue(self.invoice_line.spread_id) - spread_lines = self.invoice_line_2.spread_id.line_ids + spread_lines = self.invoice_line.spread_id.line_ids self.assertTrue(spread_lines) for line in spread_lines: diff --git a/account_spread_cost_revenue/tests/test_account_invoice_spread.py b/account_spread_cost_revenue/tests/test_account_invoice_spread.py index ea601559..fd6442c1 100644 --- a/account_spread_cost_revenue/tests/test_account_invoice_spread.py +++ b/account_spread_cost_revenue/tests/test_account_invoice_spread.py @@ -1,11 +1,12 @@ -# Copyright 2018-2019 Onestein () +# Copyright 2018-2020 Onestein () # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). import datetime +from odoo import fields from odoo.exceptions import UserError, ValidationError from odoo.modules.module import get_resource_path -from odoo.tests import common +from odoo.tests import Form, common from odoo.tools import convert_file @@ -22,75 +23,83 @@ class TestAccountInvoiceSpread(common.TransactionCase): self.registry._assertion_report, ) + def create_account_invoice(self, invoice_type, quantity=1.0, price_unit=1000.0): + """ Create an invoice as in a view by triggering its onchange methods""" + + invoice_form = Form( + self.env["account.move"].with_context(default_type=invoice_type) + ) + invoice_form.partner_id = self.env["res.partner"].create( + {"name": "Partner Name"} + ) + with invoice_form.invoice_line_ids.new() as line: + line.name = "product that costs " + str(price_unit) + line.quantity = quantity + line.price_unit = price_unit + + return invoice_form.save() + def setUp(self): super().setUp() self._load("account", "test", "account_minimal_test.xml") - type_receivable = self.env.ref("account.data_account_type_receivable") - type_payable = self.env.ref("account.data_account_type_payable") - type_revenue = self.env.ref("account.data_account_type_revenue") - - self.invoice_account = self.env["account.account"].create( - { - "name": "test_account_receivable", - "code": "123", - "user_type_id": type_receivable.id, - "reconcile": True, - } - ) - self.account_payable = self.env["account.account"].create( { - "name": "test_account_payable", - "code": "321", - "user_type_id": type_payable.id, + "name": "Test account payable", + "code": "321spread", + "user_type_id": self.env.ref( + "account.data_account_type_other_income" + ).id, "reconcile": True, } ) - self.account_revenue = self.env["account.account"].create( + self.account_receivable = self.env["account.account"].create( { - "name": "test_account_revenue", - "code": "864", - "user_type_id": type_revenue.id, + "name": "Test account receivable", + "code": "322spread", + "user_type_id": self.env.ref( + "account.data_account_type_other_income" + ).id, "reconcile": True, } ) - self.invoice_line_account = self.account_payable - - self.spread_account = self.env["account.account"].create( + spread_account_payable = self.env["account.account"].create( { "name": "test spread account_payable", - "code": "765", - "user_type_id": type_payable.id, + "code": "765spread", + "user_type_id": self.env.ref( + "account.data_account_type_other_income" + ).id, "reconcile": True, } ) - partner = self.env["res.partner"].create( - {"name": "Partner Name", "supplier": True,} - ) - self.invoice = self.env["account.invoice"].create( + spread_account_receivable = self.env["account.account"].create( { - "partner_id": partner.id, - "account_id": self.invoice_account.id, - "type": "in_invoice", - } - ) - self.invoice_line = self.env["account.invoice.line"].create( - { - "quantity": 1.0, - "price_unit": 1000.0, - "invoice_id": self.invoice.id, - "name": "product that cost 1000", - "account_id": self.invoice_account.id, + "name": "test spread account_receivable", + "code": "766spread", + "user_type_id": self.env.ref( + "account.data_account_type_other_income" + ).id, + "reconcile": True, } ) + # Invoices + self.vendor_bill = self.create_account_invoice("in_invoice") + self.sale_invoice = self.create_account_invoice("out_invoice") + self.vendor_bill_line = self.vendor_bill.invoice_line_ids[0] + self.invoice_line = self.sale_invoice.invoice_line_ids[0] + + # Set accounts to reconcilable + self.vendor_bill_line.account_id.reconcile = True + self.invoice_line.account_id.reconcile = True + analytic_tags = [(6, 0, self.env.ref("analytic.tag_contract").ids)] self.analytic_account = self.env["account.analytic.account"].create( - {"name": "test account",} + {"name": "test account"} ) self.spread = ( self.env["account.spread"] @@ -99,13 +108,13 @@ class TestAccountInvoiceSpread(common.TransactionCase): [ { "name": "test", - "debit_account_id": self.spread_account.id, - "credit_account_id": self.invoice_line_account.id, + "debit_account_id": spread_account_payable.id, + "credit_account_id": self.account_payable.id, "period_number": 12, "period_type": "month", "spread_date": datetime.date(2017, 2, 1), "estimated_amount": 1000.0, - "journal_id": self.invoice.journal_id.id, + "journal_id": self.vendor_bill.journal_id.id, "invoice_type": "in_invoice", "account_analytic_id": self.analytic_account.id, "analytic_tag_ids": analytic_tags, @@ -114,149 +123,124 @@ class TestAccountInvoiceSpread(common.TransactionCase): ) ) - self.invoice_2 = self.env["account.invoice"].create( - { - "partner_id": partner.id, - "account_id": self.invoice_account.id, - "type": "out_invoice", - } - ) - self.invoice_line_2 = self.env["account.invoice.line"].create( - { - "quantity": 1.0, - "price_unit": 1000.0, - "invoice_id": self.invoice_2.id, - "name": "product that cost 1000", - "account_id": self.invoice_line_account.id, - } - ) self.spread2 = self.env["account.spread"].create( [ { "name": "test2", - "debit_account_id": self.spread_account.id, - "credit_account_id": self.invoice_line_account.id, + "debit_account_id": spread_account_receivable.id, + "credit_account_id": self.account_receivable.id, "period_number": 12, "period_type": "month", "spread_date": datetime.date(2017, 2, 1), "estimated_amount": 1000.0, - "journal_id": self.invoice_2.journal_id.id, + "journal_id": self.sale_invoice.journal_id.id, "invoice_type": "out_invoice", } ] ) def test_01_wizard_defaults(self): - my_company = self.env.user.company_id Wizard = self.env["account.spread.invoice.line.link.wizard"] + wizard1 = Wizard.with_context( - default_invoice_line_id=self.invoice_line.id, - default_company_id=my_company.id, + default_invoice_line_id=self.vendor_bill_line.id, + default_company_id=self.env.company.id, allow_spread_planning=True, ).create({}) - self.assertEqual(wizard1.invoice_line_id, self.invoice_line) - self.assertEqual(wizard1.invoice_line_id.invoice_id, self.invoice) + self.assertEqual(wizard1.invoice_line_id, self.vendor_bill_line) + self.assertEqual(wizard1.invoice_line_id.move_id, self.vendor_bill) self.assertEqual(wizard1.invoice_type, "in_invoice") self.assertFalse(wizard1.spread_id) - self.assertEqual(wizard1.company_id, my_company) + self.assertEqual(wizard1.company_id, self.env.company) self.assertEqual(wizard1.spread_action_type, "link") self.assertFalse(wizard1.spread_account_id) self.assertFalse(wizard1.spread_journal_id) wizard2 = Wizard.with_context( - default_invoice_line_id=self.invoice_line_2.id, - default_company_id=my_company.id, + default_invoice_line_id=self.invoice_line.id, + default_company_id=self.env.company.id, ).create({}) - self.assertEqual(wizard2.invoice_line_id, self.invoice_line_2) - self.assertEqual(wizard2.invoice_line_id.invoice_id, self.invoice_2) + self.assertEqual(wizard2.invoice_line_id, self.invoice_line) + self.assertEqual(wizard2.invoice_line_id.move_id, self.sale_invoice) self.assertEqual(wizard2.invoice_type, "out_invoice") self.assertFalse(wizard2.spread_id) - self.assertEqual(wizard2.company_id, my_company) + self.assertEqual(wizard2.company_id, self.env.company) self.assertEqual(wizard2.spread_action_type, "template") self.assertFalse(wizard2.spread_account_id) self.assertFalse(wizard2.spread_journal_id) def test_02_wizard_defaults(self): - my_company = self.env.user.company_id Wizard = self.env["account.spread.invoice.line.link.wizard"] - account_revenue = self.account_revenue - account_payable = self.account_payable exp_journal = self.ref("account_spread_cost_revenue.expenses_journal") sales_journal = self.ref("account_spread_cost_revenue.sales_journal") - my_company.default_spread_revenue_account_id = account_revenue - my_company.default_spread_expense_account_id = account_payable - my_company.default_spread_revenue_journal_id = sales_journal - my_company.default_spread_expense_journal_id = exp_journal + self.env.company.default_spread_revenue_account_id = self.account_receivable + self.env.company.default_spread_expense_account_id = self.account_payable + self.env.company.default_spread_revenue_journal_id = sales_journal + self.env.company.default_spread_expense_journal_id = exp_journal - self.assertTrue(my_company.default_spread_revenue_account_id) - self.assertTrue(my_company.default_spread_expense_account_id) - self.assertTrue(my_company.default_spread_revenue_journal_id) - self.assertTrue(my_company.default_spread_expense_journal_id) + self.assertTrue(self.env.company.default_spread_revenue_account_id) + self.assertTrue(self.env.company.default_spread_expense_account_id) + self.assertTrue(self.env.company.default_spread_revenue_journal_id) + self.assertTrue(self.env.company.default_spread_expense_journal_id) wizard1 = Wizard.with_context( - default_invoice_line_id=self.invoice_line.id, - default_company_id=my_company.id, + default_invoice_line_id=self.vendor_bill_line.id, + default_company_id=self.env.company.id, allow_spread_planning=True, ).create({}) - self.assertEqual(wizard1.invoice_line_id, self.invoice_line) - self.assertEqual(wizard1.invoice_line_id.invoice_id, self.invoice) + self.assertEqual(wizard1.invoice_line_id, self.vendor_bill_line) + self.assertEqual(wizard1.invoice_line_id.move_id, self.vendor_bill) self.assertEqual(wizard1.invoice_type, "in_invoice") self.assertFalse(wizard1.spread_id) - self.assertEqual(wizard1.company_id, my_company) + self.assertEqual(wizard1.company_id, self.env.company) self.assertEqual(wizard1.spread_action_type, "link") - self.assertFalse(wizard1.spread_account_id) - self.assertFalse(wizard1.spread_journal_id) - - res_onchange = wizard1.onchange_invoice_type() - self.assertTrue(res_onchange) - self.assertTrue(res_onchange.get("domain")) - - wizard1._onchange_spread_journal_account() self.assertTrue(wizard1.spread_account_id) self.assertTrue(wizard1.spread_journal_id) - self.assertEqual(wizard1.spread_account_id, account_payable) + self.assertEqual(wizard1.spread_account_id, self.account_payable) self.assertEqual(wizard1.spread_journal_id.id, exp_journal) + self.assertTrue(wizard1.spread_invoice_type_domain_ids) wizard2 = Wizard.with_context( - default_invoice_line_id=self.invoice_line_2.id, - default_company_id=my_company.id, + default_invoice_line_id=self.invoice_line.id, + default_company_id=self.env.company.id, ).create({}) - self.assertEqual(wizard2.invoice_line_id, self.invoice_line_2) - self.assertEqual(wizard2.invoice_line_id.invoice_id, self.invoice_2) + self.assertEqual(wizard2.invoice_line_id, self.invoice_line) + self.assertEqual(wizard2.invoice_line_id.move_id, self.sale_invoice) self.assertEqual(wizard2.invoice_type, "out_invoice") self.assertFalse(wizard2.spread_id) - self.assertEqual(wizard2.company_id, my_company) + self.assertEqual(wizard2.company_id, self.env.company) self.assertEqual(wizard2.spread_action_type, "template") - self.assertFalse(wizard2.spread_account_id) - self.assertFalse(wizard2.spread_journal_id) - - res_onchange = wizard2.onchange_invoice_type() - self.assertTrue(res_onchange) - self.assertTrue(res_onchange.get("domain")) - - wizard2._onchange_spread_journal_account() self.assertTrue(wizard2.spread_account_id) self.assertTrue(wizard2.spread_journal_id) - self.assertEqual(wizard2.spread_account_id, account_revenue) + self.assertEqual(wizard2.spread_account_id, self.account_receivable) self.assertEqual(wizard2.spread_journal_id.id, sales_journal) + self.assertTrue(wizard2.spread_invoice_type_domain_ids) def test_03_link_invoice_line_with_spread_sheet(self): - my_company = self.env.user.company_id + self.env.user.write( + { + "groups_id": [ + (4, self.env.ref("analytic.group_analytic_accounting").id), + (4, self.env.ref("analytic.group_analytic_tags").id), + ], + } + ) + Wizard = self.env["account.spread.invoice.line.link.wizard"] wizard1 = Wizard.with_context( - default_invoice_line_id=self.invoice_line.id, - default_company_id=my_company.id, + default_invoice_line_id=self.vendor_bill_line.id, + default_company_id=self.env.company.id, allow_spread_planning=True, ).create({}) self.assertEqual(wizard1.spread_action_type, "link") - wizard1.spread_account_id = self.account_revenue + wizard1.spread_account_id = self.account_receivable wizard1.spread_journal_id = self.ref( "account_spread_cost_revenue.expenses_journal" ) @@ -266,27 +250,21 @@ class TestAccountInvoiceSpread(common.TransactionCase): self.assertTrue(res_action.get("res_id")) self.assertEqual(res_action.get("res_id"), self.spread.id) self.assertTrue(self.spread.invoice_line_id) - self.assertEqual(self.spread.invoice_line_id, self.invoice_line) + self.assertEqual(self.spread.invoice_line_id, self.vendor_bill_line) - spread_lines = self.spread.line_ids - for line in spread_lines: - self.assertFalse(line.move_id) - - self.invoice.journal_id.update_posted = True + self.assertFalse(any(line.move_id for line in self.spread.line_ids)) self.spread.compute_spread_board() spread_lines = self.spread.line_ids for line in spread_lines: line.create_move() self.assertTrue(line.move_id) - self.assertTrue(line.move_id.journal_id.update_posted) for ml in line.move_id.line_ids: - ml_analytic_account = ml.analytic_account_id analytic_tag = self.env.ref("analytic.tag_contract") - self.assertEqual(ml_analytic_account, self.analytic_account) + self.assertEqual(ml.analytic_account_id, self.analytic_account) self.assertEqual(ml.analytic_tag_ids, analytic_tag) - self.spread.invoice_id.action_cancel() + self.spread.invoice_id.button_cancel() self.assertTrue(self.spread.invoice_line_id) with self.assertRaises(UserError): @@ -297,21 +275,19 @@ class TestAccountInvoiceSpread(common.TransactionCase): def test_04_new_spread_sheet(self): - my_company = self.env.user.company_id Wizard = self.env["account.spread.invoice.line.link.wizard"] - spread_account = self.account_revenue spread_journal_id = self.ref("account_spread_cost_revenue.expenses_journal") wizard1 = Wizard.with_context( - default_invoice_line_id=self.invoice_line.id, - default_company_id=my_company.id, - ).create({"spread_action_type": "new",}) + default_invoice_line_id=self.vendor_bill_line.id, + default_company_id=self.env.company.id, + ).create({"spread_action_type": "new"}) self.assertEqual(wizard1.spread_action_type, "new") wizard1.write( { - "spread_account_id": spread_account.id, + "spread_account_id": self.account_receivable.id, "spread_journal_id": spread_journal_id, } ) @@ -327,9 +303,7 @@ class TestAccountInvoiceSpread(common.TransactionCase): self.assertTrue(res_context.get("default_debit_account_id")) self.assertTrue(res_context.get("default_credit_account_id")) - spread_lines = self.spread.line_ids - for line in spread_lines: - self.assertFalse(line.move_id) + self.assertFalse(any(line.move_id for line in self.spread.line_ids)) self.spread.compute_spread_board() spread_lines = self.spread.line_ids @@ -338,14 +312,14 @@ class TestAccountInvoiceSpread(common.TransactionCase): self.assertTrue(line.move_id) wizard2 = Wizard.with_context( - default_invoice_line_id=self.invoice_line_2.id, - default_company_id=my_company.id, - ).create({"spread_action_type": "new",}) + default_invoice_line_id=self.invoice_line.id, + default_company_id=self.env.company.id, + ).create({"spread_action_type": "new"}) self.assertEqual(wizard2.spread_action_type, "new") wizard2.write( { - "spread_account_id": spread_account.id, + "spread_account_id": self.account_receivable.id, "spread_journal_id": spread_journal_id, } ) @@ -361,18 +335,15 @@ class TestAccountInvoiceSpread(common.TransactionCase): self.assertTrue(res_context.get("default_debit_account_id")) self.assertTrue(res_context.get("default_credit_account_id")) - spread_lines = self.spread2.line_ids - for line in spread_lines: - self.assertFalse(line.move_id) + self.assertFalse(any(line.move_id for line in self.spread2.line_ids)) self.spread2.compute_spread_board() - for line in spread_lines: + for line in self.spread2.line_ids: line.create_move() self.assertTrue(line.move_id) def test_05_new_spread_sheet_from_template(self): - my_company = self.env.user.company_id Wizard = self.env["account.spread.invoice.line.link.wizard"] spread_account = self.account_payable @@ -391,29 +362,28 @@ class TestAccountInvoiceSpread(common.TransactionCase): ) wizard1 = Wizard.with_context( - default_invoice_line_id=self.invoice_line.id, - default_company_id=my_company.id, - ).create({"spread_action_type": "template", "template_id": template.id,}) + default_invoice_line_id=self.vendor_bill_line.id, + default_company_id=self.env.company.id, + ).create({"spread_action_type": "template", "template_id": template.id}) self.assertEqual(wizard1.spread_action_type, "template") res_action = wizard1.confirm() self.assertTrue(isinstance(res_action, dict)) self.assertTrue(res_action.get("res_id")) - spread_lines = self.spread.line_ids - for line in spread_lines: - self.assertFalse(line.move_id) + new_spread = self.env["account.spread"].browse(res_action["res_id"]) + new_spread.compute_spread_board() - self.spread.compute_spread_board() - spread_lines = self.spread.line_ids - for line in spread_lines: + self.assertFalse(any(line.move_id for line in new_spread.line_ids)) + + for line in new_spread.line_ids: line.create_move() self.assertTrue(line.move_id) wizard2 = Wizard.with_context( - default_invoice_line_id=self.invoice_line_2.id, - default_company_id=my_company.id, - ).create({"spread_action_type": "new",}) + default_invoice_line_id=self.invoice_line.id, + default_company_id=self.env.company.id, + ).create({"spread_action_type": "new"}) self.assertEqual(wizard2.spread_action_type, "new") wizard2.write( @@ -434,18 +404,16 @@ class TestAccountInvoiceSpread(common.TransactionCase): self.assertTrue(res_context.get("default_debit_account_id")) self.assertTrue(res_context.get("default_credit_account_id")) - spread_lines = self.spread2.line_ids - for line in spread_lines: - self.assertFalse(line.move_id) + self.assertFalse(any(line.move_id for line in self.spread2.line_ids)) self.spread2.compute_spread_board() - for line in spread_lines: + for line in self.spread2.line_ids: line.create_move() self.assertTrue(line.move_id) def test_06_open_wizard(self): - res_action = self.invoice_line.spread_details() + res_action = self.vendor_bill_line.spread_details() self.assertTrue(isinstance(res_action, dict)) self.assertFalse(res_action.get("res_id")) self.assertTrue(res_action.get("context")) @@ -453,28 +421,38 @@ class TestAccountInvoiceSpread(common.TransactionCase): def test_07_unlink_invoice_line_and_spread_sheet(self): self.assertFalse(self.spread.invoice_line_id) - self.invoice_line.spread_id = self.spread + + self.vendor_bill_line.spread_id = self.spread self.assertTrue(self.spread.invoice_line_id) self.spread.action_unlink_invoice_line() self.assertFalse(self.spread.invoice_line_id) self.assertFalse(self.spread2.invoice_line_id) - self.invoice_line_2.spread_id = self.spread2 + self.invoice_line.spread_id = self.spread2 self.assertTrue(self.spread2.invoice_line_id) self.spread2.action_unlink_invoice_line() self.assertFalse(self.spread2.invoice_line_id) def test_08_invoice_multi_line(self): - self.invoice_line.copy() - self.assertEqual(len(self.invoice.invoice_line_ids), 2) + invoice_form = Form(self.vendor_bill) + with invoice_form.invoice_line_ids.new() as line: + line.name = "new test line" + line.quantity = 1.0 + line.price_unit = 1000.0 + self.invoice = invoice_form.save() + self.assertEqual(len(self.vendor_bill.invoice_line_ids), 2) - self.invoice.invoice_line_ids[0].spread_id = self.spread - self.assertTrue(self.spread.invoice_line_id) - self.assertEqual(self.spread.invoice_line_id, self.invoice_line) + self.vendor_bill_line.spread_id = self.spread + self.assertTrue(self.spread.invoice_id.invoice_line_ids[0]) + self.assertEqual( + self.spread.invoice_id.invoice_line_ids[0], self.vendor_bill_line + ) + self.assertTrue(self.vendor_bill_line.spread_id) + self.assertEqual(self.vendor_bill_line.spread_check, "linked") + self.assertFalse(self.vendor_bill.invoice_line_ids[1].spread_id) + self.assertEqual(self.vendor_bill.invoice_line_ids[1].spread_check, "unlinked") - spread_lines = self.spread.line_ids - for line in spread_lines: - self.assertFalse(line.move_id) + self.assertFalse(any(line.move_id for line in self.spread.line_ids)) self.spread.compute_spread_board() spread_lines = self.spread.line_ids @@ -483,39 +461,47 @@ class TestAccountInvoiceSpread(common.TransactionCase): self.assertTrue(line.move_id) # Validate invoice - self.invoice.action_invoice_open() + self.vendor_bill.action_post() + + self.assertTrue(self.vendor_bill_line.spread_id) + self.assertEqual(self.vendor_bill_line.spread_check, "linked") + self.assertFalse(self.vendor_bill.invoice_line_ids[1].spread_id) + self.assertEqual( + self.vendor_bill.invoice_line_ids[1].spread_check, "unavailable" + ) def test_09_no_link_invoice(self): balance_sheet = self.spread.credit_account_id # Validate invoice - self.invoice.action_invoice_open() + self.vendor_bill.action_post() - invoice_mls = self.invoice.move_id.mapped("line_ids") + invoice_mls = self.vendor_bill.invoice_line_ids self.assertTrue(invoice_mls) for invoice_ml in invoice_mls: - if invoice_ml.debit: - self.assertNotEqual(invoice_ml.account_id, balance_sheet) + self.assertNotEqual(invoice_ml.account_id, balance_sheet) def test_10_link_vendor_bill_line_with_spread_sheet(self): + invoice_form = Form(self.vendor_bill) + with invoice_form.invoice_line_ids.new() as line: + line.name = "new test line" + line.quantity = 1.0 + line.price_unit = 1000.0 + self.invoice = invoice_form.save() - copied_line = self.invoice_line.copy() - copied_line.name = "new test line" self.spread.write( { "estimated_amount": 1000.0, "period_number": 12, "period_type": "month", "spread_date": datetime.date(2017, 1, 7), - "invoice_line_id": self.invoice_line.id, + "invoice_line_id": self.vendor_bill_line.id, "move_line_auto_post": False, } ) - spread_lines = self.spread.line_ids - for line in spread_lines: - self.assertFalse(line.move_id) + self.assertFalse(any(line.move_id for line in self.spread.line_ids)) self.spread.compute_spread_board() spread_lines = self.spread.line_ids @@ -536,13 +522,10 @@ class TestAccountInvoiceSpread(common.TransactionCase): self.assertEqual(spread_ml.account_id, balance_sheet) # Validate invoice - self.invoice.action_invoice_open() - - invoice_mls = self.invoice.move_id.mapped("line_ids") - self.assertTrue(invoice_mls) + self.vendor_bill.action_post() count_balance_sheet = len( - invoice_mls.filtered(lambda x: x.account_id == balance_sheet) + self.vendor_bill.line_ids.filtered(lambda x: x.account_id == balance_sheet) ) self.assertEqual(count_balance_sheet, 1) @@ -562,21 +545,24 @@ class TestAccountInvoiceSpread(common.TransactionCase): self.assertTrue(action_reconcile_view.get("context")) def test_11_link_vendor_bill_line_with_spread_sheet(self): - self.invoice_line.copy() + invoice_form = Form(self.vendor_bill) + with invoice_form.invoice_line_ids.new() as line: + line.name = "new test line" + line.quantity = 1.0 + line.price_unit = 1000.0 + self.invoice = invoice_form.save() self.spread.write( { "estimated_amount": 1000.0, "period_number": 12, "period_type": "month", "spread_date": datetime.date(2017, 1, 7), - "invoice_line_id": self.invoice_line.id, + "invoice_line_id": self.vendor_bill_line.id, "move_line_auto_post": False, } ) - spread_lines = self.spread.line_ids - for line in spread_lines: - self.assertFalse(line.move_id) + self.assertFalse(any(line.move_id for line in self.spread.line_ids)) self.spread.compute_spread_board() spread_lines = self.spread.line_ids @@ -597,9 +583,9 @@ class TestAccountInvoiceSpread(common.TransactionCase): self.assertEqual(spread_ml.account_id, balance_sheet) # Validate invoice - self.invoice.action_invoice_open() + self.vendor_bill.action_post() - invoice_mls = self.invoice.move_id.mapped("line_ids") + invoice_mls = self.vendor_bill.line_ids self.assertTrue(invoice_mls) count_balance_sheet = len( @@ -613,33 +599,39 @@ class TestAccountInvoiceSpread(common.TransactionCase): spread_mls = self.spread.line_ids.mapped("move_id.line_ids") self.assertTrue(spread_mls) for spread_ml in spread_mls: - self.assertFalse(spread_ml.full_reconcile_id) + if spread_ml.credit: + self.assertEqual(spread_ml.account_id, balance_sheet) + self.assertTrue(spread_ml.full_reconcile_id) + if spread_ml.debit: + self.assertEqual(spread_ml.account_id, expense_account) + self.assertFalse(spread_ml.full_reconcile_id) action_reconcile_view = self.spread.open_reconcile_view() self.assertTrue(isinstance(action_reconcile_view, dict)) self.assertTrue(action_reconcile_view.get("domain")[0][2]) self.assertTrue(action_reconcile_view.get("context")) - action_spread_details = self.invoice_line.spread_details() + action_spread_details = self.vendor_bill_line.spread_details() self.assertTrue(isinstance(action_spread_details, dict)) self.assertTrue(action_spread_details.get("res_id")) def test_12_link_invoice_line_with_spread_sheet_full_reconcile(self): + # Validate invoice + self.sale_invoice.action_post() + self.spread2.write( { "estimated_amount": 1000.0, "period_number": 12, "period_type": "month", "spread_date": datetime.date(2017, 1, 7), - "invoice_line_id": self.invoice_line_2.id, + "invoice_line_id": self.invoice_line.id, "move_line_auto_post": False, } ) - spread_lines = self.spread2.line_ids - for line in spread_lines: - self.assertFalse(line.move_id) + self.assertFalse(any(line.move_id for line in self.spread2.line_ids)) self.spread2.compute_spread_board() spread_lines = self.spread2.line_ids @@ -647,8 +639,8 @@ class TestAccountInvoiceSpread(common.TransactionCase): line.create_move() self.assertTrue(line.move_id) - payable_account = self.spread.credit_account_id - balance_sheet = self.spread.debit_account_id + payable_account = self.spread2.credit_account_id + balance_sheet = self.spread2.debit_account_id self.assertTrue(balance_sheet.reconcile) spread_mls = self.spread2.line_ids.mapped("move_id.line_ids") @@ -656,35 +648,25 @@ class TestAccountInvoiceSpread(common.TransactionCase): for spread_ml in spread_mls: if spread_ml.debit: self.assertEqual(spread_ml.account_id, balance_sheet) - if spread_ml.credit: - self.assertEqual(spread_ml.account_id, payable_account) - - # Validate invoice - self.invoice_2.action_invoice_open() - - invoice_mls = self.invoice_2.move_id.mapped("line_ids") - self.assertTrue(invoice_mls) - for invoice_ml in invoice_mls: - if invoice_ml.credit: - self.assertEqual(invoice_ml.account_id, balance_sheet) - - self.spread2.line_ids.create_and_reconcile_moves() - - spread_mls = self.spread2.line_ids.mapped("move_id.line_ids") - self.assertTrue(spread_mls) - for spread_ml in spread_mls: - if spread_ml.debit: + self.assertTrue(spread_ml.reconciled) self.assertTrue(spread_ml.full_reconcile_id) if spread_ml.credit: + self.assertEqual(spread_ml.account_id, payable_account) + self.assertFalse(spread_ml.reconciled) self.assertFalse(spread_ml.full_reconcile_id) + invoice_mls = self.sale_invoice.invoice_line_ids + self.assertTrue(invoice_mls) + for invoice_ml in invoice_mls: + self.assertEqual(invoice_ml.account_id, balance_sheet) + action_reconcile_view = self.spread2.open_reconcile_view() self.assertTrue(isinstance(action_reconcile_view, dict)) self.assertTrue(action_reconcile_view.get("domain")[0][2]) self.assertFalse(action_reconcile_view.get("res_id")) self.assertTrue(action_reconcile_view.get("context")) - action_spread_details = self.invoice_line_2.spread_details() + action_spread_details = self.invoice_line.spread_details() self.assertTrue(isinstance(action_spread_details, dict)) self.assertTrue(action_spread_details.get("res_id")) @@ -702,19 +684,18 @@ class TestAccountInvoiceSpread(common.TransactionCase): self.spread2.compute_spread_board() spread_lines = self.spread2.line_ids self.assertEqual(len(spread_lines), 13) + self.assertFalse(any(line.move_id for line in spread_lines)) - for line in spread_lines: - self.assertFalse(line.move_id) - - spread_lines[0]._create_moves().post() - spread_lines[1]._create_moves().post() - spread_lines[2]._create_moves().post() - spread_lines[3]._create_moves().post() + spread_lines[0].create_and_reconcile_moves() + spread_lines[1].create_and_reconcile_moves() + spread_lines[2].create_and_reconcile_moves() + spread_lines[3].create_and_reconcile_moves() self.assertEqual(spread_lines[0].move_id.state, "posted") self.assertEqual(spread_lines[1].move_id.state, "posted") self.assertEqual(spread_lines[2].move_id.state, "posted") self.assertEqual(spread_lines[3].move_id.state, "posted") + self.assertNotEqual(spread_lines[4].move_id.state, "posted") spread_mls = spread_lines[0].move_id.line_ids self.assertTrue(spread_mls) @@ -728,23 +709,26 @@ class TestAccountInvoiceSpread(common.TransactionCase): self.assertFalse(spread_ml.matched_credit_ids) self.assertFalse(spread_ml.full_reconcile_id) - balance_sheet = self.spread.debit_account_id + balance_sheet = self.spread2.debit_account_id self.assertTrue(balance_sheet.reconcile) - self.spread2.write( - {"invoice_line_id": self.invoice_line_2.id,} - ) + # Assing invoice line to spread + self.spread2.invoice_line_id = self.invoice_line + self.assertEqual(self.invoice_line.spread_id, self.spread2) # Validate invoice - self.invoice_2.action_invoice_open() - - invoice_mls = self.invoice_2.move_id.mapped("line_ids") + self.sale_invoice.action_post() + invoice_mls = self.sale_invoice.invoice_line_ids self.assertTrue(invoice_mls) for invoice_ml in invoice_mls: - if invoice_ml.credit: - self.assertEqual(invoice_ml.account_id, balance_sheet) + self.assertEqual(invoice_ml.account_id, balance_sheet) - spread_mls = spread_lines[0].move_id.line_ids + spread_lines = self.spread2.line_ids + spread_lines[4].create_and_reconcile_moves() + + self.assertEqual(spread_lines[4].move_id.state, "posted") + + spread_mls = spread_lines[4].move_id.line_ids self.assertTrue(spread_mls) for spread_ml in spread_mls: if spread_ml.debit: @@ -767,39 +751,37 @@ class TestAccountInvoiceSpread(common.TransactionCase): def test_14_create_all_moves(self): self.spread.compute_spread_board() - spread_lines = self.spread.line_ids - self.assertEqual(len(spread_lines), 12) - for line in spread_lines: - self.assertFalse(line.move_id) + + self.assertEqual(len(self.spread.line_ids), 12) + self.assertFalse(any(line.move_id for line in self.spread.line_ids)) # create moves for all the spread lines self.spread.create_all_moves() - spread_lines = self.spread.line_ids - for line in spread_lines: - self.assertTrue(line.move_id) + self.assertTrue(all(line.move_id for line in self.spread.line_ids)) with self.assertRaises(ValidationError): self.spread.unlink() def test_15_invoice_refund(self): - self.invoice_line.spread_id = self.spread + self.vendor_bill_line.spread_id = self.spread # Validate invoice - self.invoice.action_invoice_open() - self.assertTrue(self.invoice.invoice_line_ids.mapped("spread_id")) + self.vendor_bill.action_post() + self.assertTrue(self.vendor_bill.invoice_line_ids.mapped("spread_id")) # Create a refund for invoice. - self.env["account.invoice.refund"].with_context( - { - "active_model": "account.invoice", - "active_ids": [self.invoice.id], - "active_id": self.invoice.id, - } - ).create( - dict(description="Invoice Refund", filter_refund="refund",) - ).invoice_refund() - - # Invoice lines do not contain the lint to the spread. - refund = self.invoice.refund_invoice_ids[0] + move_reversal = ( + self.env["account.move.reversal"] + .with_context(active_model="account.move", active_ids=self.vendor_bill.ids) + .create( + { + "date": fields.Date.today(), + "reason": "no reason", + "refund_method": "refund", + } + ) + ) + reversal = move_reversal.reverse_moves() + refund = self.env["account.move"].browse(reversal["res_id"]) self.assertFalse(refund.invoice_line_ids.mapped("spread_id")) diff --git a/account_spread_cost_revenue/tests/test_account_spread_cost_revenue.py b/account_spread_cost_revenue/tests/test_account_spread_cost_revenue.py index f2e4eb68..d2861efa 100644 --- a/account_spread_cost_revenue/tests/test_account_spread_cost_revenue.py +++ b/account_spread_cost_revenue/tests/test_account_spread_cost_revenue.py @@ -1,4 +1,4 @@ -# Copyright 2018-2019 Onestein () +# Copyright 2018-2020 Onestein () # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). import datetime @@ -6,34 +6,28 @@ import datetime from psycopg2 import IntegrityError from odoo.exceptions import ValidationError -from odoo.modules.module import get_resource_path -from odoo.tests import common -from odoo.tools import convert_file, mute_logger +from odoo.tests import Form, common +from odoo.tools import mute_logger class TestAccountSpreadCostRevenue(common.TransactionCase): - def _load(self, module, *args): - convert_file( - self.cr, - "account_spread_cost_revenue", - get_resource_path(module, *args), - {}, - "init", - False, - "test", - self.registry._assertion_report, - ) - def setUp(self): super().setUp() - self._load("account", "test", "account_minimal_test.xml") + + self.sales_journal = self.env["account.journal"].create( + {"name": "Customer Invoices - Test", "code": "TEST1", "type": "sale"} + ) + + self.expenses_journal = self.env["account.journal"].create( + {"name": "Vendor Bills - Test", "code": "TEST2", "type": "purchase"} + ) type_receivable = self.env.ref("account.data_account_type_receivable") type_expenses = self.env.ref("account.data_account_type_expenses") type_payable = self.env.ref("account.data_account_type_payable") type_revenue = self.env.ref("account.data_account_type_revenue") - self.account_receivable = self.env["account.account"].create( + self.credit_account = self.env["account.account"].create( { "name": "test_account_receivable", "code": "123", @@ -41,9 +35,8 @@ class TestAccountSpreadCostRevenue(common.TransactionCase): "reconcile": True, } ) - self.credit_account = self.account_receivable - self.account_expenses = self.env["account.account"].create( + self.debit_account = self.env["account.account"].create( { "name": "test account_expenses", "code": "765", @@ -51,7 +44,6 @@ class TestAccountSpreadCostRevenue(common.TransactionCase): "reconcile": True, } ) - self.debit_account = self.account_expenses self.account_payable = self.env["account.account"].create( { @@ -73,6 +65,12 @@ class TestAccountSpreadCostRevenue(common.TransactionCase): def test_01_account_spread_defaults(self): this_year = datetime.date.today().year + spread_template = self.env["account.spread.template"].create( + {"name": "test", "spread_account_id": self.debit_account.id} + ) + self.assertEqual(spread_template.spread_type, "sale") + self.assertTrue(spread_template.spread_journal_id) + spread = self.env["account.spread"].create( { "name": "test", @@ -81,7 +79,6 @@ class TestAccountSpreadCostRevenue(common.TransactionCase): "credit_account_id": self.credit_account.id, } ) - my_company = self.env.user.company_id self.assertTrue(spread) self.assertFalse(spread.line_ids) @@ -93,8 +90,8 @@ class TestAccountSpreadCostRevenue(common.TransactionCase): self.assertTrue(spread.move_line_auto_post) self.assertEqual(spread.name, "test") self.assertEqual(spread.invoice_type, "out_invoice") - self.assertEqual(spread.company_id, my_company) - self.assertEqual(spread.currency_id, my_company.currency_id) + self.assertEqual(spread.company_id, self.env.company) + self.assertEqual(spread.currency_id, self.env.company.currency_id) self.assertEqual(spread.period_number, 12) self.assertEqual(spread.period_type, "month") self.assertEqual(spread.debit_account_id, self.debit_account) @@ -112,43 +109,40 @@ class TestAccountSpreadCostRevenue(common.TransactionCase): self.assertTrue(spread.display_move_line_auto_post) def test_02_config_defaults(self): - my_company = self.env.user.company_id - self.assertFalse(my_company.default_spread_revenue_account_id) - self.assertFalse(my_company.default_spread_expense_account_id) - self.assertFalse(my_company.default_spread_revenue_journal_id) - self.assertFalse(my_company.default_spread_expense_journal_id) + self.assertFalse(self.env.company.default_spread_revenue_account_id) + self.assertFalse(self.env.company.default_spread_expense_account_id) + self.assertFalse(self.env.company.default_spread_revenue_journal_id) + self.assertFalse(self.env.company.default_spread_expense_journal_id) @mute_logger("odoo.sql_db") def test_03_no_defaults(self): with self.assertRaises(IntegrityError): - self.env["account.spread"].create( - {"name": "test",} - ) + self.env["account.spread"].create({"name": "test"}) @mute_logger("odoo.sql_db") def test_04_no_defaults(self): with self.assertRaises(IntegrityError): self.env["account.spread"].create( - {"name": "test", "invoice_type": "out_invoice",} + {"name": "test", "invoice_type": "out_invoice"} ) def test_05_config_settings(self): - my_company = self.env.user.company_id + self.env.company.default_spread_revenue_account_id = self.account_revenue + self.env.company.default_spread_expense_account_id = self.account_payable + self.env.company.default_spread_revenue_journal_id = self.sales_journal + self.env.company.default_spread_expense_journal_id = self.expenses_journal - account_revenue = self.account_revenue - exp_journal = self.ref("account_spread_cost_revenue.expenses_journal") - sales_journal = self.ref("account_spread_cost_revenue.sales_journal") - my_company.default_spread_revenue_account_id = account_revenue - my_company.default_spread_expense_account_id = self.account_payable - my_company.default_spread_revenue_journal_id = sales_journal - my_company.default_spread_expense_journal_id = exp_journal + self.assertTrue(self.env.company.default_spread_revenue_account_id) + self.assertTrue(self.env.company.default_spread_expense_account_id) + self.assertTrue(self.env.company.default_spread_revenue_journal_id) + self.assertTrue(self.env.company.default_spread_expense_journal_id) - self.assertTrue(my_company.default_spread_revenue_account_id) - self.assertTrue(my_company.default_spread_expense_account_id) - self.assertTrue(my_company.default_spread_revenue_journal_id) - self.assertTrue(my_company.default_spread_expense_journal_id) - - spread = self.env["account.spread"].new({"name": "test",}) + spread_form = Form(self.env["account.spread"]) + spread_form.name = "test" + spread_form.invoice_type = "in_invoice" + spread_form.debit_account_id = self.debit_account + spread_form.credit_account_id = self.credit_account + spread = spread_form.save() self.assertTrue(spread) self.assertFalse(spread.line_ids) @@ -157,106 +151,52 @@ class TestAccountSpreadCostRevenue(common.TransactionCase): self.assertFalse(spread.invoice_id) self.assertFalse(spread.account_analytic_id) self.assertFalse(spread.analytic_tag_ids) - self.assertFalse(spread.move_line_auto_post) + self.assertTrue(spread.move_line_auto_post) - defaults = self.env["account.spread"].default_get( - ["company_id", "currency_id",] - ) + defaults = self.env["account.spread"].default_get(["company_id", "currency_id"]) - self.assertEqual(defaults["company_id"], my_company.id) - self.assertEqual(defaults["currency_id"], my_company.currency_id.id) + self.assertEqual(defaults["company_id"], self.env.company.id) + self.assertEqual(defaults["currency_id"], self.env.company.currency_id.id) - spread.invoice_type = "out_invoice" - spread.company_id = my_company - spread.onchange_invoice_type() - self.assertEqual(spread.debit_account_id, account_revenue) - self.assertFalse(spread.credit_account_id) - self.assertEqual(spread.journal_id.id, sales_journal) + spread_form = Form(spread) + spread_form.invoice_type = "out_invoice" + spread_form.company_id = self.env.company + spread = spread_form.save() + self.assertEqual(spread.debit_account_id, self.account_revenue) + self.assertFalse(spread.is_debit_account_deprecated) + self.assertEqual(spread.journal_id, self.sales_journal) self.assertEqual(spread.spread_type, "sale") - spread.invoice_type = "in_invoice" - spread.onchange_invoice_type() + spread_form = Form(spread) + spread_form.invoice_type = "in_invoice" + spread = spread_form.save() self.assertEqual(spread.credit_account_id, self.account_payable) - self.assertEqual(spread.journal_id.id, exp_journal) + self.assertFalse(spread.is_credit_account_deprecated) + self.assertEqual(spread.journal_id, self.expenses_journal) self.assertEqual(spread.spread_type, "purchase") - def test_06_invoice_line_compute_spread_check(self): - invoice_account = self.account_receivable - invoice_line_account = self.account_expenses - invoice = self.env["account.invoice"].create( - { - "partner_id": self.env.ref("base.res_partner_2").id, - "account_id": invoice_account.id, - "type": "in_invoice", - } - ) - invoice_line = self.env["account.invoice.line"].create( - { - "product_id": self.env.ref("product.product_product_4").id, - "quantity": 1.0, - "price_unit": 100.0, - "invoice_id": invoice.id, - "name": "product that cost 100", - "account_id": invoice_line_account.id, - } - ) - invoice_line2 = invoice_line.copy() - - self.assertFalse(invoice_line.spread_id) - self.assertEqual(invoice_line.spread_check, "unlinked") - - spread = self.env["account.spread"].create( - { - "name": "test", - "invoice_type": "in_invoice", - "debit_account_id": self.debit_account.id, - "credit_account_id": self.credit_account.id, - } - ) - invoice_line.spread_id = spread - self.assertTrue(invoice_line.spread_id) - self.assertEqual(invoice_line.spread_check, "linked") - self.assertFalse(invoice_line2.spread_id) - self.assertEqual(invoice_line2.spread_check, "unlinked") - - invoice.action_invoice_open() - self.assertTrue(invoice_line.spread_id) - self.assertEqual(invoice_line.spread_check, "linked") - self.assertFalse(invoice_line2.spread_id) - self.assertEqual(invoice_line2.spread_check, "unavailable") - - self.assertTrue(spread.display_create_all_moves) - self.assertTrue(spread.display_recompute_buttons) - self.assertTrue(spread.display_move_line_auto_post) - def test_07_create_spread_template(self): - account_revenue = self.account_revenue - account_payable = self.account_payable spread_template = self.env["account.spread.template"].create( { "name": "test", "spread_type": "sale", - "spread_account_id": account_revenue.id, + "spread_account_id": self.account_revenue.id, } ) - my_company = self.env.user.company_id - self.assertEqual(spread_template.company_id, my_company) + self.assertEqual(spread_template.company_id, self.env.company) self.assertTrue(spread_template.spread_journal_id) - exp_journal = self.ref("account_spread_cost_revenue.expenses_journal") - sales_journal = self.ref("account_spread_cost_revenue.sales_journal") - my_company.default_spread_revenue_account_id = account_revenue - my_company.default_spread_expense_account_id = account_payable - my_company.default_spread_revenue_journal_id = sales_journal - my_company.default_spread_expense_journal_id = exp_journal + self.env.company.default_spread_revenue_account_id = self.account_revenue + self.env.company.default_spread_expense_account_id = self.account_payable + self.env.company.default_spread_revenue_journal_id = self.sales_journal + self.env.company.default_spread_expense_journal_id = self.expenses_journal spread_template.spread_type = "purchase" - spread_template.onchange_spread_type() self.assertTrue(spread_template.spread_journal_id) self.assertTrue(spread_template.spread_account_id) - self.assertEqual(spread_template.spread_account_id, account_payable) - self.assertEqual(spread_template.spread_journal_id.id, exp_journal) + self.assertEqual(spread_template.spread_account_id, self.account_payable) + self.assertEqual(spread_template.spread_journal_id, self.expenses_journal) spread_vals = spread_template._prepare_spread_from_template() self.assertTrue(spread_vals["name"]) @@ -267,11 +207,10 @@ class TestAccountSpreadCostRevenue(common.TransactionCase): self.assertTrue(spread_vals["credit_account_id"]) spread_template.spread_type = "sale" - spread_template.onchange_spread_type() self.assertTrue(spread_template.spread_journal_id) self.assertTrue(spread_template.spread_account_id) - self.assertEqual(spread_template.spread_account_id, account_revenue) - self.assertEqual(spread_template.spread_journal_id.id, sales_journal) + self.assertEqual(spread_template.spread_account_id, self.account_revenue) + self.assertEqual(spread_template.spread_journal_id, self.sales_journal) spread_vals = spread_template._prepare_spread_from_template() self.assertTrue(spread_vals["name"]) @@ -282,12 +221,11 @@ class TestAccountSpreadCostRevenue(common.TransactionCase): self.assertTrue(spread_vals["debit_account_id"]) def test_08_check_template_invoice_type(self): - account_revenue = self.account_revenue template_sale = self.env["account.spread.template"].create( { "name": "test", "spread_type": "sale", - "spread_account_id": account_revenue.id, + "spread_account_id": self.account_revenue.id, } ) template_purchase = self.env["account.spread.template"].create( @@ -305,78 +243,35 @@ class TestAccountSpreadCostRevenue(common.TransactionCase): "credit_account_id": self.credit_account.id, } ) - spread.template_id = template_sale - self.assertEqual(spread.template_id, template_sale) + with self.assertRaises(ValidationError): spread.template_id = template_purchase - self.assertEqual(spread.invoice_type, "out_invoice") - spread.onchange_template() - self.assertEqual(spread.invoice_type, "in_invoice") - spread.template_id = False - spread.invoice_type = "in_invoice" - spread.template_id = template_purchase - self.assertEqual(spread.template_id, template_purchase) - with self.assertRaises(ValidationError): - spread.template_id = template_sale - self.assertEqual(spread.invoice_type, "in_invoice") - spread.onchange_template() - self.assertEqual(spread.invoice_type, "out_invoice") - - spread.template_id = False - spread.invoice_type = "out_invoice" spread.template_id = template_sale self.assertEqual(spread.template_id, template_sale) - with self.assertRaises(ValidationError): - spread.invoice_type = "in_invoice" - self.assertEqual(spread.invoice_type, "in_invoice") - spread.onchange_template() - self.assertEqual(spread.invoice_type, "out_invoice") - - spread.template_id = False - spread.invoice_type = "in_invoice" - spread.template_id = template_purchase - self.assertEqual(spread.template_id, template_purchase) - with self.assertRaises(ValidationError): - spread.invoice_type = "out_invoice" - self.assertEqual(spread.invoice_type, "out_invoice") - spread.onchange_template() - self.assertEqual(spread.invoice_type, "in_invoice") self.assertFalse(spread.display_create_all_moves) self.assertTrue(spread.display_recompute_buttons) self.assertTrue(spread.display_move_line_auto_post) - def test_09_wrong_invoice_type(self): - invoice_account = self.account_receivable - invoice_line_account = self.account_expenses - invoice = self.env["account.invoice"].create( - { - "partner_id": self.env.ref("base.res_partner_2").id, - "account_id": invoice_account.id, - "type": "in_invoice", - } - ) - invoice_line = self.env["account.invoice.line"].create( - { - "product_id": self.env.ref("product.product_product_4").id, - "quantity": 1.0, - "price_unit": 100.0, - "invoice_id": invoice.id, - "name": "product that cost 100", - "account_id": invoice_line_account.id, - } - ) spread = self.env["account.spread"].create( { "name": "test", - "invoice_type": "out_invoice", + "invoice_type": "in_invoice", "debit_account_id": self.debit_account.id, "credit_account_id": self.credit_account.id, } ) + with self.assertRaises(ValidationError): - invoice_line.spread_id = spread + spread.template_id = template_sale + + spread.template_id = template_purchase + self.assertEqual(spread.template_id, template_purchase) + + self.assertFalse(spread.display_create_all_moves) + self.assertTrue(spread.display_recompute_buttons) + self.assertTrue(spread.display_move_line_auto_post) def test_10_account_spread_unlink(self): spread = self.env["account.spread"].create( diff --git a/account_spread_cost_revenue/tests/test_compute_spread_board.py b/account_spread_cost_revenue/tests/test_compute_spread_board.py index 748f1695..0caa6284 100644 --- a/account_spread_cost_revenue/tests/test_compute_spread_board.py +++ b/account_spread_cost_revenue/tests/test_compute_spread_board.py @@ -1,4 +1,4 @@ -# Copyright 2017-2019 Onestein () +# Copyright 2017-2020 Onestein () # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). import datetime @@ -113,7 +113,6 @@ class TestComputeSpreadBoard(common.TransactionCase): line.create_move() self.assertTrue(line.move_id) - self.spread.journal_id.update_posted = True self.spread.action_recalculate_spread() spread_lines = self.spread.line_ids for line in spread_lines: @@ -313,7 +312,6 @@ class TestComputeSpreadBoard(common.TransactionCase): self.assertTrue(isinstance(attrs, dict)) # post and then unlink all created moves - self.spread.journal_id.write({"update_posted": True}) for line in self.spread.line_ids: line.move_id.post() self.spread.line_ids.unlink_move() @@ -354,9 +352,7 @@ class TestComputeSpreadBoard(common.TransactionCase): with self.assertRaises(UserError): line.create_move() - self.spread.write( - {"move_line_auto_post": True,} - ) + self.spread.write({"move_line_auto_post": True}) self.spread.action_recalculate_spread() for line in self.spread.line_ids: @@ -379,9 +375,9 @@ class TestComputeSpreadBoard(common.TransactionCase): self.spread.compute_spread_board() spread_lines = self.spread.line_ids self.assertEqual(len(spread_lines), 3) - self.assertEqual(115.32, spread_lines[0].amount) - self.assertEqual(115.32, spread_lines[1].amount) - self.assertEqual(115.32, spread_lines[2].amount) + self.assertAlmostEquals(115.32, spread_lines[0].amount) + self.assertAlmostEquals(115.32, spread_lines[1].amount) + self.assertAlmostEquals(115.32, spread_lines[2].amount) self.assertEqual(datetime.date(2017, 1, 31), spread_lines[0].date) self.assertEqual(datetime.date(2017, 2, 28), spread_lines[1].date) self.assertEqual(datetime.date(2017, 3, 31), spread_lines[2].date) @@ -427,7 +423,6 @@ class TestComputeSpreadBoard(common.TransactionCase): action = line.open_move() self.assertTrue(action) - self.spread.journal_id.update_posted = True self.spread.line_ids.unlink_move() for line in self.spread.line_ids: self.assertFalse(line.move_id) @@ -471,7 +466,7 @@ class TestComputeSpreadBoard(common.TransactionCase): def test_12_supplier_invoice_auto_post(self): # spread date set self.spread.write( - {"period_number": 8, "period_type": "month", "move_line_auto_post": True,} + {"period_number": 8, "period_type": "month", "move_line_auto_post": True} ) self.spread.compute_spread_board() @@ -496,9 +491,7 @@ class TestComputeSpreadBoard(common.TransactionCase): self.assertEqual(self.spread.unposted_amount, 0.0) def test_13_create_move_in_invoice_auto_post(self): - self.spread2.write( - {"period_number": 4, "move_line_auto_post": True,} - ) + self.spread2.write({"period_number": 4, "move_line_auto_post": True}) self.spread_account.reconcile = True self.assertTrue(self.spread_account.reconcile) diff --git a/account_spread_cost_revenue/views/account_invoice.xml b/account_spread_cost_revenue/views/account_invoice.xml deleted file mode 100644 index f9b6adae..00000000 --- a/account_spread_cost_revenue/views/account_invoice.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - - account.invoice - - - - - - - - - account.invoice - - - - - - - - diff --git a/account_spread_cost_revenue/views/account_move.xml b/account_spread_cost_revenue/views/account_move.xml new file mode 100644 index 00000000..debd3b8e --- /dev/null +++ b/account_spread_cost_revenue/views/account_move.xml @@ -0,0 +1,31 @@ + + + + account.move + + + + + + + + + {'journal_type':'general', 'search_default_group_by_move': 0, 'search_default_posted':1, 'name_groupby':1} + Journal Items + account.move.line + [('display_type', 'not in', ('line_section', 'line_note'))] + + tree,pivot,graph,form,kanban + + diff --git a/account_spread_cost_revenue/views/account_spread.xml b/account_spread_cost_revenue/views/account_spread.xml index 710e122d..931c9c04 100644 --- a/account_spread_cost_revenue/views/account_spread.xml +++ b/account_spread_cost_revenue/views/account_spread.xml @@ -35,7 +35,7 @@ /> -
+
-
+