From d9b8da57991fee69166e5e18af699ea4aefcfa00 Mon Sep 17 00:00:00 2001 From: Alexis de Lattre Date: Fri, 31 Jul 2015 15:19:54 +0200 Subject: [PATCH] Add module sale_margin_no_onchange --- sale_margin_no_onchange/__init__.py | 3 + sale_margin_no_onchange/__openerp__.py | 43 ++++++++ sale_margin_no_onchange/sale.py | 139 +++++++++++++++++++++++++ sale_margin_no_onchange/sale_view.xml | 37 +++++++ 4 files changed, 222 insertions(+) create mode 100644 sale_margin_no_onchange/__init__.py create mode 100644 sale_margin_no_onchange/__openerp__.py create mode 100644 sale_margin_no_onchange/sale.py create mode 100644 sale_margin_no_onchange/sale_view.xml diff --git a/sale_margin_no_onchange/__init__.py b/sale_margin_no_onchange/__init__.py new file mode 100644 index 0000000..1d47105 --- /dev/null +++ b/sale_margin_no_onchange/__init__.py @@ -0,0 +1,3 @@ +# -*- encoding: utf-8 -*- + +from . import sale diff --git a/sale_margin_no_onchange/__openerp__.py b/sale_margin_no_onchange/__openerp__.py new file mode 100644 index 0000000..7393efb --- /dev/null +++ b/sale_margin_no_onchange/__openerp__.py @@ -0,0 +1,43 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# Sale Margin No Onchange module for Odoo +# Copyright (C) 2015 Akretion (http://www.akretion.com) +# @author Alexis de Lattre +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + + +{ + 'name': 'Sale Margin No Onchange', + 'version': '0.1', + 'category': 'Accounting & Finance', + 'license': 'AGPL-3', + 'summary': 'Copy standard price on sale order line and compute margins', + 'description': """ +This module copies the field *standard_price* of the product on the sale order line when the sale order line is created. The allows the computation of the margin of the sale order. + +This module has been written by Alexis de Lattre from Akretion +. + """, + 'author': 'Akretion', + 'website': 'http://www.akretion.com', + 'depends': ['sale'], + 'data': [ + 'sale_view.xml', + ], + 'installable': True, +} diff --git a/sale_margin_no_onchange/sale.py b/sale_margin_no_onchange/sale.py new file mode 100644 index 0000000..d577c1b --- /dev/null +++ b/sale_margin_no_onchange/sale.py @@ -0,0 +1,139 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# Sale Margin No Onchange module for Odoo +# Copyright (C) 2015 Akretion (http://www.akretion.com) +# @author Alexis de Lattre +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +from openerp import models, fields, api +import openerp.addons.decimal_precision as dp + + +class SaleOrderLine(models.Model): + _inherit = 'sale.order.line' + + standard_price_company_currency = fields.Float( + string='Cost Price in Company Currency', readonly=True, + digits=dp.get_precision('Product Price')) + standard_price_sale_currency = fields.Float( + string='Cost Price in Sale Currency', readonly=True, + compute='_compute_margin', store=True, + digits=dp.get_precision('Account')) + margin_sale_currency = fields.Float( + string='Margin in Sale Currency', readonly=True, store=True, + compute='_compute_margin', + digits=dp.get_precision('Account')) + margin_company_currency = fields.Float( + string='Margin in Company Currency', readonly=True, store=True, + compute='_compute_margin', + digits=dp.get_precision('Account')) + + @api.one + @api.depends( + 'standard_price_company_currency', 'order_id.pricelist_id', + 'order_id.date_order', 'product_uom_qty', 'price_subtotal') + def _compute_margin(self): + standard_price_sale_cur = 0.0 + margin_sale_cur = 0.0 + margin_comp_cur = 0.0 + if self.order_id and self.order_id.currency_id: + # it works in _get_current_rate + # even if we set date = False in context + standard_price_sale_cur =\ + self.order_id.company_id.currency_id.with_context( + date=self.order_id.date_order).compute( + self.standard_price_company_currency, + self.order_id.currency_id) + margin_sale_cur =\ + self.price_subtotal\ + - self.product_uom_qty * standard_price_sale_cur + margin_comp_cur = self.order_id.currency_id.with_context( + date=self.order_id.date_order).compute( + margin_sale_cur, self.order_id.company_id.currency_id) + self.standard_price_sale_currency = standard_price_sale_cur + self.margin_sale_currency = margin_sale_cur + self.margin_company_currency = margin_comp_cur + + # We want to copy standard_price on sale order line + @api.model + def create(self, vals): + if vals.get('product_id'): + pp = self.env['product.product'].browse(vals['product_id']) + std_price = pp.standard_price + sale_uom_id = vals.get('product_uom') + if sale_uom_id and sale_uom_id != pp.uom_id.id: + std_price = self.env['product.uom']._compute_price( + pp.uom_id.id, std_price, sale_uom_id) + vals['standard_price_company_currency'] = std_price + return super(SaleOrderLine, self).create(vals) + + @api.multi + def write(self, vals): + if not vals: + vals = {} + if 'product_id' in vals or 'product_uom' in vals: + for sol in self: + if 'product_id' in vals: + if vals.get('product_id'): + pp = self.env['product.product'].browse( + vals['product_id']) + else: + pp = False + else: + pp = sol.product_id or False + # product_uom is a required field, + # so it's different from product_id + if 'product_uom' in vals: + sale_uom = self.env['product.uom'].browse( + vals['product_uom']) + else: + sale_uom = sol.product_uom + std_price = 0.0 + if pp: + std_price = pp.standard_price + if sale_uom != pp.uom_id: + std_price = self.env['product.uom']._compute_price( + pp.uom_id.id, std_price, sale_uom.id) + sol.write({'standard_price_company_currency': std_price}) + return super(SaleOrderLine, self).write(vals) + + +class SaleOrder(models.Model): + _inherit = 'sale.order' + + margin_sale_currency = fields.Float( + string='Margin in Sale Currency', + readonly=True, compute='_compute_margin', store=True, + digits=dp.get_precision('Account')) + margin_company_currency = fields.Float( + string='Margin in Company Currency', + readonly=True, compute='_compute_margin', store=True, + digits=dp.get_precision('Account')) + + @api.one + @api.depends( + 'order_line.margin_sale_currency', + 'order_line.margin_company_currency') + def _compute_margin(self): + margin_sale_cur = 0.0 + margin_comp_cur = 0.0 + for sol in self.order_line: + margin_sale_cur += sol.margin_sale_currency + margin_comp_cur += sol.margin_company_currency + self.margin_sale_currency = margin_sale_cur + self.margin_company_currency = margin_comp_cur diff --git a/sale_margin_no_onchange/sale_view.xml b/sale_margin_no_onchange/sale_view.xml new file mode 100644 index 0000000..f8c6b4e --- /dev/null +++ b/sale_margin_no_onchange/sale_view.xml @@ -0,0 +1,37 @@ + + + + + + + + + margin.sale.order.form + sale.order + + + + + + + + + + + + + + + + + +