Browse Source

Merge pull request #321 from NL66278/10.0-product_contract-fix-recurring

[10.0] [FIX] product_contract. Correctly create contract from template.
pull/354/head
Pedro M. Baeza 6 years ago
committed by GitHub
parent
commit
dace58094e
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 7
      product_contract/README.rst
  2. 4
      product_contract/__init__.py
  3. 7
      product_contract/__manifest__.py
  4. 2
      product_contract/models/__init__.py
  5. 21
      product_contract/models/sale_order.py
  6. 36
      product_contract/models/sale_order_line.py
  7. 2
      product_contract/tests/test_product_template.py
  8. 34
      product_contract/tests/test_sale_order.py

7
product_contract/README.rst

@ -1,5 +1,5 @@
.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg .. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
:target: https://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3 :alt: License: AGPL-3
================ ================
@ -7,8 +7,8 @@ Product Contract
================ ================
This module adds support for products to be linked to contract templates. 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.
It also adds functionality to automatically create a contract from the
template, when a ``sale.order`` contains a product that implements a contract.
Usage Usage
===== =====
@ -48,6 +48,7 @@ Contributors
------------ ------------
* Ted Salmon <tsalmon@laslabs.com> * Ted Salmon <tsalmon@laslabs.com>
* Ronald Portier <rportier@therp.nl>
Maintainer Maintainer

4
product_contract/__init__.py

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

7
product_contract/__manifest__.py

@ -1,15 +1,14 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright 2017 LasLabs Inc. # Copyright 2017 LasLabs Inc.
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
{ {
'name': 'Product Contract', 'name': 'Product Contract',
'version': '10.0.1.0.0',
'version': '10.0.1.1.0',
'category': 'Contract Management', 'category': 'Contract Management',
'license': 'AGPL-3', 'license': 'AGPL-3',
'author': "LasLabs, " 'author': "LasLabs, "
"Odoo Community Association (OCA)", "Odoo Community Association (OCA)",
'website': 'https://laslabs.com',
'website': 'https://github.com/oca/contract',
'depends': [ 'depends': [
'contract', 'contract',
'product', 'product',

2
product_contract/models/__init__.py

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

21
product_contract/models/sale_order.py

@ -1,7 +1,8 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright 2017 LasLabs Inc. # Copyright 2017 LasLabs Inc.
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
# Copyright 2019 Therp BV <https://therp.nl>.
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
# pylint: disable=missing-docstring,protected-access
from odoo import api, models from odoo import api, models
@ -11,17 +12,7 @@ class SaleOrder(models.Model):
@api.multi @api.multi
def action_confirm(self): def action_confirm(self):
""" If we have a contract in the order, set it up """ """ 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()
for order in self:
# create_contract() already filters on contract order lines.
order.order_line.create_contract()
return super(SaleOrder, self).action_confirm() return super(SaleOrder, self).action_confirm()

36
product_contract/models/sale_order_line.py

@ -1,8 +1,9 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright 2017 LasLabs Inc. # Copyright 2017 LasLabs Inc.
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from odoo import fields, models
# Copyright 2019 Therp BV <https://therp.nl>.
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
# pylint: disable=missing-docstring,protected-access
from odoo import api, fields, models
class SaleOrderLine(models.Model): class SaleOrderLine(models.Model):
@ -10,5 +11,30 @@ class SaleOrderLine(models.Model):
contract_id = fields.Many2one( contract_id = fields.Many2one(
comodel_name='account.analytic.account', comodel_name='account.analytic.account',
string='Contract'
)
string='Contract')
@api.multi
def create_contract(self):
"""Create contract for sale order line.
Should be called on confirmation of sale order.
"""
for line in self.filtered('product_id.is_contract'):
contract_vals = line._prepare_contract_vals()
contract = self.env['account.analytic.account'].create(
contract_vals)
line.contract_id = contract.id
@api.multi
def _prepare_contract_vals(self):
"""Prepare values to create contract from template."""
self.ensure_one()
contract_tmpl = self.product_id.contract_template_id
order = self.order_id
contract = self.env['account.analytic.account'].new({
'name': '%s Contract' % order.name,
'partner_id': order.partner_id.id,
'contract_template_id': contract_tmpl.id,
'recurring_invoices': True})
contract._onchange_contract_template_id()
return contract._convert_to_write(contract._cache)

2
product_contract/tests/test_product_template.py

@ -15,7 +15,7 @@ class TestProductTemplate(TransactionCase):
self.contract = self.env['account.analytic.contract'].create({ self.contract = self.env['account.analytic.contract'].create({
'name': 'Test', 'name': 'Test',
'recurring_rule_type': 'yearly', 'recurring_rule_type': 'yearly',
'recurring_interval': 12345,
'recurring_interval': 1,
}) })
def test_change_is_contract(self): def test_change_is_contract(self):

34
product_contract/tests/test_sale_order.py

@ -1,8 +1,8 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright 2017 LasLabs Inc. # Copyright 2017 LasLabs Inc.
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from mock import MagicMock
# Copyright 2019 Therp BV <https://therp.nl>.
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
# pylint: disable=missing-docstring,protected-access,invalid-name
from odoo.tests.common import TransactionCase from odoo.tests.common import TransactionCase
@ -15,26 +15,16 @@ class TestSaleOrder(TransactionCase):
self.contract = self.env['account.analytic.contract'].create({ self.contract = self.env['account.analytic.contract'].create({
'name': 'Test', 'name': 'Test',
'recurring_rule_type': 'yearly', 'recurring_rule_type': 'yearly',
'recurring_interval': 12345,
})
'recurring_interval': 1})
self.product.product_tmpl_id.is_contract = True self.product.product_tmpl_id.is_contract = True
self.product.product_tmpl_id.contract_template_id = self.contract.id self.product.product_tmpl_id.contract_template_id = self.contract.id
def tearDown(self):
self.env['account.analytic.account']._revert_method(
'create',
)
super(TestSaleOrder, self).tearDown()
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()
)
def test_action_confirm(self):
"""Contract should be created when sale is confirmed."""
self.sale.action_confirm() 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,
})
contract_model = self.env['account.analytic.account']
product_contract = contract_model.search([
('recurring_invoices', '=', True),
('partner_id', '=', self.sale.partner_id.id),
('contract_template_id', '=', self.contract.id)], limit=1)
self.assertTrue(product_contract)
Loading…
Cancel
Save