From d850270d0d3ce582e48d7afd23713fc47fccf391 Mon Sep 17 00:00:00 2001 From: Ainara Date: Wed, 5 Nov 2014 11:30:40 +0100 Subject: [PATCH 01/13] [ADD] mrp_production_real_cost --- mrp_production_real_cost/__init__.py | 19 +++ mrp_production_real_cost/__openerp__.py | 44 +++++ mrp_production_real_cost/i18n/es.po | 38 +++++ .../i18n/mrp_production_real_costs.pot | 38 +++++ mrp_production_real_cost/models/__init__.py | 22 +++ .../models/mrp_production.py | 47 ++++++ .../models/mrp_production_workcenter_line.py | 92 +++++++++++ .../models/project_task_work.py | 48 ++++++ mrp_production_real_cost/models/stock_move.py | 153 ++++++++++++++++++ .../views/mrp_production_view.xml | 16 ++ 10 files changed, 517 insertions(+) create mode 100644 mrp_production_real_cost/__init__.py create mode 100644 mrp_production_real_cost/__openerp__.py create mode 100644 mrp_production_real_cost/i18n/es.po create mode 100644 mrp_production_real_cost/i18n/mrp_production_real_costs.pot create mode 100644 mrp_production_real_cost/models/__init__.py create mode 100644 mrp_production_real_cost/models/mrp_production.py create mode 100644 mrp_production_real_cost/models/mrp_production_workcenter_line.py create mode 100644 mrp_production_real_cost/models/project_task_work.py create mode 100644 mrp_production_real_cost/models/stock_move.py create mode 100644 mrp_production_real_cost/views/mrp_production_view.xml diff --git a/mrp_production_real_cost/__init__.py b/mrp_production_real_cost/__init__.py new file mode 100644 index 000000000..324fad228 --- /dev/null +++ b/mrp_production_real_cost/__init__.py @@ -0,0 +1,19 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see http://www.gnu.org/licenses/. +# +############################################################################## + +from . import models diff --git a/mrp_production_real_cost/__openerp__.py b/mrp_production_real_cost/__openerp__.py new file mode 100644 index 000000000..c4d8bddcd --- /dev/null +++ b/mrp_production_real_cost/__openerp__.py @@ -0,0 +1,44 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see http://www.gnu.org/licenses/. +# +############################################################################## + +{ + "name": "Mrp Real Costs", + "version": "1.0", + "depends": ["analytic", + "project_timesheet", + "mrp_project_link", + "mrp_operations_time_control", + "stock_account", + "mrp_production_project_estimated_cost"], + "author": "OdooMRP team", + "category": "MRP", + "description": """ + - This module allows to control the real cost of a production order, + creating lines in the analytic account defined in the order that is + created by the module mrp_project_link. + + - Updates product standard price when a production orders final product + is done. + (Product stock * Product standard price + Production real cost) / + (Product stock + Final product quantity) + """, + 'data': ["views/mrp_production_view.xml"], + 'demo': [], + 'installable': True, + 'auto_install': False, +} diff --git a/mrp_production_real_cost/i18n/es.po b/mrp_production_real_cost/i18n/es.po new file mode 100644 index 000000000..3a5b746f5 --- /dev/null +++ b/mrp_production_real_cost/i18n/es.po @@ -0,0 +1,38 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * mrp_production_real_costs +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 8.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2014-11-11 15:06+0000\n" +"PO-Revision-Date: 2014-11-11 16:12+0100\n" +"Last-Translator: \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: \n" + +#. module: mrp_production_real_costs +#: model:ir.model,name:mrp_production_real_costs.model_project_task_work +msgid "Project Task Work" +msgstr "Trabajo de tarea" + +#. module: mrp_production_real_costs +#: model:ir.model,name:mrp_production_real_costs.model_stock_move +msgid "Stock Move" +msgstr "Movimiento de existencias" + +#. module: mrp_production_real_costs +#: model:ir.model,name:mrp_production_real_costs.model_mrp_production_workcenter_line +msgid "Work Order" +msgstr "Orden de trabajo" + +#. module: mrp_production_real_costs +#: code:addons/mrp_production_real_costs/models/mrp_production_workcenter_line.py:59 +#, python-format +msgid "You must define a general account for this Workcenter: [%s] %s" +msgstr "Es necesario que defina una cuenta contable para este centro de producción: [%s] %s" + diff --git a/mrp_production_real_cost/i18n/mrp_production_real_costs.pot b/mrp_production_real_cost/i18n/mrp_production_real_costs.pot new file mode 100644 index 000000000..69ecdc8cb --- /dev/null +++ b/mrp_production_real_cost/i18n/mrp_production_real_costs.pot @@ -0,0 +1,38 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * mrp_production_real_costs +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 8.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2014-11-11 15:06+0000\n" +"PO-Revision-Date: 2014-11-11 16:09+0100\n" +"Last-Translator: \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: \n" + +#. module: mrp_production_real_costs +#: model:ir.model,name:mrp_production_real_costs.model_project_task_work +msgid "Project Task Work" +msgstr "" + +#. module: mrp_production_real_costs +#: model:ir.model,name:mrp_production_real_costs.model_stock_move +msgid "Stock Move" +msgstr "" + +#. module: mrp_production_real_costs +#: model:ir.model,name:mrp_production_real_costs.model_mrp_production_workcenter_line +msgid "Work Order" +msgstr "" + +#. module: mrp_production_real_costs +#: code:addons/mrp_production_real_costs/models/mrp_production_workcenter_line.py:59 +#, python-format +msgid "You must define a general account for this Workcenter: [%s] %s" +msgstr "" + diff --git a/mrp_production_real_cost/models/__init__.py b/mrp_production_real_cost/models/__init__.py new file mode 100644 index 000000000..271c541d3 --- /dev/null +++ b/mrp_production_real_cost/models/__init__.py @@ -0,0 +1,22 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see http://www.gnu.org/licenses/. +# +############################################################################## + +from . import stock_move +from . import mrp_production_workcenter_line +from . import project_task_work +from . import mrp_production diff --git a/mrp_production_real_cost/models/mrp_production.py b/mrp_production_real_cost/models/mrp_production.py new file mode 100644 index 000000000..984ac116b --- /dev/null +++ b/mrp_production_real_cost/models/mrp_production.py @@ -0,0 +1,47 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see http://www.gnu.org/licenses/. +# +############################################################################## + +from openerp import models, fields, api + + +class MrpProduction(models.Model): + + _inherit = 'mrp.production' + + @api.one + @api.depends('analytic_line_ids', 'analytic_line_ids.amount', + 'product_qty') + def get_real_cost(self): + self.real_cost = sum([-line.amount for line in + self.analytic_line_ids]) + self.unit_real_cost = self.real_cost / self.product_qty + + real_cost = fields.Float("Total Real Cost", compute="get_real_cost", + store=True) + unit_real_cost = fields.Float("Unit Real Cost", compute="get_real_cost", + store=True) + + @api.multi + def action_production_end(self): + res = super(MrpProduction, self).action_production_end() + analytic_line_obj = self.env['account.analytic.line'] + for record in self: + cost_lines = analytic_line_obj.search([('mrp_production_id', '=', + record.id)]) + record.real_cost = sum([-line.amount for line in cost_lines]) + return res diff --git a/mrp_production_real_cost/models/mrp_production_workcenter_line.py b/mrp_production_real_cost/models/mrp_production_workcenter_line.py new file mode 100644 index 000000000..c58d3f0b9 --- /dev/null +++ b/mrp_production_real_cost/models/mrp_production_workcenter_line.py @@ -0,0 +1,92 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see http://www.gnu.org/licenses/. +# +############################################################################## + +from openerp import models, api +from datetime import datetime + + +class MrpProductionWorkcenterLine(models.Model): + + _inherit = 'mrp.production.workcenter.line' + + @api.multi + def _create_analytic_line(self): + self.ensure_one() + analytic_line_obj = self.env['account.analytic.line'] + property_obj = self.env['ir.property'] + task_obj = self.env['project.task'] + if self.workcenter_id.costs_hour > 0.0: + hour_uom = self.env.ref('product.product_uom_hour', False) + operation_line = self.operation_time_lines[-1] + production = self.production_id + workcenter = self.workcenter_id + product = workcenter.product_id + journal_id = workcenter.costs_journal_id or False + if not journal_id: + journal_id = self.env.ref( + 'mrp_production_project_estimated_cost.analytic_journal_' + 'machines', False) + analytic_account_id = production.analytic_account_id.id or False + task_id = False + if production: + task = task_obj.search([('mrp_production_id', '=', + production.id), + ('wk_order', '=', False)]) + if task: + task_id = task[0].id + name = ((production.name or '') + '-' + + (self.routing_wc_line.operation.code or '') + '-' + + (product.default_code or '')) + general_acc = ( + workcenter.costs_general_account_id.id or + product.property_account_expense.id or + product.categ_id.property_account_expense_categ.id or + property_obj.get('property_account_expense_categ', + 'product.category')) + price = workcenter.costs_hour + analytic_vals = {'name': name, + 'ref': name, + 'date': datetime.now().strftime('%Y-%m-%d'), + 'user_id': self.env.uid, + 'product_id': product.id, + 'product_uom_id': hour_uom.id, + 'amount': -(price * operation_line.uptime), + 'unit_amount': operation_line.uptime, + 'journal_id': journal_id.id, + 'account_id': analytic_account_id, + 'general_account_id': general_acc, + 'task_id': task_id, + 'mrp_production_id': production.id or False, + 'workorder': self.id, + 'estim_avg_cost': 0.0, + 'estim_std_cost': 0.0 + } + analytic_line = analytic_line_obj.create(analytic_vals) + return analytic_line + + @api.multi + def action_pause(self): + result = super(MrpProductionWorkcenterLine, self).action_pause() + self._create_analytic_line() + return result + + @api.multi + def action_done(self): + result = super(MrpProductionWorkcenterLine, self).action_done() + self._create_analytic_line() + return result diff --git a/mrp_production_real_cost/models/project_task_work.py b/mrp_production_real_cost/models/project_task_work.py new file mode 100644 index 000000000..b951b2a00 --- /dev/null +++ b/mrp_production_real_cost/models/project_task_work.py @@ -0,0 +1,48 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see http://www.gnu.org/licenses/. +# +############################################################################## + +from openerp import models, api + + +class ProjectTaskWork(models.Model): + + _inherit = 'project.task.work' + + @api.model + def create(self, vals): + result = super(ProjectTaskWork, self).create(vals) + if result.hr_analytic_timesheet_id and result.task_id: + analytic_line = result.hr_analytic_timesheet_id.line_id + task = result.task_id + if task.mrp_production_id or task.wk_order: + analytic_line.write({'mrp_production_id': + task.mrp_production_id.id, + 'workorder': task.wk_order.id}) + return result + + @api.model + def write(self, vals): + result = super(ProjectTaskWork, self).write(vals) + if 'hr_analytic_timesheet_id' in vals or 'task_id' in vals: + analytic_line = self.hr_analytic_timesheet_id.line_id + task = self.task_id + if task.mrp_production_id or task.wk_order: + analytic_line.write({'mrp_production_id': + task.mrp_production_id.id, + 'workorder': task.wk_order.id}) + return result diff --git a/mrp_production_real_cost/models/stock_move.py b/mrp_production_real_cost/models/stock_move.py new file mode 100644 index 000000000..e91979c78 --- /dev/null +++ b/mrp_production_real_cost/models/stock_move.py @@ -0,0 +1,153 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see http://www.gnu.org/licenses/. +# +############################################################################## + +from openerp import models, api +from datetime import datetime +import math + + +class StockMove(models.Model): + + _inherit = 'stock.move' + + @api.multi + def action_consume(self, product_qty, location_id=False, + restrict_lot_id=False, restrict_partner_id=False, + consumed_for=False): + task_obj = self.env['project.task'] + property_obj = self.env['ir.property'] + analytic_line_obj = self.env['account.analytic.line'] + result = super(StockMove, self).action_consume( + product_qty, location_id=location_id, + restrict_lot_id=restrict_lot_id, + restrict_partner_id=restrict_partner_id, consumed_for=consumed_for) + for record in self: + price = record.product_id.standard_price + if price > 0.0: + if record.production_id or record.raw_material_production_id: + product = record.product_id + journal_id = self.env.ref( + 'mrp_production_project_estimated_cost.analytic_' + 'journal_materials', False) + production_id = False + analytic_account_id = False + task_id = False + if record.production_id: + production = record.production_id + elif record.raw_material_production_id: + production = record.raw_material_production_id + if production: + production_id = production.id + analytic_account_id = production.analytic_account_id.id + task = task_obj.search( + [('mrp_production_id', '=', production_id), + ('wk_order', '=', False)]) + if task: + task_id = task[0].id + name = ( + (production.name or '') + '-' + + (record.work_order.routing_wc_line.operation.code or + '') + '-' + (product.default_code or '')) + general_account = ( + product.property_account_expense.id or + product.categ_id.property_account_expense_categ.id or + property_obj.get('property_account_expense_categ', + 'product.category')) + date = datetime.now().strftime('%Y-%m-%d') + uom_id = record.product_id.uom_id.id + if record.raw_material_production_id: + analytic_vals = {'name': name, + 'ref': name, + 'date': date, + 'user_id': self.env.uid, + 'product_id': product.id, + 'product_uom_id': uom_id, + 'amount': -(price * product_qty), + 'unit_amount': product_qty, + 'journal_id': journal_id.id, + 'account_id': analytic_account_id, + 'general_account_id': general_account, + 'task_id': task_id, + 'mrp_production_id': production_id, + 'workorder': record.work_order.id, + 'estim_avg_cost': 0.0, + 'estim_std_cost': 0.0 + } + analytic_line_obj.create(analytic_vals) + elif record.production_id: + amount = 0.0 + unit_amount = 0.0 + for wc in production.workcenter_lines: + cycle_cost = wc.workcenter_id.costs_cycle + cycle_units = wc.workcenter_id.capacity_per_cycle + cycle = int(math.ceil(product_qty / cycle_units)) + amount += cycle * cycle_cost + unit_amount += cycle + analytic_vals = {'name': name, + 'ref': name, + 'date': date, + 'user_id': self.env.uid, + 'product_id': product.id, + 'product_uom_id': uom_id, + 'amount': amount, + 'unit_amount': unit_amount, + 'journal_id': journal_id.id, + 'account_id': analytic_account_id, + 'general_account_id': general_account, + 'task_id': task_id, + 'mrp_production_id': production_id, + 'workorder': record.work_order.id, + 'estim_avg_cost': 0.0, + 'estim_std_cost': 0.0 + } + analytic_line_obj.create(analytic_vals) + return result + + @api.multi + def product_price_update_before_done(self): + analytic_line_obj = self.env['account.analytic.line'] + super(StockMove, self).product_price_update_before_done() + for move in self: + # adapt standard price on production final moves if the + # product cost_method is 'average' + if (move.production_id) and (move.product_id.cost_method == + 'average'): + analytic_lines = analytic_line_obj.search( + [('mrp_production_id', '=', move.production_id.id)]) + prod_total_cost = sum([-line.amount for line in + analytic_lines]) + product = move.product_id + product_avail = product.qty_available + amount_unit = product.standard_price + new_std_price = ((amount_unit * product_avail + + prod_total_cost) / (product_avail >= 0.0 or + 0.0 + move.product_qty)) + # Write the standard price, as SUPERUSER_ID because a warehouse + # manager may not have the right to write on products + product.sudo().write({'standard_price': new_std_price}) + + @api.multi + def get_unit_price(self): + self.ensure_one() + if self.production_id: + analytic_line_obj = self.env['account.analytic.line'] + analytic_lines = analytic_line_obj.search( + [('mrp_production_id', '=', self.production_id.id)]) + return sum([-line.amount for line in analytic_lines]) + else: + return super(StockMove, self).get_unit_price() diff --git a/mrp_production_real_cost/views/mrp_production_view.xml b/mrp_production_real_cost/views/mrp_production_view.xml new file mode 100644 index 000000000..bbeb27a2d --- /dev/null +++ b/mrp_production_real_cost/views/mrp_production_view.xml @@ -0,0 +1,16 @@ + + + + + mrp.production.project.form.view.inh.estimatedcost + mrp.production + + + + + + + + + + From 43cee0dcc64bfc4bf4e26539cc7811351ed04afc Mon Sep 17 00:00:00 2001 From: "Pedro M. Baeza" Date: Thu, 19 Feb 2015 23:28:57 +0100 Subject: [PATCH 02/13] [IMP] mrp_production_real_cost: Reorganize views --- mrp_production_real_cost/__openerp__.py | 4 +++- mrp_production_real_cost/views/mrp_production_view.xml | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/mrp_production_real_cost/__openerp__.py b/mrp_production_real_cost/__openerp__.py index c4d8bddcd..70e21c54e 100644 --- a/mrp_production_real_cost/__openerp__.py +++ b/mrp_production_real_cost/__openerp__.py @@ -25,7 +25,9 @@ "mrp_operations_time_control", "stock_account", "mrp_production_project_estimated_cost"], - "author": "OdooMRP team", + "author": "OdooMRP team," + "AvanzOSC," + "Serv. Tecnol. Avanzados - Pedro M. Baeza", "category": "MRP", "description": """ - This module allows to control the real cost of a production order, diff --git a/mrp_production_real_cost/views/mrp_production_view.xml b/mrp_production_real_cost/views/mrp_production_view.xml index bbeb27a2d..8cfbeff95 100644 --- a/mrp_production_real_cost/views/mrp_production_view.xml +++ b/mrp_production_real_cost/views/mrp_production_view.xml @@ -6,7 +6,7 @@ mrp.production - + From debf602781c7ad43c19ea770a6e5a7d19a4a1bfd Mon Sep 17 00:00:00 2001 From: agaldona Date: Thu, 14 May 2015 14:35:51 +0200 Subject: [PATCH 03/13] [IMP] mrp_production_real_costs: calculo de precio coste de producto. --- mrp_production_real_cost/models/stock_move.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/mrp_production_real_cost/models/stock_move.py b/mrp_production_real_cost/models/stock_move.py index e91979c78..ee907b771 100644 --- a/mrp_production_real_cost/models/stock_move.py +++ b/mrp_production_real_cost/models/stock_move.py @@ -135,19 +135,21 @@ class StockMove(models.Model): product_avail = product.qty_available amount_unit = product.standard_price new_std_price = ((amount_unit * product_avail + - prod_total_cost) / (product_avail >= 0.0 or - 0.0 + move.product_qty)) + prod_total_cost) / + ((product_avail >= 0.0 and product_avail or + 0.0) + move.product_qty)) # Write the standard price, as SUPERUSER_ID because a warehouse # manager may not have the right to write on products product.sudo().write({'standard_price': new_std_price}) @api.multi - def get_unit_price(self): + def get_price_unit(self): self.ensure_one() if self.production_id: analytic_line_obj = self.env['account.analytic.line'] analytic_lines = analytic_line_obj.search( [('mrp_production_id', '=', self.production_id.id)]) - return sum([-line.amount for line in analytic_lines]) + return (sum([-line.amount for line in analytic_lines]) / + self.product_qty) else: - return super(StockMove, self).get_unit_price() + return super(StockMove, self).get_price_unit() From 3a038d162d10affe0b80bbc6c965967ce8331308 Mon Sep 17 00:00:00 2001 From: Eric Caudal Date: Wed, 20 May 2015 01:40:42 +0200 Subject: [PATCH 04/13] [IMP] Improve some README files --- mrp_production_real_cost/README.rst | 11 +++++++++++ mrp_production_real_cost/__openerp__.py | 13 +------------ 2 files changed, 12 insertions(+), 12 deletions(-) create mode 100644 mrp_production_real_cost/README.rst diff --git a/mrp_production_real_cost/README.rst b/mrp_production_real_cost/README.rst new file mode 100644 index 000000000..1575ef3b4 --- /dev/null +++ b/mrp_production_real_cost/README.rst @@ -0,0 +1,11 @@ +Real costs in manufacturing orders +================================== + +This module allows to manage the control of Manufacturing Orders actual costs, +by creating analytic lines as defined in the MO (from *mrp_project_link*). + +It also updates product standard price when a manufacturing orders is finished +according this formula: + +(Product stock * Product standard price + Production real cost) / +(Product stock + Final product quantity) diff --git a/mrp_production_real_cost/__openerp__.py b/mrp_production_real_cost/__openerp__.py index 70e21c54e..76d843098 100644 --- a/mrp_production_real_cost/__openerp__.py +++ b/mrp_production_real_cost/__openerp__.py @@ -17,7 +17,7 @@ ############################################################################## { - "name": "Mrp Real Costs", + "name": "MRP real costs", "version": "1.0", "depends": ["analytic", "project_timesheet", @@ -29,18 +29,7 @@ "AvanzOSC," "Serv. Tecnol. Avanzados - Pedro M. Baeza", "category": "MRP", - "description": """ - - This module allows to control the real cost of a production order, - creating lines in the analytic account defined in the order that is - created by the module mrp_project_link. - - - Updates product standard price when a production orders final product - is done. - (Product stock * Product standard price + Production real cost) / - (Product stock + Final product quantity) - """, 'data': ["views/mrp_production_view.xml"], - 'demo': [], 'installable': True, 'auto_install': False, } From 5d30b9317ef38cc7a5b6d193c5acf75a074dcfc8 Mon Sep 17 00:00:00 2001 From: agaldona Date: Wed, 20 May 2015 15:31:46 +0200 Subject: [PATCH 05/13] [IMP] mrp_production_real_cost: Use variant cost price --- .../models/mrp_production.py | 19 ++- .../models/mrp_production_workcenter_line.py | 52 ++---- mrp_production_real_cost/models/stock_move.py | 151 ++++++------------ 3 files changed, 79 insertions(+), 143 deletions(-) diff --git a/mrp_production_real_cost/models/mrp_production.py b/mrp_production_real_cost/models/mrp_production.py index 984ac116b..bfe7c544c 100644 --- a/mrp_production_real_cost/models/mrp_production.py +++ b/mrp_production_real_cost/models/mrp_production.py @@ -23,12 +23,17 @@ class MrpProduction(models.Model): _inherit = 'mrp.production' + @api.multi + def calc_mrp_real_cost(self): + self.ensure_one() + return sum([-line.amount for line in + self.analytic_line_ids.filtered(lambda l: l.amount < 0)]) + @api.one @api.depends('analytic_line_ids', 'analytic_line_ids.amount', 'product_qty') def get_real_cost(self): - self.real_cost = sum([-line.amount for line in - self.analytic_line_ids]) + self.real_cost = self.calc_mrp_real_cost() self.unit_real_cost = self.real_cost / self.product_qty real_cost = fields.Float("Total Real Cost", compute="get_real_cost", @@ -39,9 +44,11 @@ class MrpProduction(models.Model): @api.multi def action_production_end(self): res = super(MrpProduction, self).action_production_end() - analytic_line_obj = self.env['account.analytic.line'] for record in self: - cost_lines = analytic_line_obj.search([('mrp_production_id', '=', - record.id)]) - record.real_cost = sum([-line.amount for line in cost_lines]) + mrp_cost = record.calc_mrp_real_cost() + done_lines = record.move_created_ids2.filtered(lambda l: + l.state == 'done') + done_lines.create_produce_cost_line(mrp_cost) + record.real_cost = mrp_cost + done_lines.product_price_update_production_done() return res diff --git a/mrp_production_real_cost/models/mrp_production_workcenter_line.py b/mrp_production_real_cost/models/mrp_production_workcenter_line.py index c58d3f0b9..356e98890 100644 --- a/mrp_production_real_cost/models/mrp_production_workcenter_line.py +++ b/mrp_production_real_cost/models/mrp_production_workcenter_line.py @@ -17,7 +17,6 @@ ############################################################################## from openerp import models, api -from datetime import datetime class MrpProductionWorkcenterLine(models.Model): @@ -28,7 +27,6 @@ class MrpProductionWorkcenterLine(models.Model): def _create_analytic_line(self): self.ensure_one() analytic_line_obj = self.env['account.analytic.line'] - property_obj = self.env['ir.property'] task_obj = self.env['project.task'] if self.workcenter_id.costs_hour > 0.0: hour_uom = self.env.ref('product.product_uom_hour', False) @@ -36,46 +34,22 @@ class MrpProductionWorkcenterLine(models.Model): production = self.production_id workcenter = self.workcenter_id product = workcenter.product_id - journal_id = workcenter.costs_journal_id or False - if not journal_id: - journal_id = self.env.ref( - 'mrp_production_project_estimated_cost.analytic_journal_' - 'machines', False) - analytic_account_id = production.analytic_account_id.id or False - task_id = False - if production: - task = task_obj.search([('mrp_production_id', '=', - production.id), - ('wk_order', '=', False)]) - if task: - task_id = task[0].id + journal_id = workcenter.costs_journal_id or self.env.ref( + 'mrp_production_project_estimated_cost.analytic_journal_' + 'machines', False) name = ((production.name or '') + '-' + (self.routing_wc_line.operation.code or '') + '-' + (product.default_code or '')) - general_acc = ( - workcenter.costs_general_account_id.id or - product.property_account_expense.id or - product.categ_id.property_account_expense_categ.id or - property_obj.get('property_account_expense_categ', - 'product.category')) - price = workcenter.costs_hour - analytic_vals = {'name': name, - 'ref': name, - 'date': datetime.now().strftime('%Y-%m-%d'), - 'user_id': self.env.uid, - 'product_id': product.id, - 'product_uom_id': hour_uom.id, - 'amount': -(price * operation_line.uptime), - 'unit_amount': operation_line.uptime, - 'journal_id': journal_id.id, - 'account_id': analytic_account_id, - 'general_account_id': general_acc, - 'task_id': task_id, - 'mrp_production_id': production.id or False, - 'workorder': self.id, - 'estim_avg_cost': 0.0, - 'estim_std_cost': 0.0 - } + general_acc = workcenter.costs_general_account_id or False + price = -(workcenter.costs_hour * operation_line.uptime) + analytic_vals = production._prepare_cost_analytic_line( + journal_id, name, production, product, + general_account=general_acc, workorder=self, + qty=operation_line.uptime, amount=price) + task = task_obj.search([('mrp_production_id', '=', production.id), + ('wk_order', '=', False)]) + analytic_vals['task_id'] = task and task[0].id or False + analytic_vals['product_uom_id'] = hour_uom.id analytic_line = analytic_line_obj.create(analytic_vals) return analytic_line diff --git a/mrp_production_real_cost/models/stock_move.py b/mrp_production_real_cost/models/stock_move.py index ee907b771..0c5d55f70 100644 --- a/mrp_production_real_cost/models/stock_move.py +++ b/mrp_production_real_cost/models/stock_move.py @@ -17,139 +17,94 @@ ############################################################################## from openerp import models, api -from datetime import datetime -import math class StockMove(models.Model): _inherit = 'stock.move' + @api.multi + def create_produce_cost_line(self, amount): + task_obj = self.env['project.task'] + analytic_line_obj = self.env['account.analytic.line'] + for record in self: + if amount > 0.0: + if record.production_id: + product = record.product_id + production = record.production_id + journal_id = self.env.ref( + 'mrp_production_project_estimated_cost.analytic_' + 'journal_materials', False) + name = ('Final product - ' + (production.name or '') + + '-' + (product.default_code or '')) + vals = production._prepare_cost_analytic_line( + journal_id, name, production, product, + qty=record.product_qty, amount=amount) + task = task_obj.search( + [('mrp_production_id', '=', production.id), + ('wk_order', '=', False)]) + vals['task_id'] = task and task[0].id or False + analytic_line_obj.create(vals) + @api.multi def action_consume(self, product_qty, location_id=False, restrict_lot_id=False, restrict_partner_id=False, consumed_for=False): task_obj = self.env['project.task'] - property_obj = self.env['ir.property'] analytic_line_obj = self.env['account.analytic.line'] result = super(StockMove, self).action_consume( product_qty, location_id=location_id, restrict_lot_id=restrict_lot_id, restrict_partner_id=restrict_partner_id, consumed_for=consumed_for) for record in self: - price = record.product_id.standard_price + price = record.product_id.cost_price if price > 0.0: - if record.production_id or record.raw_material_production_id: + if record.raw_material_production_id: product = record.product_id journal_id = self.env.ref( 'mrp_production_project_estimated_cost.analytic_' 'journal_materials', False) - production_id = False - analytic_account_id = False - task_id = False - if record.production_id: - production = record.production_id - elif record.raw_material_production_id: - production = record.raw_material_production_id - if production: - production_id = production.id - analytic_account_id = production.analytic_account_id.id - task = task_obj.search( - [('mrp_production_id', '=', production_id), - ('wk_order', '=', False)]) - if task: - task_id = task[0].id + production = record.raw_material_production_id name = ( (production.name or '') + '-' + (record.work_order.routing_wc_line.operation.code or '') + '-' + (product.default_code or '')) - general_account = ( - product.property_account_expense.id or - product.categ_id.property_account_expense_categ.id or - property_obj.get('property_account_expense_categ', - 'product.category')) - date = datetime.now().strftime('%Y-%m-%d') - uom_id = record.product_id.uom_id.id - if record.raw_material_production_id: - analytic_vals = {'name': name, - 'ref': name, - 'date': date, - 'user_id': self.env.uid, - 'product_id': product.id, - 'product_uom_id': uom_id, - 'amount': -(price * product_qty), - 'unit_amount': product_qty, - 'journal_id': journal_id.id, - 'account_id': analytic_account_id, - 'general_account_id': general_account, - 'task_id': task_id, - 'mrp_production_id': production_id, - 'workorder': record.work_order.id, - 'estim_avg_cost': 0.0, - 'estim_std_cost': 0.0 - } - analytic_line_obj.create(analytic_vals) - elif record.production_id: - amount = 0.0 - unit_amount = 0.0 - for wc in production.workcenter_lines: - cycle_cost = wc.workcenter_id.costs_cycle - cycle_units = wc.workcenter_id.capacity_per_cycle - cycle = int(math.ceil(product_qty / cycle_units)) - amount += cycle * cycle_cost - unit_amount += cycle - analytic_vals = {'name': name, - 'ref': name, - 'date': date, - 'user_id': self.env.uid, - 'product_id': product.id, - 'product_uom_id': uom_id, - 'amount': amount, - 'unit_amount': unit_amount, - 'journal_id': journal_id.id, - 'account_id': analytic_account_id, - 'general_account_id': general_account, - 'task_id': task_id, - 'mrp_production_id': production_id, - 'workorder': record.work_order.id, - 'estim_avg_cost': 0.0, - 'estim_std_cost': 0.0 - } - analytic_line_obj.create(analytic_vals) + analytic_vals = production._prepare_cost_analytic_line( + journal_id, name, production, product, + workorder=record.work_order, qty=record.product_qty, + amount=(-price * record.product_qty)) + task = task_obj.search( + [('mrp_production_id', '=', production.id), + ('wk_order', '=', False)]) + analytic_vals['task_id'] = task and task[0].id or False + analytic_line_obj.create(analytic_vals) return result @api.multi - def product_price_update_before_done(self): - analytic_line_obj = self.env['account.analytic.line'] - super(StockMove, self).product_price_update_before_done() + def product_price_update_production_done(self): for move in self: - # adapt standard price on production final moves if the - # product cost_method is 'average' if (move.production_id) and (move.product_id.cost_method == 'average'): - analytic_lines = analytic_line_obj.search( - [('mrp_production_id', '=', move.production_id.id)]) - prod_total_cost = sum([-line.amount for line in - analytic_lines]) + prod_total_cost = move.production_id.calc_mrp_real_cost() product = move.product_id product_avail = product.qty_available - amount_unit = product.standard_price - new_std_price = ((amount_unit * product_avail + + amount_unit = product.cost_price + template_avail = product.product_tmpl_id.qty_available + template_price = product.standard_price + new_cost_price = ((amount_unit * product_avail + prod_total_cost) / - ((product_avail >= 0.0 and product_avail or + ((product_avail >= 0.0 and product_avail or + 0.0) + move.product_qty)) + new_std_price = ((template_price * template_avail + + prod_total_cost) / + ((template_avail >= 0.0 and template_avail or 0.0) + move.product_qty)) - # Write the standard price, as SUPERUSER_ID because a warehouse - # manager may not have the right to write on products - product.sudo().write({'standard_price': new_std_price}) + product.sudo().write({'cost_price': new_cost_price, + 'standard_price': new_std_price}) - @api.multi - def get_price_unit(self): - self.ensure_one() - if self.production_id: - analytic_line_obj = self.env['account.analytic.line'] - analytic_lines = analytic_line_obj.search( - [('mrp_production_id', '=', self.production_id.id)]) - return (sum([-line.amount for line in analytic_lines]) / - self.product_qty) + @api.model + def get_price_unit(self, move): + if move.production_id: + return move.production_id.calc_mrp_real_cost() / move.product_qty else: - return super(StockMove, self).get_price_unit() + return super(StockMove, self).get_price_unit(move) From ec923b14d0d6494d1d30b3aa654f359a454fd12d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matja=C5=BE=20Mozeti=C4=8D?= Date: Sat, 15 Aug 2015 18:53:19 +0200 Subject: [PATCH 06/13] Slovene translations of odoomrp modules --- mrp_production_real_cost/i18n/sl.po | 39 +++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 mrp_production_real_cost/i18n/sl.po diff --git a/mrp_production_real_cost/i18n/sl.po b/mrp_production_real_cost/i18n/sl.po new file mode 100644 index 000000000..65fe21fdb --- /dev/null +++ b/mrp_production_real_cost/i18n/sl.po @@ -0,0 +1,39 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * mrp_production_real_costs +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 8.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2014-11-11 15:06+0000\n" +"PO-Revision-Date: 2015-08-15 09:02+0200\n" +"Last-Translator: Matjaz Mozetic \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: \n" +"Language: sl\n" +"X-Generator: Poedit 1.8.4\n" + +#. module: mrp_production_real_costs +#: model:ir.model,name:mrp_production_real_costs.model_project_task_work +msgid "Project Task Work" +msgstr "Delo na projektnem opravilu" + +#. module: mrp_production_real_costs +#: model:ir.model,name:mrp_production_real_costs.model_stock_move +msgid "Stock Move" +msgstr "Premik zaloge" + +#. module: mrp_production_real_costs +#: model:ir.model,name:mrp_production_real_costs.model_mrp_production_workcenter_line +msgid "Work Order" +msgstr "Delovni nalog" + +#. module: mrp_production_real_costs +#: code:addons/mrp_production_real_costs/models/mrp_production_workcenter_line.py:59 +#, python-format +msgid "You must define a general account for this Workcenter: [%s] %s" +msgstr "Določiti morate splošni konto za ta delovni center: [%s] %s" From 44b2fa7713bb6a57f91a50ef2d59d53bcf53e629 Mon Sep 17 00:00:00 2001 From: alfredoavanzosc Date: Thu, 10 Sep 2015 12:11:35 +0200 Subject: [PATCH 07/13] [IMP] mrp_production_project_estimated_cost: Show "Estimated Average Cost" field in mrp.production tree view. [IMP] mrp_production_real_cost: Show "Total Real Cost" field in mrp.production tree view. --- mrp_production_real_cost/models/mrp_production.py | 9 +++++++++ .../views/mrp_production_view.xml | 11 +++++++++++ 2 files changed, 20 insertions(+) diff --git a/mrp_production_real_cost/models/mrp_production.py b/mrp_production_real_cost/models/mrp_production.py index bfe7c544c..4db8a082a 100644 --- a/mrp_production_real_cost/models/mrp_production.py +++ b/mrp_production_real_cost/models/mrp_production.py @@ -36,10 +36,19 @@ class MrpProduction(models.Model): self.real_cost = self.calc_mrp_real_cost() self.unit_real_cost = self.real_cost / self.product_qty + @api.one + @api.depends('avg_cost', 'real_cost') + def get_percentage_difference(self): + self.percentage_difference = 0 + if self.avg_cost and self.real_cost: + self.percentage_difference = (self.real_cost * 100 / self.avg_cost) + real_cost = fields.Float("Total Real Cost", compute="get_real_cost", store=True) unit_real_cost = fields.Float("Unit Real Cost", compute="get_real_cost", store=True) + percentage_difference = fields.Float( + "% difference", compute="get_percentage_difference", store=True) @api.multi def action_production_end(self): diff --git a/mrp_production_real_cost/views/mrp_production_view.xml b/mrp_production_real_cost/views/mrp_production_view.xml index 8cfbeff95..22d455b50 100644 --- a/mrp_production_real_cost/views/mrp_production_view.xml +++ b/mrp_production_real_cost/views/mrp_production_view.xml @@ -12,5 +12,16 @@ + + mrp.production.tree.view.inh.realcost + mrp.production + + + + + + + + From 23e516310063a1a5d0b355d6975e185a80e24092 Mon Sep 17 00:00:00 2001 From: agaldona Date: Wed, 30 Sep 2015 14:42:07 +0200 Subject: [PATCH 08/13] [IMP] mrp_production_real_cost: make independent from estimated costs --- mrp_production_real_cost/__openerp__.py | 6 +- .../data/analytic_journal_data.xml | 26 ++++++++ mrp_production_real_cost/models/__init__.py | 1 + mrp_production_real_cost/models/mrp_bom.py | 22 +++++++ .../models/mrp_production.py | 46 ++++++++++++++- .../models/mrp_production_workcenter_line.py | 59 +++++++++++++++++-- mrp_production_real_cost/models/stock_move.py | 21 ++++--- .../views/mrp_production_view.xml | 46 +++++++++++---- 8 files changed, 201 insertions(+), 26 deletions(-) create mode 100644 mrp_production_real_cost/data/analytic_journal_data.xml create mode 100644 mrp_production_real_cost/models/mrp_bom.py diff --git a/mrp_production_real_cost/__openerp__.py b/mrp_production_real_cost/__openerp__.py index 76d843098..d5cfaf6aa 100644 --- a/mrp_production_real_cost/__openerp__.py +++ b/mrp_production_real_cost/__openerp__.py @@ -24,12 +24,16 @@ "mrp_project_link", "mrp_operations_time_control", "stock_account", + "product_variant_cost", "mrp_production_project_estimated_cost"], "author": "OdooMRP team," "AvanzOSC," "Serv. Tecnol. Avanzados - Pedro M. Baeza", "category": "MRP", - 'data': ["views/mrp_production_view.xml"], + 'data': [ + "data/analytic_journal_data.xml", + "views/mrp_production_view.xml" + ], 'installable': True, 'auto_install': False, } diff --git a/mrp_production_real_cost/data/analytic_journal_data.xml b/mrp_production_real_cost/data/analytic_journal_data.xml new file mode 100644 index 000000000..2849b60e8 --- /dev/null +++ b/mrp_production_real_cost/data/analytic_journal_data.xml @@ -0,0 +1,26 @@ + + + + + + Materials + MAT + general + True + + + + Operators + OPE + general + True + + + + Machines + MACH + general + True + + + diff --git a/mrp_production_real_cost/models/__init__.py b/mrp_production_real_cost/models/__init__.py index 271c541d3..e81c2bb0a 100644 --- a/mrp_production_real_cost/models/__init__.py +++ b/mrp_production_real_cost/models/__init__.py @@ -20,3 +20,4 @@ from . import stock_move from . import mrp_production_workcenter_line from . import project_task_work from . import mrp_production +from . import mrp_bom diff --git a/mrp_production_real_cost/models/mrp_bom.py b/mrp_production_real_cost/models/mrp_bom.py new file mode 100644 index 000000000..8ac5d55fa --- /dev/null +++ b/mrp_production_real_cost/models/mrp_bom.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +############################################################################## +# For copyright and license notices, see __openerp__.py file in root directory +############################################################################## +from openerp import models + + +class MrpBom(models.Model): + _inherit = 'mrp.bom' + + def _get_workorder_operations(self, result2, factor, level=0, + routing_id=False): + res = super(MrpBom, self)._get_workorder_operations( + result2, factor, level=level, routing_id=routing_id) + workcenter_obj = self.env['mrp.workcenter'] + for wkr in res: + wc = workcenter_obj.browse(wkr.get('workcenter_id', False)) + wkr['pre_cost'] = (wkr.get('time_start', 0.0) * + wc.pre_op_product.cost_price) + wkr['post_cost'] = (wkr.get('time_stop', 0.0) * + wc.post_op_product.cost_price) + return result2 diff --git a/mrp_production_real_cost/models/mrp_production.py b/mrp_production_real_cost/models/mrp_production.py index 4db8a082a..a15b906eb 100644 --- a/mrp_production_real_cost/models/mrp_production.py +++ b/mrp_production_real_cost/models/mrp_production.py @@ -16,7 +16,7 @@ # ############################################################################## -from openerp import models, fields, api +from openerp import models, fields, api, exceptions, _ class MrpProduction(models.Model): @@ -61,3 +61,47 @@ class MrpProduction(models.Model): record.real_cost = mrp_cost done_lines.product_price_update_production_done() return res + + @api.model + def _prepare_real_cost_analytic_line( + self, journal, name, production, product, general_account=None, + workorder=None, qty=1, amount=0): + """ + Prepare the vals for creating an analytic entry for real cost + :param journal: Journal of the entry + :param name: Name of the entry + :param production: Origin product + :param product: Product for the entry + :param general_account: General account for the entry + :param workorder: Origin workorder + :param qty: Quantity for the entry. This quantity will multiply both + standard and average costs for the entry costs. + :param amount: Cost for calculating real cost. + :return: Dictionary with the analytic entry vals. + """ + analytic_line_obj = self.env['account.analytic.line'] + property_obj = self.env['ir.property'] + if not general_account: + general_account = ( + product.property_account_income or + product.categ_id.property_account_income_categ or + property_obj.get('property_account_expense_categ', + 'product.category')) + if not production.analytic_account_id: + raise exceptions.Warning( + _('You must define one Analytic Account for this MO: %s') % + (production.name)) + return { + 'name': name, + 'mrp_production_id': production.id, + 'workorder': workorder and workorder.id or False, + 'account_id': self.analytic_account_id.id, + 'journal_id': journal.id, + 'user_id': self.env.uid, + 'date': analytic_line_obj._get_default_date(), + 'product_id': product and product.id or False, + 'unit_amount': qty, + 'amount': amount, + 'product_uom_id': product.uom_id.id, + 'general_account_id': general_account.id, + } diff --git a/mrp_production_real_cost/models/mrp_production_workcenter_line.py b/mrp_production_real_cost/models/mrp_production_workcenter_line.py index 356e98890..298165d0a 100644 --- a/mrp_production_real_cost/models/mrp_production_workcenter_line.py +++ b/mrp_production_real_cost/models/mrp_production_workcenter_line.py @@ -16,13 +16,23 @@ # ############################################################################## -from openerp import models, api +from openerp import models, api, fields class MrpProductionWorkcenterLine(models.Model): _inherit = 'mrp.production.workcenter.line' + @api.one + def _get_prepost_cost(self): + wc = self.workcenter_id + self.pre_cost = self.time_start * wc.pre_op_product.cost_price + self.post_cost = self.time_stop * wc.post_op_product.cost_price + + pre_cost = fields.Float('Pre-Operation Cost', default=_get_prepost_cost) + post_cost = fields.Float('Post-Operation Cost', + default=_get_prepost_cost) + @api.multi def _create_analytic_line(self): self.ensure_one() @@ -35,14 +45,13 @@ class MrpProductionWorkcenterLine(models.Model): workcenter = self.workcenter_id product = workcenter.product_id journal_id = workcenter.costs_journal_id or self.env.ref( - 'mrp_production_project_estimated_cost.analytic_journal_' - 'machines', False) + 'mrp.analytic_journal_machines', False) name = ((production.name or '') + '-' + (self.routing_wc_line.operation.code or '') + '-' + (product.default_code or '')) general_acc = workcenter.costs_general_account_id or False price = -(workcenter.costs_hour * operation_line.uptime) - analytic_vals = production._prepare_cost_analytic_line( + analytic_vals = production._prepare_real_cost_analytic_line( journal_id, name, production, product, general_account=general_acc, workorder=self, qty=operation_line.uptime, amount=price) @@ -53,6 +62,46 @@ class MrpProductionWorkcenterLine(models.Model): analytic_line = analytic_line_obj.create(analytic_vals) return analytic_line + @api.multi + def _create_pre_post_cost_lines(self, cost_type='pre'): + self.ensure_one() + analytic_line_obj = self.env['account.analytic.line'] + task_obj = self.env['project.task'] + hour_uom = self.env.ref('product.product_uom_hour', False) + production = self.production_id + workcenter = self.workcenter_id + journal_id = workcenter.costs_journal_id or self.env.ref( + 'mrp.analytic_journal_machines', False) + general_acc = workcenter.costs_general_account_id or False + qty = 0 + price = 0 + product = False + name = '' + if cost_type == 'pre': + product = workcenter.pre_op_product + name = ((production.name or '') + '-' + + (self.routing_wc_line.operation.code or '') + '-PRE-' + + (product.default_code or '')) + price = -(self.pre_cost) + qty = self.time_start + elif cost_type == 'post': + product = workcenter.post_op_product + name = ((production.name or '') + '-' + + (self.routing_wc_line.operation.code or '') + '-POST-' + + (product.default_code or '')) + price = -(self.post_cost) + qty = self.time_stop + if price: + analytic_vals = production._prepare_real_cost_analytic_line( + journal_id, name, production, product, + general_account=general_acc, workorder=self, + qty=qty, amount=price) + task = task_obj.search([('mrp_production_id', '=', production.id), + ('wk_order', '=', False)]) + analytic_vals['task_id'] = task and task[0].id or False + analytic_vals['product_uom_id'] = hour_uom.id + analytic_line_obj.create(analytic_vals) + @api.multi def action_pause(self): result = super(MrpProductionWorkcenterLine, self).action_pause() @@ -63,4 +112,6 @@ class MrpProductionWorkcenterLine(models.Model): def action_done(self): result = super(MrpProductionWorkcenterLine, self).action_done() self._create_analytic_line() + self._create_pre_post_cost_lines(cost_type='pre') + self._create_pre_post_cost_lines(cost_type='post') return result diff --git a/mrp_production_real_cost/models/stock_move.py b/mrp_production_real_cost/models/stock_move.py index 0c5d55f70..9c47221a7 100644 --- a/mrp_production_real_cost/models/stock_move.py +++ b/mrp_production_real_cost/models/stock_move.py @@ -33,11 +33,10 @@ class StockMove(models.Model): product = record.product_id production = record.production_id journal_id = self.env.ref( - 'mrp_production_project_estimated_cost.analytic_' - 'journal_materials', False) + 'mrp.analytic_journal_materials', False) name = ('Final product - ' + (production.name or '') + '-' + (product.default_code or '')) - vals = production._prepare_cost_analytic_line( + vals = production._prepare_real_cost_analytic_line( journal_id, name, production, product, qty=record.product_qty, amount=amount) task = task_obj.search( @@ -62,17 +61,18 @@ class StockMove(models.Model): if record.raw_material_production_id: product = record.product_id journal_id = self.env.ref( - 'mrp_production_project_estimated_cost.analytic_' - 'journal_materials', False) + 'mrp.analytic_journal_materials', False) production = record.raw_material_production_id name = ( (production.name or '') + '-' + (record.work_order.routing_wc_line.operation.code or '') + '-' + (product.default_code or '')) - analytic_vals = production._prepare_cost_analytic_line( - journal_id, name, production, product, - workorder=record.work_order, qty=record.product_qty, - amount=(-price * record.product_qty)) + analytic_vals = ( + production._prepare_real_cost_analytic_line( + journal_id, name, production, product, + workorder=record.work_order, + qty=record.product_qty, + amount=(-price * record.product_qty))) task = task_obj.search( [('mrp_production_id', '=', production.id), ('wk_order', '=', False)]) @@ -91,6 +91,9 @@ class StockMove(models.Model): amount_unit = product.cost_price template_avail = product.product_tmpl_id.qty_available template_price = product.standard_price + if move.state == 'done': + product_avail -= move.product_qty + template_avail -= move.product_qty new_cost_price = ((amount_unit * product_avail + prod_total_cost) / ((product_avail >= 0.0 and product_avail or diff --git a/mrp_production_real_cost/views/mrp_production_view.xml b/mrp_production_real_cost/views/mrp_production_view.xml index 22d455b50..f6c9397a1 100644 --- a/mrp_production_real_cost/views/mrp_production_view.xml +++ b/mrp_production_real_cost/views/mrp_production_view.xml @@ -1,27 +1,51 @@ - - mrp.production.project.form.view.inh.estimatedcost + + mrp.production.form.view.costs mrp.production - + - - - - + + + + - - mrp.production.tree.view.inh.realcost + + + mrp.production.form.view.real.costs mrp.production - + - + + + + + + + + + + + + + + + + + + + mrp.production.tree.real.costs + mrp.production + + + + From a80e867abdabf3fdf86dcf1326268d8a453c40be Mon Sep 17 00:00:00 2001 From: "Pedro M. Baeza" Date: Fri, 9 Oct 2015 18:18:26 +0200 Subject: [PATCH 09/13] OCA Transbot updated translations from Transifex --- mrp_production_real_cost/i18n/en_US.po | 79 ++++++++++++++++++++++++++ mrp_production_real_cost/i18n/es.po | 68 +++++++++++++++++----- mrp_production_real_cost/i18n/pt_BR.po | 79 ++++++++++++++++++++++++++ mrp_production_real_cost/i18n/sl.po | 67 +++++++++++++++++----- 4 files changed, 267 insertions(+), 26 deletions(-) create mode 100644 mrp_production_real_cost/i18n/en_US.po create mode 100644 mrp_production_real_cost/i18n/pt_BR.po diff --git a/mrp_production_real_cost/i18n/en_US.po b/mrp_production_real_cost/i18n/en_US.po new file mode 100644 index 000000000..543c75b96 --- /dev/null +++ b/mrp_production_real_cost/i18n/en_US.po @@ -0,0 +1,79 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * mrp_production_real_costs +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: odoomrp-wip (8.0)\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-10-07 10:44+0000\n" +"PO-Revision-Date: 2015-10-04 00:01+0000\n" +"Last-Translator: OCA Transbot \n" +"Language-Team: English (United States) (http://www.transifex.com/oca/odoomrp-wip-8-0/language/en_US/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Language: en_US\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#. module: mrp_production_real_costs +#: field:mrp.production,percentage_difference:0 +msgid "% difference" +msgstr "" + +#. module: mrp_production_real_costs +#: model:ir.model,name:mrp_production_real_costs.model_mrp_bom +msgid "Bill of Material" +msgstr "" + +#. module: mrp_production_real_costs +#: model:ir.model,name:mrp_production_real_costs.model_mrp_production +msgid "Manufacturing Order" +msgstr "" + +#. module: mrp_production_real_costs +#: view:mrp.production:mrp_production_real_costs.mrp_production_form_view_real_costs +msgid "Manufacturing costs" +msgstr "" + +#. module: mrp_production_real_costs +#: field:mrp.production.workcenter.line,post_cost:0 +msgid "Post-Operation Cost" +msgstr "" + +#. module: mrp_production_real_costs +#: field:mrp.production.workcenter.line,pre_cost:0 +msgid "Pre-Operation Cost" +msgstr "" + +#. module: mrp_production_real_costs +#: model:ir.model,name:mrp_production_real_costs.model_project_task_work +msgid "Project Task Work" +msgstr "" + +#. module: mrp_production_real_costs +#: model:ir.model,name:mrp_production_real_costs.model_stock_move +msgid "Stock Move" +msgstr "" + +#. module: mrp_production_real_costs +#: field:mrp.production,real_cost:0 +msgid "Total Real Cost" +msgstr "" + +#. module: mrp_production_real_costs +#: field:mrp.production,unit_real_cost:0 +msgid "Unit Real Cost" +msgstr "" + +#. module: mrp_production_real_costs +#: model:ir.model,name:mrp_production_real_costs.model_mrp_production_workcenter_line +msgid "Work Order" +msgstr "Work Order" + +#. module: mrp_production_real_costs +#: code:addons/mrp_production_real_costs/models/mrp_production.py:92 +#, python-format +msgid "You must define one Analytic Account for this MO: %s" +msgstr "" diff --git a/mrp_production_real_cost/i18n/es.po b/mrp_production_real_cost/i18n/es.po index 3a5b746f5..e007d3730 100644 --- a/mrp_production_real_cost/i18n/es.po +++ b/mrp_production_real_cost/i18n/es.po @@ -1,19 +1,52 @@ # Translation of Odoo Server. # This file contains the translation of the following modules: -# * mrp_production_real_costs -# +# * mrp_production_real_costs +# +# Translators: +# Pedro M. Baeza , 2015 msgid "" msgstr "" -"Project-Id-Version: Odoo Server 8.0\n" +"Project-Id-Version: odoomrp-wip (8.0)\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2014-11-11 15:06+0000\n" -"PO-Revision-Date: 2014-11-11 16:12+0100\n" -"Last-Translator: \n" -"Language-Team: \n" +"POT-Creation-Date: 2015-10-07 10:44+0000\n" +"PO-Revision-Date: 2015-10-09 10:55+0000\n" +"Last-Translator: Pedro M. Baeza \n" +"Language-Team: Spanish (http://www.transifex.com/oca/odoomrp-wip-8-0/language/es/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: \n" +"Content-Transfer-Encoding: \n" +"Language: es\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#. module: mrp_production_real_costs +#: field:mrp.production,percentage_difference:0 +msgid "% difference" +msgstr "% diferencia" + +#. module: mrp_production_real_costs +#: model:ir.model,name:mrp_production_real_costs.model_mrp_bom +msgid "Bill of Material" +msgstr "Lista de material" + +#. module: mrp_production_real_costs +#: model:ir.model,name:mrp_production_real_costs.model_mrp_production +msgid "Manufacturing Order" +msgstr "Órden de producción" + +#. module: mrp_production_real_costs +#: view:mrp.production:mrp_production_real_costs.mrp_production_form_view_real_costs +msgid "Manufacturing costs" +msgstr "Costes de fabricación" + +#. module: mrp_production_real_costs +#: field:mrp.production.workcenter.line,post_cost:0 +msgid "Post-Operation Cost" +msgstr "" + +#. module: mrp_production_real_costs +#: field:mrp.production.workcenter.line,pre_cost:0 +msgid "Pre-Operation Cost" +msgstr "" #. module: mrp_production_real_costs #: model:ir.model,name:mrp_production_real_costs.model_project_task_work @@ -25,14 +58,23 @@ msgstr "Trabajo de tarea" msgid "Stock Move" msgstr "Movimiento de existencias" +#. module: mrp_production_real_costs +#: field:mrp.production,real_cost:0 +msgid "Total Real Cost" +msgstr "" + +#. module: mrp_production_real_costs +#: field:mrp.production,unit_real_cost:0 +msgid "Unit Real Cost" +msgstr "" + #. module: mrp_production_real_costs #: model:ir.model,name:mrp_production_real_costs.model_mrp_production_workcenter_line msgid "Work Order" msgstr "Orden de trabajo" #. module: mrp_production_real_costs -#: code:addons/mrp_production_real_costs/models/mrp_production_workcenter_line.py:59 +#: code:addons/mrp_production_real_costs/models/mrp_production.py:92 #, python-format -msgid "You must define a general account for this Workcenter: [%s] %s" -msgstr "Es necesario que defina una cuenta contable para este centro de producción: [%s] %s" - +msgid "You must define one Analytic Account for this MO: %s" +msgstr "Debe definir una cuenta analítica para esta MO: %s" diff --git a/mrp_production_real_cost/i18n/pt_BR.po b/mrp_production_real_cost/i18n/pt_BR.po new file mode 100644 index 000000000..16b8a2445 --- /dev/null +++ b/mrp_production_real_cost/i18n/pt_BR.po @@ -0,0 +1,79 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * mrp_production_real_costs +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: odoomrp-wip (8.0)\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-10-07 10:44+0000\n" +"PO-Revision-Date: 2015-10-09 03:39+0000\n" +"Last-Translator: danimaribeiro \n" +"Language-Team: Portuguese (Brazil) (http://www.transifex.com/oca/odoomrp-wip-8-0/language/pt_BR/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Language: pt_BR\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +#. module: mrp_production_real_costs +#: field:mrp.production,percentage_difference:0 +msgid "% difference" +msgstr "" + +#. module: mrp_production_real_costs +#: model:ir.model,name:mrp_production_real_costs.model_mrp_bom +msgid "Bill of Material" +msgstr "Lista de materiais" + +#. module: mrp_production_real_costs +#: model:ir.model,name:mrp_production_real_costs.model_mrp_production +msgid "Manufacturing Order" +msgstr "Ordem de Produção" + +#. module: mrp_production_real_costs +#: view:mrp.production:mrp_production_real_costs.mrp_production_form_view_real_costs +msgid "Manufacturing costs" +msgstr "" + +#. module: mrp_production_real_costs +#: field:mrp.production.workcenter.line,post_cost:0 +msgid "Post-Operation Cost" +msgstr "" + +#. module: mrp_production_real_costs +#: field:mrp.production.workcenter.line,pre_cost:0 +msgid "Pre-Operation Cost" +msgstr "" + +#. module: mrp_production_real_costs +#: model:ir.model,name:mrp_production_real_costs.model_project_task_work +msgid "Project Task Work" +msgstr "" + +#. module: mrp_production_real_costs +#: model:ir.model,name:mrp_production_real_costs.model_stock_move +msgid "Stock Move" +msgstr "Movimentação de estoque" + +#. module: mrp_production_real_costs +#: field:mrp.production,real_cost:0 +msgid "Total Real Cost" +msgstr "" + +#. module: mrp_production_real_costs +#: field:mrp.production,unit_real_cost:0 +msgid "Unit Real Cost" +msgstr "" + +#. module: mrp_production_real_costs +#: model:ir.model,name:mrp_production_real_costs.model_mrp_production_workcenter_line +msgid "Work Order" +msgstr "Ordem de serviço" + +#. module: mrp_production_real_costs +#: code:addons/mrp_production_real_costs/models/mrp_production.py:92 +#, python-format +msgid "You must define one Analytic Account for this MO: %s" +msgstr "" diff --git a/mrp_production_real_cost/i18n/sl.po b/mrp_production_real_cost/i18n/sl.po index 65fe21fdb..0f6d5fd05 100644 --- a/mrp_production_real_cost/i18n/sl.po +++ b/mrp_production_real_cost/i18n/sl.po @@ -1,21 +1,52 @@ # Translation of Odoo Server. # This file contains the translation of the following modules: -# * mrp_production_real_costs -# +# * mrp_production_real_costs +# +# Translators: +# Matjaž Mozetič , 2015 msgid "" msgstr "" -"Project-Id-Version: Odoo Server 8.0\n" +"Project-Id-Version: odoomrp-wip (8.0)\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2014-11-11 15:06+0000\n" -"PO-Revision-Date: 2015-08-15 09:02+0200\n" -"Last-Translator: Matjaz Mozetic \n" -"Language-Team: \n" +"POT-Creation-Date: 2015-10-07 10:44+0000\n" +"PO-Revision-Date: 2015-10-05 04:55+0000\n" +"Last-Translator: Matjaž Mozetič \n" +"Language-Team: Slovenian (http://www.transifex.com/oca/odoomrp-wip-8-0/language/sl/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: \n" +"Content-Transfer-Encoding: \n" "Language: sl\n" -"X-Generator: Poedit 1.8.4\n" +"Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3);\n" + +#. module: mrp_production_real_costs +#: field:mrp.production,percentage_difference:0 +msgid "% difference" +msgstr "% razlike" + +#. module: mrp_production_real_costs +#: model:ir.model,name:mrp_production_real_costs.model_mrp_bom +msgid "Bill of Material" +msgstr "Kosovnica" + +#. module: mrp_production_real_costs +#: model:ir.model,name:mrp_production_real_costs.model_mrp_production +msgid "Manufacturing Order" +msgstr "Proizvodni nalog" + +#. module: mrp_production_real_costs +#: view:mrp.production:mrp_production_real_costs.mrp_production_form_view_real_costs +msgid "Manufacturing costs" +msgstr "Proizvodni stroški" + +#. module: mrp_production_real_costs +#: field:mrp.production.workcenter.line,post_cost:0 +msgid "Post-Operation Cost" +msgstr "Po-operativni stroški" + +#. module: mrp_production_real_costs +#: field:mrp.production.workcenter.line,pre_cost:0 +msgid "Pre-Operation Cost" +msgstr "Pred operativni stroški" #. module: mrp_production_real_costs #: model:ir.model,name:mrp_production_real_costs.model_project_task_work @@ -27,13 +58,23 @@ msgstr "Delo na projektnem opravilu" msgid "Stock Move" msgstr "Premik zaloge" +#. module: mrp_production_real_costs +#: field:mrp.production,real_cost:0 +msgid "Total Real Cost" +msgstr "Skupni realni stroški" + +#. module: mrp_production_real_costs +#: field:mrp.production,unit_real_cost:0 +msgid "Unit Real Cost" +msgstr "Realni strošek enote" + #. module: mrp_production_real_costs #: model:ir.model,name:mrp_production_real_costs.model_mrp_production_workcenter_line msgid "Work Order" msgstr "Delovni nalog" #. module: mrp_production_real_costs -#: code:addons/mrp_production_real_costs/models/mrp_production_workcenter_line.py:59 +#: code:addons/mrp_production_real_costs/models/mrp_production.py:92 #, python-format -msgid "You must define a general account for this Workcenter: [%s] %s" -msgstr "Določiti morate splošni konto za ta delovni center: [%s] %s" +msgid "You must define one Analytic Account for this MO: %s" +msgstr "Potrebno je določiti analitični konto za proizvodni nalog: %s" From 034eeac76133c4fde57de11e67daed660152b384 Mon Sep 17 00:00:00 2001 From: agaldona Date: Fri, 9 Oct 2015 11:39:43 +0200 Subject: [PATCH 10/13] [IMP] mrp_production_project_estimated_cost: Cost load in positive. [IMP] mrp_production_real_costs: The quant's cost will be loaded every Consume or Produce action and when ends a MO. New configurable check to load final product cost in analytic or not Closes #1001 #1010 --- mrp_production_real_cost/__init__.py | 1 + mrp_production_real_cost/__openerp__.py | 3 +- mrp_production_real_cost/models/__init__.py | 1 + mrp_production_real_cost/models/mrp_config.py | 43 +++++++ .../models/mrp_production.py | 31 ++++- mrp_production_real_cost/models/stock_move.py | 111 ++++++------------ .../views/res_config_view.xml | 18 +++ mrp_production_real_cost/wizard/__init__.py | 6 + .../wizard/mrp_product_produce.py | 20 ++++ 9 files changed, 160 insertions(+), 74 deletions(-) create mode 100644 mrp_production_real_cost/models/mrp_config.py create mode 100644 mrp_production_real_cost/views/res_config_view.xml create mode 100644 mrp_production_real_cost/wizard/__init__.py create mode 100644 mrp_production_real_cost/wizard/mrp_product_produce.py diff --git a/mrp_production_real_cost/__init__.py b/mrp_production_real_cost/__init__.py index 324fad228..ecfcca241 100644 --- a/mrp_production_real_cost/__init__.py +++ b/mrp_production_real_cost/__init__.py @@ -17,3 +17,4 @@ ############################################################################## from . import models +from . import wizard diff --git a/mrp_production_real_cost/__openerp__.py b/mrp_production_real_cost/__openerp__.py index d5cfaf6aa..8c64469a0 100644 --- a/mrp_production_real_cost/__openerp__.py +++ b/mrp_production_real_cost/__openerp__.py @@ -32,7 +32,8 @@ "category": "MRP", 'data': [ "data/analytic_journal_data.xml", - "views/mrp_production_view.xml" + "views/mrp_production_view.xml", + "views/res_config_view.xml" ], 'installable': True, 'auto_install': False, diff --git a/mrp_production_real_cost/models/__init__.py b/mrp_production_real_cost/models/__init__.py index e81c2bb0a..e87caf4c2 100644 --- a/mrp_production_real_cost/models/__init__.py +++ b/mrp_production_real_cost/models/__init__.py @@ -21,3 +21,4 @@ from . import mrp_production_workcenter_line from . import project_task_work from . import mrp_production from . import mrp_bom +from . import mrp_config diff --git a/mrp_production_real_cost/models/mrp_config.py b/mrp_production_real_cost/models/mrp_config.py new file mode 100644 index 000000000..5c3d89efe --- /dev/null +++ b/mrp_production_real_cost/models/mrp_config.py @@ -0,0 +1,43 @@ +# -*- coding: utf-8 -*- +# (c) 2015 Ainara Galdona - AvanzOSC +# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html + +from openerp import api, fields, models + + +class MrpConfigSettings(models.TransientModel): + _inherit = 'mrp.config.settings' + + final_product_analytic_cost = fields.Boolean( + string='Load final product analytic cost', + help='This will allow you to define if those BoM passed back to draft' + ' are still activated or not') + + def _get_parameter(self, key, default=False): + param_obj = self.env['ir.config_parameter'] + rec = param_obj.search([('key', '=', key)]) + return rec or default + + def _write_or_create_param(self, key, value): + param_obj = self.env['ir.config_parameter'] + rec = self._get_parameter(key) + if rec: + if not value: + rec.unlink() + else: + rec.value = value + elif value: + param_obj.create({'key': key, 'value': value}) + + @api.multi + def get_default_parameters(self): + def get_value(key, default=''): + rec = self._get_parameter(key) + return rec and rec.value or default + return {'final_product_analytic_cost': get_value('final.product.cost', + False)} + + @api.multi + def set_parameters(self): + self._write_or_create_param('final.product.cost', + self.final_product_analytic_cost) diff --git a/mrp_production_real_cost/models/mrp_production.py b/mrp_production_real_cost/models/mrp_production.py index a15b906eb..42067aef2 100644 --- a/mrp_production_real_cost/models/mrp_production.py +++ b/mrp_production_real_cost/models/mrp_production.py @@ -52,16 +52,45 @@ class MrpProduction(models.Model): @api.multi def action_production_end(self): + task_obj = self.env['project.task'] + analytic_line_obj = self.env['account.analytic.line'] res = super(MrpProduction, self).action_production_end() for record in self: mrp_cost = record.calc_mrp_real_cost() done_lines = record.move_created_ids2.filtered(lambda l: l.state == 'done') - done_lines.create_produce_cost_line(mrp_cost) + create_cost = self.env['mrp.config.settings']._get_parameter( + 'final.product.cost') + if create_cost and create_cost.value and mrp_cost > 0.0: + journal_id = self.env.ref('mrp.analytic_journal_materials', + False) + qty = sum([l.product_qty for l in done_lines]) + name = ('Final product - ' + (record.name or '') + + '-' + (record.product_id.default_code or '')) + vals = record._prepare_real_cost_analytic_line( + journal_id, name, record, record.product_id, qty=qty, + amount=mrp_cost) + task = task_obj.search([('mrp_production_id', '=', record.id), + ('wk_order', '=', False)]) + vals['task_id'] = task and task[0].id or False + analytic_line_obj.create(vals) record.real_cost = mrp_cost done_lines.product_price_update_production_done() + # Reload produced quants cost to consider all production costs. + # Material, machine and manual costs. + self.load_final_quant_cost() return res + @api.multi + def load_final_quant_cost(self): + for production in self: + mrp_cost = production.calc_mrp_real_cost() + done_lines = production.move_created_ids2.filtered( + lambda l: l.state == 'done') + total_qty = sum([l.product_qty for l in done_lines]) + quants = done_lines.mapped('quant_ids') + quants.write({'cost': mrp_cost / total_qty}) + @api.model def _prepare_real_cost_analytic_line( self, journal, name, production, product, general_account=None, diff --git a/mrp_production_real_cost/models/stock_move.py b/mrp_production_real_cost/models/stock_move.py index 9c47221a7..bca465fce 100644 --- a/mrp_production_real_cost/models/stock_move.py +++ b/mrp_production_real_cost/models/stock_move.py @@ -24,86 +24,53 @@ class StockMove(models.Model): _inherit = 'stock.move' @api.multi - def create_produce_cost_line(self, amount): + def action_done(self): task_obj = self.env['project.task'] analytic_line_obj = self.env['account.analytic.line'] + result = super(StockMove, self).action_done() for record in self: - if amount > 0.0: - if record.production_id: - product = record.product_id - production = record.production_id - journal_id = self.env.ref( - 'mrp.analytic_journal_materials', False) - name = ('Final product - ' + (production.name or '') + - '-' + (product.default_code or '')) - vals = production._prepare_real_cost_analytic_line( - journal_id, name, production, product, - qty=record.product_qty, amount=amount) - task = task_obj.search( - [('mrp_production_id', '=', production.id), - ('wk_order', '=', False)]) - vals['task_id'] = task and task[0].id or False - analytic_line_obj.create(vals) - - @api.multi - def action_consume(self, product_qty, location_id=False, - restrict_lot_id=False, restrict_partner_id=False, - consumed_for=False): - task_obj = self.env['project.task'] - analytic_line_obj = self.env['account.analytic.line'] - result = super(StockMove, self).action_consume( - product_qty, location_id=location_id, - restrict_lot_id=restrict_lot_id, - restrict_partner_id=restrict_partner_id, consumed_for=consumed_for) - for record in self: - price = record.product_id.cost_price - if price > 0.0: - if record.raw_material_production_id: - product = record.product_id - journal_id = self.env.ref( - 'mrp.analytic_journal_materials', False) - production = record.raw_material_production_id - name = ( - (production.name or '') + '-' + - (record.work_order.routing_wc_line.operation.code or - '') + '-' + (product.default_code or '')) - analytic_vals = ( - production._prepare_real_cost_analytic_line( - journal_id, name, production, product, - workorder=record.work_order, - qty=record.product_qty, - amount=(-price * record.product_qty))) - task = task_obj.search( - [('mrp_production_id', '=', production.id), - ('wk_order', '=', False)]) - analytic_vals['task_id'] = task and task[0].id or False - analytic_line_obj.create(analytic_vals) + if (not record.raw_material_production_id or not + record.product_id.cost_price): + continue + journal_id = self.env.ref('mrp.analytic_journal_materials', False) + production = record.raw_material_production_id + name = ((production.name or '') + '-' + + (record.work_order.routing_wc_line.operation.code or '') + + '-' + (record.product_id.default_code or '')) + analytic_vals = (production._prepare_real_cost_analytic_line( + journal_id, name, production, record.product_id, + workorder=record.work_order, qty=record.product_qty, + amount=(-record.product_id.cost_price * record.product_qty))) + task = task_obj.search([('mrp_production_id', '=', production.id), + ('wk_order', '=', False)]) + analytic_vals['task_id'] = task and task[0].id or False + analytic_line_obj.create(analytic_vals) return result @api.multi def product_price_update_production_done(self): for move in self: - if (move.production_id) and (move.product_id.cost_method == - 'average'): - prod_total_cost = move.production_id.calc_mrp_real_cost() - product = move.product_id - product_avail = product.qty_available - amount_unit = product.cost_price - template_avail = product.product_tmpl_id.qty_available - template_price = product.standard_price - if move.state == 'done': - product_avail -= move.product_qty - template_avail -= move.product_qty - new_cost_price = ((amount_unit * product_avail + - prod_total_cost) / - ((product_avail >= 0.0 and product_avail or - 0.0) + move.product_qty)) - new_std_price = ((template_price * template_avail + - prod_total_cost) / - ((template_avail >= 0.0 and template_avail or - 0.0) + move.product_qty)) - product.sudo().write({'cost_price': new_cost_price, - 'standard_price': new_std_price}) + if (not move.production_id or move.product_id.cost_method != + 'average'): + continue + prod_total_cost = move.production_id.calc_mrp_real_cost() + product = move.product_id + product_avail = product.qty_available + amount_unit = product.cost_price + template_avail = product.product_tmpl_id.qty_available + template_price = product.standard_price + if move.state == 'done': + product_avail -= move.product_qty + template_avail -= move.product_qty + new_cost_price = ((amount_unit * product_avail + prod_total_cost) / + ((product_avail >= 0.0 and product_avail or 0.0) + + move.product_qty)) + new_std_price = ((template_price * template_avail + + prod_total_cost) / + ((template_avail >= 0.0 and template_avail or + 0.0) + move.product_qty)) + product.sudo().write({'cost_price': new_cost_price, + 'standard_price': new_std_price}) @api.model def get_price_unit(self, move): diff --git a/mrp_production_real_cost/views/res_config_view.xml b/mrp_production_real_cost/views/res_config_view.xml new file mode 100644 index 000000000..f3e3f75fc --- /dev/null +++ b/mrp_production_real_cost/views/res_config_view.xml @@ -0,0 +1,18 @@ + + + + + mrp.config.settings.costs + mrp.config.settings + + + +
+ +
+
+
+
+
+
diff --git a/mrp_production_real_cost/wizard/__init__.py b/mrp_production_real_cost/wizard/__init__.py new file mode 100644 index 000000000..92d4c4468 --- /dev/null +++ b/mrp_production_real_cost/wizard/__init__.py @@ -0,0 +1,6 @@ +# -*- coding: utf-8 -*- +############################################################################## +# For copyright and license notices, see __openerp__.py file in root directory +############################################################################## + +from . import mrp_product_produce diff --git a/mrp_production_real_cost/wizard/mrp_product_produce.py b/mrp_production_real_cost/wizard/mrp_product_produce.py new file mode 100644 index 000000000..ad2ebddba --- /dev/null +++ b/mrp_production_real_cost/wizard/mrp_product_produce.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +############################################################################## +# For copyright and license notices, see __openerp__.py file in root directory +############################################################################## +from openerp import models, api + + +class MrpProductProduce(models.TransientModel): + + _inherit = 'mrp.product.produce' + + # Reload produced quants cost every consume or produce action in a MO. + @api.multi + def do_produce(self): + res = super(MrpProductProduce, self).do_produce() + production_obj = self.env['mrp.production'] + production_id = self.env.context.get('active_id', False) + production = production_obj.browse(production_id) + production.load_final_quant_cost() + return res From d5f2769a3a132eae09fbea4d920e56ca1ee728d6 Mon Sep 17 00:00:00 2001 From: "Pedro M. Baeza" Date: Fri, 13 Nov 2015 16:00:00 +0100 Subject: [PATCH 11/13] [FIX+IMP] mrp_production_real_costs: Use hook --- mrp_production_real_cost/__openerp__.py | 4 +- mrp_production_real_cost/i18n/es.po | 25 ++++- mrp_production_real_cost/i18n/it.po | 97 +++++++++++++++++++ mrp_production_real_cost/i18n/pt_BR.po | 25 ++++- mrp_production_real_cost/i18n/ro.po | 97 +++++++++++++++++++ mrp_production_real_cost/i18n/sl.po | 23 ++++- mrp_production_real_cost/models/__init__.py | 1 - mrp_production_real_cost/models/mrp_bom.py | 24 +++-- .../models/mrp_production.py | 6 +- .../models/mrp_production_workcenter_line.py | 4 +- .../models/project_task_work.py | 48 --------- mrp_production_real_cost/models/stock_move.py | 9 +- 12 files changed, 279 insertions(+), 84 deletions(-) create mode 100644 mrp_production_real_cost/i18n/it.po create mode 100644 mrp_production_real_cost/i18n/ro.po delete mode 100644 mrp_production_real_cost/models/project_task_work.py diff --git a/mrp_production_real_cost/__openerp__.py b/mrp_production_real_cost/__openerp__.py index 8c64469a0..c09892453 100644 --- a/mrp_production_real_cost/__openerp__.py +++ b/mrp_production_real_cost/__openerp__.py @@ -1,4 +1,4 @@ -# -*- encoding: utf-8 -*- +# -*- coding: utf-8 -*- ############################################################################## # # This program is free software: you can redistribute it and/or modify @@ -18,7 +18,7 @@ { "name": "MRP real costs", - "version": "1.0", + "version": "8.0.1.0.1", "depends": ["analytic", "project_timesheet", "mrp_project_link", diff --git a/mrp_production_real_cost/i18n/es.po b/mrp_production_real_cost/i18n/es.po index e007d3730..3c3bfe947 100644 --- a/mrp_production_real_cost/i18n/es.po +++ b/mrp_production_real_cost/i18n/es.po @@ -8,9 +8,9 @@ msgid "" msgstr "" "Project-Id-Version: odoomrp-wip (8.0)\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2015-10-07 10:44+0000\n" -"PO-Revision-Date: 2015-10-09 10:55+0000\n" -"Last-Translator: Pedro M. Baeza \n" +"POT-Creation-Date: 2015-11-20 18:10+0000\n" +"PO-Revision-Date: 2015-11-20 18:13+0000\n" +"Last-Translator: OCA Transbot \n" "Language-Team: Spanish (http://www.transifex.com/oca/odoomrp-wip-8-0/language/es/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -28,6 +28,11 @@ msgstr "% diferencia" msgid "Bill of Material" msgstr "Lista de material" +#. module: mrp_production_real_costs +#: field:mrp.config.settings,final_product_analytic_cost:0 +msgid "Load final product analytic cost" +msgstr "" + #. module: mrp_production_real_costs #: model:ir.model,name:mrp_production_real_costs.model_mrp_production msgid "Manufacturing Order" @@ -48,6 +53,11 @@ msgstr "" msgid "Pre-Operation Cost" msgstr "" +#. module: mrp_production_real_costs +#: model:ir.model,name:mrp_production_real_costs.model_mrp_product_produce +msgid "Product Produce" +msgstr "Fabricar producto" + #. module: mrp_production_real_costs #: model:ir.model,name:mrp_production_real_costs.model_project_task_work msgid "Project Task Work" @@ -58,6 +68,13 @@ msgstr "Trabajo de tarea" msgid "Stock Move" msgstr "Movimiento de existencias" +#. module: mrp_production_real_costs +#: help:mrp.config.settings,final_product_analytic_cost:0 +msgid "" +"This will allow you to define if those BoM passed back to draft are still " +"activated or not" +msgstr "De esta manera podrás definir si aquellas LdM vueltas a estado borrador pueden mantenerse activas o no" + #. module: mrp_production_real_costs #: field:mrp.production,real_cost:0 msgid "Total Real Cost" @@ -74,7 +91,7 @@ msgid "Work Order" msgstr "Orden de trabajo" #. module: mrp_production_real_costs -#: code:addons/mrp_production_real_costs/models/mrp_production.py:92 +#: code:addons/mrp_production_real_costs/models/mrp_production.py:121 #, python-format msgid "You must define one Analytic Account for this MO: %s" msgstr "Debe definir una cuenta analítica para esta MO: %s" diff --git a/mrp_production_real_cost/i18n/it.po b/mrp_production_real_cost/i18n/it.po new file mode 100644 index 000000000..c7e6444a0 --- /dev/null +++ b/mrp_production_real_cost/i18n/it.po @@ -0,0 +1,97 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * mrp_production_real_costs +# +# Translators: +# Massimiliano Casa , 2015 +msgid "" +msgstr "" +"Project-Id-Version: odoomrp-wip (8.0)\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-11-20 18:10+0000\n" +"PO-Revision-Date: 2015-10-30 13:07+0000\n" +"Last-Translator: OCA Transbot \n" +"Language-Team: Italian (http://www.transifex.com/oca/odoomrp-wip-8-0/language/it/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Language: it\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#. module: mrp_production_real_costs +#: field:mrp.production,percentage_difference:0 +msgid "% difference" +msgstr "% differenza" + +#. module: mrp_production_real_costs +#: model:ir.model,name:mrp_production_real_costs.model_mrp_bom +msgid "Bill of Material" +msgstr "Distinta base" + +#. module: mrp_production_real_costs +#: field:mrp.config.settings,final_product_analytic_cost:0 +msgid "Load final product analytic cost" +msgstr "" + +#. module: mrp_production_real_costs +#: model:ir.model,name:mrp_production_real_costs.model_mrp_production +msgid "Manufacturing Order" +msgstr "Ordine di produzione" + +#. module: mrp_production_real_costs +#: view:mrp.production:mrp_production_real_costs.mrp_production_form_view_real_costs +msgid "Manufacturing costs" +msgstr "Costi di produzione" + +#. module: mrp_production_real_costs +#: field:mrp.production.workcenter.line,post_cost:0 +msgid "Post-Operation Cost" +msgstr "Costo Post-lavorazione" + +#. module: mrp_production_real_costs +#: field:mrp.production.workcenter.line,pre_cost:0 +msgid "Pre-Operation Cost" +msgstr "Costo Pre-lavorazione" + +#. module: mrp_production_real_costs +#: model:ir.model,name:mrp_production_real_costs.model_mrp_product_produce +msgid "Product Produce" +msgstr "" + +#. module: mrp_production_real_costs +#: model:ir.model,name:mrp_production_real_costs.model_project_task_work +msgid "Project Task Work" +msgstr "Attività Progetto" + +#. module: mrp_production_real_costs +#: model:ir.model,name:mrp_production_real_costs.model_stock_move +msgid "Stock Move" +msgstr "" + +#. module: mrp_production_real_costs +#: help:mrp.config.settings,final_product_analytic_cost:0 +msgid "" +"This will allow you to define if those BoM passed back to draft are still " +"activated or not" +msgstr "" + +#. module: mrp_production_real_costs +#: field:mrp.production,real_cost:0 +msgid "Total Real Cost" +msgstr "Costo Reale Totale " + +#. module: mrp_production_real_costs +#: field:mrp.production,unit_real_cost:0 +msgid "Unit Real Cost" +msgstr "Costo unitario reale" + +#. module: mrp_production_real_costs +#: model:ir.model,name:mrp_production_real_costs.model_mrp_production_workcenter_line +msgid "Work Order" +msgstr "Ordine di lavorazione" + +#. module: mrp_production_real_costs +#: code:addons/mrp_production_real_costs/models/mrp_production.py:121 +#, python-format +msgid "You must define one Analytic Account for this MO: %s" +msgstr "Bisogna definire un conto analitico per questo MO: %s" diff --git a/mrp_production_real_cost/i18n/pt_BR.po b/mrp_production_real_cost/i18n/pt_BR.po index 16b8a2445..fb9efa393 100644 --- a/mrp_production_real_cost/i18n/pt_BR.po +++ b/mrp_production_real_cost/i18n/pt_BR.po @@ -7,9 +7,9 @@ msgid "" msgstr "" "Project-Id-Version: odoomrp-wip (8.0)\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2015-10-07 10:44+0000\n" -"PO-Revision-Date: 2015-10-09 03:39+0000\n" -"Last-Translator: danimaribeiro \n" +"POT-Creation-Date: 2015-11-20 18:10+0000\n" +"PO-Revision-Date: 2015-10-30 13:07+0000\n" +"Last-Translator: OCA Transbot \n" "Language-Team: Portuguese (Brazil) (http://www.transifex.com/oca/odoomrp-wip-8-0/language/pt_BR/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -27,6 +27,11 @@ msgstr "" msgid "Bill of Material" msgstr "Lista de materiais" +#. module: mrp_production_real_costs +#: field:mrp.config.settings,final_product_analytic_cost:0 +msgid "Load final product analytic cost" +msgstr "" + #. module: mrp_production_real_costs #: model:ir.model,name:mrp_production_real_costs.model_mrp_production msgid "Manufacturing Order" @@ -47,6 +52,11 @@ msgstr "" msgid "Pre-Operation Cost" msgstr "" +#. module: mrp_production_real_costs +#: model:ir.model,name:mrp_production_real_costs.model_mrp_product_produce +msgid "Product Produce" +msgstr "Produzir produto" + #. module: mrp_production_real_costs #: model:ir.model,name:mrp_production_real_costs.model_project_task_work msgid "Project Task Work" @@ -57,6 +67,13 @@ msgstr "" msgid "Stock Move" msgstr "Movimentação de estoque" +#. module: mrp_production_real_costs +#: help:mrp.config.settings,final_product_analytic_cost:0 +msgid "" +"This will allow you to define if those BoM passed back to draft are still " +"activated or not" +msgstr "Isto permite você definir se as BOM's passadas para provisório são ativadas ou não." + #. module: mrp_production_real_costs #: field:mrp.production,real_cost:0 msgid "Total Real Cost" @@ -73,7 +90,7 @@ msgid "Work Order" msgstr "Ordem de serviço" #. module: mrp_production_real_costs -#: code:addons/mrp_production_real_costs/models/mrp_production.py:92 +#: code:addons/mrp_production_real_costs/models/mrp_production.py:121 #, python-format msgid "You must define one Analytic Account for this MO: %s" msgstr "" diff --git a/mrp_production_real_cost/i18n/ro.po b/mrp_production_real_cost/i18n/ro.po new file mode 100644 index 000000000..ba0497e83 --- /dev/null +++ b/mrp_production_real_cost/i18n/ro.po @@ -0,0 +1,97 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * mrp_production_real_costs +# +# Translators: +# Dorin Hongu , 2015 +msgid "" +msgstr "" +"Project-Id-Version: odoomrp-wip (8.0)\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-11-20 18:10+0000\n" +"PO-Revision-Date: 2015-11-18 00:48+0000\n" +"Last-Translator: Dorin Hongu \n" +"Language-Team: Romanian (http://www.transifex.com/oca/odoomrp-wip-8-0/language/ro/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Language: ro\n" +"Plural-Forms: nplurals=3; plural=(n==1?0:(((n%100>19)||((n%100==0)&&(n!=0)))?2:1));\n" + +#. module: mrp_production_real_costs +#: field:mrp.production,percentage_difference:0 +msgid "% difference" +msgstr "% diferență" + +#. module: mrp_production_real_costs +#: model:ir.model,name:mrp_production_real_costs.model_mrp_bom +msgid "Bill of Material" +msgstr "Listă de materiale" + +#. module: mrp_production_real_costs +#: field:mrp.config.settings,final_product_analytic_cost:0 +msgid "Load final product analytic cost" +msgstr "" + +#. module: mrp_production_real_costs +#: model:ir.model,name:mrp_production_real_costs.model_mrp_production +msgid "Manufacturing Order" +msgstr "Comandă fabricație" + +#. module: mrp_production_real_costs +#: view:mrp.production:mrp_production_real_costs.mrp_production_form_view_real_costs +msgid "Manufacturing costs" +msgstr "Costuri fabricație" + +#. module: mrp_production_real_costs +#: field:mrp.production.workcenter.line,post_cost:0 +msgid "Post-Operation Cost" +msgstr "" + +#. module: mrp_production_real_costs +#: field:mrp.production.workcenter.line,pre_cost:0 +msgid "Pre-Operation Cost" +msgstr "" + +#. module: mrp_production_real_costs +#: model:ir.model,name:mrp_production_real_costs.model_mrp_product_produce +msgid "Product Produce" +msgstr "" + +#. module: mrp_production_real_costs +#: model:ir.model,name:mrp_production_real_costs.model_project_task_work +msgid "Project Task Work" +msgstr "" + +#. module: mrp_production_real_costs +#: model:ir.model,name:mrp_production_real_costs.model_stock_move +msgid "Stock Move" +msgstr "Mișcare stoc" + +#. module: mrp_production_real_costs +#: help:mrp.config.settings,final_product_analytic_cost:0 +msgid "" +"This will allow you to define if those BoM passed back to draft are still " +"activated or not" +msgstr "" + +#. module: mrp_production_real_costs +#: field:mrp.production,real_cost:0 +msgid "Total Real Cost" +msgstr "Total costuri reale" + +#. module: mrp_production_real_costs +#: field:mrp.production,unit_real_cost:0 +msgid "Unit Real Cost" +msgstr "" + +#. module: mrp_production_real_costs +#: model:ir.model,name:mrp_production_real_costs.model_mrp_production_workcenter_line +msgid "Work Order" +msgstr "Comandă de lucru" + +#. module: mrp_production_real_costs +#: code:addons/mrp_production_real_costs/models/mrp_production.py:121 +#, python-format +msgid "You must define one Analytic Account for this MO: %s" +msgstr "" diff --git a/mrp_production_real_cost/i18n/sl.po b/mrp_production_real_cost/i18n/sl.po index 0f6d5fd05..af50cfb29 100644 --- a/mrp_production_real_cost/i18n/sl.po +++ b/mrp_production_real_cost/i18n/sl.po @@ -8,8 +8,8 @@ msgid "" msgstr "" "Project-Id-Version: odoomrp-wip (8.0)\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2015-10-07 10:44+0000\n" -"PO-Revision-Date: 2015-10-05 04:55+0000\n" +"POT-Creation-Date: 2015-11-20 18:10+0000\n" +"PO-Revision-Date: 2015-10-31 05:16+0000\n" "Last-Translator: Matjaž Mozetič \n" "Language-Team: Slovenian (http://www.transifex.com/oca/odoomrp-wip-8-0/language/sl/)\n" "MIME-Version: 1.0\n" @@ -28,6 +28,11 @@ msgstr "% razlike" msgid "Bill of Material" msgstr "Kosovnica" +#. module: mrp_production_real_costs +#: field:mrp.config.settings,final_product_analytic_cost:0 +msgid "Load final product analytic cost" +msgstr "Naloži zadnji analitični strošek proizvoda" + #. module: mrp_production_real_costs #: model:ir.model,name:mrp_production_real_costs.model_mrp_production msgid "Manufacturing Order" @@ -48,6 +53,11 @@ msgstr "Po-operativni stroški" msgid "Pre-Operation Cost" msgstr "Pred operativni stroški" +#. module: mrp_production_real_costs +#: model:ir.model,name:mrp_production_real_costs.model_mrp_product_produce +msgid "Product Produce" +msgstr "Izdelava proizvoda" + #. module: mrp_production_real_costs #: model:ir.model,name:mrp_production_real_costs.model_project_task_work msgid "Project Task Work" @@ -58,6 +68,13 @@ msgstr "Delo na projektnem opravilu" msgid "Stock Move" msgstr "Premik zaloge" +#. module: mrp_production_real_costs +#: help:mrp.config.settings,final_product_analytic_cost:0 +msgid "" +"This will allow you to define if those BoM passed back to draft are still " +"activated or not" +msgstr "Omogoča določanje, če naj kosovnice, ki se vračajo v stanje osnutka, ostanejo aktivirane ali ne" + #. module: mrp_production_real_costs #: field:mrp.production,real_cost:0 msgid "Total Real Cost" @@ -74,7 +91,7 @@ msgid "Work Order" msgstr "Delovni nalog" #. module: mrp_production_real_costs -#: code:addons/mrp_production_real_costs/models/mrp_production.py:92 +#: code:addons/mrp_production_real_costs/models/mrp_production.py:121 #, python-format msgid "You must define one Analytic Account for this MO: %s" msgstr "Potrebno je določiti analitični konto za proizvodni nalog: %s" diff --git a/mrp_production_real_cost/models/__init__.py b/mrp_production_real_cost/models/__init__.py index e87caf4c2..95f9cbed8 100644 --- a/mrp_production_real_cost/models/__init__.py +++ b/mrp_production_real_cost/models/__init__.py @@ -18,7 +18,6 @@ from . import stock_move from . import mrp_production_workcenter_line -from . import project_task_work from . import mrp_production from . import mrp_bom from . import mrp_config diff --git a/mrp_production_real_cost/models/mrp_bom.py b/mrp_production_real_cost/models/mrp_bom.py index 8ac5d55fa..8499f49cc 100644 --- a/mrp_production_real_cost/models/mrp_bom.py +++ b/mrp_production_real_cost/models/mrp_bom.py @@ -2,21 +2,19 @@ ############################################################################## # For copyright and license notices, see __openerp__.py file in root directory ############################################################################## -from openerp import models +from openerp import models, api class MrpBom(models.Model): _inherit = 'mrp.bom' - def _get_workorder_operations(self, result2, factor, level=0, - routing_id=False): - res = super(MrpBom, self)._get_workorder_operations( - result2, factor, level=level, routing_id=routing_id) - workcenter_obj = self.env['mrp.workcenter'] - for wkr in res: - wc = workcenter_obj.browse(wkr.get('workcenter_id', False)) - wkr['pre_cost'] = (wkr.get('time_start', 0.0) * - wc.pre_op_product.cost_price) - wkr['post_cost'] = (wkr.get('time_stop', 0.0) * - wc.post_op_product.cost_price) - return result2 + @api.multi + def _prepare_wc_line(self, wc_use, level=0, factor=1): + res = super(MrpBom, self)._prepare_wc_line( + wc_use, level=level, factor=factor) + wc = wc_use.workcenter_id + res['pre_cost'] = ( + res.get('time_start', 0.0) * wc.pre_op_product.cost_price) + res['post_cost'] = ( + res.get('time_stop', 0.0) * wc.post_op_product.cost_price) + return res diff --git a/mrp_production_real_cost/models/mrp_production.py b/mrp_production_real_cost/models/mrp_production.py index 42067aef2..7c5f13994 100644 --- a/mrp_production_real_cost/models/mrp_production.py +++ b/mrp_production_real_cost/models/mrp_production.py @@ -71,7 +71,7 @@ class MrpProduction(models.Model): journal_id, name, record, record.product_id, qty=qty, amount=mrp_cost) task = task_obj.search([('mrp_production_id', '=', record.id), - ('wk_order', '=', False)]) + ('workorder', '=', False)]) vals['task_id'] = task and task[0].id or False analytic_line_obj.create(vals) record.real_cost = mrp_cost @@ -112,8 +112,8 @@ class MrpProduction(models.Model): property_obj = self.env['ir.property'] if not general_account: general_account = ( - product.property_account_income or - product.categ_id.property_account_income_categ or + product.property_account_expense or + product.categ_id.property_account_expense_categ or property_obj.get('property_account_expense_categ', 'product.category')) if not production.analytic_account_id: diff --git a/mrp_production_real_cost/models/mrp_production_workcenter_line.py b/mrp_production_real_cost/models/mrp_production_workcenter_line.py index 298165d0a..81da71591 100644 --- a/mrp_production_real_cost/models/mrp_production_workcenter_line.py +++ b/mrp_production_real_cost/models/mrp_production_workcenter_line.py @@ -56,7 +56,7 @@ class MrpProductionWorkcenterLine(models.Model): general_account=general_acc, workorder=self, qty=operation_line.uptime, amount=price) task = task_obj.search([('mrp_production_id', '=', production.id), - ('wk_order', '=', False)]) + ('workorder', '=', False)]) analytic_vals['task_id'] = task and task[0].id or False analytic_vals['product_uom_id'] = hour_uom.id analytic_line = analytic_line_obj.create(analytic_vals) @@ -97,7 +97,7 @@ class MrpProductionWorkcenterLine(models.Model): general_account=general_acc, workorder=self, qty=qty, amount=price) task = task_obj.search([('mrp_production_id', '=', production.id), - ('wk_order', '=', False)]) + ('workorder', '=', False)]) analytic_vals['task_id'] = task and task[0].id or False analytic_vals['product_uom_id'] = hour_uom.id analytic_line_obj.create(analytic_vals) diff --git a/mrp_production_real_cost/models/project_task_work.py b/mrp_production_real_cost/models/project_task_work.py deleted file mode 100644 index b951b2a00..000000000 --- a/mrp_production_real_cost/models/project_task_work.py +++ /dev/null @@ -1,48 +0,0 @@ -# -*- encoding: utf-8 -*- -############################################################################## -# -# 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 General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see http://www.gnu.org/licenses/. -# -############################################################################## - -from openerp import models, api - - -class ProjectTaskWork(models.Model): - - _inherit = 'project.task.work' - - @api.model - def create(self, vals): - result = super(ProjectTaskWork, self).create(vals) - if result.hr_analytic_timesheet_id and result.task_id: - analytic_line = result.hr_analytic_timesheet_id.line_id - task = result.task_id - if task.mrp_production_id or task.wk_order: - analytic_line.write({'mrp_production_id': - task.mrp_production_id.id, - 'workorder': task.wk_order.id}) - return result - - @api.model - def write(self, vals): - result = super(ProjectTaskWork, self).write(vals) - if 'hr_analytic_timesheet_id' in vals or 'task_id' in vals: - analytic_line = self.hr_analytic_timesheet_id.line_id - task = self.task_id - if task.mrp_production_id or task.wk_order: - analytic_line.write({'mrp_production_id': - task.mrp_production_id.id, - 'workorder': task.wk_order.id}) - return result diff --git a/mrp_production_real_cost/models/stock_move.py b/mrp_production_real_cost/models/stock_move.py index bca465fce..de519174a 100644 --- a/mrp_production_real_cost/models/stock_move.py +++ b/mrp_production_real_cost/models/stock_move.py @@ -42,7 +42,7 @@ class StockMove(models.Model): workorder=record.work_order, qty=record.product_qty, amount=(-record.product_id.cost_price * record.product_qty))) task = task_obj.search([('mrp_production_id', '=', production.id), - ('wk_order', '=', False)]) + ('workorder', '=', False)]) analytic_vals['task_id'] = task and task[0].id or False analytic_line_obj.create(analytic_vals) return result @@ -62,9 +62,10 @@ class StockMove(models.Model): if move.state == 'done': product_avail -= move.product_qty template_avail -= move.product_qty - new_cost_price = ((amount_unit * product_avail + prod_total_cost) / - ((product_avail >= 0.0 and product_avail or 0.0) - + move.product_qty)) + new_cost_price = ( + (amount_unit * product_avail + prod_total_cost) / + ((product_avail >= 0.0 and product_avail or 0.0) + + move.product_qty)) new_std_price = ((template_price * template_avail + prod_total_cost) / ((template_avail >= 0.0 and template_avail or From 06942b61b1bb9fcfaac7d8ea8f719bd5c380d012 Mon Sep 17 00:00:00 2001 From: davidtranhp Date: Fri, 4 Dec 2015 20:46:49 +0700 Subject: [PATCH 12/13] [Add] Vietnamese translations --- mrp_production_real_cost/i18n/vi_VN.po | 93 ++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 mrp_production_real_cost/i18n/vi_VN.po diff --git a/mrp_production_real_cost/i18n/vi_VN.po b/mrp_production_real_cost/i18n/vi_VN.po new file mode 100644 index 000000000..e220f2311 --- /dev/null +++ b/mrp_production_real_cost/i18n/vi_VN.po @@ -0,0 +1,93 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * mrp_production_real_costs +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 8.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-11-28 09:04+0000\n" +"PO-Revision-Date: 2015-11-28 09:04+0000\n" +"Last-Translator: <>\n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: mrp_production_real_costs +#: field:mrp.production,percentage_difference:0 +msgid "% difference" +msgstr "% khác biệt" + +#. module: mrp_production_real_costs +#: model:ir.model,name:mrp_production_real_costs.model_mrp_bom +msgid "Bill of Material" +msgstr "Định mức Nguyên liệu" + +#. module: mrp_production_real_costs +#: field:mrp.config.settings,final_product_analytic_cost:0 +msgid "Load final product analytic cost" +msgstr "Load final product analytic cost" + +#. module: mrp_production_real_costs +#: model:ir.model,name:mrp_production_real_costs.model_mrp_production +msgid "Manufacturing Order" +msgstr "Lệnh sản xuất" + +#. module: mrp_production_real_costs +#: view:mrp.production:mrp_production_real_costs.mrp_production_form_view_real_costs +msgid "Manufacturing costs" +msgstr "Chi phí Sản xuất" + +#. module: mrp_production_real_costs +#: field:mrp.production.workcenter.line,post_cost:0 +msgid "Post-Operation Cost" +msgstr "Chi phí Sau sản xuất" + +#. module: mrp_production_real_costs +#: field:mrp.production.workcenter.line,pre_cost:0 +msgid "Pre-Operation Cost" +msgstr "Chi phí Trước sản xuất" + +#. module: mrp_production_real_costs +#: model:ir.model,name:mrp_production_real_costs.model_mrp_product_produce +msgid "Product Produce" +msgstr "Sản xuất sản phẩm" + +#. module: mrp_production_real_costs +#: model:ir.model,name:mrp_production_real_costs.model_project_task_work +msgid "Project Task Work" +msgstr "Project Task Work" + +#. module: mrp_production_real_costs +#: model:ir.model,name:mrp_production_real_costs.model_stock_move +msgid "Stock Move" +msgstr "Dịch chuyển kho" + +#. module: mrp_production_real_costs +#: help:mrp.config.settings,final_product_analytic_cost:0 +msgid "This will allow you to define if those BoM passed back to draft are still activated or not" +msgstr "This will allow you to define if those BoM passed back to draft are still activated or not" + +#. module: mrp_production_real_costs +#: field:mrp.production,real_cost:0 +msgid "Total Real Cost" +msgstr "Tổng chi thực tế" + +#. module: mrp_production_real_costs +#: field:mrp.production,unit_real_cost:0 +msgid "Unit Real Cost" +msgstr "Unit Real Cost" + +#. module: mrp_production_real_costs +#: model:ir.model,name:mrp_production_real_costs.model_mrp_production_workcenter_line +msgid "Work Order" +msgstr "Hoạt động sản xuất" + +#. module: mrp_production_real_costs +#: code:addons/mrp_production_real_costs/models/mrp_production.py:121 +#, python-format +msgid "You must define one Analytic Account for this MO: %s" +msgstr "Bạn phải định nghĩa một Tài khoản Quản trị cho MO này: %s" + From 86a455a0db91f3a0065895761f325ea14095d672 Mon Sep 17 00:00:00 2001 From: "Pedro M. Baeza" Date: Thu, 10 Dec 2015 14:51:17 +0100 Subject: [PATCH 13/13] [IMP] mrp_production_real_cost: Tests + cleaning + adaptation to OCA --- mrp_production_real_cost/README.rst | 76 ++++- mrp_production_real_cost/__init__.py | 22 +- mrp_production_real_cost/__openerp__.py | 56 ++-- .../demo/mrp_production_demo.xml | 21 ++ mrp_production_real_cost/i18n/en_US.po | 79 ----- .../i18n/mrp_production_real_costs.pot | 38 --- mrp_production_real_cost/models/__init__.py | 28 +- mrp_production_real_cost/models/mrp_bom.py | 11 +- mrp_production_real_cost/models/mrp_config.py | 43 --- .../models/mrp_production.py | 113 ++----- .../models/mrp_production_workcenter_line.py | 48 +-- mrp_production_real_cost/models/stock_move.py | 67 ++-- .../static/description/icon.png | Bin 0 -> 10215 bytes .../static/description/icon.svg | 297 ++++++++++++++++++ mrp_production_real_cost/tests/__init__.py | 6 + .../tests/test_mrp_production_real_cost.py | 43 +++ .../views/mrp_production_view.xml | 1 - .../views/res_config_view.xml | 18 -- mrp_production_real_cost/wizard/__init__.py | 6 - .../wizard/mrp_product_produce.py | 20 -- mrp_project/tests/test_mrp_project.py | 3 + oca_dependencies.txt | 2 + 22 files changed, 557 insertions(+), 441 deletions(-) create mode 100644 mrp_production_real_cost/demo/mrp_production_demo.xml delete mode 100644 mrp_production_real_cost/i18n/en_US.po delete mode 100644 mrp_production_real_cost/i18n/mrp_production_real_costs.pot delete mode 100644 mrp_production_real_cost/models/mrp_config.py create mode 100644 mrp_production_real_cost/static/description/icon.png create mode 100644 mrp_production_real_cost/static/description/icon.svg create mode 100644 mrp_production_real_cost/tests/__init__.py create mode 100644 mrp_production_real_cost/tests/test_mrp_production_real_cost.py delete mode 100644 mrp_production_real_cost/views/res_config_view.xml delete mode 100644 mrp_production_real_cost/wizard/__init__.py delete mode 100644 mrp_production_real_cost/wizard/mrp_product_produce.py diff --git a/mrp_production_real_cost/README.rst b/mrp_production_real_cost/README.rst index 1575ef3b4..e1c6c98bd 100644 --- a/mrp_production_real_cost/README.rst +++ b/mrp_production_real_cost/README.rst @@ -1,11 +1,85 @@ +.. 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 + +================================== Real costs in manufacturing orders ================================== This module allows to manage the control of Manufacturing Orders actual costs, -by creating analytic lines as defined in the MO (from *mrp_project_link*). +by creating analytic lines as defined in the MO (from *mrp_project*). It also updates product standard price when a manufacturing orders is finished according this formula: (Product stock * Product standard price + Production real cost) / (Product stock + Final product quantity) + +Installation +============ + +This module depends on the module *product_variant_cost_price*, that is +available in: + +https://github.com/OCA/product-variant + +Usage +===== + +Operating with a manufacture order, analytic entries adding costs will be +created when: + +* Some raw material is consumed. +* A work order is finished or paused. + +Also, thanks to *project_timesheet* modules, users time is also translated to +costs in the linked analytic account. + + + +.. 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/8.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 smashing it by providing a detailed and welcomed `feedback +`_. + +Credits +======= + +Contributors +------------ + +* Pedro M. Baeza +* Ana Juaristi +* Ainara Galdona + +Images +------ + +* Original Odoo MRP icon +* Thanks to https://openclipart.org/detail/224801/black-and-white-calculator + +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. \ No newline at end of file diff --git a/mrp_production_real_cost/__init__.py b/mrp_production_real_cost/__init__.py index ecfcca241..a72b54a4a 100644 --- a/mrp_production_real_cost/__init__.py +++ b/mrp_production_real_cost/__init__.py @@ -1,20 +1,6 @@ -# -*- encoding: utf-8 -*- -############################################################################## -# -# 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 General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see http://www.gnu.org/licenses/. -# -############################################################################## +# -*- coding: utf-8 -*- +# © 2014-2015 Avanzosc +# © 2014-2015 Pedro M. Baeza +# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html from . import models -from . import wizard diff --git a/mrp_production_real_cost/__openerp__.py b/mrp_production_real_cost/__openerp__.py index c09892453..2fa957fbd 100644 --- a/mrp_production_real_cost/__openerp__.py +++ b/mrp_production_real_cost/__openerp__.py @@ -1,40 +1,32 @@ # -*- coding: utf-8 -*- -############################################################################## -# -# 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 General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see http://www.gnu.org/licenses/. -# -############################################################################## +# © 2014-2015 Avanzosc +# © 2014-2015 Antiun Ingeniería +# © 2014-2015 Pedro M. Baeza +# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html { - "name": "MRP real costs", - "version": "8.0.1.0.1", - "depends": ["analytic", - "project_timesheet", - "mrp_project_link", - "mrp_operations_time_control", - "stock_account", - "product_variant_cost", - "mrp_production_project_estimated_cost"], - "author": "OdooMRP team," - "AvanzOSC," - "Serv. Tecnol. Avanzados - Pedro M. Baeza", - "category": "MRP", + "name": "Real costs in manufacturing orders", + "version": "8.0.1.0.0", + "depends": [ + "project_timesheet", + "mrp_project", + "mrp_operations_extension", + "mrp_operations_time_control", + "stock_account", + "product_variant_cost_price", + ], + "author": "OdooMRP team, " + "AvanzOSC, " + "Serv. Tecnol. Avanzados - Pedro M. Baeza, " + "Antiun Ingeniería S.L., " + "Odoo Community Association (OCA)", + "category": "Manufacturing", 'data': [ "data/analytic_journal_data.xml", "views/mrp_production_view.xml", - "views/res_config_view.xml" - ], + ], + 'demo': [ + 'demo/mrp_production_demo.xml', + ], 'installable': True, - 'auto_install': False, } diff --git a/mrp_production_real_cost/demo/mrp_production_demo.xml b/mrp_production_real_cost/demo/mrp_production_demo.xml new file mode 100644 index 000000000..bfaea931c --- /dev/null +++ b/mrp_production_real_cost/demo/mrp_production_demo.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/mrp_production_real_cost/i18n/en_US.po b/mrp_production_real_cost/i18n/en_US.po deleted file mode 100644 index 543c75b96..000000000 --- a/mrp_production_real_cost/i18n/en_US.po +++ /dev/null @@ -1,79 +0,0 @@ -# Translation of Odoo Server. -# This file contains the translation of the following modules: -# * mrp_production_real_costs -# -# Translators: -msgid "" -msgstr "" -"Project-Id-Version: odoomrp-wip (8.0)\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2015-10-07 10:44+0000\n" -"PO-Revision-Date: 2015-10-04 00:01+0000\n" -"Last-Translator: OCA Transbot \n" -"Language-Team: English (United States) (http://www.transifex.com/oca/odoomrp-wip-8-0/language/en_US/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: \n" -"Language: en_US\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -#. module: mrp_production_real_costs -#: field:mrp.production,percentage_difference:0 -msgid "% difference" -msgstr "" - -#. module: mrp_production_real_costs -#: model:ir.model,name:mrp_production_real_costs.model_mrp_bom -msgid "Bill of Material" -msgstr "" - -#. module: mrp_production_real_costs -#: model:ir.model,name:mrp_production_real_costs.model_mrp_production -msgid "Manufacturing Order" -msgstr "" - -#. module: mrp_production_real_costs -#: view:mrp.production:mrp_production_real_costs.mrp_production_form_view_real_costs -msgid "Manufacturing costs" -msgstr "" - -#. module: mrp_production_real_costs -#: field:mrp.production.workcenter.line,post_cost:0 -msgid "Post-Operation Cost" -msgstr "" - -#. module: mrp_production_real_costs -#: field:mrp.production.workcenter.line,pre_cost:0 -msgid "Pre-Operation Cost" -msgstr "" - -#. module: mrp_production_real_costs -#: model:ir.model,name:mrp_production_real_costs.model_project_task_work -msgid "Project Task Work" -msgstr "" - -#. module: mrp_production_real_costs -#: model:ir.model,name:mrp_production_real_costs.model_stock_move -msgid "Stock Move" -msgstr "" - -#. module: mrp_production_real_costs -#: field:mrp.production,real_cost:0 -msgid "Total Real Cost" -msgstr "" - -#. module: mrp_production_real_costs -#: field:mrp.production,unit_real_cost:0 -msgid "Unit Real Cost" -msgstr "" - -#. module: mrp_production_real_costs -#: model:ir.model,name:mrp_production_real_costs.model_mrp_production_workcenter_line -msgid "Work Order" -msgstr "Work Order" - -#. module: mrp_production_real_costs -#: code:addons/mrp_production_real_costs/models/mrp_production.py:92 -#, python-format -msgid "You must define one Analytic Account for this MO: %s" -msgstr "" diff --git a/mrp_production_real_cost/i18n/mrp_production_real_costs.pot b/mrp_production_real_cost/i18n/mrp_production_real_costs.pot deleted file mode 100644 index 69ecdc8cb..000000000 --- a/mrp_production_real_cost/i18n/mrp_production_real_costs.pot +++ /dev/null @@ -1,38 +0,0 @@ -# Translation of Odoo Server. -# This file contains the translation of the following modules: -# * mrp_production_real_costs -# -msgid "" -msgstr "" -"Project-Id-Version: Odoo Server 8.0\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2014-11-11 15:06+0000\n" -"PO-Revision-Date: 2014-11-11 16:09+0100\n" -"Last-Translator: \n" -"Language-Team: \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: \n" - -#. module: mrp_production_real_costs -#: model:ir.model,name:mrp_production_real_costs.model_project_task_work -msgid "Project Task Work" -msgstr "" - -#. module: mrp_production_real_costs -#: model:ir.model,name:mrp_production_real_costs.model_stock_move -msgid "Stock Move" -msgstr "" - -#. module: mrp_production_real_costs -#: model:ir.model,name:mrp_production_real_costs.model_mrp_production_workcenter_line -msgid "Work Order" -msgstr "" - -#. module: mrp_production_real_costs -#: code:addons/mrp_production_real_costs/models/mrp_production_workcenter_line.py:59 -#, python-format -msgid "You must define a general account for this Workcenter: [%s] %s" -msgstr "" - diff --git a/mrp_production_real_cost/models/__init__.py b/mrp_production_real_cost/models/__init__.py index 95f9cbed8..770634caa 100644 --- a/mrp_production_real_cost/models/__init__.py +++ b/mrp_production_real_cost/models/__init__.py @@ -1,23 +1,9 @@ -# -*- encoding: utf-8 -*- -############################################################################## -# -# 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 General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see http://www.gnu.org/licenses/. -# -############################################################################## +# -*- coding: utf-8 -*- +# © 2014-2015 Avanzosc +# © 2014-2015 Pedro M. Baeza +# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html -from . import stock_move -from . import mrp_production_workcenter_line -from . import mrp_production from . import mrp_bom -from . import mrp_config +from . import mrp_production +from . import mrp_production_workcenter_line +from . import stock_move diff --git a/mrp_production_real_cost/models/mrp_bom.py b/mrp_production_real_cost/models/mrp_bom.py index 8499f49cc..753e003e8 100644 --- a/mrp_production_real_cost/models/mrp_bom.py +++ b/mrp_production_real_cost/models/mrp_bom.py @@ -1,7 +1,8 @@ # -*- coding: utf-8 -*- -############################################################################## -# For copyright and license notices, see __openerp__.py file in root directory -############################################################################## +# © 2014-2015 Avanzosc +# © 2014-2015 Pedro M. Baeza +# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html + from openerp import models, api @@ -14,7 +15,7 @@ class MrpBom(models.Model): wc_use, level=level, factor=factor) wc = wc_use.workcenter_id res['pre_cost'] = ( - res.get('time_start', 0.0) * wc.pre_op_product.cost_price) + res.get('time_start', 0.0) * wc.pre_op_product.standard_price) res['post_cost'] = ( - res.get('time_stop', 0.0) * wc.post_op_product.cost_price) + res.get('time_stop', 0.0) * wc.post_op_product.standard_price) return res diff --git a/mrp_production_real_cost/models/mrp_config.py b/mrp_production_real_cost/models/mrp_config.py deleted file mode 100644 index 5c3d89efe..000000000 --- a/mrp_production_real_cost/models/mrp_config.py +++ /dev/null @@ -1,43 +0,0 @@ -# -*- coding: utf-8 -*- -# (c) 2015 Ainara Galdona - AvanzOSC -# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html - -from openerp import api, fields, models - - -class MrpConfigSettings(models.TransientModel): - _inherit = 'mrp.config.settings' - - final_product_analytic_cost = fields.Boolean( - string='Load final product analytic cost', - help='This will allow you to define if those BoM passed back to draft' - ' are still activated or not') - - def _get_parameter(self, key, default=False): - param_obj = self.env['ir.config_parameter'] - rec = param_obj.search([('key', '=', key)]) - return rec or default - - def _write_or_create_param(self, key, value): - param_obj = self.env['ir.config_parameter'] - rec = self._get_parameter(key) - if rec: - if not value: - rec.unlink() - else: - rec.value = value - elif value: - param_obj.create({'key': key, 'value': value}) - - @api.multi - def get_default_parameters(self): - def get_value(key, default=''): - rec = self._get_parameter(key) - return rec and rec.value or default - return {'final_product_analytic_cost': get_value('final.product.cost', - False)} - - @api.multi - def set_parameters(self): - self._write_or_create_param('final.product.cost', - self.final_product_analytic_cost) diff --git a/mrp_production_real_cost/models/mrp_production.py b/mrp_production_real_cost/models/mrp_production.py index 7c5f13994..49b5f4e0c 100644 --- a/mrp_production_real_cost/models/mrp_production.py +++ b/mrp_production_real_cost/models/mrp_production.py @@ -1,96 +1,40 @@ -# -*- encoding: utf-8 -*- -############################################################################## -# -# 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 General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see http://www.gnu.org/licenses/. -# -############################################################################## +# -*- coding: utf-8 -*- +# © 2014-2015 Avanzosc +# © 2014-2015 Pedro M. Baeza +# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html -from openerp import models, fields, api, exceptions, _ +from openerp import api, fields, models class MrpProduction(models.Model): - _inherit = 'mrp.production' @api.multi - def calc_mrp_real_cost(self): - self.ensure_one() - return sum([-line.amount for line in - self.analytic_line_ids.filtered(lambda l: l.amount < 0)]) - - @api.one @api.depends('analytic_line_ids', 'analytic_line_ids.amount', 'product_qty') - def get_real_cost(self): - self.real_cost = self.calc_mrp_real_cost() - self.unit_real_cost = self.real_cost / self.product_qty + def _compute_real_cost(self): + for production in self: + cost_lines = production.analytic_line_ids.filtered( + lambda l: l.amount < 0) + production.real_cost = -sum(cost_lines.mapped('amount')) + production.unit_real_cost = ( + production.real_cost / production.product_qty) - @api.one - @api.depends('avg_cost', 'real_cost') - def get_percentage_difference(self): - self.percentage_difference = 0 - if self.avg_cost and self.real_cost: - self.percentage_difference = (self.real_cost * 100 / self.avg_cost) - - real_cost = fields.Float("Total Real Cost", compute="get_real_cost", - store=True) - unit_real_cost = fields.Float("Unit Real Cost", compute="get_real_cost", - store=True) - percentage_difference = fields.Float( - "% difference", compute="get_percentage_difference", store=True) + analytic_line_ids = fields.One2many( + comodel_name="account.analytic.line", inverse_name="mrp_production_id", + string="Cost Lines") + real_cost = fields.Float( + "Total Real Cost", compute="_compute_real_cost", store=True) + unit_real_cost = fields.Float( + "Unit Real Cost", compute="_compute_real_cost", store=True) @api.multi def action_production_end(self): - task_obj = self.env['project.task'] - analytic_line_obj = self.env['account.analytic.line'] res = super(MrpProduction, self).action_production_end() - for record in self: - mrp_cost = record.calc_mrp_real_cost() - done_lines = record.move_created_ids2.filtered(lambda l: - l.state == 'done') - create_cost = self.env['mrp.config.settings']._get_parameter( - 'final.product.cost') - if create_cost and create_cost.value and mrp_cost > 0.0: - journal_id = self.env.ref('mrp.analytic_journal_materials', - False) - qty = sum([l.product_qty for l in done_lines]) - name = ('Final product - ' + (record.name or '') + - '-' + (record.product_id.default_code or '')) - vals = record._prepare_real_cost_analytic_line( - journal_id, name, record, record.product_id, qty=qty, - amount=mrp_cost) - task = task_obj.search([('mrp_production_id', '=', record.id), - ('workorder', '=', False)]) - vals['task_id'] = task and task[0].id or False - analytic_line_obj.create(vals) - record.real_cost = mrp_cost - done_lines.product_price_update_production_done() - # Reload produced quants cost to consider all production costs. - # Material, machine and manual costs. - self.load_final_quant_cost() + self.mapped('move_created_ids2').filtered( + lambda l: l.state == 'done').product_price_update_production_done() return res - @api.multi - def load_final_quant_cost(self): - for production in self: - mrp_cost = production.calc_mrp_real_cost() - done_lines = production.move_created_ids2.filtered( - lambda l: l.state == 'done') - total_qty = sum([l.product_qty for l in done_lines]) - quants = done_lines.mapped('quant_ids') - quants.write({'cost': mrp_cost / total_qty}) - @api.model def _prepare_real_cost_analytic_line( self, journal, name, production, product, general_account=None, @@ -110,16 +54,11 @@ class MrpProduction(models.Model): """ analytic_line_obj = self.env['account.analytic.line'] property_obj = self.env['ir.property'] - if not general_account: - general_account = ( - product.property_account_expense or - product.categ_id.property_account_expense_categ or - property_obj.get('property_account_expense_categ', - 'product.category')) - if not production.analytic_account_id: - raise exceptions.Warning( - _('You must define one Analytic Account for this MO: %s') % - (production.name)) + general_account = ( + general_account or product.property_account_expense or + product.categ_id.property_account_expense_categ or + property_obj.get('property_account_expense_categ', + 'product.category')) return { 'name': name, 'mrp_production_id': production.id, diff --git a/mrp_production_real_cost/models/mrp_production_workcenter_line.py b/mrp_production_real_cost/models/mrp_production_workcenter_line.py index 81da71591..8a60546c8 100644 --- a/mrp_production_real_cost/models/mrp_production_workcenter_line.py +++ b/mrp_production_real_cost/models/mrp_production_workcenter_line.py @@ -1,37 +1,17 @@ -# -*- encoding: utf-8 -*- -############################################################################## -# -# 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 General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see http://www.gnu.org/licenses/. -# -############################################################################## +# -*- coding: utf-8 -*- +# © 2014-2015 Avanzosc +# © 2014-2015 Pedro M. Baeza +# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html -from openerp import models, api, fields +from openerp import api, fields, models class MrpProductionWorkcenterLine(models.Model): _inherit = 'mrp.production.workcenter.line' - @api.one - def _get_prepost_cost(self): - wc = self.workcenter_id - self.pre_cost = self.time_start * wc.pre_op_product.cost_price - self.post_cost = self.time_stop * wc.post_op_product.cost_price - - pre_cost = fields.Float('Pre-Operation Cost', default=_get_prepost_cost) - post_cost = fields.Float('Post-Operation Cost', - default=_get_prepost_cost) + pre_cost = fields.Float('Pre-Operation Cost') + post_cost = fields.Float('Post-Operation Cost') @api.multi def _create_analytic_line(self): @@ -82,14 +62,14 @@ class MrpProductionWorkcenterLine(models.Model): name = ((production.name or '') + '-' + (self.routing_wc_line.operation.code or '') + '-PRE-' + (product.default_code or '')) - price = -(self.pre_cost) + price = -self.pre_cost qty = self.time_start elif cost_type == 'post': product = workcenter.post_op_product name = ((production.name or '') + '-' + (self.routing_wc_line.operation.code or '') + '-POST-' + (product.default_code or '')) - price = -(self.post_cost) + price = -self.post_cost qty = self.time_stop if price: analytic_vals = production._prepare_real_cost_analytic_line( @@ -98,10 +78,17 @@ class MrpProductionWorkcenterLine(models.Model): qty=qty, amount=price) task = task_obj.search([('mrp_production_id', '=', production.id), ('workorder', '=', False)]) - analytic_vals['task_id'] = task and task[0].id or False + analytic_vals['task_id'] = task[:1].id analytic_vals['product_uom_id'] = hour_uom.id analytic_line_obj.create(analytic_vals) + @api.multi + def action_start_working(self): + result = super(MrpProductionWorkcenterLine, + self).action_start_working() + self._create_pre_post_cost_lines(cost_type='pre') + return result + @api.multi def action_pause(self): result = super(MrpProductionWorkcenterLine, self).action_pause() @@ -112,6 +99,5 @@ class MrpProductionWorkcenterLine(models.Model): def action_done(self): result = super(MrpProductionWorkcenterLine, self).action_done() self._create_analytic_line() - self._create_pre_post_cost_lines(cost_type='pre') self._create_pre_post_cost_lines(cost_type='post') return result diff --git a/mrp_production_real_cost/models/stock_move.py b/mrp_production_real_cost/models/stock_move.py index de519174a..67259cbd2 100644 --- a/mrp_production_real_cost/models/stock_move.py +++ b/mrp_production_real_cost/models/stock_move.py @@ -1,26 +1,12 @@ -# -*- encoding: utf-8 -*- -############################################################################## -# -# 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 General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see http://www.gnu.org/licenses/. -# -############################################################################## +# -*- coding: utf-8 -*- +# © 2014-2015 Avanzosc +# © 2014-2015 Pedro M. Baeza +# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html -from openerp import models, api +from openerp import api, models class StockMove(models.Model): - _inherit = 'stock.move' @api.multi @@ -28,10 +14,9 @@ class StockMove(models.Model): task_obj = self.env['project.task'] analytic_line_obj = self.env['account.analytic.line'] result = super(StockMove, self).action_done() - for record in self: - if (not record.raw_material_production_id or not - record.product_id.cost_price): - continue + records = self.filtered(lambda x: (x.raw_material_production_id and + x.product_id.standard_price)) + for record in records: journal_id = self.env.ref('mrp.analytic_journal_materials', False) production = record.raw_material_production_id name = ((production.name or '') + '-' + @@ -40,7 +25,8 @@ class StockMove(models.Model): analytic_vals = (production._prepare_real_cost_analytic_line( journal_id, name, production, record.product_id, workorder=record.work_order, qty=record.product_qty, - amount=(-record.product_id.cost_price * record.product_qty))) + amount=(-record.product_id.standard_price * + record.product_qty))) task = task_obj.search([('mrp_production_id', '=', production.id), ('workorder', '=', False)]) analytic_vals['task_id'] = task and task[0].id or False @@ -49,33 +35,32 @@ class StockMove(models.Model): @api.multi def product_price_update_production_done(self): - for move in self: - if (not move.production_id or move.product_id.cost_method != - 'average'): - continue - prod_total_cost = move.production_id.calc_mrp_real_cost() + records = self.filtered( + lambda x: (x.production_id and + x.product_id.cost_method == 'average')) + for move in records: + prod_total_cost = move.production_id.real_cost product = move.product_id product_avail = product.qty_available - amount_unit = product.cost_price - template_avail = product.product_tmpl_id.qty_available - template_price = product.standard_price + amount_unit = product.standard_price + tmpl_available = product.product_tmpl_id.qty_available + tmpl_price = product.product_tmpl_id.standard_price if move.state == 'done': product_avail -= move.product_qty - template_avail -= move.product_qty - new_cost_price = ( + tmpl_available -= move.product_qty + new_product_price = ( (amount_unit * product_avail + prod_total_cost) / ((product_avail >= 0.0 and product_avail or 0.0) + move.product_qty)) - new_std_price = ((template_price * template_avail + - prod_total_cost) / - ((template_avail >= 0.0 and template_avail or - 0.0) + move.product_qty)) - product.sudo().write({'cost_price': new_cost_price, - 'standard_price': new_std_price}) + new_tmpl_price = ((tmpl_price * tmpl_available + prod_total_cost) / + ((tmpl_available > 0.0 and tmpl_available or + 0.0) + move.product_qty)) + product.sudo().standard_price = new_product_price + product.sudo().product_tmpl_id.standard_price = new_tmpl_price @api.model def get_price_unit(self, move): if move.production_id: - return move.production_id.calc_mrp_real_cost() / move.product_qty + return move.production_id.real_cost / move.product_qty else: return super(StockMove, self).get_price_unit(move) diff --git a/mrp_production_real_cost/static/description/icon.png b/mrp_production_real_cost/static/description/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..7c1450374c3c285ac84473df033b8d901baff85e GIT binary patch literal 10215 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 Zn5-T@dpQo71Ru%+G*op|DwVCn{|hG{U>*Pf literal 0 HcmV?d00001 diff --git a/mrp_production_real_cost/static/description/icon.svg b/mrp_production_real_cost/static/description/icon.svg new file mode 100644 index 000000000..7e3b32308 --- /dev/null +++ b/mrp_production_real_cost/static/description/icon.svg @@ -0,0 +1,297 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/mrp_production_real_cost/tests/__init__.py b/mrp_production_real_cost/tests/__init__.py new file mode 100644 index 000000000..63eef852e --- /dev/null +++ b/mrp_production_real_cost/tests/__init__.py @@ -0,0 +1,6 @@ +# -*- coding: utf-8 -*- +# © 2015 Pedro M. Baeza +# © 2015 Antiun Ingeniería +# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html + +from . import test_mrp_production_real_cost diff --git a/mrp_production_real_cost/tests/test_mrp_production_real_cost.py b/mrp_production_real_cost/tests/test_mrp_production_real_cost.py new file mode 100644 index 000000000..2b0bea051 --- /dev/null +++ b/mrp_production_real_cost/tests/test_mrp_production_real_cost.py @@ -0,0 +1,43 @@ +# -*- coding: utf-8 -*- +# © 2015 Pedro M. Baeza +# © 2015 Antiun Ingeniería +# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html + +from openerp.tests import common +import time + + +class TestMrpProductionRealCost(common.TransactionCase): + def setUp(self): + super(TestMrpProductionRealCost, self).setUp() + self.production = self.env.ref( + 'mrp_operations_extension.mrp_production_opeext') + self.production.signal_workflow('button_confirm') + self.production.force_production() + + def test_flow(self): + line = self.production.workcenter_lines[1] + line.pre_cost = 10 + line.post_cost = 20 + line.signal_workflow('button_start_working') + self.assertEqual(len(self.production.analytic_line_ids), 1) + time.sleep(1) + line.signal_workflow('button_pause') + self.assertEqual(len(self.production.analytic_line_ids), 2) + line.signal_workflow('button_resume') + time.sleep(1) + line.signal_workflow('button_done') + self.assertEqual(len(self.production.analytic_line_ids), 4) + self.production.analytic_line_ids[:1].amount = -10 + self.assertTrue(self.production.real_cost) + + def test_produce(self): + # Set an impossible price to see if it changes + initial_price = 999999999 + self.production.product_id.standard_price = initial_price + self.production.product_id.cost_method = 'average' + self.production.action_produce( + self.production.id, self.production.product_qty, 'consume_produce') + self.assertEqual(len(self.production.analytic_line_ids), 4) + self.assertNotEqual( + initial_price, self.production.product_id.standard_price) diff --git a/mrp_production_real_cost/views/mrp_production_view.xml b/mrp_production_real_cost/views/mrp_production_view.xml index f6c9397a1..94be0262f 100644 --- a/mrp_production_real_cost/views/mrp_production_view.xml +++ b/mrp_production_real_cost/views/mrp_production_view.xml @@ -42,7 +42,6 @@ - diff --git a/mrp_production_real_cost/views/res_config_view.xml b/mrp_production_real_cost/views/res_config_view.xml deleted file mode 100644 index f3e3f75fc..000000000 --- a/mrp_production_real_cost/views/res_config_view.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - mrp.config.settings.costs - mrp.config.settings - - - -
- -
-
-
-
-
-
diff --git a/mrp_production_real_cost/wizard/__init__.py b/mrp_production_real_cost/wizard/__init__.py deleted file mode 100644 index 92d4c4468..000000000 --- a/mrp_production_real_cost/wizard/__init__.py +++ /dev/null @@ -1,6 +0,0 @@ -# -*- coding: utf-8 -*- -############################################################################## -# For copyright and license notices, see __openerp__.py file in root directory -############################################################################## - -from . import mrp_product_produce diff --git a/mrp_production_real_cost/wizard/mrp_product_produce.py b/mrp_production_real_cost/wizard/mrp_product_produce.py deleted file mode 100644 index ad2ebddba..000000000 --- a/mrp_production_real_cost/wizard/mrp_product_produce.py +++ /dev/null @@ -1,20 +0,0 @@ -# -*- coding: utf-8 -*- -############################################################################## -# For copyright and license notices, see __openerp__.py file in root directory -############################################################################## -from openerp import models, api - - -class MrpProductProduce(models.TransientModel): - - _inherit = 'mrp.product.produce' - - # Reload produced quants cost every consume or produce action in a MO. - @api.multi - def do_produce(self): - res = super(MrpProductProduce, self).do_produce() - production_obj = self.env['mrp.production'] - production_id = self.env.context.get('active_id', False) - production = production_obj.browse(production_id) - production.load_final_quant_cost() - return res diff --git a/mrp_project/tests/test_mrp_project.py b/mrp_project/tests/test_mrp_project.py index cbc070785..431716bf1 100644 --- a/mrp_project/tests/test_mrp_project.py +++ b/mrp_project/tests/test_mrp_project.py @@ -71,6 +71,9 @@ class TestMrpProject(common.TransactionCase): def test_button_end_work(self): work = self.env['project.task.work'].create( {'task_id': self.task.id, + 'name': 'Test', + 'user_id': self.env.uid, + 'hours': 0, 'date': fields.Datetime.now()}) time.sleep(1) work.button_end_work() diff --git a/oca_dependencies.txt b/oca_dependencies.txt index 8e9d3e0ce..3ca90d77a 100644 --- a/oca_dependencies.txt +++ b/oca_dependencies.txt @@ -2,3 +2,5 @@ # Add a repository url and branch if you need a forked version product-attribute account-analytic +product-variant +