Browse Source

[ADD] product_contract: Create module

* Add contract functionality to `product.templates`
* Add logic to create contracts from `sale.order` that contains contract products.
pull/208/head
Ted Salmon 8 years ago
committed by Thomas Binsfeld
parent
commit
43d21a3a4a
  1. 66
      product_contract/README.rst
  2. 5
      product_contract/__init__.py
  3. 23
      product_contract/__manifest__.py
  4. 7
      product_contract/models/__init__.py
  5. 23
      product_contract/models/product_template.py
  6. 27
      product_contract/models/sale_order.py
  7. 14
      product_contract/models/sale_order_line.py
  8. 6
      product_contract/tests/__init__.py
  9. 31
      product_contract/tests/test_product_template.py
  10. 34
      product_contract/tests/test_sale_order.py
  11. 29
      product_contract/views/product_template_view.xml

66
product_contract/README.rst

@ -0,0 +1,66 @@
.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3
================
Product Contract
================
This module adds support for products to be linked to contract templates.
It also adds functionality to automatically create a contract, from the template,
when a ``sale.order`` contains a product that implements a contract.
Usage
=====
To use this module, you need to:
#. Go to Sales -> Products and select or create a product.
#. Check "Is a contract" and select the contract template related to the
product
.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas
:alt: Try me on Runbot
:target: https://runbot.odoo-community.org/runbot/110/10.0
Known issues / Roadmap
======================
* None
Bug Tracker
===========
Bugs are tracked on `GitHub Issues
<https://github.com/OCA/contract/issues>`_. In case of trouble, please
check there if your issue has already been reported. If you spotted it first,
help us smash it by providing detailed and welcomed feedback.
Credits
=======
Images
------
* Odoo Community Association: `Icon <https://github.com/OCA/maintainer-tools/blob/master/template/module/static/description/icon.svg>`_.
Contributors
------------
* Ted Salmon <tsalmon@laslabs.com>
Maintainer
----------
.. image:: https://odoo-community.org/logo.png
:alt: Odoo Community Association
:target: https://odoo-community.org
This module is maintained by the OCA.
OCA, or the Odoo Community Association, is a nonprofit organization whose
mission is to support the collaborative development of Odoo features and
promote its widespread use.
To contribute to this module, please visit https://odoo-community.org.

5
product_contract/__init__.py

@ -0,0 +1,5 @@
# -*- coding: utf-8 -*-
# Copyright 2017 LasLabs Inc.
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from . import models

23
product_contract/__manifest__.py

@ -0,0 +1,23 @@
# -*- coding: utf-8 -*-
# Copyright 2017 LasLabs Inc.
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
{
'name': 'Product Contract',
'version': '10.0.1.0.0',
'category': 'Contract Management',
'license': 'AGPL-3',
'author': "LasLabs, "
"Odoo Community Association (OCA)",
'website': 'https://laslabs.com',
'depends': [
'contract',
'product',
'sale',
],
'data': [
'views/product_template_view.xml',
],
'installable': True,
'application': False,
}

7
product_contract/models/__init__.py

@ -0,0 +1,7 @@
# -*- coding: utf-8 -*-
# Copyright 2017 LasLabs Inc.
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from . import product_template
from . import sale_order
from . import sale_order_line

23
product_contract/models/product_template.py

@ -0,0 +1,23 @@
# -*- coding: utf-8 -*-
# Copyright 2017 LasLabs Inc.
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from odoo import api, fields, models
class ProductTemplate(models.Model):
_inherit = 'product.template'
is_contract = fields.Boolean('Is a contract')
contract_template_id = fields.Many2one(
comodel_name='account.analytic.contract',
string='Contract Template',
)
@api.onchange('is_contract')
def _change_is_contract(self):
""" Clear the relation to contract_template_id when downgrading
product from contract
"""
if not self.is_contract:
self.contract_template_id = False

27
product_contract/models/sale_order.py

@ -0,0 +1,27 @@
# -*- coding: utf-8 -*-
# Copyright 2017 LasLabs Inc.
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from odoo import api, models
class SaleOrder(models.Model):
_inherit = 'sale.order'
@api.multi
def action_confirm(self):
""" If we have a contract in the order, set it up """
for rec in self:
order_lines = self.mapped('order_line').filtered(
lambda r: r.product_id.is_contract
)
for line in order_lines:
contract_tmpl = line.product_id.contract_template_id
contract = self.env['account.analytic.account'].create({
'name': '%s Contract' % rec.name,
'partner_id': rec.partner_id.id,
'contract_template_id': contract_tmpl.id,
})
line.contract_id = contract.id
contract.recurring_create_invoice()
return super(SaleOrder, self).action_confirm()

14
product_contract/models/sale_order_line.py

@ -0,0 +1,14 @@
# -*- coding: utf-8 -*-
# Copyright 2017 LasLabs Inc.
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from odoo import fields, models
class SaleOrderLine(models.Model):
_inherit = 'sale.order.line'
contract_id = fields.Many2one(
comodel_name='account.analytic.account',
string='Contract'
)

6
product_contract/tests/__init__.py

@ -0,0 +1,6 @@
# -*- coding: utf-8 -*-
# Copyright 2017 LasLabs Inc.
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from . import test_product_template
from . import test_sale_order

31
product_contract/tests/test_product_template.py

@ -0,0 +1,31 @@
# -*- coding: utf-8 -*-
# Copyright 2017 LasLabs Inc.
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from odoo.tests.common import TransactionCase
class TestProductTemplate(TransactionCase):
def setUp(self):
super(TestProductTemplate, self).setUp()
self.product = self.env.ref(
'product.product_product_4_product_template'
)
self.contract = self.env['account.analytic.contract'].create({
'name': 'Test',
'recurring_rule_type': 'yearly',
'recurring_interval': 12345,
})
def test_change_is_contract(self):
""" It should verify that the contract_template_id is removed
when is_contract is False """
self.product.is_contract = True
self.product.contract_template_id = self.contract.id
self.product.is_contract = False
self.product._change_is_contract()
self.assertEquals(
len(self.product.contract_template_id),
0
)

34
product_contract/tests/test_sale_order.py

@ -0,0 +1,34 @@
# -*- coding: utf-8 -*-
# Copyright 2017 LasLabs Inc.
# 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',
'recurring_rule_type': 'yearly',
'recurring_interval': 12345,
})
self.product.product_tmpl_id.is_contract = True
self.product.product_tmpl_id.contract_template_id = self.contract.id
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.env['account.analytic.account']._patch_method(
'create', MagicMock()
)
self.sale.action_confirm()
self.env['account.analytic.account'].create.assert_called_once_with({
'name': '%s Contract' % self.sale.name,
'partner_id': self.sale.partner_id.id,
'contract_template_id': self.contract.id,
})

29
product_contract/views/product_template_view.xml

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2017 LasLabs Inc.
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
-->
<odoo>
<record id="product_template_form_contract_view" model="ir.ui.view">
<field name="name">account.invoice.select.contract</field>
<field name="model">product.template</field>
<field name="inherit_id" ref="product.product_template_form_view"/>
<field name="arch" type="xml">
<xpath expr="//div[@name='options']" position="inside">
<div>
<field name="is_contract" />
<label for="is_contract" />
</div>
</xpath>
<xpath expr="//group[@name='group_standard_price']" position="inside">
<field name="contract_template_id"
attrs="{'invisible': [('is_contract', '=', False)],
'required':[('is_contract', '=', True)]}" />
</xpath>
</field>
</record>
</odoo>
Loading…
Cancel
Save