diff --git a/product_contract/models/product_template.py b/product_contract/models/product_template.py index 1d06c07886..75c579376b 100644 --- a/product_contract/models/product_template.py +++ b/product_contract/models/product_template.py @@ -167,3 +167,55 @@ def _check_contract_product_type(self): """ if any([product.is_contract and product.type != "service" for product in self]): raise ValidationError(_("Contract product should be service type")) + + @api.constrains("recurrence_number") + def _check_recurrence_number_is_strictly_positive(self): + for product in self: + if not product.is_contract: + continue + if product.recurrence_number <= 0: + raise ValidationError( + _( + "Value of %r should be strictly positive", + product._fields["recurrence_number"].string, + ) + ) + + @api.constrains("recurring_interval") + def _check_recurring_interval_is_strictly_positive(self): + for product in self: + if not product.is_contract: + continue + if product.recurring_interval <= 0: + raise ValidationError( + _( + "Value of %r should be strictly positive", + product._fields["recurring_interval"].string, + ) + ) + + @api.constrains("auto_renew_interval") + def _check_auto_renew_interval_is_strictly_positive(self): + for product in self: + if not product.is_contract or not product.is_auto_renew: + continue + if product.auto_renew_interval <= 0: + raise ValidationError( + _( + "Value of %r should be strictly positive", + product._fields["auto_renew_interval"].string, + ) + ) + + @api.constrains("termination_notice_interval") + def _check_termination_notice_interval_is_positive(self): + for product in self: + if not product.is_contract or not product.is_auto_renew: + continue + if product.termination_notice_interval < 0: + raise ValidationError( + _( + "Value of %r should be positive", + product._fields["termination_notice_interval"].string, + ) + ) diff --git a/product_contract/models/sale_order_line_contract_mixin.py b/product_contract/models/sale_order_line_contract_mixin.py index 58fc3fc6c5..2b9832ed7f 100644 --- a/product_contract/models/sale_order_line_contract_mixin.py +++ b/product_contract/models/sale_order_line_contract_mixin.py @@ -3,7 +3,8 @@ from dateutil.relativedelta import relativedelta -from odoo import api, fields, models +from odoo import _, api, fields, models +from odoo.exceptions import ValidationError class SaleOrderLineContractMixin(models.AbstractModel): @@ -224,3 +225,42 @@ def _get_date_end(self): - relativedelta(days=1) ) return date_end + + @api.constrains("recurrence_number") + def _check_recurrence_number_is_strictly_positive(self): + for line in self: + if not line.is_contract: + return + if line.recurrence_number <= 0: + raise ValidationError( + _( + "Value of %r should be strictly positive", + line._fields["recurrence_number"].string, + ) + ) + + @api.constrains("recurring_interval") + def _check_recurring_interval_is_strictly_positive(self): + for line in self: + if not line.is_contract: + return + if line.recurring_interval <= 0: + raise ValidationError( + _( + "Value of %r should be strictly positive", + line._fields["recurring_interval"].string, + ) + ) + + @api.constrains("auto_renew_interval") + def _check_auto_renew_interval_is_strictly_positive(self): + for line in self: + if not line.is_contract or not line.is_auto_renew: + return + if line.auto_renew_interval <= 0: + raise ValidationError( + _( + "Value of %r should be strictly positive", + line._fields["auto_renew_interval"].string, + ) + ) diff --git a/product_contract/tests/test_product.py b/product_contract/tests/test_product.py index d5f1c767a4..da89e7be34 100644 --- a/product_contract/tests/test_product.py +++ b/product_contract/tests/test_product.py @@ -37,3 +37,55 @@ def test_check_contract_product_type(self): """ with self.assertRaises(ValidationError): self.consu_product.is_contract = True + + def test_check_recurrence_number_is_strictly_positive(self): + """ + It should raise ValidationError if recurrence_number is not strictly positive + for a contract product + """ + self.service_product.is_contract = True + self.service_product.property_contract_template_id = self.contract.id + with self.assertRaises(ValidationError): + self.service_product.recurrence_number = -1 + with self.assertRaises(ValidationError): + self.service_product.recurrence_number = 0 + self.service_product.recurrence_number = 1 + + def test_check_recurring_interval_is_strictly_positive(self): + """ + It should raise ValidationError if recurring_interval is not strictly positive + for a contract product + """ + self.service_product.is_contract = True + self.service_product.property_contract_template_id = self.contract.id + with self.assertRaises(ValidationError): + self.service_product.recurring_interval = -1 + with self.assertRaises(ValidationError): + self.service_product.recurring_interval = 0 + self.service_product.recurring_interval = 1 + + def test_check_auto_renew_interval_is_strictly_positive(self): + """ + It should raise ValidationError if auto_renew_interval is not strictly positive + for a contract product + """ + self.service_product.is_contract = True + self.service_product.is_auto_renew = True + self.service_product.property_contract_template_id = self.contract.id + with self.assertRaises(ValidationError): + self.service_product.auto_renew_interval = -1 + with self.assertRaises(ValidationError): + self.service_product.auto_renew_interval = 0 + self.service_product.auto_renew_interval = 1 + + def test_check_termination_notice_interval_is_positive(self): + """ + It should raise ValidationError if termination_notice_interval is not positive + for a contract product + """ + self.service_product.is_contract = True + self.service_product.is_auto_renew = True + self.service_product.property_contract_template_id = self.contract.id + with self.assertRaises(ValidationError): + self.service_product.termination_notice_interval = -1 + self.service_product.termination_notice_interval = 0 diff --git a/product_contract/tests/test_sale_order.py b/product_contract/tests/test_sale_order.py index 3bf8aac2e9..db6b3db645 100644 --- a/product_contract/tests/test_sale_order.py +++ b/product_contract/tests/test_sale_order.py @@ -669,3 +669,39 @@ def test_order_line_date_start_confirm(self): sale.order_line.contract_id.contract_line_ids.date_start, fields.Date.to_date("2025-02-28"), ) + + def test_check_recurrence_number_is_strictly_positive(self): + """ + It should raise ValidationError if recurrence_number is not strictly positive + for a sale order line with a contract product + """ + self.sale.order_line.is_auto_renew = True + with self.assertRaises(ValidationError): + self.sale.order_line.recurrence_number = -1 + with self.assertRaises(ValidationError): + self.sale.order_line.recurrence_number = 0 + self.sale.order_line.recurrence_number = 1 + + def test_check_recurring_interval_is_strictly_positive(self): + """ + It should raise ValidationError if recurring_interval is not strictly positive + for a sale order line with a contract product + """ + self.sale.order_line.is_auto_renew = True + with self.assertRaises(ValidationError): + self.sale.order_line.recurring_interval = -1 + with self.assertRaises(ValidationError): + self.sale.order_line.recurring_interval = 0 + self.sale.order_line.recurring_interval = 1 + + def test_check_auto_renew_interval_is_strictly_positive(self): + """ + It should raise ValidationError if auto_renew_interval is not strictly positive + for a sale order line with a contract product + """ + self.sale.order_line.is_auto_renew = True + with self.assertRaises(ValidationError): + self.sale.order_line.auto_renew_interval = -1 + with self.assertRaises(ValidationError): + self.sale.order_line.auto_renew_interval = 0 + self.sale.order_line.auto_renew_interval = 1