mirror of
https://github.com/OCA/contract.git
synced 2025-02-13 17:57:24 +02:00
@@ -25,20 +25,37 @@ class SaleOrder(models.Model):
|
|||||||
_("You can't upsell or downsell a terminated contract")
|
_("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")
|
@api.depends("order_line.contract_id", "state")
|
||||||
def _compute_need_contract_creation(self):
|
def _compute_need_contract_creation(self):
|
||||||
self.update({"need_contract_creation": False})
|
self.update({"need_contract_creation": False})
|
||||||
for rec in self:
|
for rec in self:
|
||||||
if rec.state in ("sale", "done"):
|
if rec.state in ("sale", "done"):
|
||||||
line_to_create_contract = rec.order_line.filtered(
|
line_to_create_contract = rec._get_line_to_create_contract()
|
||||||
lambda r: not r.contract_id and r.product_id.is_contract
|
line_to_update_contract = rec._get_line_to_update_contract()
|
||||||
)
|
|
||||||
line_to_update_contract = rec.order_line.filtered(
|
|
||||||
lambda r: r.contract_id
|
|
||||||
and r.product_id.is_contract
|
|
||||||
and r
|
|
||||||
not in r.contract_id.contract_line_ids.mapped("sale_order_line_id")
|
|
||||||
)
|
|
||||||
if line_to_create_contract or line_to_update_contract:
|
if line_to_create_contract or line_to_update_contract:
|
||||||
rec.need_contract_creation = True
|
rec.need_contract_creation = True
|
||||||
|
|
||||||
@@ -66,15 +83,8 @@ class SaleOrder(models.Model):
|
|||||||
contract_model = self.env["contract.contract"]
|
contract_model = self.env["contract.contract"]
|
||||||
contracts = []
|
contracts = []
|
||||||
for rec in self.filtered("is_contract"):
|
for rec in self.filtered("is_contract"):
|
||||||
line_to_create_contract = rec.order_line.filtered(
|
line_to_create_contract = rec._get_line_to_create_contract()
|
||||||
lambda r: not r.contract_id and r.product_id.is_contract
|
line_to_update_contract = rec._get_line_to_update_contract()
|
||||||
)
|
|
||||||
line_to_update_contract = rec.order_line.filtered(
|
|
||||||
lambda r: r.contract_id
|
|
||||||
and r.product_id.is_contract
|
|
||||||
and r
|
|
||||||
not in r.contract_id.contract_line_ids.mapped("sale_order_line_id")
|
|
||||||
)
|
|
||||||
contract_templates = self.env["contract.template"]
|
contract_templates = self.env["contract.template"]
|
||||||
for order_line in line_to_create_contract:
|
for order_line in line_to_create_contract:
|
||||||
contract_template = order_line.product_id.with_company(
|
contract_template = order_line.product_id.with_company(
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ class SaleOrderLine(models.Model):
|
|||||||
_inherit = "sale.order.line"
|
_inherit = "sale.order.line"
|
||||||
|
|
||||||
is_contract = fields.Boolean(
|
is_contract = fields.Boolean(
|
||||||
string="Is a contract", related="product_id.is_contract"
|
string="Is a contract",
|
||||||
)
|
)
|
||||||
contract_id = fields.Many2one(
|
contract_id = fields.Many2one(
|
||||||
comodel_name="contract.contract", string="Contract", copy=False
|
comodel_name="contract.contract", string="Contract", copy=False
|
||||||
@@ -120,10 +120,10 @@ class SaleOrderLine(models.Model):
|
|||||||
)
|
)
|
||||||
return date_end
|
return date_end
|
||||||
|
|
||||||
@api.depends("product_id")
|
@api.depends("product_id", "is_contract")
|
||||||
def _compute_auto_renew(self):
|
def _compute_auto_renew(self):
|
||||||
for rec in self:
|
for rec in self:
|
||||||
if rec.product_id.is_contract:
|
if rec.is_contract:
|
||||||
rec.product_uom_qty = rec.product_id.default_qty
|
rec.product_uom_qty = rec.product_id.default_qty
|
||||||
rec.recurring_rule_type = rec.product_id.recurring_rule_type
|
rec.recurring_rule_type = rec.product_id.recurring_rule_type
|
||||||
rec.recurring_invoicing_type = rec.product_id.recurring_invoicing_type
|
rec.recurring_invoicing_type = rec.product_id.recurring_invoicing_type
|
||||||
@@ -135,11 +135,21 @@ class SaleOrderLine(models.Model):
|
|||||||
rec.auto_renew_interval = rec.product_id.auto_renew_interval
|
rec.auto_renew_interval = rec.product_id.auto_renew_interval
|
||||||
rec.auto_renew_rule_type = rec.product_id.auto_renew_rule_type
|
rec.auto_renew_rule_type = rec.product_id.auto_renew_rule_type
|
||||||
|
|
||||||
@api.onchange("date_start", "product_uom_qty", "recurring_rule_type")
|
@api.onchange("date_start", "product_uom_qty", "recurring_rule_type", "is_contract")
|
||||||
def onchange_date_start(self):
|
def onchange_date_start(self):
|
||||||
for rec in self.filtered("product_id.is_contract"):
|
for rec in self.filtered("is_contract"):
|
||||||
rec.date_end = rec._get_date_end() if rec.date_start else False
|
rec.date_end = rec._get_date_end() if rec.date_start else False
|
||||||
|
|
||||||
|
@api.onchange("product_id")
|
||||||
|
def product_id_change(self):
|
||||||
|
super().product_id_change()
|
||||||
|
for rec in self:
|
||||||
|
if rec.product_id.is_contract:
|
||||||
|
rec.is_contract = True
|
||||||
|
else:
|
||||||
|
# Don't initialize wrong values
|
||||||
|
rec.is_contract = False
|
||||||
|
|
||||||
def _get_contract_line_qty(self):
|
def _get_contract_line_qty(self):
|
||||||
"""Returns the quantity to be put on new contract lines."""
|
"""Returns the quantity to be put on new contract lines."""
|
||||||
self.ensure_one()
|
self.ensure_one()
|
||||||
@@ -259,6 +269,16 @@ class SaleOrderLine(models.Model):
|
|||||||
_("Contract product has different contract template")
|
_("Contract product has different contract template")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@api.constrains("product_id", "contract_id")
|
||||||
|
def _check_contract_sale_line_is_contract(self):
|
||||||
|
for rec in self:
|
||||||
|
if rec.is_contract and not rec.product_id.is_contract:
|
||||||
|
raise ValidationError(
|
||||||
|
_(
|
||||||
|
'You can check the field "Is a contract" only for Contract product'
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
def _compute_invoice_status(self):
|
def _compute_invoice_status(self):
|
||||||
res = super()._compute_invoice_status()
|
res = super()._compute_invoice_status()
|
||||||
self.filtered("contract_id").update({"invoice_status": "no"})
|
self.filtered("contract_id").update({"invoice_status": "no"})
|
||||||
@@ -274,12 +294,12 @@ class SaleOrderLine(models.Model):
|
|||||||
"qty_delivered",
|
"qty_delivered",
|
||||||
"product_uom_qty",
|
"product_uom_qty",
|
||||||
"order_id.state",
|
"order_id.state",
|
||||||
"product_id.is_contract",
|
"is_contract",
|
||||||
)
|
)
|
||||||
def _get_to_invoice_qty(self):
|
def _get_to_invoice_qty(self):
|
||||||
"""
|
"""
|
||||||
sale line linked to contracts must not be invoiced from sale order
|
sale line linked to contracts must not be invoiced from sale order
|
||||||
"""
|
"""
|
||||||
res = super()._get_to_invoice_qty()
|
res = super()._get_to_invoice_qty()
|
||||||
self.filtered("product_id.is_contract").update({"qty_to_invoice": 0.0})
|
self.filtered("is_contract").update({"qty_to_invoice": 0.0})
|
||||||
return res
|
return res
|
||||||
|
|||||||
@@ -65,8 +65,15 @@ class TestSaleOrder(SavepointCase):
|
|||||||
cls.order_line1 = cls.sale.order_line.filtered(
|
cls.order_line1 = cls.sale.order_line.filtered(
|
||||||
lambda l: l.product_id == cls.product1
|
lambda l: l.product_id == cls.product1
|
||||||
)
|
)
|
||||||
|
|
||||||
cls.order_line1.date_start = "2018-01-01"
|
cls.order_line1.date_start = "2018-01-01"
|
||||||
cls.order_line1.product_uom_qty = 12
|
cls.order_line1.product_uom_qty = 12
|
||||||
|
cls.order_line1.product_id_change()
|
||||||
|
cls.order_line2 = cls.sale.order_line.filtered(
|
||||||
|
lambda l: l.product_id == cls.product2
|
||||||
|
)
|
||||||
|
cls.order_line2.product_id_change()
|
||||||
|
|
||||||
pricelist = cls.sale.partner_id.property_product_pricelist.id
|
pricelist = cls.sale.partner_id.property_product_pricelist.id
|
||||||
cls.contract = cls.env["contract.contract"].create(
|
cls.contract = cls.env["contract.contract"].create(
|
||||||
{
|
{
|
||||||
@@ -194,7 +201,7 @@ class TestSaleOrder(SavepointCase):
|
|||||||
{
|
{
|
||||||
"name": "Contract",
|
"name": "Contract",
|
||||||
"contract_template_id": self.contract_template2.id,
|
"contract_template_id": self.contract_template2.id,
|
||||||
"partner_id": self.sale.partner_id.id,
|
"partner_id": self.env.user.partner_id.id,
|
||||||
"line_recurrence": True,
|
"line_recurrence": True,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@@ -218,6 +225,7 @@ class TestSaleOrder(SavepointCase):
|
|||||||
def test_no_contract_proudct(self):
|
def test_no_contract_proudct(self):
|
||||||
"""it should create contract for only product contract"""
|
"""it should create contract for only product contract"""
|
||||||
self.product1.is_contract = False
|
self.product1.is_contract = False
|
||||||
|
self.order_line1.product_id_change()
|
||||||
self.sale.action_confirm()
|
self.sale.action_confirm()
|
||||||
self.assertFalse(self.order_line1.contract_id)
|
self.assertFalse(self.order_line1.contract_id)
|
||||||
|
|
||||||
@@ -241,6 +249,7 @@ class TestSaleOrder(SavepointCase):
|
|||||||
def test_sale_order_create_invoice(self):
|
def test_sale_order_create_invoice(self):
|
||||||
"""Should not invoice contract product on sale order create invoice"""
|
"""Should not invoice contract product on sale order create invoice"""
|
||||||
self.product2.is_contract = False
|
self.product2.is_contract = False
|
||||||
|
self.order_line2.product_id_change()
|
||||||
self.product2.invoice_policy = "order"
|
self.product2.invoice_policy = "order"
|
||||||
self.order_line1._compute_auto_renew()
|
self.order_line1._compute_auto_renew()
|
||||||
self.sale.action_confirm()
|
self.sale.action_confirm()
|
||||||
|
|||||||
@@ -38,6 +38,7 @@
|
|||||||
position="after"
|
position="after"
|
||||||
>
|
>
|
||||||
<field name="contract_template_id" attrs="{'invisible': []}" />
|
<field name="contract_template_id" attrs="{'invisible': []}" />
|
||||||
|
<field name="is_contract" invisible="1" />
|
||||||
<field
|
<field
|
||||||
name="contract_id"
|
name="contract_id"
|
||||||
options='{"no_create": True}'
|
options='{"no_create": True}'
|
||||||
|
|||||||
Reference in New Issue
Block a user