diff --git a/mrp_repair_discount/README.rst b/mrp_repair_discount/README.rst new file mode 100644 index 000000000..af6861745 --- /dev/null +++ b/mrp_repair_discount/README.rst @@ -0,0 +1,50 @@ +.. 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 + +=================== +MRP Repair Discount +=================== + +This module extends the functionality of mrp repair adding +new field discount on operations lines + +Usage +===== + +.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas + :alt: Try me on Runbot + :target: https://runbot.odoo-community.org/runbot/129/10.0 + +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 +======= + +Contributors +------------ + +* Nicola Malcontenti +* Pedro M. Baeza +* Lorenzo Battistini + +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/mrp_repair_discount/__init__.py b/mrp_repair_discount/__init__.py new file mode 100644 index 000000000..df4a96296 --- /dev/null +++ b/mrp_repair_discount/__init__.py @@ -0,0 +1,5 @@ +# -*- coding: utf-8 -*- +# Copyright 2015 Nicola Malcontenti - Agile Business Group +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from . import models diff --git a/mrp_repair_discount/__manifest__.py b/mrp_repair_discount/__manifest__.py new file mode 100644 index 000000000..01e764519 --- /dev/null +++ b/mrp_repair_discount/__manifest__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2015 Nicola Malcontenti - Agile Business Group +# Copyright 2016 Pedro M. Baeza +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +{ + "name": "MRP Repair Discount", + "version": "10.0.1.0.0", + "category": "Manufacturing", + "license": "AGPL-3", + "author": "Agile Business Group, " + "Tecnativa, " + "Odoo Community Association (OCA)", + "website": "http://www.agilebg.com", + 'depends': ['mrp_repair'], + "data": ["views/mrp_repair_view.xml"], + "installable": True, +} diff --git a/mrp_repair_discount/models/__init__.py b/mrp_repair_discount/models/__init__.py new file mode 100644 index 000000000..f579834b0 --- /dev/null +++ b/mrp_repair_discount/models/__init__.py @@ -0,0 +1,5 @@ +# -*- coding: utf-8 -*- +# Copyright 2015 Nicola Malcontenti - Agile Business Group +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from . import mrp_repair diff --git a/mrp_repair_discount/models/mrp_repair.py b/mrp_repair_discount/models/mrp_repair.py new file mode 100644 index 000000000..91160ca48 --- /dev/null +++ b/mrp_repair_discount/models/mrp_repair.py @@ -0,0 +1,118 @@ +# -*- coding: utf-8 -*- +# Copyright 2015 Nicola Malcontenti - Agile Business Group +# Copyright 2016 Pedro M. Baeza +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from odoo import api, fields, models +import openerp.addons.decimal_precision as dp + + +class RepairFee(models.Model): + _inherit = 'mrp.repair.fee' + + @api.one + @api.depends( + 'to_invoice', + 'price_unit', + 'repair_id', + 'product_uom_qty', + 'product_id') + def _compute_price_subtotal(self): + if not self.to_invoice: + self.price_subtotal = 0.0 + else: + taxes = self.env['account.tax'].compute_all( + self.price_unit, self.repair_id.pricelist_id.currency_id, + self.product_uom_qty, self.product_id, + self.repair_id.partner_id) + self.price_subtotal = ( + taxes['total_excluded'] * (1 - (self.discount or 0.0) / 100.0)) + + discount = fields.Float(string='Discount (%)') + price_subtotal = fields.Float( + 'Subtotal', + compute='_compute_price_subtotal', + digits=dp.get_precision('Account')) + + +class MrpRepairLine(models.Model): + _inherit = 'mrp.repair.line' + + @api.one + @api.depends( + 'to_invoice', + 'price_unit', + 'repair_id', + 'product_uom_qty', + 'product_id') + def _compute_price_subtotal(self): + if not self.to_invoice: + self.price_subtotal = 0.0 + else: + taxes = self.env['account.tax'].compute_all( + self.price_unit, self.repair_id.pricelist_id.currency_id, + self.product_uom_qty, self.product_id, + self.repair_id.partner_id) + self.price_subtotal = ( + taxes['total_excluded'] * (1 - (self.discount or 0.0) / 100.0)) + + discount = fields.Float(string='Discount (%)') + price_subtotal = fields.Float( + 'Subtotal', + compute='_compute_price_subtotal', + digits=dp.get_precision('Account')) + + +class MrpRepair(models.Model): + _inherit = 'mrp.repair' + + @api.multi + def action_invoice_create(self, group=False): + res = super(MrpRepair, self).action_invoice_create(group) + for repair in self: + operations = repair.operations.filtered('to_invoice') + fees_lines = repair.fees_lines.filtered('to_invoice') + if repair.invoice_method != 'none': + for op in operations: + op.invoice_line_id.discount = op.discount + if operations: + repair.invoice_id.compute_taxes() + for fl in fees_lines: + fl.invoice_line_id.discount = fl.discount + if fees_lines: + repair.invoice_id.compute_taxes() + return res + + def _calc_line_base_price(self, line): + return line.price_unit * (1 - (line.discount or 0.0) / 100.0) + + @api.multi + @api.depends('operations', 'fees_lines') + def _compute_tax(self): + for repair in self: + val = 0.0 + cur = repair.pricelist_id.currency_id + for line in repair.operations: + if line.to_invoice: + tax_calculate = line.tax_id.compute_all( + self._calc_line_base_price(line), + self.pricelist_id.currency_id, + line.product_uom_qty, + line.product_id, + repair.partner_id) + for c in tax_calculate['taxes']: + val += c['amount'] + for line in repair.fees_lines: + if line.to_invoice: + tax_calculate = line.tax_id.compute_all( + self._calc_line_base_price(line), + self.pricelist_id.currency_id, + line.product_uom_qty, + line.product_id, + repair.partner_id) + for c in tax_calculate['taxes']: + val += c['amount'] + repair.amount_tax = cur.round(val) + + amount_tax = fields.Float( + string='Taxes', compute='_compute_tax') diff --git a/mrp_repair_discount/tests/__init__.py b/mrp_repair_discount/tests/__init__.py new file mode 100644 index 000000000..eb17b9cae --- /dev/null +++ b/mrp_repair_discount/tests/__init__.py @@ -0,0 +1,4 @@ +# -*- coding: utf-8 -*- +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from . import test_mrp_repair_discount diff --git a/mrp_repair_discount/tests/test_mrp_repair_discount.py b/mrp_repair_discount/tests/test_mrp_repair_discount.py new file mode 100644 index 000000000..8cf3ed735 --- /dev/null +++ b/mrp_repair_discount/tests/test_mrp_repair_discount.py @@ -0,0 +1,59 @@ +# -*- coding: utf-8 -*- +# Copyright 2016 Pedro M. Baeza +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from odoo.tests import common + + +class TestMrpRepairDiscount(common.SavepointCase): + @classmethod + def setUpClass(cls): + super(TestMrpRepairDiscount, cls).setUpClass() + cls.product = cls.env['product.product'].create({ + 'name': 'Test product', + 'standard_price': 10, + 'list_price': 20, + }) + cls.partner = cls.env['res.partner'].create({ + 'name': 'Test partner', + }) + cls.location = cls.env['stock.location'].create({ + 'name': 'Test location', + }) + cls.repair = cls.env['mrp.repair'].create({ + 'product_id': cls.product.id, + 'partner_id': cls.partner.id, + 'partner_invoice_id': cls.partner.id, + 'product_uom': cls.product.uom_id.id, + 'location_id': cls.location.id, + 'location_dest_id': cls.location.id, + 'invoice_method': 'b4repair', + }) + cls.repair_line = cls.env['mrp.repair.line'].create({ + 'repair_id': cls.repair.id, + 'type': 'add', + 'product_id': cls.product.id, + 'product_uom': cls.product.uom_id.id, + 'name': 'Test line', + 'location_id': cls.repair.location_id.id, + 'location_dest_id': cls.repair.location_dest_id.id, + 'product_uom_qty': 1, + 'price_unit': 20, + 'discount': 50, + 'to_invoice': True, + }) + + def test_discount(self): + self.assertAlmostEqual( + self.repair_line.price_subtotal, 10) + self.assertAlmostEqual( + self.repair.amount_total, 10) + + def test_invoice_create(self): + self.repair.state = '2binvoiced' + res = self.repair.action_invoice_create() + invoice = self.env['account.invoice'].browse(res.values()[0]) + invoice_line = invoice.invoice_line_ids[0] + self.assertEqual(invoice_line.discount, 50) + self.assertAlmostEqual( + invoice_line.price_subtotal, 10) diff --git a/mrp_repair_discount/views/mrp_repair_view.xml b/mrp_repair_discount/views/mrp_repair_view.xml new file mode 100644 index 000000000..72a8f92bc --- /dev/null +++ b/mrp_repair_discount/views/mrp_repair_view.xml @@ -0,0 +1,16 @@ + + + + mrp.repair.discount.form + mrp.repair + + + + + + + + + + +