diff --git a/product_contract_variable_quantity/README.rst b/product_contract_variable_quantity/README.rst new file mode 100644 index 000000000..cc6bbf962 --- /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 000000000..0ee8b5073 --- /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 000000000..21e7d8b4f --- /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 000000000..d25a9d7ce --- /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 000000000..a28b5b9bd --- /dev/null +++ b/product_contract_variable_quantity/models/contract_line.py @@ -0,0 +1,16 @@ +# Copyright 2017 LasLabs Inc. +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + + +from odoo import api, fields, models + + +class AccountAnalyticInvoiceLine(models.Model): + _inherit = 'account.analytic.invoice.line' + + @api.onchange('product_id') + def onchange_product(self): + super(AccountAnalyticInvoiceLine, self).onchange_product() + if self.product_id.is_contract: + self.qty_type = self.product_id.qty_type + self.qty_formula_id = self.product_id.qty_formula_id 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 000000000..ad039bf2d --- /dev/null +++ b/product_contract_variable_quantity/models/product_template.py @@ -0,0 +1,31 @@ +# 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 + """ + super(ProductTemplate, self)._change_is_contract() + if not self.is_contract: + self.qty_type = False + self.qty_formula_id = False 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 000000000..bb58b3978 --- /dev/null +++ b/product_contract_variable_quantity/models/sale_order_line.py @@ -0,0 +1,40 @@ +# -*- 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, _ +from odoo.exceptions import ValidationError + + +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): + super(SaleOrderLine, self).onchange_product() + if self.product_id.is_contract: + self.qty_type = self.product_id.qty_type + self.qty_formula_id = self.product_id.qty_formula_id + + @api.multi + def _prepare_contract_line_values(self, contract): + values = super(SaleOrderLine, self)._prepare_contract_line_values( + contract + ) + 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 000000000..50e6298db --- /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 000000000..6e1777dbc --- /dev/null +++ b/product_contract_variable_quantity/readme/DESCRIPTION.rst @@ -0,0 +1 @@ +This module enable 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 000000000..3a0328b51 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 000000000..b5d241da0 --- /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 000000000..97c7012c3 --- /dev/null +++ b/product_contract_variable_quantity/tests/test_sale_order.py @@ -0,0 +1,59 @@ +# -*- 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 +from odoo.exceptions import ValidationError + + +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['account.analytic.contract'].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, + '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_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.recurring_invoice_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) 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 000000000..b215174f0 --- /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 000000000..c441c273b --- /dev/null +++ b/product_contract_variable_quantity/views/sale_order.xml @@ -0,0 +1,38 @@ + + + + + + + + sale.order.form (in + product_contract_variable_quantity) + + sale.order + + + + + + + + + + + + {'required': [('qty_type', '=', 'fixed')], 'invisible': [('qty_type', '!=', 'fixed')]} + + + + +