diff --git a/product_contract_variable_quantity/README.rst b/product_contract_variable_quantity/README.rst new file mode 100644 index 00000000..cc6bbf96 --- /dev/null +++ b/product_contract_variable_quantity/README.rst @@ -0,0 +1,87 @@ +.. 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 Variable Quantity +================================== + +Product contract with variable quantity + +Installation +============ + +To install this module, you need to: + +#. Do this ... + +Configuration +============= + +To configure this module, you need to: + +#. Go to ... + +.. figure:: path/to/local/image.png + :alt: alternative description + :width: 600 px + +Usage +===== + +To use this module, you need to: + +#. Go to ... + +.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas + :alt: Try me on Runbot + :target: https://runbot.odoo-community.org/runbot/{repo_id}/{branch} + +.. repo_id is available in https://github.com/OCA/maintainer-tools/blob/master/tools/repos_with_ids.txt +.. branch is "8.0" for example + + +Bug Tracker +=========== + +Bugs are tracked on `GitHub 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 `_. + +Contributors +------------ + +* Firstname Lastname +* Second Person + +Funders +------- + +The development of this module has been financially supported by: + +* Company 1 name +* Company 2 name + +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. diff --git a/product_contract_variable_quantity/__init__.py b/product_contract_variable_quantity/__init__.py new file mode 100644 index 00000000..0ee8b507 --- /dev/null +++ b/product_contract_variable_quantity/__init__.py @@ -0,0 +1,2 @@ +from . import models +from . import tests diff --git a/product_contract_variable_quantity/__manifest__.py b/product_contract_variable_quantity/__manifest__.py new file mode 100644 index 00000000..21e7d8b4 --- /dev/null +++ b/product_contract_variable_quantity/__manifest__.py @@ -0,0 +1,15 @@ +# Copyright 2018 ACSONE SA/NV +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +{ + 'name': 'Product Contract Variable Quantity', + 'summary': """ + Product contract with variable quantity""", + 'version': '12.0.1.0.0', + 'license': 'AGPL-3', + 'author': 'ACSONE SA/NV,Odoo Community Association (OCA)', + 'website': 'https://github.com/OCA/contract', + 'depends': ['contract_variable_quantity', 'product_contract'], + 'data': ['views/product_template.xml', 'views/sale_order.xml'], + 'demo': [], +} diff --git a/product_contract_variable_quantity/models/__init__.py b/product_contract_variable_quantity/models/__init__.py new file mode 100644 index 00000000..d25a9d7c --- /dev/null +++ b/product_contract_variable_quantity/models/__init__.py @@ -0,0 +1,6 @@ +# Copyright 2018 ACSONE SA/NV +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from . import contract_line +from . import product_template +from . import sale_order_line diff --git a/product_contract_variable_quantity/models/contract_line.py b/product_contract_variable_quantity/models/contract_line.py new file mode 100644 index 00000000..c2177ab8 --- /dev/null +++ b/product_contract_variable_quantity/models/contract_line.py @@ -0,0 +1,17 @@ +# Copyright 2017 LasLabs Inc. +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + + +from odoo import api, models + + +class ContractLine(models.Model): + _inherit = 'contract.line' + + @api.onchange('product_id') + def _onchange_product_id_recurring_info(self): + res = super(ContractLine, self)._onchange_product_id_recurring_info() + if self.product_id.is_contract: + self.qty_type = self.product_id.qty_type + self.qty_formula_id = self.product_id.qty_formula_id + return res diff --git a/product_contract_variable_quantity/models/product_template.py b/product_contract_variable_quantity/models/product_template.py new file mode 100644 index 00000000..a99ae9aa --- /dev/null +++ b/product_contract_variable_quantity/models/product_template.py @@ -0,0 +1,32 @@ +# Copyright 2018 ACSONE SA/NV +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import api, fields, models + + +class ProductTemplate(models.Model): + _inherit = 'product.template' + + qty_type = fields.Selection( + selection=[ + ('fixed', 'Fixed quantity'), + ('variable', 'Variable quantity'), + ], + required=False, + default='fixed', + string="Qty. type", + ) + qty_formula_id = fields.Many2one( + comodel_name="contract.line.qty.formula", string="Qty. formula" + ) + + @api.onchange('is_contract') + def _change_is_contract(self): + """ Clear the relation to contract_template_id when downgrading + product from contract + """ + res = super(ProductTemplate, self)._change_is_contract() + if not self.is_contract: + self.qty_type = False + self.qty_formula_id = False + return res diff --git a/product_contract_variable_quantity/models/sale_order_line.py b/product_contract_variable_quantity/models/sale_order_line.py new file mode 100644 index 00000000..3cb055ac --- /dev/null +++ b/product_contract_variable_quantity/models/sale_order_line.py @@ -0,0 +1,43 @@ +# -*- 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 api, fields, models + + +class SaleOrderLine(models.Model): + _inherit = 'sale.order.line' + + qty_type = fields.Selection( + selection=[ + ('fixed', 'Fixed quantity'), + ('variable', 'Variable quantity'), + ], + required=False, + default='fixed', + string="Qty. type", + ) + qty_formula_id = fields.Many2one( + comodel_name="contract.line.qty.formula", string="Qty. formula" + ) + + @api.onchange('product_id') + def onchange_product(self): + res = super(SaleOrderLine, self).onchange_product() + for rec in self: + if rec.product_id.is_contract: + rec.qty_type = rec.product_id.qty_type + rec.qty_formula_id = rec.product_id.qty_formula_id + return res + + @api.multi + def _prepare_contract_line_values( + self, contract, predecessor_contract_line=False + ): + values = super(SaleOrderLine, self)._prepare_contract_line_values( + contract, predecessor_contract_line + ) + values['qty_type'] = self.qty_type + values['qty_formula_id'] = self.qty_formula_id.id + return values diff --git a/product_contract_variable_quantity/readme/CONTRIBUTORS.rst b/product_contract_variable_quantity/readme/CONTRIBUTORS.rst new file mode 100644 index 00000000..50e6298d --- /dev/null +++ b/product_contract_variable_quantity/readme/CONTRIBUTORS.rst @@ -0,0 +1 @@ +* Souheil Bejaoui diff --git a/product_contract_variable_quantity/readme/DESCRIPTION.rst b/product_contract_variable_quantity/readme/DESCRIPTION.rst new file mode 100644 index 00000000..3e5d5e3c --- /dev/null +++ b/product_contract_variable_quantity/readme/DESCRIPTION.rst @@ -0,0 +1 @@ +This module add default values to contract products for variable quantity formula. \ No newline at end of file diff --git a/product_contract_variable_quantity/static/description/icon.png b/product_contract_variable_quantity/static/description/icon.png new file mode 100644 index 00000000..3a0328b5 Binary files /dev/null and b/product_contract_variable_quantity/static/description/icon.png differ diff --git a/product_contract_variable_quantity/tests/__init__.py b/product_contract_variable_quantity/tests/__init__.py new file mode 100644 index 00000000..b5d241da --- /dev/null +++ b/product_contract_variable_quantity/tests/__init__.py @@ -0,0 +1,4 @@ +# Copyright 2018 ACSONE SA/NV. +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from . import test_sale_order diff --git a/product_contract_variable_quantity/tests/test_sale_order.py b/product_contract_variable_quantity/tests/test_sale_order.py new file mode 100644 index 00000000..a80332c9 --- /dev/null +++ b/product_contract_variable_quantity/tests/test_sale_order.py @@ -0,0 +1,70 @@ +# -*- coding: utf-8 -*- +# Copyright 2018 ACSONE SA/NV. +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from odoo.tests.common import TransactionCase + + +class TestSaleOrder(TransactionCase): + def setUp(self): + super(TestSaleOrder, self).setUp() + self.product1 = self.env.ref('product.product_product_1') + self.sale = self.env.ref('sale.sale_order_2') + self.contract_template1 = self.env['contract.template'].create( + {'name': 'Template 1'} + ) + self.formula = self.env['contract.line.qty.formula'].create( + { + 'name': 'Test formula', + # For testing each of the possible variables + 'code': 'env["res.users"]\n' + 'context.get("lang")\n' + 'user.id\n' + 'line.qty_type\n' + 'contract.id\n' + 'invoice.id\n' + 'result = 12', + } + ) + self.product1.write( + { + 'is_contract': True, + 'default_qty': 12, + 'contract_template_id': self.contract_template1.id, + 'qty_formula_id': self.formula.id, + 'qty_type': 'variable', + } + ) + self.order_line1 = self.sale.order_line.filtered( + lambda l: l.product_id == self.product1 + ) + + def test_change_is_contract(self): + product_tmpl = self.product1.product_tmpl_id + product_tmpl.is_contract = False + self.assertTrue(product_tmpl.qty_type) + product_tmpl._change_is_contract() + self.assertFalse(product_tmpl.qty_type) + + def test_onchange_product_id(self): + self.order_line1.onchange_product() + self.assertEqual( + self.order_line1.qty_formula_id, self.product1.qty_formula_id + ) + self.assertEqual(self.order_line1.qty_type, self.product1.qty_type) + + def test_action_confirm(self): + self.order_line1.onchange_product() + self.sale.action_confirm() + contract = self.order_line1.contract_id + contract_line = contract.contract_line_ids.filtered( + lambda line: line.product_id == self.product1 + ) + self.assertEqual( + contract_line.qty_formula_id, self.product1.qty_formula_id + ) + self.assertEqual(contract_line.qty_type, self.product1.qty_type) + self.assertEqual(contract_line.qty_type, 'variable') + self.product1.product_tmpl_id.qty_type = 'fixed' + contract_line._onchange_product_id_recurring_info() + self.assertEqual(contract_line.qty_type, 'fixed') diff --git a/product_contract_variable_quantity/views/product_template.xml b/product_contract_variable_quantity/views/product_template.xml new file mode 100644 index 00000000..b215174f --- /dev/null +++ b/product_contract_variable_quantity/views/product_template.xml @@ -0,0 +1,30 @@ + + + + + + + + account.invoice.select.contract (in + product_contract_variable_quantity) + + product.template + + + + + + + + + + + + diff --git a/product_contract_variable_quantity/views/sale_order.xml b/product_contract_variable_quantity/views/sale_order.xml new file mode 100644 index 00000000..802d8059 --- /dev/null +++ b/product_contract_variable_quantity/views/sale_order.xml @@ -0,0 +1,37 @@ + + + + + + + + sale.order.form (in + product_contract_variable_quantity) + + sale.order + + + + + + + + + + + + + + + + diff --git a/setup/product_contract_variable_quantity/odoo/addons/product_contract_variable_quantity b/setup/product_contract_variable_quantity/odoo/addons/product_contract_variable_quantity new file mode 120000 index 00000000..6b525359 --- /dev/null +++ b/setup/product_contract_variable_quantity/odoo/addons/product_contract_variable_quantity @@ -0,0 +1 @@ +../../../../product_contract_variable_quantity \ No newline at end of file diff --git a/setup/product_contract_variable_quantity/setup.py b/setup/product_contract_variable_quantity/setup.py new file mode 100644 index 00000000..28c57bb6 --- /dev/null +++ b/setup/product_contract_variable_quantity/setup.py @@ -0,0 +1,6 @@ +import setuptools + +setuptools.setup( + setup_requires=['setuptools-odoo'], + odoo_addon=True, +)