mirror of
https://github.com/OCA/contract.git
synced 2025-02-13 17:57:24 +02:00
156 lines
6.2 KiB
Python
156 lines
6.2 KiB
Python
# Copyright 2017 LasLabs Inc.
|
|
# Copyright 2018 ACSONE SA/NV.
|
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
|
|
|
from odoo import _, api, fields, models
|
|
from odoo.exceptions import ValidationError
|
|
|
|
|
|
class SaleOrder(models.Model):
|
|
_inherit = "sale.order"
|
|
|
|
is_contract = fields.Boolean(string="Is a contract", compute="_compute_is_contract")
|
|
contract_count = fields.Integer(compute="_compute_contract_count")
|
|
need_contract_creation = fields.Boolean(compute="_compute_need_contract_creation")
|
|
|
|
@api.constrains("state")
|
|
def _check_contact_is_not_terminated(self):
|
|
for rec in self:
|
|
if rec.state not in (
|
|
"sale",
|
|
"done",
|
|
"cancel",
|
|
) and rec.order_line.filtered("contract_id.is_terminated"):
|
|
raise ValidationError(
|
|
_("You can't upsell or downsell a terminated contract")
|
|
)
|
|
|
|
def _get_line_to_create_contract(self):
|
|
"""
|
|
Override this method to define more filter criteria of line for which we create contract
|
|
:return: line to create contract
|
|
"""
|
|
self.ensure_one()
|
|
line_to_create_contract = self.order_line.filtered(
|
|
lambda r: not r.contract_id and r.is_contract
|
|
)
|
|
return line_to_create_contract
|
|
|
|
def _get_line_to_update_contract(self):
|
|
"""
|
|
Override this method to define more filter criteria of line for which we update contract
|
|
:return: line to update contract
|
|
"""
|
|
self.ensure_one()
|
|
line_to_update_contract = self.order_line.filtered(
|
|
lambda r: r.contract_id
|
|
and r.is_contract
|
|
and r not in r.contract_id.contract_line_ids.mapped("sale_order_line_id")
|
|
)
|
|
return line_to_update_contract
|
|
|
|
@api.depends("order_line.contract_id", "state")
|
|
def _compute_need_contract_creation(self):
|
|
self.update({"need_contract_creation": False})
|
|
for rec in self:
|
|
if rec.state in ("sale", "done"):
|
|
line_to_create_contract = rec._get_line_to_create_contract()
|
|
line_to_update_contract = rec._get_line_to_update_contract()
|
|
if line_to_create_contract or line_to_update_contract:
|
|
rec.need_contract_creation = True
|
|
|
|
@api.depends("order_line")
|
|
def _compute_is_contract(self):
|
|
self.is_contract = any(self.order_line.mapped("is_contract"))
|
|
|
|
def _prepare_contract_value(self, contract_template):
|
|
self.ensure_one()
|
|
return {
|
|
"name": "{template_name}: {sale_name}".format(
|
|
template_name=contract_template.name, sale_name=self.name
|
|
),
|
|
"partner_id": self.partner_id.id,
|
|
"company_id": self.company_id.id,
|
|
"contract_template_id": contract_template.id,
|
|
"user_id": self.user_id.id,
|
|
"payment_term_id": self.payment_term_id.id,
|
|
"fiscal_position_id": self.fiscal_position_id.id,
|
|
"invoice_partner_id": self.partner_invoice_id.id,
|
|
"line_recurrence": self.partner_invoice_id.id,
|
|
}
|
|
|
|
def action_create_contract(self):
|
|
contract_model = self.env["contract.contract"]
|
|
contracts = []
|
|
for rec in self.filtered("is_contract"):
|
|
line_to_create_contract = rec._get_line_to_create_contract()
|
|
line_to_update_contract = rec._get_line_to_update_contract()
|
|
contract_templates = self.env["contract.template"]
|
|
for order_line in line_to_create_contract:
|
|
contract_template = order_line.product_id.with_company(
|
|
rec.company_id
|
|
).property_contract_template_id
|
|
if not contract_template:
|
|
raise ValidationError(
|
|
_(
|
|
"You must specify a contract "
|
|
"template for '{}' product in '{}' company."
|
|
).format(order_line.product_id.name, rec.company_id.name)
|
|
)
|
|
contract_templates |= contract_template
|
|
for contract_template in contract_templates:
|
|
order_lines = line_to_create_contract.filtered(
|
|
lambda r, template=contract_template: r.product_id.with_company(
|
|
r.order_id.company_id
|
|
).property_contract_template_id
|
|
== template
|
|
)
|
|
contract = contract_model.create(
|
|
rec._prepare_contract_value(contract_template)
|
|
)
|
|
contracts.append(contract)
|
|
contract._onchange_contract_template_id()
|
|
contract._onchange_contract_type()
|
|
order_lines.create_contract_line(contract)
|
|
order_lines.write({"contract_id": contract.id})
|
|
for line in line_to_update_contract:
|
|
line.create_contract_line(line.contract_id)
|
|
return contract_model.browse(contracts)
|
|
|
|
def action_confirm(self):
|
|
"""If we have a contract in the order, set it up"""
|
|
self.filtered(
|
|
lambda order: (order.company_id.create_contract_at_sale_order_confirmation)
|
|
).action_create_contract()
|
|
return super(SaleOrder, self).action_confirm()
|
|
|
|
@api.depends("order_line")
|
|
def _compute_contract_count(self):
|
|
for rec in self:
|
|
rec.contract_count = len(rec.order_line.mapped("contract_id"))
|
|
|
|
def action_show_contracts(self):
|
|
self.ensure_one()
|
|
action = self.env["ir.actions.act_window"]._for_xml_id(
|
|
"contract.action_customer_contract"
|
|
)
|
|
|
|
contracts = (
|
|
self.env["contract.line"]
|
|
.search([("sale_order_line_id", "in", self.order_line.ids)])
|
|
.mapped("contract_id")
|
|
)
|
|
action["domain"] = [
|
|
("contract_line_ids.sale_order_line_id", "in", self.order_line.ids)
|
|
]
|
|
if len(contracts) == 1:
|
|
# If there is only one contract, open it directly
|
|
action.update(
|
|
{
|
|
"res_id": contracts.id,
|
|
"view_mode": "form",
|
|
"views": filter(lambda view: view[1] == "form", action["views"]),
|
|
}
|
|
)
|
|
return action
|