From 23e516310063a1a5d0b355d6975e185a80e24092 Mon Sep 17 00:00:00 2001 From: agaldona Date: Wed, 30 Sep 2015 14:42:07 +0200 Subject: [PATCH] [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 + + + +