Skip to content

Commit

Permalink
[IMP] product_contract: Allow creating sales orders with lines that l…
Browse files Browse the repository at this point in the history
…ack a contract template

Before this commit, confirming a sales order would raise an exception if any line lacked a configured contract template, preventing the creation of the contract.

Now, sales order lines without a contract template are automatically added to a new contract without a template, allowing the process to continue seamlessly.
  • Loading branch information
carlos-lopez-tecnativa committed Jan 21, 2025
1 parent 891236a commit 5146e47
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 16 deletions.
27 changes: 15 additions & 12 deletions product_contract/models/sale_order.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,11 @@ def _compute_is_contract(self):

def _prepare_contract_value(self, contract_template):
self.ensure_one()
name = (
f"{contract_template.name}: {self.name}" if contract_template else self.name
)
return {
"name": f"{contract_template.name}: {self.name}",
"name": name,
"partner_id": self.partner_id.id,
"company_id": self.company_id.id,
"contract_template_id": contract_template.id,
Expand All @@ -63,6 +66,7 @@ def _prepare_contract_value(self, contract_template):
def action_create_contract(self):
contract_model = self.env["contract.contract"]
contracts = []
lines_without_contract = self.env["sale.order.line"].browse()
for rec in self.filtered("is_contract"):
line_to_create_contract = rec.order_line.filtered(
lambda r: not r.contract_id and r.product_id.is_contract
Expand All @@ -80,17 +84,8 @@ def action_create_contract(self):
rec.company_id
).property_contract_template_id
if not contract_template:
raise ValidationError(
_(
"You must specify a contract "
"template for '%(product_name)s' product "
"in '%(company_name)s' company."
)
% {
"product_name": order_line.product_id.name,
"company_name": rec.company_id.name,
}
)
lines_without_contract |= order_line
continue
contract_templates |= contract_template
for contract_template in contract_templates:
order_lines = line_to_create_contract.filtered(
Expand All @@ -109,6 +104,14 @@ def action_create_contract(self):
order_lines.write({"contract_id": contract.id})
for line in line_to_update_contract:
line.create_contract_line(line.contract_id)
if lines_without_contract:
contract = contract_model.create(
rec._prepare_contract_value(self.env["contract.template"])
)
contracts.append(contract.id)
contract._onchange_contract_type()
lines_without_contract.create_contract_line(contract)
lines_without_contract.write({"contract_id": contract.id})
return contract_model.browse(contracts)

def action_confirm(self):
Expand Down
64 changes: 60 additions & 4 deletions product_contract/tests/test_sale_order.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from freezegun import freeze_time

from odoo import fields
from odoo.exceptions import UserError, ValidationError
from odoo.exceptions import ValidationError
from odoo.fields import Date
from odoo.tests.common import TransactionCase

Expand Down Expand Up @@ -127,9 +127,8 @@ def test_change_sale_company(self):
other_company = self.env["res.company"].create(
{"name": "other company", "parent_id": self.sale.company_id.id}
)
with self.assertRaises(UserError):
self.sale.company_id = other_company
self.sale.action_confirm()
self.sale.company_id = other_company
self.assertFalse(self.sale.order_line.mapped("contract_template_id"))

def test_change_sale_company_2(self):
"""Contract company must be the sale order company."""
Expand Down Expand Up @@ -374,6 +373,63 @@ def test_order_lines_with_the_same_contract_template(self):
)
self.assertEqual(len(contracts), 1)

def test_order_lines_without_contract_template(self):
"""It should create one contract with lines without contract
template"""
self.product1.with_company(self.sale.company_id).write(
{"is_contract": True, "property_contract_template_id": False}
)
self.product2.with_company(self.sale.company_id).write(
{"is_contract": True, "property_contract_template_id": False}
)
self.sale.order_line._compute_auto_renew()
self.assertFalse(self.sale.order_line.mapped("contract_template_id"))
self.sale.action_confirm()
contracts = self.sale.order_line.mapped("contract_id")
self.assertEqual(len(contracts), 1)
self.assertEqual(len(contracts.contract_line_ids), 2)
self.assertEqual(contracts.name, self.sale.name)
contracts = (
self.env["contract.line"]
.search([("sale_order_line_id", "in", self.sale.order_line.ids)])
.mapped("contract_id")
)
self.assertEqual(len(contracts), 1)

def test_order_lines_without_contract_template2(self):
"""It should create two contracts
product1 with contract template
product2 without contract template
"""
self.product2.with_company(self.sale.company_id).write(
{"is_contract": True, "property_contract_template_id": False}
)
self.sale.order_line._compute_auto_renew()
line_product_1 = self.sale.order_line.filtered(
lambda line: line.product_id == self.product1
)
line_product_2 = self.sale.order_line.filtered(
lambda line: line.product_id == self.product2
)
self.assertEqual(line_product_1.contract_template_id, self.contract_template1)
self.assertFalse(line_product_2.contract_template_id)
self.sale.action_confirm()
contracts = self.sale.order_line.mapped("contract_id")
self.assertEqual(len(contracts), 2)
self.assertEqual(len(line_product_1.contract_id.contract_line_ids), 1)
self.assertEqual(len(line_product_2.contract_id.contract_line_ids), 1)
self.assertEqual(
line_product_1.contract_id.name,
f"{self.contract_template1.name}: {self.sale.name}",
)
self.assertEqual(line_product_2.contract_id.name, self.sale.name)
contracts = (
self.env["contract.line"]
.search([("sale_order_line_id", "in", self.sale.order_line.ids)])
.mapped("contract_id")
)
self.assertEqual(len(contracts), 2)

def _create_contract_product(
self, recurring_rule_type, contract_start_date_method, force_month=False
):
Expand Down

0 comments on commit 5146e47

Please sign in to comment.