diff --git a/account_spread_cost_revenue/__manifest__.py b/account_spread_cost_revenue/__manifest__.py index e4350daa..b93c0f17 100644 --- a/account_spread_cost_revenue/__manifest__.py +++ b/account_spread_cost_revenue/__manifest__.py @@ -11,9 +11,7 @@ "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", diff --git a/account_spread_cost_revenue/data/spread_cron.xml b/account_spread_cost_revenue/data/spread_cron.xml index 202f14c7..b77437b8 100644 --- a/account_spread_cost_revenue/data/spread_cron.xml +++ b/account_spread_cost_revenue/data/spread_cron.xml @@ -1,17 +1,15 @@ - + - Cost/revenue Spread: Create Entries - - + + 1 days -1 - - + + code model._create_entries() - diff --git a/account_spread_cost_revenue/models/account_invoice.py b/account_spread_cost_revenue/models/account_invoice.py index 7de31920..acfbedd1 100644 --- a/account_spread_cost_revenue/models/account_invoice.py +++ b/account_spread_cost_revenue/models/account_invoice.py @@ -5,7 +5,7 @@ from odoo import api, models class AccountInvoice(models.Model): - _inherit = 'account.invoice' + _inherit = "account.invoice" def action_invoice_open(self): for invoice in self: @@ -16,7 +16,7 @@ class AccountInvoice(models.Model): def action_move_create(self): """Invoked when validating the invoices.""" res = super().action_move_create() - spreads = self.mapped('invoice_line_ids.spread_id') + spreads = self.mapped("invoice_line_ids.spread_id") spreads.compute_spread_board() spreads.reconcile_spread_moves() return res @@ -26,14 +26,14 @@ class AccountInvoice(models.Model): """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) + 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'): + 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 + line["account_id"] = account.id return res @api.multi @@ -41,8 +41,8 @@ class AccountInvoice(models.Model): """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') + 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() @@ -53,7 +53,7 @@ class AccountInvoice(models.Model): result = super()._refund_cleanup_lines(lines) for i, line in enumerate(lines): for name in line._fields.keys(): - if name == 'spread_id': + if name == "spread_id": result[i][2][name] = False break return result diff --git a/account_spread_cost_revenue/models/account_invoice_line.py b/account_spread_cost_revenue/models/account_invoice_line.py index 88fe9a64..16595129 100644 --- a/account_spread_cost_revenue/models/account_invoice_line.py +++ b/account_spread_cost_revenue/models/account_invoice_line.py @@ -6,27 +6,27 @@ from odoo.exceptions import UserError class AccountInvoiceLine(models.Model): - _inherit = 'account.invoice.line' + _inherit = "account.invoice.line" - spread_id = fields.Many2one( - 'account.spread', - string='Spread Board', - copy=False) - spread_check = fields.Selection([ - ('linked', 'Linked'), - ('unlinked', 'Unlinked'), - ('unavailable', 'Unavailable') - ], compute='_compute_spread_check') + spread_id = fields.Many2one("account.spread", string="Spread Board", copy=False) + spread_check = fields.Selection( + [ + ("linked", "Linked"), + ("unlinked", "Unlinked"), + ("unavailable", "Unavailable"), + ], + compute="_compute_spread_check", + ) - @api.depends('spread_id', 'invoice_id.state') + @api.depends("spread_id", "invoice_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': - line.spread_check = 'unlinked' + line.spread_check = "linked" + elif line.invoice_id.state == "draft": + line.spread_check = "unlinked" else: - line.spread_check = 'unavailable' + line.spread_check = "unavailable" @api.multi def spread_details(self): @@ -38,14 +38,14 @@ 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', - 'target': 'current', - 'readonly': False, - 'res_id': self.spread_id.id, + "name": _("Spread Details"), + "view_type": "form", + "view_mode": "form", + "res_model": "account.spread", + "type": "ir.actions.act_window", + "target": "current", + "readonly": False, + "res_id": self.spread_id.id, } # In case no spread board is linked to the invoice line @@ -58,13 +58,13 @@ class AccountInvoiceLine(models.Model): allow_spread_planning=company.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', - 'target': 'new', - 'context': ctx, + "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", + "target": "new", + "context": ctx, } def create_auto_spread(self): @@ -76,33 +76,46 @@ class AccountInvoiceLine(models.Model): return False if aline.account_id and iline.account_id != aline.account_id: return False - if aline.analytic_account_id and \ - iline.account_analytic_id != aline.analytic_account_id: + if ( + aline.analytic_account_id + and iline.account_analytic_id != aline.analytic_account_id + ): return False return True for line in self: - if line.spread_check == 'linked': + if line.spread_check == "linked": continue spread_type = ( - 'sale' if line.invoice_type in ['out_invoice', 'out_refund'] - else 'purchase') - spread_auto = self.env['account.spread.template.auto'].search( - [('template_id.auto_spread', '=', True), - ('template_id.spread_type', '=', spread_type)]) + "sale" + if line.invoice_type in ["out_invoice", "out_refund"] + else "purchase" + ) + spread_auto = self.env["account.spread.template.auto"].search( + [ + ("template_id.auto_spread", "=", True), + ("template_id.spread_type", "=", spread_type), + ] + ) matched = spread_auto.filtered(lambda a, i=line: _filter_line(a, i)) - template = matched.mapped('template_id') + template = matched.mapped("template_id") if not template: continue elif len(template) > 1: raise UserError( - _('Too many auto spread templates (%s) matched with the ' - 'invoice line, %s') % (len(template), line.display_name)) + _( + "Too many auto spread templates (%s) matched with the " + "invoice line, %s" + ) + % (len(template), line.display_name) + ) # Found auto spread template for this invoice line, create it - wizard = self.env['account.spread.invoice.line.link.wizard'].new({ - 'invoice_line_id': line.id, - 'company_id': line.company_id.id, - 'spread_action_type': 'template', - 'template_id': template.id, - }) + wizard = self.env["account.spread.invoice.line.link.wizard"].new( + { + "invoice_line_id": line.id, + "company_id": line.company_id.id, + "spread_action_type": "template", + "template_id": template.id, + } + ) wizard.confirm() diff --git a/account_spread_cost_revenue/models/account_spread.py b/account_spread_cost_revenue/models/account_spread.py index 53314ba8..3408b156 100644 --- a/account_spread_cost_revenue/models/account_spread.py +++ b/account_spread_cost_revenue/models/account_spread.py @@ -7,154 +7,145 @@ import time from dateutil.relativedelta import relativedelta from odoo import _, api, fields, models -from odoo.addons import decimal_precision as dp 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' - _description = 'Account Spread' - _inherit = ['mail.thread'] + _name = "account.spread" + _description = "Account Spread" + _inherit = ["mail.thread"] name = fields.Char(required=True) - template_id = fields.Many2one( - 'account.spread.template', - string='Spread Template') - invoice_type = fields.Selection([ - ('out_invoice', 'Customer Invoice'), - ('in_invoice', 'Vendor Bill'), - ('out_refund', 'Customer Credit Note'), - ('in_refund', 'Vendor Credit Note')], - required=True) - spread_type = fields.Selection([ - ('sale', 'Customer'), - ('purchase', 'Supplier')], - compute='_compute_spread_type', - required=True) + template_id = fields.Many2one("account.spread.template", string="Spread Template") + invoice_type = fields.Selection( + [ + ("out_invoice", "Customer Invoice"), + ("in_invoice", "Vendor Bill"), + ("out_refund", "Customer Credit Note"), + ("in_refund", "Vendor Credit Note"), + ], + required=True, + ) + spread_type = fields.Selection( + [("sale", "Customer"), ("purchase", "Supplier")], + compute="_compute_spread_type", + required=True, + ) period_number = fields.Integer( - string='Number of Repetitions', + string="Number of Repetitions", default=12, help="Define the number of spread lines", - required=True) - period_type = fields.Selection([ - ('month', 'Month'), - ('quarter', 'Quarter'), - ('year', 'Year')], - default='month', - help="Period length for the entries", - required=True) - use_invoice_line_account = fields.Boolean( - string="Use invoice line's account", + required=True, ) + period_type = fields.Selection( + [("month", "Month"), ("quarter", "Quarter"), ("year", "Year")], + default="month", + help="Period length for the entries", + required=True, + ) + use_invoice_line_account = fields.Boolean(string="Use invoice line's account",) credit_account_id = fields.Many2one( - 'account.account', - string='Credit Account', - required=True) + "account.account", string="Credit Account", required=True + ) debit_account_id = fields.Many2one( - 'account.account', - string='Debit Account', - required=True) + "account.account", string="Debit Account", required=True + ) is_credit_account_deprecated = fields.Boolean( - compute='_compute_deprecated_accounts') - is_debit_account_deprecated = fields.Boolean( - compute='_compute_deprecated_accounts') + 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') + digits=dp.get_precision("Account"), compute="_compute_amounts" + ) unposted_amount = fields.Float( - digits=dp.get_precision('Account'), - compute='_compute_amounts') + digits=dp.get_precision("Account"), compute="_compute_amounts" + ) posted_amount = fields.Float( - digits=dp.get_precision('Account'), - compute='_compute_amounts') + 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) + digits=dp.get_precision("Account"), compute="_compute_amounts" + ) + all_posted = fields.Boolean(compute="_compute_amounts", store=True) line_ids = fields.One2many( - 'account.spread.line', - 'spread_id', - string='Spread Lines') + "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) + string="Start Date", default=time.strftime("%Y-01-01"), required=True + ) + journal_id = fields.Many2one("account.journal", string="Journal", required=True) invoice_line_ids = fields.One2many( - 'account.invoice.line', - 'spread_id', - copy=False, - string='Invoice Lines') + "account.invoice.line", "spread_id", copy=False, string="Invoice Lines" + ) invoice_line_id = fields.Many2one( - 'account.invoice.line', - string='Invoice line', - compute='_compute_invoice_line', - inverse='_inverse_invoice_line', - store=True) + "account.invoice.line", + string="Invoice line", + compute="_compute_invoice_line", + inverse="_inverse_invoice_line", + store=True, + ) invoice_id = fields.Many2one( - related='invoice_line_id.invoice_id', + related="invoice_line_id.invoice_id", readonly=True, store=True, - string='Invoice') - estimated_amount = fields.Float(digits=dp.get_precision('Account')) + string="Invoice", + ) + estimated_amount = fields.Float(digits=dp.get_precision("Account")) company_id = fields.Many2one( - 'res.company', + "res.company", default=lambda self: self.env.user.company_id, - string='Company', - required=True) - currency_id = fields.Many2one( - 'res.currency', - string='Currency', + string="Company", required=True, - default=lambda self: self.env.user.company_id.currency_id.id) + ) + currency_id = fields.Many2one( + "res.currency", + string="Currency", + required=True, + default=lambda self: self.env.user.company_id.currency_id.id, + ) account_analytic_id = fields.Many2one( - 'account.analytic.account', - string='Analytic Account') - analytic_tag_ids = fields.Many2many( - 'account.analytic.tag', - string='Analytic Tags') - move_line_auto_post = fields.Boolean('Auto-post lines', default=True) + "account.analytic.account", string="Analytic Account" + ) + 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", string="Display Button All Moves" + ) display_recompute_buttons = fields.Boolean( - compute='_compute_display_recompute_buttons', - string='Display Buttons Recompute') + compute="_compute_display_recompute_buttons", string="Display Buttons Recompute" + ) display_move_line_auto_post = fields.Boolean( - compute='_compute_display_move_line_auto_post', - string='Display Button Auto-post lines') + compute="_compute_display_move_line_auto_post", + string="Display Button Auto-post lines", + ) active = fields.Boolean(default=True) @api.model def default_get(self, fields): res = super().default_get(fields) - if 'company_id' not in 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 + 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 return res - @api.depends('invoice_type') + @api.depends("invoice_type") def _compute_spread_type(self): for spread in self: - if spread.invoice_type in ['out_invoice', 'out_refund']: - spread.spread_type = 'sale' + if spread.invoice_type in ["out_invoice", "out_refund"]: + spread.spread_type = "sale" else: - spread.spread_type = 'purchase' + spread.spread_type = "purchase" - @api.depends('invoice_line_ids', 'invoice_line_ids.invoice_id') + @api.depends("invoice_line_ids", "invoice_line_ids.invoice_id") def _compute_invoice_line(self): for spread in self: invoice_lines = spread.invoice_line_ids @@ -165,9 +156,9 @@ class AccountSpread(models.Model): 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", @@ -189,13 +180,13 @@ class AccountSpread(models.Model): spread.invoice_line_id.price_subtotal, spread.currency_id, spread.company_id, - invoice._get_currency_rate_date() or fields.Date.today() + invoice._get_currency_rate_date() or fields.Date.today(), ) for spread_line in spread.line_ids: if spread_line.move_id: moves_amount += spread_line.amount - if spread_line.move_id.state == 'posted': + 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 @@ -216,7 +207,7 @@ class AccountSpread(models.Model): for spread in self: spread.display_recompute_buttons = True if not spread.company_id.allow_spread_planning: - if spread.invoice_id.state == 'draft': + if spread.invoice_id.state == "draft": spread.display_recompute_buttons = False @api.multi @@ -230,17 +221,17 @@ class AccountSpread(models.Model): def _get_spread_entry_name(self, seq): """Use this method to customise the name of the accounting entry.""" self.ensure_one() - return (self.name or '') + '/' + str(seq) + return (self.name or "") + "/" + str(seq) - @api.onchange('template_id') + @api.onchange("template_id") def onchange_template(self): if self.template_id: - if self.template_id.spread_type == 'sale': - if self.invoice_type in ['in_invoice', 'in_refund']: - self.invoice_type = 'out_invoice' + if self.template_id.spread_type == "sale": + if self.invoice_type in ["in_invoice", "in_refund"]: + self.invoice_type = "out_invoice" else: - if self.invoice_type in ['out_invoice', 'out_refund']: - self.invoice_type = 'in_invoice' + if self.invoice_type in ["out_invoice", "out_refund"]: + self.invoice_type = "in_invoice" if self.template_id.period_number: self.period_number = self.template_id.period_number if self.template_id.period_type: @@ -248,64 +239,72 @@ class AccountSpread(models.Model): if self.template_id.start_date: self.spread_date = self.template_id.start_date - @api.onchange('invoice_type', 'company_id') + @api.onchange("invoice_type", "company_id") def onchange_invoice_type(self): company = self.company_id - if not self.env.context.get('default_journal_id'): + 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'): + if self.invoice_type in ("out_invoice", "in_refund"): journal = company.default_spread_revenue_journal_id if journal: self.journal_id = journal - if not self.env.context.get('default_debit_account_id'): - if self.invoice_type in ('out_invoice', 'in_refund'): + 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 - if not self.env.context.get('default_credit_account_id'): - if self.invoice_type in ('in_invoice', 'out_refund'): + 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 - @api.constrains('invoice_id', 'invoice_type') + @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')) + raise ValidationError( + _("The Invoice Type does not correspond to the Invoice") + ) - @api.constrains('journal_id') + @api.constrains("journal_id") def _check_journal(self): for spread in self: - moves = spread.mapped('line_ids.move_id').filtered('journal_id') + 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.')) + raise ValidationError( + _("The Journal is not consistent with the account moves.") + ) - @api.constrains('template_id', 'invoice_type') + @api.constrains("template_id", "invoice_type") def _check_template_invoice_type(self): for spread in self: - 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')) + 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" + ) + ) @api.multi def _get_spread_period_duration(self): """Converts the selected period_type to number of months.""" self.ensure_one() - if self.period_type == 'year': + if self.period_type == "year": return 12 - elif self.period_type == 'quarter': + elif self.period_type == "quarter": return 3 return 1 @@ -348,10 +347,11 @@ class AccountSpread(models.Model): self.ensure_one() posted_line_ids = self.line_ids.filtered( - lambda x: x.move_id.state == 'posted').sorted( - key=lambda l: l.date) + lambda x: x.move_id.state == "posted" + ).sorted(key=lambda l: l.date) unposted_line_ids = self.line_ids.filtered( - lambda x: not x.move_id.state == 'posted') + lambda x: not x.move_id.state == "posted" + ) # Remove old unposted spread lines. commands = [(2, line_id.id, False) for line_id in unposted_line_ids] @@ -375,19 +375,19 @@ class AccountSpread(models.Model): continue unposted_amount -= amount vals = { - 'amount': amount, - 'spread_id': self.id, - 'name': self._get_spread_entry_name(sequence), - 'date': self._get_last_day_of_month(spread_date), + "amount": amount, + "spread_id": self.id, + "name": self._get_spread_entry_name(sequence), + "date": self._get_last_day_of_month(spread_date), } commands.append((0, False, vals)) spread_date = self._next_line_date(month_day, spread_date) - self.write({'line_ids': commands}) - invoice_type_selection = dict(self.fields_get( - allfields=['invoice_type'] - )['invoice_type']['selection'])[self.invoice_type] + self.write({"line_ids": commands}) + invoice_type_selection = dict( + self.fields_get(allfields=["invoice_type"])["invoice_type"]["selection"] + )[self.invoice_type] msg_body = _("Spread table '%s' created.") % invoice_type_selection self.message_post(body=msg_body) @@ -430,60 +430,68 @@ class AccountSpread(models.Model): def action_recalculate_spread(self): """Recalculate spread""" self.ensure_one() - spread_lines = self.mapped('line_ids').filtered('move_id') + spread_lines = self.mapped("line_ids").filtered("move_id") spread_lines.unlink_move() self.compute_spread_board() - self.env['account.spread.line']._create_entries() + 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""" self.ensure_one() - self.mapped('line_ids').filtered('move_id').unlink_move() - self.mapped('line_ids').unlink() + 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': + if self.invoice_id.state != "draft": raise UserError( - _("Cannot unlink invoice lines if the invoice is validated")) + _("Cannot unlink invoice lines if the invoice is validated") + ) 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 = self.mapped("line_ids.move_id.line_ids") spread_mls.remove_move_reconcile() self._message_post_unlink_invoice_line() - self.write({'invoice_line_ids': [(5, 0, 0)]}) + 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")) + inv_link = ( + "%s" % (invoice_id, _("Invoice")) + ) msg_body = _("Unlinked invoice line '%s' (view %s).") % ( - spread.invoice_line_id.name, inv_link) + spread.invoice_line_id.name, + inv_link, + ) spread.message_post(body=msg_body) - spread_link = '%s' % (spread.id, _("Spread")) + spread_link = ( + "%s" % (spread.id, _("Spread")) + ) msg_body = _("Unlinked '%s' (invoice line %s).") % ( - spread_link, spread.invoice_line_id.name) + spread_link, + spread.invoice_line_id.name, + ) 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.')) - if self.mapped('line_ids.move_id').filtered( - lambda m: m.state == 'posted'): + _("Cannot delete spread(s) that are linked " "to an invoice line.") + ) + if self.mapped("line_ids.move_id").filtered(lambda m: m.state == "posted"): raise ValidationError( - _('Cannot delete spread(s): there are ' - 'posted Journal Entries.')) + _("Cannot delete spread(s): there are " "posted Journal Entries.") + ) return super().unlink() @api.multi @@ -499,40 +507,40 @@ class AccountSpread(models.Model): if not self.invoice_id.number: return - spread_mls = self.line_ids.mapped('move_id.line_ids') + spread_mls = self.line_ids.mapped("move_id.line_ids") if created_moves: - spread_mls |= created_moves.mapped('line_ids') + 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') + in_invoice_or_out_refund = ("in_invoice", "out_refund") if self.invoice_type in in_invoice_or_out_refund and spread_sign: - spread_mls = spread_mls.filtered(lambda x: x.credit != 0.) + 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.) + spread_mls = spread_mls.filtered(lambda x: x.debit != 0.0) elif spread_sign: - spread_mls = spread_mls.filtered(lambda x: x.debit != 0.) + spread_mls = spread_mls.filtered(lambda x: x.debit != 0.0) else: - spread_mls = spread_mls.filtered(lambda x: x.credit != 0.) + spread_mls = spread_mls.filtered(lambda x: x.credit != 0.0) - invoice_mls = self.invoice_id.move_id.mapped('line_ids') + 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.) + 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.) + invoice_mls = invoice_mls.filtered(lambda x: x.credit != 0.0) elif spread_sign: - invoice_mls = invoice_mls.filtered(lambda x: x.credit != 0.) + invoice_mls = invoice_mls.filtered(lambda x: x.credit != 0.0) else: - invoice_mls = invoice_mls.filtered(lambda x: x.debit != 0.) + invoice_mls = invoice_mls.filtered(lambda x: x.debit != 0.0) - to_be_reconciled = self.env['account.move.line'] + 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] + 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 @@ -546,11 +554,10 @@ class AccountSpread(models.Model): @api.multi def create_all_moves(self): - for line in self.mapped('line_ids').filtered(lambda l: not l.move_id): + for line in self.mapped("line_ids").filtered(lambda l: not l.move_id): line.create_move() - @api.depends( - 'debit_account_id.deprecated', 'credit_account_id.deprecated') + @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) @@ -561,5 +568,5 @@ class AccountSpread(models.Model): @api.multi def open_reconcile_view(self): self.ensure_one() - spread_mls = self.line_ids.mapped('move_id.line_ids') + spread_mls = self.line_ids.mapped("move_id.line_ids") return spread_mls.open_reconcile_view() diff --git a/account_spread_cost_revenue/models/account_spread_line.py b/account_spread_cost_revenue/models/account_spread_line.py index 9b9b40f0..531724e3 100644 --- a/account_spread_cost_revenue/models/account_spread_line.py +++ b/account_spread_cost_revenue/models/account_spread_line.py @@ -2,22 +2,23 @@ # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). from odoo import _, api, fields, models -from odoo.addons import decimal_precision as dp from odoo.exceptions import UserError +from odoo.addons import decimal_precision as dp + class AccountInvoiceSpreadLine(models.Model): - _name = 'account.spread.line' - _description = 'Account Spread Lines' - _order = 'date' + _name = "account.spread.line" + _description = "Account Spread Lines" + _order = "date" - name = fields.Char('Description', readonly=True) - amount = fields.Float(digits=dp.get_precision('Account'), required=True) + name = fields.Char("Description", readonly=True) + amount = fields.Float(digits=dp.get_precision("Account"), required=True) date = fields.Date(required=True) spread_id = fields.Many2one( - 'account.spread', string='Spread Board', ondelete='cascade') - move_id = fields.Many2one( - 'account.move', string='Journal Entry', readonly=True) + "account.spread", string="Spread Board", ondelete="cascade" + ) + move_id = fields.Many2one("account.move", string="Journal Entry", readonly=True) @api.multi def create_and_reconcile_moves(self): @@ -25,19 +26,19 @@ class AccountInvoiceSpreadLine(models.Model): for spread_line in self: spread = spread_line.spread_id spread_line_list = grouped_lines.get( - spread, self.env['account.spread.line']) - grouped_lines.update({ - spread: spread_line_list + spread_line - }) + spread, self.env["account.spread.line"] + ) + grouped_lines.update({spread: spread_line_list + spread_line}) for spread in grouped_lines: created_moves = grouped_lines[spread]._create_moves() if created_moves: post_msg = _("Created move(s) ") post_msg += ", ".join( - '%s' % (move.id, move.name) - for move in created_moves) + "%s" % (move.id, move.name) + for move in created_moves + ) spread.message_post(body=post_msg) spread._reconcile_spread_moves(created_moves) @@ -62,15 +63,19 @@ class AccountInvoiceSpreadLine(models.Model): @api.multi def _create_moves(self): if self.filtered(lambda l: l.move_id): - raise UserError(_('This spread line is already linked to a ' - 'journal entry! Please post or delete it.')) + raise UserError( + _( + "This spread line is already linked to a " + "journal entry! Please post or delete it." + ) + ) - created_moves = self.env['account.move'] + created_moves = self.env["account.move"] for line in self: move_vals = line._prepare_move() - move = self.env['account.move'].create(move_vals) + move = self.env["account.move"].create(move_vals) - line.write({'move_id': move.id}) + line.write({"move_id": move.id}) created_moves += move return created_moves @@ -78,7 +83,7 @@ class AccountInvoiceSpreadLine(models.Model): def _prepare_move(self): self.ensure_one() - spread_date = self.env.context.get('spread_date') or self.date + 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] @@ -87,37 +92,49 @@ class AccountInvoiceSpreadLine(models.Model): current_currency = spread.currency_id not_same_curr = company_currency != current_currency amount = current_currency._convert( - self.amount, company_currency, spread.company_id, spread_date) + self.amount, company_currency, spread.company_id, spread_date + ) - line_ids = [(0, 0, { - 'name': spread.name.split('\n')[0][:64], - 'account_id': spread.debit_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, - 'analytic_account_id': analytic.id, - 'analytic_tag_ids': analytic_tags, - 'currency_id': not_same_curr and current_currency.id or False, - 'amount_currency': not_same_curr and - 1.0 * self.amount or 0.0, - }), (0, 0, { - 'name': spread.name.split('\n')[0][:64], - 'account_id': spread.credit_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, - 'analytic_account_id': analytic.id, - 'analytic_tag_ids': analytic_tags, - 'currency_id': not_same_curr and current_currency.id or False, - 'amount_currency': not_same_curr and self.amount or 0.0, - })] + line_ids = [ + ( + 0, + 0, + { + "name": spread.name.split("\n")[0][:64], + "account_id": spread.debit_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, + "analytic_account_id": analytic.id, + "analytic_tag_ids": analytic_tags, + "currency_id": not_same_curr and current_currency.id or False, + "amount_currency": not_same_curr and -1.0 * self.amount or 0.0, + }, + ), + ( + 0, + 0, + { + "name": spread.name.split("\n")[0][:64], + "account_id": spread.credit_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, + "analytic_account_id": analytic.id, + "analytic_tag_ids": analytic_tags, + "currency_id": not_same_curr and current_currency.id or False, + "amount_currency": not_same_curr and self.amount or 0.0, + }, + ), + ] return { - 'name': self.name or "/", - 'ref': self.name, - 'date': spread_date, - 'journal_id': spread.journal_id.id, - 'line_ids': line_ids, - 'company_id': spread.company_id.id, + "name": self.name or "/", + "ref": self.name, + "date": spread_date, + "journal_id": spread.journal_id.id, + "line_ids": line_ids, + "company_id": spread.company_id.id, } @api.multi @@ -127,13 +144,13 @@ class AccountInvoiceSpreadLine(models.Model): """ self.ensure_one() return { - 'name': _("Journal Entry"), - 'view_type': 'form', - 'view_mode': 'form', - 'res_model': 'account.move', - 'view_id': False, - 'type': 'ir.actions.act_window', - 'res_id': self.move_id.id, + "name": _("Journal Entry"), + "view_type": "form", + "view_mode": "form", + "res_model": "account.move", + "view_id": False, + "type": "ir.actions.act_window", + "res_id": self.move_id.id, } @api.multi @@ -143,7 +160,7 @@ class AccountInvoiceSpreadLine(models.Model): """ for line in self: move = line.move_id - if move.state == 'posted': + if move.state == "posted": move.button_cancel() move.line_ids.remove_move_reconcile() post_msg = _("Deleted move %s") % line.move_id.id @@ -156,18 +173,21 @@ class AccountInvoiceSpreadLine(models.Model): """Find spread line entries where date is in the past and create moves for them. Method also called by the cron job. """ - lines = self.search([ - ('date', '<=', fields.Date.today()), - ('move_id', '=', False) - ]) + lines = self.search( + [("date", "<=", fields.Date.today()), ("move_id", "=", False)] + ) lines.create_and_reconcile_moves() - unposted_moves = self.search([('move_id', '!=', False)]).mapped( - 'move_id').filtered(lambda m: m.state != 'posted') - unposted_moves.filtered( - lambda m: m.company_id.force_move_auto_post).post() + unposted_moves = ( + self.search([("move_id", "!=", False)]) + .mapped("move_id") + .filtered(lambda m: m.state != "posted") + ) + unposted_moves.filtered(lambda m: m.company_id.force_move_auto_post).post() - spreads_to_archive = self.env['account.spread'].search([ - ('all_posted', '=', True) - ]).filtered(lambda s: s.company_id.auto_archive) - spreads_to_archive.write({'active': False}) + spreads_to_archive = ( + self.env["account.spread"] + .search([("all_posted", "=", True)]) + .filtered(lambda s: s.company_id.auto_archive) + ) + 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 943d4c35..b35f064c 100644 --- a/account_spread_cost_revenue/models/account_spread_template.py +++ b/account_spread_cost_revenue/models/account_spread_template.py @@ -1,89 +1,89 @@ # Copyright 2018-2019 Onestein () # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -from odoo import api, fields, models, _ +from odoo import _, api, fields, models from odoo.exceptions import UserError class AccountSpreadTemplate(models.Model): - _name = 'account.spread.template' - _description = 'Account Spread Template' + _name = "account.spread.template" + _description = "Account Spread Template" name = fields.Char(required=True) - spread_type = fields.Selection([ - ('sale', 'Customer'), - ('purchase', 'Supplier')], - default='sale', - required=True) + spread_type = fields.Selection( + [("sale", "Customer"), ("purchase", "Supplier")], default="sale", required=True + ) company_id = fields.Many2one( - 'res.company', + "res.company", default=lambda self: self.env.user.company_id, - string='Company', - required=True) + string="Company", + required=True, + ) spread_journal_id = fields.Many2one( - 'account.journal', - string='Journal', - required=True) + "account.journal", string="Journal", required=True + ) use_invoice_line_account = fields.Boolean( string="Invoice account as spread account", help="Use invoice line's account as Balance sheet / spread account.\n" - "In this case, user need to select expense/revenue account too.") + "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", required=False + ) exp_rev_account_id = fields.Many2one( - 'account.account', - string='Expense/Revenue Account', - help="Optional account to overwrite the existing expense/revenue " - "account") + "account.account", + string="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") - period_type = fields.Selection([ - ('month', 'Month'), - ('quarter', 'Quarter'), - ('year', 'Year')], - help="Period length for the entries") + string="Number of Repetitions", help="Define the number of spread lines" + ) + period_type = fields.Selection( + [("month", "Month"), ("quarter", "Quarter"), ("year", "Year")], + help="Period length for the entries", + ) start_date = fields.Date() auto_spread = fields.Boolean( - string='Auto assign template on invoice validate', + string="Auto assign template on invoice validate", help="If checked, provide option to auto create spread during " - "invoice validation, based on product/account/analytic in invoice line." + "invoice validation, based on product/account/analytic in invoice line.", ) auto_spread_ids = fields.One2many( - comodel_name='account.spread.template.auto', - string='Auto Spread On', - inverse_name='template_id', + comodel_name="account.spread.template.auto", + string="Auto Spread On", + inverse_name="template_id", ) @api.model def default_get(self, fields): res = super().default_get(fields) - if 'company_id' not in 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 + 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 return res - @api.constrains('auto_spread', 'auto_spread_ids') + @api.constrains("auto_spread", "auto_spread_ids") def _check_product_account(self): - for rec in self.filtered('auto_spread'): + for rec in self.filtered("auto_spread"): for line in rec.auto_spread_ids: if not line.product_id and not line.account_id: - raise UserError(_('Please select product and/or account ' - 'on auto spread options')) + raise UserError( + _( + "Please select product and/or account " + "on auto spread options" + ) + ) - @api.onchange('spread_type', 'company_id') + @api.onchange("spread_type", "company_id") def onchange_spread_type(self): company = self.company_id - if self.spread_type == 'sale': + if self.spread_type == "sale": account = company.default_spread_revenue_account_id journal = company.default_spread_revenue_journal_id else: @@ -94,7 +94,7 @@ class AccountSpreadTemplate(models.Model): if journal: self.spread_journal_id = journal - @api.onchange('use_invoice_line_account') + @api.onchange("use_invoice_line_account") def _onchange_user_invoice_line_account(self): self.exp_rev_account_id = False @@ -102,32 +102,32 @@ class AccountSpreadTemplate(models.Model): self.ensure_one() company = self.company_id spread_vals = { - 'name': self.name, - 'template_id': self.id, - 'journal_id': self.spread_journal_id.id, - 'use_invoice_line_account': self.use_invoice_line_account, - 'company_id': company.id, + "name": self.name, + "template_id": self.id, + "journal_id": self.spread_journal_id.id, + "use_invoice_line_account": self.use_invoice_line_account, + "company_id": company.id, } account_id = spread_account_id or self.spread_account_id.id - if self.spread_type == 'sale': - invoice_type = 'out_invoice' - spread_vals['debit_account_id'] = account_id + if self.spread_type == "sale": + invoice_type = "out_invoice" + spread_vals["debit_account_id"] = account_id else: - invoice_type = 'in_invoice' - spread_vals['credit_account_id'] = account_id + invoice_type = "in_invoice" + spread_vals["credit_account_id"] = account_id if self.period_number: - spread_vals['period_number'] = self.period_number + spread_vals["period_number"] = self.period_number if self.period_type: - spread_vals['period_type'] = self.period_type + spread_vals["period_type"] = self.period_type if self.start_date: - spread_vals['spread_date'] = self.start_date + spread_vals["spread_date"] = self.start_date - spread_vals['invoice_type'] = invoice_type + spread_vals["invoice_type"] = invoice_type return spread_vals - @api.constrains('auto_spread_ids', 'auto_spread') + @api.constrains("auto_spread_ids", "auto_spread") def _check_auto_spread_ids_unique(self): query = """ select product_id, account_id, analytic_account_id @@ -141,43 +141,31 @@ class AccountSpreadTemplate(models.Model): self._cr.execute(query, [self._ids]) results = [] for res in self._cr.fetchall(): - 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('%s / %s / %s' % (product.name, account.name, analytic.name)) + 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)) if results: raise UserError( - _('Followings are duplicated combinations,\n\n%s' % '\n'.join(results))) + _("Followings are duplicated combinations,\n\n%s" % "\n".join(results)) + ) class AccountSpreadTemplateAuto(models.Model): - _name = 'account.spread.template.auto' - _description = 'Auto create spread, based on product/account/analytic' + _name = "account.spread.template.auto" + _description = "Auto create spread, based on product/account/analytic" template_id = fields.Many2one( - comodel_name='account.spread.template', - string='Spread Template', + comodel_name="account.spread.template", + string="Spread Template", required=True, - ondelete='cascade', + ondelete="cascade", index=True, ) - company_id = fields.Many2one( - related='template_id.company_id', - store=True, - ) - name = fields.Char( - required=True, - default='/', - ) - product_id = fields.Many2one( - comodel_name='product.product', - string='Product', - ) - account_id = fields.Many2one( - comodel_name='account.account', - string='Account', - ) + company_id = fields.Many2one(related="template_id.company_id", store=True,) + name = fields.Char(required=True, default="/",) + product_id = fields.Many2one(comodel_name="product.product", string="Product",) + account_id = fields.Many2one(comodel_name="account.account", string="Account",) analytic_account_id = fields.Many2one( - comodel_name='account.analytic.account', - string='Analytic', + comodel_name="account.analytic.account", string="Analytic", ) diff --git a/account_spread_cost_revenue/models/res_company.py b/account_spread_cost_revenue/models/res_company.py index 8b5d17eb..afddf497 100644 --- a/account_spread_cost_revenue/models/res_company.py +++ b/account_spread_cost_revenue/models/res_company.py @@ -5,29 +5,36 @@ from odoo import fields, models class ResCompany(models.Model): - _inherit = 'res.company' + _inherit = "res.company" default_spread_revenue_account_id = fields.Many2one( - 'account.account', string='Revenue Spread Account') + "account.account", string="Revenue Spread Account" + ) default_spread_expense_account_id = fields.Many2one( - 'account.account', string='Expense Spread Account') + "account.account", string="Expense Spread Account" + ) default_spread_revenue_journal_id = fields.Many2one( - 'account.journal', string='Revenue Spread Journal') + "account.journal", string="Revenue Spread Journal" + ) default_spread_expense_journal_id = fields.Many2one( - 'account.journal', string='Expense Spread Journal') + "account.journal", string="Expense Spread Journal" + ) allow_spread_planning = fields.Boolean( default=True, help="Disable this option if you do not want to allow the " - "spreading before the invoice is validated.") + "spreading before the invoice is validated.", + ) force_move_auto_post = fields.Boolean( - 'Auto-post spread lines', + "Auto-post spread lines", help="Enable this option if you want to post automatically the " - "accounting moves of all the spreads.") + "accounting moves of all the spreads.", + ) auto_archive = fields.Boolean( - 'Auto-archive spread', + "Auto-archive spread", help="Enable this option if you want the cron job to automatically " - "archive the spreads when all lines are posted.") + "archive the spreads when all lines are posted.", + ) diff --git a/account_spread_cost_revenue/security/account_spread_security.xml b/account_spread_cost_revenue/security/account_spread_security.xml index 9090c609..1e72ba70 100644 --- a/account_spread_cost_revenue/security/account_spread_security.xml +++ b/account_spread_cost_revenue/security/account_spread_security.xml @@ -1,27 +1,29 @@ - + - Account Spread multi-company - - - ['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])] + + + ['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])] - Account Spread Template multi-company - - - ['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])] + + + ['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])] - Account Spread Tempalte Auto multi-company - - - ['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])] + + + ['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])] - 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 68b941fc..c3fdde5b 100644 --- a/account_spread_cost_revenue/static/src/js/account_spread.js +++ b/account_spread_cost_revenue/static/src/js/account_spread.js @@ -1,41 +1,41 @@ -odoo.define('account_spread_cost_revenue.widget', function (require) { +odoo.define("account_spread_cost_revenue.widget", function(require) { "use strict"; - var AbstractField = require('web.AbstractField'); - var core = require('web.core'); - var registry = require('web.field_registry'); + var AbstractField = require("web.AbstractField"); + var core = require("web.core"); + var registry = require("web.field_registry"); var _t = core._t; var AccountSpreadWidget = AbstractField.extend({ events: _.extend({}, AbstractField.prototype.events, { - 'click': '_onClick', + click: "_onClick", }), description: "", /** * @override */ - isSet: function () { - return this.value !== 'unavailable'; + isSet: function() { + return this.value !== "unavailable"; }, /** * @override * @private */ - _render: function () { - var className = ''; - var style = 'btn fa fa-arrow-circle-right o_spread_line '; - var title = ''; - if (this.recordData.spread_check === 'linked') { - className = 'o_is_linked'; - title = _t('Linked to spread'); + _render: function() { + var className = ""; + var style = "btn fa fa-arrow-circle-right o_spread_line "; + var title = ""; + if (this.recordData.spread_check === "linked") { + className = "o_is_linked"; + title = _t("Linked to spread"); } else { - title = _t('Not linked to spread'); + title = _t("Not linked to spread"); } - var $button = $('