diff --git a/product_contract/__manifest__.py b/product_contract/__manifest__.py
index 970265ff..f369b825 100644
--- a/product_contract/__manifest__.py
+++ b/product_contract/__manifest__.py
@@ -17,7 +17,8 @@
'contract_sale',
],
'data': [
- 'views/product_template_view.xml',
+ 'views/product_template.xml',
+ 'views/sale_order.xml',
],
'installable': True,
'application': False,
diff --git a/product_contract/models/product_template.py b/product_contract/models/product_template.py
index 1016c60c..1d256201 100644
--- a/product_contract/models/product_template.py
+++ b/product_contract/models/product_template.py
@@ -15,6 +15,30 @@ class ProductTemplate(models.Model):
comodel_name='account.analytic.contract', string='Contract Template'
)
+ recurring_rule_type = fields.Selection(
+ [
+ ('daily', 'Day(s)'),
+ ('weekly', 'Week(s)'),
+ ('monthly', 'Month(s)'),
+ ('monthlylastday', 'Month(s) last day'),
+ ('yearly', 'Year(s)'),
+ ],
+ default='monthly',
+ string='Recurrence',
+ help="Specify Interval for automatic invoice generation.",
+ )
+ recurring_invoicing_type = fields.Selection(
+ [('pre-paid', 'Pre-paid'), ('post-paid', 'Post-paid')],
+ default='pre-paid',
+ 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)",
+ )
+
@api.onchange('is_contract')
def _change_is_contract(self):
""" Clear the relation to contract_template_id when downgrading
diff --git a/product_contract/models/sale_order.py b/product_contract/models/sale_order.py
index 45f2eec7..443eaaff 100644
--- a/product_contract/models/sale_order.py
+++ b/product_contract/models/sale_order.py
@@ -2,12 +2,22 @@
# Copyright 2017 LasLabs Inc.
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
-from odoo import api, models
+from odoo import fields, api, models
class SaleOrder(models.Model):
_inherit = 'sale.order'
+ is_contract = fields.Boolean(
+ string='Is a contract', compute="_compute_is_contract"
+ )
+
+ @api.depends('order_line')
+ def _compute_is_contract(self):
+ self.is_contract = any(
+ self.order_line.mapped('is_contract')
+ )
+
@api.multi
def action_confirm(self):
""" If we have a contract in the order, set it up """
diff --git a/product_contract/models/sale_order_line.py b/product_contract/models/sale_order_line.py
index c76c1059..23da9c1c 100644
--- a/product_contract/models/sale_order_line.py
+++ b/product_contract/models/sale_order_line.py
@@ -1,14 +1,57 @@
# -*- coding: utf-8 -*-
# Copyright 2017 LasLabs Inc.
+# Copyright 2017 ACSONE SA/NV.
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
-from odoo import fields, models
+from odoo import api, fields, models
class SaleOrderLine(models.Model):
_inherit = 'sale.order.line'
+ is_contract = fields.Boolean(
+ string='Is a contract', related="product_id.is_contract"
+ )
contract_id = fields.Many2one(
- comodel_name='account.analytic.account',
- string='Contract'
+ comodel_name='account.analytic.account', string='Contract'
+ )
+ recurring_rule_type = fields.Selection(
+ [
+ ('daily', 'Day(s)'),
+ ('weekly', 'Week(s)'),
+ ('monthly', 'Month(s)'),
+ ('monthlylastday', 'Month(s) last day'),
+ ('yearly', 'Year(s)'),
+ ],
+ default='monthly',
+ string='Recurrence',
+ help="Specify Interval for automatic invoice generation.",
+ copy=False,
+ )
+ recurring_invoicing_type = fields.Selection(
+ [('pre-paid', 'Pre-paid'), ('post-paid', 'Post-paid')],
+ default='pre-paid',
+ string='Invoicing type',
+ 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', default=fields.Date.today())
+ date_end = fields.Date(string='Date End', index=True)
+ recurring_next_date = fields.Date(
+ default=fields.Date.today(), copy=False, string='Date of Next Invoice'
+ )
+
+ @api.onchange('product_id')
+ def onchange_product(self):
+ if self.product_id.is_contract:
+ self.recurring_rule_type = self.product_id.recurring_rule_type
+ self.recurring_invoicing_type = (
+ self.product_id.recurring_invoicing_type
+ )
+ self.recurring_interval = self.product_id.recurring_interval
diff --git a/product_contract/tests/__init__.py b/product_contract/tests/__init__.py
index b4af49c0..4766d5ea 100644
--- a/product_contract/tests/__init__.py
+++ b/product_contract/tests/__init__.py
@@ -1,6 +1,8 @@
# -*- coding: utf-8 -*-
# Copyright 2017 LasLabs Inc.
+# Copyright 2018 ACSONE SA/NV.
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from . import test_product
from . import test_sale_order
+from . import test_sale_order_line
diff --git a/product_contract/tests/test_sale_order.py b/product_contract/tests/test_sale_order.py
index f8a90e34..e8f66602 100644
--- a/product_contract/tests/test_sale_order.py
+++ b/product_contract/tests/test_sale_order.py
@@ -27,6 +27,8 @@ class TestSaleOrder(TransactionCase):
def test_action_done(self):
""" It should create a contract when the sale for a contract is set
to done for the first time """
+
+ self.assertTrue(self.sale.is_contract)
self.env['account.analytic.account']._patch_method(
'create', MagicMock()
)
diff --git a/product_contract/tests/test_sale_order_line.py b/product_contract/tests/test_sale_order_line.py
new file mode 100644
index 00000000..1f109059
--- /dev/null
+++ b/product_contract/tests/test_sale_order_line.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Copyright 2018 ACSONE SA/NV.
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
+
+from mock import MagicMock
+from odoo.tests.common import TransactionCase
+
+
+class TestSaleOrder(TransactionCase):
+
+ def setUp(self):
+ super(TestSaleOrder, self).setUp()
+ self.product = self.env.ref('product.product_product_1')
+ self.sale = self.env.ref('sale.sale_order_2')
+ self.contract = self.env['account.analytic.contract'].create({
+ 'name': 'Test',
+ })
+ self.product.product_tmpl_id.is_contract = True
+ self.sale_order_line = self.sale.order_line.filtered(
+ lambda l: l.product_id == self.product
+ )
+
+ def test_onchange_product(self):
+ """ It should get recurrence invoicing info to the sale line from
+ its product """
+ self.assertEqual(
+ self.sale_order_line.recurring_rule_type,
+ self.product.recurring_rule_type
+ )
+ self.assertEqual(
+ self.sale_order_line.recurring_interval,
+ self.product.recurring_interval
+ )
+ self.assertEqual(
+ self.sale_order_line.recurring_invoicing_type,
+ self.product.recurring_invoicing_type
+ )
diff --git a/product_contract/views/product_template.xml b/product_contract/views/product_template.xml
new file mode 100644
index 00000000..9eb3b38f
--- /dev/null
+++ b/product_contract/views/product_template.xml
@@ -0,0 +1,44 @@
+
+
+
+
+
+
+
+ account.invoice.select.contract
+ product.template
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/product_contract/views/product_template_view.xml b/product_contract/views/product_template_view.xml
deleted file mode 100644
index 46c2e05c..00000000
--- a/product_contract/views/product_template_view.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
-
-
-
- account.invoice.select.contract
- product.template
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/product_contract/views/sale_order.xml b/product_contract/views/sale_order.xml
new file mode 100644
index 00000000..f27c4025
--- /dev/null
+++ b/product_contract/views/sale_order.xml
@@ -0,0 +1,63 @@
+
+
+
+
+
+
+
+ sale.order.form (in product_contract)
+ sale.order
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+