mirror of
https://github.com/OCA/contract.git
synced 2025-02-13 17:57:24 +02:00
[MIG] contract: Migration to 13.0
- Standard procedure - Adapt invoice creation to new account.move - Tests adapted
This commit is contained in:
committed by
Jean-Charles Drubay
parent
92a4e7781e
commit
9ed0486d44
@@ -6,11 +6,9 @@ from . import contract_template
|
||||
from . import contract
|
||||
from . import contract_template_line
|
||||
from . import contract_line
|
||||
from . import account_invoice
|
||||
from . import account_invoice_line
|
||||
from . import account_move
|
||||
from . import res_partner
|
||||
from . import contract_tag
|
||||
from . import res_company
|
||||
from . import res_config_settings
|
||||
from . import contract_terminate_reason
|
||||
from . import ir_ui_view
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Copyright 2004-2010 OpenERP SA
|
||||
# Copyright 2014 Angel Moya <angel.moya@domatix.com>
|
||||
# Copyright 2015 Pedro M. Baeza <pedro.baeza@tecnativa.com>
|
||||
# Copyright 2015-2020 Tecnativa - Pedro M. Baeza
|
||||
# Copyright 2016-2018 Carlos Dauden <carlos.dauden@tecnativa.com>
|
||||
# Copyright 2016-2017 LasLabs Inc.
|
||||
# Copyright 2018 ACSONE SA/NV
|
||||
@@ -39,7 +39,7 @@ class ContractAbstractContract(models.AbstractModel):
|
||||
"res.company",
|
||||
string="Company",
|
||||
required=True,
|
||||
default=lambda self: self.env["res.company"]._company_default_get(self._name),
|
||||
default=lambda self: self.env.company.id,
|
||||
)
|
||||
|
||||
@api.onchange("contract_type")
|
||||
|
||||
@@ -10,8 +10,6 @@ from odoo import api, fields, models
|
||||
from odoo.exceptions import ValidationError
|
||||
from odoo.tools.translate import _
|
||||
|
||||
from odoo.addons import decimal_precision as dp
|
||||
|
||||
|
||||
class ContractAbstractContractLine(models.AbstractModel):
|
||||
_name = "contract.abstract.contract.line"
|
||||
@@ -35,13 +33,11 @@ class ContractAbstractContractLine(models.AbstractModel):
|
||||
inverse="_inverse_price_unit",
|
||||
)
|
||||
price_subtotal = fields.Float(
|
||||
compute="_compute_price_subtotal",
|
||||
digits=dp.get_precision("Account"),
|
||||
string="Sub Total",
|
||||
compute="_compute_price_subtotal", digits="Account", string="Sub Total",
|
||||
)
|
||||
discount = fields.Float(
|
||||
string="Discount (%)",
|
||||
digits=dp.get_precision("Discount"),
|
||||
digits="Discount",
|
||||
help="Discount that is applied in generated invoices."
|
||||
" It should be less or equal to 100",
|
||||
)
|
||||
@@ -123,7 +119,7 @@ class ContractAbstractContractLine(models.AbstractModel):
|
||||
ondelete="cascade",
|
||||
)
|
||||
display_type = fields.Selection(
|
||||
selection=[("line_section", "Section"), ("line_note", "Note"),],
|
||||
selection=[("line_section", "Section"), ("line_note", "Note")],
|
||||
default=False,
|
||||
help="Technical field for UX purpose.",
|
||||
)
|
||||
@@ -140,6 +136,7 @@ class ContractAbstractContractLine(models.AbstractModel):
|
||||
"- Custom: Depending on the recurrence to be define.",
|
||||
)
|
||||
is_recurring_note = fields.Boolean(compute="_compute_is_recurring_note")
|
||||
company_id = fields.Many2one(related="contract_id.company_id", store=True)
|
||||
|
||||
@api.model
|
||||
def _get_default_recurring_invoicing_offset(
|
||||
@@ -153,7 +150,8 @@ class ContractAbstractContractLine(models.AbstractModel):
|
||||
else:
|
||||
return 1
|
||||
|
||||
def is_recurring_note(self):
|
||||
@api.depends("display_type", "note_invoicing_mode")
|
||||
def _compute_is_recurring_note(self):
|
||||
for record in self:
|
||||
record.is_recurring_note = (
|
||||
record.display_type == "line_note"
|
||||
@@ -163,7 +161,8 @@ class ContractAbstractContractLine(models.AbstractModel):
|
||||
@api.depends("recurring_invoicing_type", "recurring_rule_type")
|
||||
def _compute_recurring_invoicing_offset(self):
|
||||
for rec in self:
|
||||
rec.recurring_invoicing_offset = self._get_default_recurring_invoicing_offset(
|
||||
method = self._get_default_recurring_invoicing_offset
|
||||
rec.recurring_invoicing_offset = method(
|
||||
rec.recurring_invoicing_type, rec.recurring_rule_type
|
||||
)
|
||||
|
||||
@@ -206,7 +205,6 @@ class ContractAbstractContractLine(models.AbstractModel):
|
||||
for line in self.filtered(lambda x: not x.automatic_price):
|
||||
line.specific_price = line.price_unit
|
||||
|
||||
@api.multi
|
||||
@api.depends("quantity", "price_unit", "discount")
|
||||
def _compute_price_subtotal(self):
|
||||
for line in self:
|
||||
@@ -219,14 +217,12 @@ class ContractAbstractContractLine(models.AbstractModel):
|
||||
else:
|
||||
line.price_subtotal = subtotal
|
||||
|
||||
@api.multi
|
||||
@api.constrains("discount")
|
||||
def _check_discount(self):
|
||||
for line in self:
|
||||
if line.discount > 100:
|
||||
raise ValidationError(_("Discount should be less or equal to 100"))
|
||||
|
||||
@api.multi
|
||||
@api.onchange("product_id")
|
||||
def _onchange_product_id(self):
|
||||
if not self.product_id:
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
# © 2016 Carlos Dauden <carlos.dauden@tecnativa.com>
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from odoo import fields, models
|
||||
|
||||
|
||||
class AccountInvoice(models.Model):
|
||||
_inherit = "account.invoice"
|
||||
|
||||
# We keep this field for migration purpose
|
||||
old_contract_id = fields.Many2one("contract.contract", oldname="contract_id")
|
||||
@@ -1,12 +0,0 @@
|
||||
# Copyright 2018 ACSONE SA/NV.
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from odoo import fields, models
|
||||
|
||||
|
||||
class AccountInvoiceLine(models.Model):
|
||||
_inherit = "account.invoice.line"
|
||||
|
||||
contract_line_id = fields.Many2one(
|
||||
"contract.line", string="Contract Line", index=True
|
||||
)
|
||||
21
contract/models/account_move.py
Normal file
21
contract/models/account_move.py
Normal file
@@ -0,0 +1,21 @@
|
||||
# Copyright 2016 Tecnativa - Carlos Dauden
|
||||
# Copyright 2018 ACSONE SA/NV.
|
||||
# Copyright 2020 Tecnativa - Pedro M. Baeza
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from odoo import fields, models
|
||||
|
||||
|
||||
class AccountInvoice(models.Model):
|
||||
_inherit = "account.move"
|
||||
|
||||
# We keep this field for migration purpose
|
||||
old_contract_id = fields.Many2one("contract.contract")
|
||||
|
||||
|
||||
class AccountMoveLine(models.Model):
|
||||
_inherit = "account.move.line"
|
||||
|
||||
contract_line_id = fields.Many2one(
|
||||
"contract.line", string="Contract Line", index=True
|
||||
)
|
||||
@@ -1,6 +1,6 @@
|
||||
# Copyright 2004-2010 OpenERP SA
|
||||
# Copyright 2014 Angel Moya <angel.moya@domatix.com>
|
||||
# Copyright 2015 Pedro M. Baeza <pedro.baeza@tecnativa.com>
|
||||
# Copyright 2015-2020 Tecnativa - Pedro M. Baeza
|
||||
# Copyright 2016-2018 Carlos Dauden <carlos.dauden@tecnativa.com>
|
||||
# Copyright 2016-2017 LasLabs Inc.
|
||||
# Copyright 2018 ACSONE SA/NV
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
from odoo import api, fields, models
|
||||
from odoo.exceptions import UserError, ValidationError
|
||||
from odoo.tests import Form
|
||||
from odoo.tools.translate import _
|
||||
|
||||
|
||||
@@ -106,7 +107,6 @@ class ContractContract(models.Model):
|
||||
track_visibility="onchange",
|
||||
)
|
||||
|
||||
@api.multi
|
||||
def _inverse_partner_id(self):
|
||||
for rec in self:
|
||||
if not rec.invoice_partner_id:
|
||||
@@ -114,18 +114,15 @@ class ContractContract(models.Model):
|
||||
"invoice"
|
||||
]
|
||||
|
||||
@api.multi
|
||||
def _get_related_invoices(self):
|
||||
self.ensure_one()
|
||||
|
||||
invoices = (
|
||||
self.env["account.invoice.line"]
|
||||
self.env["account.move.line"]
|
||||
.search([("contract_line_id", "in", self.contract_line_ids.ids,)])
|
||||
.mapped("invoice_id")
|
||||
)
|
||||
invoices |= self.env["account.invoice"].search(
|
||||
[("old_contract_id", "=", self.id)]
|
||||
.mapped("move_id")
|
||||
)
|
||||
invoices |= self.env["account.move"].search([("old_contract_id", "=", self.id)])
|
||||
return invoices
|
||||
|
||||
def _get_computed_currency(self):
|
||||
@@ -162,31 +159,18 @@ class ContractContract(models.Model):
|
||||
else:
|
||||
rec.manual_currency_id = False
|
||||
|
||||
@api.multi
|
||||
def _compute_invoice_count(self):
|
||||
for rec in self:
|
||||
rec.invoice_count = len(rec._get_related_invoices())
|
||||
|
||||
@api.multi
|
||||
def action_show_invoices(self):
|
||||
self.ensure_one()
|
||||
tree_view_ref = (
|
||||
"account.invoice_supplier_tree"
|
||||
if self.contract_type == "purchase"
|
||||
else "account.invoice_tree_with_onboarding"
|
||||
)
|
||||
form_view_ref = (
|
||||
"account.invoice_supplier_form"
|
||||
if self.contract_type == "purchase"
|
||||
else "account.invoice_form"
|
||||
)
|
||||
tree_view = self.env.ref(tree_view_ref, raise_if_not_found=False)
|
||||
form_view = self.env.ref(form_view_ref, raise_if_not_found=False)
|
||||
tree_view = self.env.ref("account.view_invoice_tree", raise_if_not_found=False)
|
||||
form_view = self.env.ref("account.view_move_form", raise_if_not_found=False)
|
||||
action = {
|
||||
"type": "ir.actions.act_window",
|
||||
"name": "Invoices",
|
||||
"res_model": "account.invoice",
|
||||
"view_type": "form",
|
||||
"res_model": "account.move",
|
||||
"view_mode": "tree,kanban,form,calendar,pivot,graph,activity",
|
||||
"domain": [("id", "in", self._get_related_invoices().ids)],
|
||||
}
|
||||
@@ -216,6 +200,8 @@ class ContractContract(models.Model):
|
||||
).mapped("recurring_next_date")
|
||||
if recurring_next_date:
|
||||
contract.recurring_next_date = min(recurring_next_date)
|
||||
else:
|
||||
contract.recurring_next_date = False
|
||||
|
||||
@api.depends("contract_line_ids.create_invoice_visibility")
|
||||
def _compute_create_invoice_visibility(self):
|
||||
@@ -279,7 +265,6 @@ class ContractContract(models.Model):
|
||||
}
|
||||
}
|
||||
|
||||
@api.multi
|
||||
def _convert_contract_lines(self, contract):
|
||||
self.ensure_one()
|
||||
new_lines = self.env["contract.line"]
|
||||
@@ -295,8 +280,12 @@ class ContractContract(models.Model):
|
||||
new_lines._onchange_is_auto_renew()
|
||||
return new_lines
|
||||
|
||||
@api.multi
|
||||
def _prepare_invoice(self, date_invoice, journal=None):
|
||||
"""Prepare in a Form the values for the generated invoice record.
|
||||
|
||||
:return: A tuple with the vals dictionary and the Form with the
|
||||
preloaded values for being used in lines.
|
||||
"""
|
||||
self.ensure_one()
|
||||
if not journal:
|
||||
journal = (
|
||||
@@ -318,36 +307,30 @@ class ContractContract(models.Model):
|
||||
invoice_type = "out_invoice"
|
||||
if self.contract_type == "purchase":
|
||||
invoice_type = "in_invoice"
|
||||
vinvoice = (
|
||||
self.env["account.invoice"]
|
||||
.with_context(force_company=self.company_id.id,)
|
||||
.new(
|
||||
{
|
||||
"company_id": self.company_id.id,
|
||||
"partner_id": self.invoice_partner_id.id,
|
||||
"type": invoice_type,
|
||||
}
|
||||
move_form = Form(
|
||||
self.env["account.move"].with_context(
|
||||
force_company=self.company_id.id, default_type=invoice_type
|
||||
)
|
||||
)
|
||||
vinvoice._onchange_partner_id()
|
||||
invoice_vals = vinvoice._convert_to_write(vinvoice._cache)
|
||||
move_form.partner_id = self.invoice_partner_id
|
||||
if self.payment_term_id:
|
||||
move_form.invoice_payment_term_id = self.payment_term_id
|
||||
if self.fiscal_position_id:
|
||||
move_form.fiscal_position_id = self.fiscal_position_id
|
||||
invoice_vals = move_form._values_to_save(all_fields=True)
|
||||
invoice_vals.update(
|
||||
{
|
||||
"name": self.code,
|
||||
"ref": self.code,
|
||||
"company_id": self.company_id.id,
|
||||
"currency_id": self.currency_id.id,
|
||||
"date_invoice": date_invoice,
|
||||
"invoice_date": date_invoice,
|
||||
"journal_id": journal.id,
|
||||
"origin": self.name,
|
||||
"invoice_origin": self.name,
|
||||
"user_id": self.user_id.id,
|
||||
}
|
||||
)
|
||||
if self.payment_term_id:
|
||||
invoice_vals["payment_term_id"] = self.payment_term_id.id
|
||||
if self.fiscal_position_id:
|
||||
invoice_vals["fiscal_position_id"] = self.fiscal_position_id.id
|
||||
return invoice_vals
|
||||
return invoice_vals, move_form
|
||||
|
||||
@api.multi
|
||||
def action_contract_send(self):
|
||||
self.ensure_one()
|
||||
template = self.env.ref("contract.email_contract_template", False)
|
||||
@@ -362,7 +345,6 @@ class ContractContract(models.Model):
|
||||
return {
|
||||
"name": _("Compose Email"),
|
||||
"type": "ir.actions.act_window",
|
||||
"view_type": "form",
|
||||
"view_mode": "form",
|
||||
"res_model": "mail.compose.message",
|
||||
"views": [(compose_form.id, "form")],
|
||||
@@ -371,40 +353,6 @@ class ContractContract(models.Model):
|
||||
"context": ctx,
|
||||
}
|
||||
|
||||
@api.model
|
||||
def _finalize_invoice_values(self, invoice_values):
|
||||
"""Provided for keeping compatibility in this version."""
|
||||
# TODO: Must be removed in >=13.0
|
||||
return invoice_values
|
||||
|
||||
@api.model
|
||||
def _finalize_invoice_creation(self, invoices):
|
||||
"""This method is called right after the creation of the invoices.
|
||||
|
||||
Override it when you need to do something after the records are created
|
||||
in the DB. If you need to modify any value, better to do it on the
|
||||
_prepare_* methods on contract or contract line.
|
||||
"""
|
||||
invoices.compute_taxes()
|
||||
|
||||
@api.model
|
||||
def _finalize_and_create_invoices(self, invoices_values):
|
||||
"""This method:
|
||||
|
||||
- creates the invoices
|
||||
- finalizes the created invoices (tax computation...)
|
||||
|
||||
:param invoices_values: list of dictionaries (invoices values)
|
||||
:return: created invoices (account.invoice)
|
||||
"""
|
||||
final_invoices_values = []
|
||||
# TODO: This call must be removed in >=13.0
|
||||
for invoice_values in invoices_values:
|
||||
final_invoices_values.append(self._finalize_invoice_values(invoice_values))
|
||||
invoices = self.env["account.invoice"].create(final_invoices_values)
|
||||
self._finalize_invoice_creation(invoices)
|
||||
return invoices
|
||||
|
||||
@api.model
|
||||
def _get_contracts_to_invoice_domain(self, date_ref=None):
|
||||
"""
|
||||
@@ -419,7 +367,6 @@ class ContractContract(models.Model):
|
||||
domain.extend([("recurring_next_date", "<=", date_ref)])
|
||||
return domain
|
||||
|
||||
@api.multi
|
||||
def _get_lines_to_invoice(self, date_ref):
|
||||
"""
|
||||
This method fetches and returns the lines to invoice on the contract
|
||||
@@ -460,7 +407,6 @@ class ContractContract(models.Model):
|
||||
previous = line
|
||||
return lines2invoice.sorted()
|
||||
|
||||
@api.multi
|
||||
def _prepare_recurring_invoices_values(self, date_ref=False):
|
||||
"""
|
||||
This method builds the list of invoices values to create, based on
|
||||
@@ -479,21 +425,15 @@ class ContractContract(models.Model):
|
||||
contract_lines = contract._get_lines_to_invoice(date_ref)
|
||||
if not contract_lines:
|
||||
continue
|
||||
invoice_values = contract._prepare_invoice(date_ref)
|
||||
invoice_vals, move_form = contract._prepare_invoice(date_ref)
|
||||
invoice_vals["invoice_line_ids"] = []
|
||||
for line in contract_lines:
|
||||
invoice_values.setdefault("invoice_line_ids", [])
|
||||
invoice_line_values = line._prepare_invoice_line(
|
||||
invoice_values=invoice_values,
|
||||
)
|
||||
if invoice_line_values:
|
||||
invoice_values["invoice_line_ids"].append(
|
||||
(0, 0, invoice_line_values)
|
||||
)
|
||||
invoices_values.append(invoice_values)
|
||||
invoice_line_vals = line._prepare_invoice_line(move_form=move_form)
|
||||
invoice_vals["invoice_line_ids"].append((0, 0, invoice_line_vals))
|
||||
invoices_values.append(invoice_vals)
|
||||
contract_lines._update_recurring_next_date()
|
||||
return invoices_values
|
||||
|
||||
@api.multi
|
||||
def recurring_create_invoice(self):
|
||||
"""
|
||||
This method triggers the creation of the next invoices of the contracts
|
||||
@@ -511,17 +451,16 @@ class ContractContract(models.Model):
|
||||
)
|
||||
return invoice
|
||||
|
||||
@api.multi
|
||||
def _recurring_create_invoice(self, date_ref=False):
|
||||
invoices_values = self._prepare_recurring_invoices_values(date_ref)
|
||||
return self._finalize_and_create_invoices(invoices_values)
|
||||
return self.env["account.move"].create(invoices_values)
|
||||
|
||||
@api.model
|
||||
def cron_recurring_create_invoice(self, date_ref=None):
|
||||
if not date_ref:
|
||||
date_ref = fields.Date.context_today(self)
|
||||
domain = self._get_contracts_to_invoice_domain(date_ref)
|
||||
invoices = self.env["account.invoice"]
|
||||
invoices = self.env["account.move"]
|
||||
# Invoice by companies, so assignation emails get correct context
|
||||
companies_to_invoice = self.read_group(domain, ["company_id"], ["company_id"])
|
||||
for row in companies_to_invoice:
|
||||
@@ -531,7 +470,6 @@ class ContractContract(models.Model):
|
||||
invoices |= contracts_to_invoice._recurring_create_invoice(date_ref)
|
||||
return invoices
|
||||
|
||||
@api.multi
|
||||
def action_terminate_contract(self):
|
||||
self.ensure_one()
|
||||
context = {"default_contract_id": self.id}
|
||||
@@ -539,13 +477,11 @@ class ContractContract(models.Model):
|
||||
"type": "ir.actions.act_window",
|
||||
"name": _("Terminate Contract"),
|
||||
"res_model": "contract.contract.terminate",
|
||||
"view_type": "form",
|
||||
"view_mode": "form",
|
||||
"target": "new",
|
||||
"context": context,
|
||||
}
|
||||
|
||||
@api.multi
|
||||
def _terminate_contract(
|
||||
self, terminate_reason_id, terminate_comment, terminate_date
|
||||
):
|
||||
@@ -563,7 +499,6 @@ class ContractContract(models.Model):
|
||||
)
|
||||
return True
|
||||
|
||||
@api.multi
|
||||
def action_cancel_contract_termination(self):
|
||||
self.ensure_one()
|
||||
self.write(
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
# Copyright 2017 LasLabs Inc.
|
||||
# Copyright 2018 ACSONE SA/NV.
|
||||
# Copyright 2020 Tecnativa - Pedro M. Baeza
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from datetime import timedelta
|
||||
@@ -118,7 +119,6 @@ class ContractLine(models.Model):
|
||||
default=True,
|
||||
)
|
||||
|
||||
@api.multi
|
||||
@api.depends(
|
||||
"date_end", "termination_notice_rule_type", "termination_notice_interval",
|
||||
)
|
||||
@@ -128,14 +128,15 @@ class ContractLine(models.Model):
|
||||
rec.termination_notice_date = rec.date_end - self.get_relative_delta(
|
||||
rec.termination_notice_rule_type, rec.termination_notice_interval,
|
||||
)
|
||||
else:
|
||||
rec.termination_notice_date = False
|
||||
|
||||
@api.multi
|
||||
@api.depends("is_canceled", "date_start", "date_end", "is_auto_renew")
|
||||
def _compute_state(self):
|
||||
today = fields.Date.context_today(self)
|
||||
for rec in self:
|
||||
rec.state = False
|
||||
if rec.display_type:
|
||||
rec.state = False
|
||||
continue
|
||||
if rec.is_canceled:
|
||||
rec.state = "canceled"
|
||||
@@ -192,8 +193,8 @@ class ContractLine(models.Model):
|
||||
("date_end", ">=", today),
|
||||
("date_end", "=", False),
|
||||
"|",
|
||||
"&",
|
||||
("is_auto_renew", "=", True),
|
||||
"&",
|
||||
("is_auto_renew", "=", False),
|
||||
("termination_notice_date", ">", today),
|
||||
]
|
||||
@@ -290,16 +291,16 @@ class ContractLine(models.Model):
|
||||
)
|
||||
def _compute_allowed(self):
|
||||
for rec in self:
|
||||
rec.update(
|
||||
{
|
||||
"is_plan_successor_allowed": False,
|
||||
"is_stop_plan_successor_allowed": False,
|
||||
"is_stop_allowed": False,
|
||||
"is_cancel_allowed": False,
|
||||
"is_un_cancel_allowed": False,
|
||||
}
|
||||
)
|
||||
if rec.contract_id.is_terminated:
|
||||
rec.update(
|
||||
{
|
||||
"is_plan_successor_allowed": False,
|
||||
"is_stop_plan_successor_allowed": False,
|
||||
"is_stop_allowed": False,
|
||||
"is_cancel_allowed": False,
|
||||
"is_un_cancel_allowed": False,
|
||||
}
|
||||
)
|
||||
continue
|
||||
if rec.date_start:
|
||||
allowed = get_allowed(
|
||||
@@ -315,7 +316,9 @@ class ContractLine(models.Model):
|
||||
rec.update(
|
||||
{
|
||||
"is_plan_successor_allowed": allowed.plan_successor,
|
||||
"is_stop_plan_successor_allowed": allowed.stop_plan_successor,
|
||||
"is_stop_plan_successor_allowed": (
|
||||
allowed.stop_plan_successor
|
||||
),
|
||||
"is_stop_allowed": allowed.stop,
|
||||
"is_cancel_allowed": allowed.cancel,
|
||||
"is_un_cancel_allowed": allowed.uncancel,
|
||||
@@ -618,7 +621,13 @@ class ContractLine(models.Model):
|
||||
% line.name
|
||||
)
|
||||
|
||||
@api.depends("recurring_next_date", "date_start", "date_end")
|
||||
@api.depends(
|
||||
"display_type",
|
||||
"is_recurring_note",
|
||||
"recurring_next_date",
|
||||
"date_start",
|
||||
"date_end",
|
||||
)
|
||||
def _compute_create_invoice_visibility(self):
|
||||
# TODO: depending on the lines, and their order, some sections
|
||||
# have no meaning in certain invoices
|
||||
@@ -633,51 +642,31 @@ class ContractLine(models.Model):
|
||||
else:
|
||||
rec.create_invoice_visibility = False
|
||||
|
||||
@api.multi
|
||||
def _prepare_invoice_line(self, invoice_id=False, invoice_values=False):
|
||||
def _prepare_invoice_line(self, move_form):
|
||||
self.ensure_one()
|
||||
dates = self._get_period_to_invoice(
|
||||
self.last_date_invoiced, self.recurring_next_date
|
||||
)
|
||||
invoice_line_vals = {
|
||||
"display_type": self.display_type,
|
||||
"product_id": self.product_id.id,
|
||||
"quantity": self._get_quantity_to_invoice(*dates),
|
||||
"uom_id": self.uom_id.id,
|
||||
"discount": self.discount,
|
||||
"contract_line_id": self.id,
|
||||
}
|
||||
if invoice_id:
|
||||
invoice_line_vals["invoice_id"] = invoice_id.id
|
||||
invoice_line = (
|
||||
self.env["account.invoice.line"]
|
||||
.with_context(force_company=self.contract_id.company_id.id,)
|
||||
.new(invoice_line_vals)
|
||||
)
|
||||
if invoice_values and not invoice_id:
|
||||
invoice = (
|
||||
self.env["account.invoice"]
|
||||
.with_context(force_company=self.contract_id.company_id.id,)
|
||||
.new(invoice_values)
|
||||
)
|
||||
invoice_line.invoice_id = invoice
|
||||
# Get other invoice line values from product onchange
|
||||
invoice_line._onchange_product_id()
|
||||
invoice_line_vals = invoice_line._convert_to_write(invoice_line._cache)
|
||||
# Insert markers
|
||||
line_form = move_form.invoice_line_ids.new()
|
||||
line_form.display_type = self.display_type
|
||||
line_form.product_id = self.product_id
|
||||
invoice_line_vals = line_form._values_to_save(all_fields=True)
|
||||
name = self._insert_markers(dates[0], dates[1])
|
||||
invoice_line_vals.update(
|
||||
{
|
||||
"quantity": self._get_quantity_to_invoice(*dates),
|
||||
"product_uom_id": self.uom_id.id,
|
||||
"discount": self.discount,
|
||||
"contract_line_id": self.id,
|
||||
"sequence": self.sequence,
|
||||
"name": name,
|
||||
"account_analytic_id": self.analytic_account_id.id,
|
||||
"analytic_account_id": self.analytic_account_id.id,
|
||||
"analytic_tag_ids": [(6, 0, self.analytic_tag_ids.ids)],
|
||||
"price_unit": self.price_unit,
|
||||
}
|
||||
)
|
||||
return invoice_line_vals
|
||||
|
||||
@api.multi
|
||||
def _get_period_to_invoice(
|
||||
self, last_date_invoiced, recurring_next_date, stop_at_date_end=True
|
||||
):
|
||||
@@ -702,7 +691,6 @@ class ContractLine(models.Model):
|
||||
)
|
||||
return first_date_invoiced, last_date_invoiced, recurring_next_date
|
||||
|
||||
@api.multi
|
||||
def _insert_markers(self, first_date_invoiced, last_date_invoiced):
|
||||
self.ensure_one()
|
||||
lang_obj = self.env["res.lang"]
|
||||
@@ -713,7 +701,6 @@ class ContractLine(models.Model):
|
||||
name = name.replace("#END#", last_date_invoiced.strftime(date_format))
|
||||
return name
|
||||
|
||||
@api.multi
|
||||
def _update_recurring_next_date(self):
|
||||
for rec in self:
|
||||
last_date_invoiced = rec.next_period_date_end
|
||||
@@ -732,7 +719,6 @@ class ContractLine(models.Model):
|
||||
}
|
||||
)
|
||||
|
||||
@api.multi
|
||||
def _init_last_date_invoiced(self):
|
||||
"""Used to init last_date_invoiced for migration purpose"""
|
||||
for rec in self:
|
||||
@@ -778,7 +764,6 @@ class ContractLine(models.Model):
|
||||
else:
|
||||
return relativedelta(years=interval)
|
||||
|
||||
@api.multi
|
||||
def _delay(self, delay_delta):
|
||||
"""
|
||||
Delay a contract line
|
||||
@@ -811,7 +796,6 @@ class ContractLine(models.Model):
|
||||
}
|
||||
)
|
||||
|
||||
@api.multi
|
||||
def _prepare_value_for_stop(self, date_end, manual_renew_needed):
|
||||
self.ensure_one()
|
||||
return {
|
||||
@@ -828,7 +812,6 @@ class ContractLine(models.Model):
|
||||
),
|
||||
}
|
||||
|
||||
@api.multi
|
||||
def stop(self, date_end, manual_renew_needed=False, post_message=True):
|
||||
"""
|
||||
Put date_end on contract line
|
||||
@@ -868,7 +851,6 @@ class ContractLine(models.Model):
|
||||
)
|
||||
return True
|
||||
|
||||
@api.multi
|
||||
def _prepare_value_for_plan_successor(
|
||||
self, date_start, date_end, is_auto_renew, recurring_next_date=False
|
||||
):
|
||||
@@ -893,7 +875,6 @@ class ContractLine(models.Model):
|
||||
values["predecessor_contract_line_id"] = self.id
|
||||
return values
|
||||
|
||||
@api.multi
|
||||
def plan_successor(
|
||||
self,
|
||||
date_start,
|
||||
@@ -939,7 +920,6 @@ class ContractLine(models.Model):
|
||||
rec.contract_id.message_post(body=msg)
|
||||
return contract_line
|
||||
|
||||
@api.multi
|
||||
def stop_plan_successor(self, date_start, date_end, is_auto_renew):
|
||||
"""
|
||||
Stop a contract line for a defined period and start it later
|
||||
@@ -1035,7 +1015,6 @@ class ContractLine(models.Model):
|
||||
rec.contract_id.message_post(body=msg)
|
||||
return contract_line
|
||||
|
||||
@api.multi
|
||||
def cancel(self):
|
||||
if not all(self.mapped("is_cancel_allowed")):
|
||||
raise ValidationError(_("Cancel not allowed for this line"))
|
||||
@@ -1053,7 +1032,6 @@ class ContractLine(models.Model):
|
||||
)
|
||||
return self.write({"is_canceled": True, "is_auto_renew": False})
|
||||
|
||||
@api.multi
|
||||
def uncancel(self, recurring_next_date):
|
||||
if not all(self.mapped("is_un_cancel_allowed")):
|
||||
raise ValidationError(_("Un-cancel not allowed for this line"))
|
||||
@@ -1075,7 +1053,6 @@ class ContractLine(models.Model):
|
||||
rec.recurring_next_date = recurring_next_date
|
||||
return True
|
||||
|
||||
@api.multi
|
||||
def action_uncancel(self):
|
||||
self.ensure_one()
|
||||
context = {
|
||||
@@ -1088,14 +1065,12 @@ class ContractLine(models.Model):
|
||||
"type": "ir.actions.act_window",
|
||||
"name": "Un-Cancel Contract Line",
|
||||
"res_model": "contract.line.wizard",
|
||||
"view_type": "form",
|
||||
"view_mode": "form",
|
||||
"views": [(view_id, "form")],
|
||||
"target": "new",
|
||||
"context": context,
|
||||
}
|
||||
|
||||
@api.multi
|
||||
def action_plan_successor(self):
|
||||
self.ensure_one()
|
||||
context = {
|
||||
@@ -1110,14 +1085,12 @@ class ContractLine(models.Model):
|
||||
"type": "ir.actions.act_window",
|
||||
"name": "Plan contract line successor",
|
||||
"res_model": "contract.line.wizard",
|
||||
"view_type": "form",
|
||||
"view_mode": "form",
|
||||
"views": [(view_id, "form")],
|
||||
"target": "new",
|
||||
"context": context,
|
||||
}
|
||||
|
||||
@api.multi
|
||||
def action_stop(self):
|
||||
self.ensure_one()
|
||||
context = {
|
||||
@@ -1130,14 +1103,12 @@ class ContractLine(models.Model):
|
||||
"type": "ir.actions.act_window",
|
||||
"name": "Terminate contract line",
|
||||
"res_model": "contract.line.wizard",
|
||||
"view_type": "form",
|
||||
"view_mode": "form",
|
||||
"views": [(view_id, "form")],
|
||||
"target": "new",
|
||||
"context": context,
|
||||
}
|
||||
|
||||
@api.multi
|
||||
def action_stop_plan_successor(self):
|
||||
self.ensure_one()
|
||||
context = {
|
||||
@@ -1152,14 +1123,12 @@ class ContractLine(models.Model):
|
||||
"type": "ir.actions.act_window",
|
||||
"name": "Suspend contract line",
|
||||
"res_model": "contract.line.wizard",
|
||||
"view_type": "form",
|
||||
"view_mode": "form",
|
||||
"views": [(view_id, "form")],
|
||||
"target": "new",
|
||||
"context": context,
|
||||
}
|
||||
|
||||
@api.multi
|
||||
def _get_renewal_new_date_end(self):
|
||||
self.ensure_one()
|
||||
date_start = self.date_end + relativedelta(days=1)
|
||||
@@ -1168,7 +1137,6 @@ class ContractLine(models.Model):
|
||||
)
|
||||
return date_end
|
||||
|
||||
@api.multi
|
||||
def _renew_create_line(self, date_end):
|
||||
self.ensure_one()
|
||||
date_start = self.date_end + relativedelta(days=1)
|
||||
@@ -1180,13 +1148,11 @@ class ContractLine(models.Model):
|
||||
new_line._onchange_date_start()
|
||||
return new_line
|
||||
|
||||
@api.multi
|
||||
def _renew_extend_line(self, date_end):
|
||||
self.ensure_one()
|
||||
self.date_end = date_end
|
||||
return self
|
||||
|
||||
@api.multi
|
||||
def renew(self):
|
||||
res = self.env["contract.line"]
|
||||
for rec in self:
|
||||
@@ -1240,7 +1206,6 @@ class ContractLine(models.Model):
|
||||
view_id = self.env.ref("contract.contract_line_customer_form_view").id
|
||||
return super().fields_view_get(view_id, view_type, toolbar, submenu)
|
||||
|
||||
@api.multi
|
||||
def unlink(self):
|
||||
"""stop unlink uncnacled lines"""
|
||||
for record in self:
|
||||
@@ -1248,7 +1213,6 @@ class ContractLine(models.Model):
|
||||
raise ValidationError(_("Contract line must be canceled before delete"))
|
||||
return super().unlink()
|
||||
|
||||
@api.multi
|
||||
def _get_quantity_to_invoice(
|
||||
self, period_first_date, period_last_date, invoice_date
|
||||
):
|
||||
|
||||
@@ -11,5 +11,5 @@ class ContractTag(models.Model):
|
||||
|
||||
name = fields.Char(requirment=True)
|
||||
company_id = fields.Many2one(
|
||||
"res.company", string="Company", default=lambda self: self.env.user.company_id,
|
||||
"res.company", string="Company", default=lambda self: self.env.company.id,
|
||||
)
|
||||
|
||||
@@ -20,5 +20,4 @@ class ContractTemplateLine(models.Model):
|
||||
comodel_name="contract.template",
|
||||
required=True,
|
||||
ondelete="cascade",
|
||||
oldname="analytic_account_id",
|
||||
)
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
# Copyright 2020 Tecnativa - Jairo Llopis
|
||||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
|
||||
|
||||
from odoo import api, models
|
||||
|
||||
|
||||
class IrUiView(models.Model):
|
||||
_inherit = "ir.ui.view"
|
||||
|
||||
@api.model
|
||||
def _prepare_qcontext(self):
|
||||
"""Patch context to use fw-compatible v13 company."""
|
||||
# TODO Delete this method in v13; it's upstream there
|
||||
result = super()._prepare_qcontext()
|
||||
if self.env.context.get("allowed_company_ids"):
|
||||
result["res_company"] = (
|
||||
self.env["res.company"]
|
||||
.browse(self.env.context["allowed_company_ids"][0])
|
||||
.sudo()
|
||||
)
|
||||
return result
|
||||
@@ -14,7 +14,7 @@ class ResPartner(models.Model):
|
||||
string="Purchase Contracts", compute="_compute_contract_count",
|
||||
)
|
||||
contract_ids = fields.One2many(
|
||||
comodel_name="contract.contract", inverse="partner_id", string="Contracts",
|
||||
comodel_name="contract.contract", inverse_name="partner_id", string="Contracts",
|
||||
)
|
||||
|
||||
def _compute_contract_count(self):
|
||||
|
||||
Reference in New Issue
Block a user