diff --git a/product_contract/__manifest__.py b/product_contract/__manifest__.py
index aa0f3b742..5f1128942 100644
--- a/product_contract/__manifest__.py
+++ b/product_contract/__manifest__.py
@@ -7,7 +7,9 @@
'version': '12.0.1.0.0',
'category': 'Contract Management',
'license': 'AGPL-3',
- 'author': "LasLabs, " "ACSONE SA/NV, " "Odoo Community Association (OCA)",
+ 'author': "LasLabs, "
+ "ACSONE SA/NV, "
+ "Odoo Community Association (OCA)",
'website': 'https://github.com/oca/contract',
'depends': ['product', 'contract_sale'],
'data': [
diff --git a/product_contract/models/contract_line.py b/product_contract/models/contract_line.py
index ca5cd9a5c..1e0cd4fef 100644
--- a/product_contract/models/contract_line.py
+++ b/product_contract/models/contract_line.py
@@ -33,10 +33,10 @@ class AccountAnalyticInvoiceLine(models.Model):
rec.recurring_invoicing_type = (
rec.product_id.recurring_invoicing_type
)
- rec.recurring_interval = rec.product_id.recurring_interval
+ rec.recurring_interval = 1
rec.is_auto_renew = rec.product_id.is_auto_renew
- 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_interval = rec.product_id.default_qty
+ rec.auto_renew_rule_type = rec.product_id.recurring_rule_type
rec.termination_notice_interval = (
rec.product_id.termination_notice_interval
)
diff --git a/product_contract/models/product_template.py b/product_contract/models/product_template.py
index d3fd0b559..f73cc3afd 100644
--- a/product_contract/models/product_template.py
+++ b/product_contract/models/product_template.py
@@ -13,7 +13,7 @@ class ProductTemplate(models.Model):
contract_template_id = fields.Many2one(
comodel_name='account.analytic.contract', string='Contract Template'
)
-
+ default_qty = fields.Integer(string="Default Quantity")
recurring_rule_type = fields.Selection(
[
('daily', 'Day(s)'),
@@ -23,7 +23,7 @@ class ProductTemplate(models.Model):
('yearly', 'Year(s)'),
],
default='monthly',
- string='Recurrence',
+ string='Invoice Every',
help="Specify Interval for automatic invoice generation.",
)
recurring_invoicing_type = fields.Selection(
@@ -32,23 +32,7 @@ class ProductTemplate(models.Model):
string='Invoicing type',
help="Specify if process date is 'from' or 'to' invoicing date",
)
- recurring_interval = fields.Integer(
- default=1,
- string='Repeat Every',
- help="Repeat every (Days/Week/Month/Year)",
- )
is_auto_renew = fields.Boolean(string="Auto Renew", default=False)
- auto_renew_interval = fields.Integer(
- default=1,
- string='Renew Every',
- help="Renew every (Days/Week/Month/Year)",
- )
- auto_renew_rule_type = fields.Selection(
- [('monthly', 'Month(s)'), ('yearly', 'Year(s)')],
- default='yearly',
- string='Renewal type',
- help="Specify Interval for automatic renewal.",
- )
termination_notice_interval = fields.Integer(
default=1, string='Termination Notice Before'
)
diff --git a/product_contract/models/sale_order_line.py b/product_contract/models/sale_order_line.py
index a99f96d3d..049f778c1 100644
--- a/product_contract/models/sale_order_line.py
+++ b/product_contract/models/sale_order_line.py
@@ -31,8 +31,7 @@ class SaleOrderLine(models.Model):
('yearly', 'Year(s)'),
],
default='monthly',
- string='Recurrence',
- help="Specify Interval for automatic invoice generation.",
+ string='Invoice Every',
copy=False,
)
recurring_invoicing_type = fields.Selection(
@@ -42,12 +41,6 @@ class SaleOrderLine(models.Model):
help="Specify if process date is 'from' or 'to' invoicing date",
copy=False,
)
- recurring_interval = fields.Integer(
- default=1,
- string='Repeat Every',
- help="Repeat every (Days/Week/Month/Year)",
- copy=False,
- )
date_start = fields.Date(string='Date Start')
date_end = fields.Date(string='Date End')
@@ -57,48 +50,42 @@ class SaleOrderLine(models.Model):
required=False,
copy=False,
)
- is_auto_renew = fields.Boolean(
- string="Auto Renew", related="product_id.is_auto_renew", readonly=True
- )
@api.onchange('product_id')
def onchange_product(self):
contract_line_env = self.env['account.analytic.invoice.line']
for rec in self:
if rec.product_id.is_contract:
+ rec.product_uom_qty = rec.product_id.default_qty
rec.recurring_rule_type = rec.product_id.recurring_rule_type
rec.recurring_invoicing_type = (
rec.product_id.recurring_invoicing_type
)
- rec.recurring_interval = rec.product_id.recurring_interval
rec.date_start = rec.date_start or fields.Date.today()
- if rec.product_id.is_auto_renew:
- rec.date_end = (
- rec.date_start
- + contract_line_env.get_relative_delta(
- rec.product_id.auto_renew_rule_type,
- rec.product_id.auto_renew_interval,
- )
- - relativedelta(days=1)
+ rec.date_end = (
+ rec.date_start
+ + contract_line_env.get_relative_delta(
+ rec.product_id.recurring_rule_type,
+ int(rec.product_uom_qty),
)
+ - relativedelta(days=1)
+ )
- @api.onchange('date_start')
+ @api.onchange('date_start', 'product_uom_qty', 'recurring_rule_type')
def onchange_date_start(self):
for rec in self:
- if rec.product_id.is_auto_renew:
- if not rec.date_start:
- rec.date_end = False
- else:
- rec.date_end = (
- rec.date_start
- + self.env[
- 'account.analytic.invoice.line'
- ].get_relative_delta(
- rec.product_id.auto_renew_rule_type,
- rec.product_id.auto_renew_interval,
- )
- - relativedelta(days=1)
+ if not rec.date_start:
+ rec.date_end = False
+ else:
+ rec.date_end = (
+ rec.date_start
+ + self.env[
+ 'account.analytic.invoice.line'
+ ].get_relative_delta(
+ rec.recurring_rule_type, int(rec.product_uom_qty)
)
+ - relativedelta(days=1)
+ )
@api.multi
def _prepare_contract_line_values(
@@ -111,7 +98,7 @@ class SaleOrderLine(models.Model):
self.date_start or fields.Date.today(),
self.recurring_invoicing_type,
self.recurring_rule_type,
- self.recurring_interval,
+ int(self.product_uom_qty),
)
termination_notice_interval = (
self.product_id.termination_notice_interval
@@ -123,19 +110,31 @@ class SaleOrderLine(models.Model):
'sequence': self.sequence,
'product_id': self.product_id.id,
'name': self.name,
- 'quantity': self.product_uom_qty,
+ # The quantity on the generated contract line is 1, as it
+ # correspond to the most common use cases:
+ # - quantity on the SO line = number of periods sold and unit
+ # price the price of one period, so the
+ # total amount of the SO corresponds to the planned value
+ # of the contract; in this case the quantity on the contract
+ # line must be 1
+ # - quantity on the SO line = number of hours sold,
+ # automatic invoicing of the actual hours through a variable
+ # quantity formula, in which case the quantity on the contract
+ # line is not used
+ # Other use cases are easy to implement by overriding this method.
+ 'quantity': 1.0,
'uom_id': self.product_uom.id,
'price_unit': self.price_unit,
'discount': self.discount,
'date_end': self.date_end,
'date_start': self.date_start or fields.Date.today(),
'recurring_next_date': recurring_next_date,
- 'recurring_interval': self.recurring_interval,
+ 'recurring_interval': 1,
'recurring_invoicing_type': self.recurring_invoicing_type,
'recurring_rule_type': self.recurring_rule_type,
'is_auto_renew': self.product_id.is_auto_renew,
- 'auto_renew_interval': self.product_id.auto_renew_interval,
- 'auto_renew_rule_type': self.product_id.auto_renew_rule_type,
+ 'auto_renew_interval': self.product_uom_qty,
+ 'auto_renew_rule_type': self.product_id.recurring_rule_type,
'termination_notice_interval': termination_notice_interval,
'termination_notice_rule_type': termination_notice_rule_type,
'contract_id': contract.id,
@@ -153,8 +152,9 @@ class SaleOrderLine(models.Model):
rec.date_start - relativedelta(days=1)
)
new_contract_line = contract_line_env.create(
- rec._prepare_contract_line_values(contract,
- rec.contract_line_id)
+ rec._prepare_contract_line_values(
+ contract, rec.contract_line_id
+ )
)
if rec.contract_line_id:
rec.contract_line_id.successor_contract_line_id = (
diff --git a/product_contract/tests/test_sale_order.py b/product_contract/tests/test_sale_order.py
index a13aa121d..331806593 100644
--- a/product_contract/tests/test_sale_order.py
+++ b/product_contract/tests/test_sale_order.py
@@ -41,7 +41,7 @@ class TestSaleOrder(TransactionCase):
self.product1.write(
{
'is_contract': True,
- 'is_auto_renew': True,
+ 'default_qty': 12,
'contract_template_id': self.contract_template1.id,
}
)
@@ -55,6 +55,7 @@ class TestSaleOrder(TransactionCase):
lambda l: l.product_id == self.product1
)
self.order_line1.date_start = '2018-01-01'
+ self.order_line1.product_uom_qty = 12
pricelist = self.sale.partner_id.property_product_pricelist.id
self.contract = self.env["account.analytic.account"].create(
{
@@ -91,10 +92,6 @@ class TestSaleOrder(TransactionCase):
contract"""
self.assertTrue(self.sale.is_contract)
- def test_action_confirm_auto_renew_without_date_end(self):
- with self.assertRaises(ValidationError):
- self.sale.action_confirm()
-
def test_action_confirm(self):
""" It should create a contract for each contract template used in
order_line """
@@ -122,10 +119,6 @@ class TestSaleOrder(TransactionCase):
self.order_line1.recurring_rule_type,
self.product1.recurring_rule_type,
)
- self.assertEqual(
- self.order_line1.recurring_interval,
- self.product1.recurring_interval,
- )
self.assertEqual(
self.order_line1.recurring_invoicing_type,
self.product1.recurring_invoicing_type,
@@ -228,10 +221,8 @@ class TestSaleOrder(TransactionCase):
{
'recurring_rule_type': 'monthly',
'recurring_invoicing_type': 'pre-paid',
- 'recurring_interval': '2',
'is_auto_renew': True,
- 'auto_renew_interval': '6',
- 'auto_renew_rule_type': 'monthly',
+ 'default_qty': 12,
'termination_notice_interval': '6',
'termination_notice_rule_type': 'weekly',
}
@@ -249,9 +240,9 @@ class TestSaleOrder(TransactionCase):
self.assertEqual(
self.contract_line.recurring_invoicing_type, 'pre-paid'
)
- self.assertEqual(self.contract_line.recurring_interval, 2)
+ self.assertEqual(self.contract_line.recurring_interval, 1)
self.assertEqual(self.contract_line.is_auto_renew, True)
- self.assertEqual(self.contract_line.auto_renew_interval, 6)
+ self.assertEqual(self.contract_line.auto_renew_interval, 12)
self.assertEqual(self.contract_line.auto_renew_rule_type, 'monthly')
self.assertEqual(self.contract_line.termination_notice_interval, 6)
self.assertEqual(
diff --git a/product_contract/views/product_template.xml b/product_contract/views/product_template.xml
index dcc54caed..fd26d5555 100644
--- a/product_contract/views/product_template.xml
+++ b/product_contract/views/product_template.xml
@@ -29,30 +29,16 @@
-
-
-
-
-
+
+
-
-
-
-
-
-
+
-
-
-
-
-
+
-
+