[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
This commit is contained in:
agaldona
2015-10-09 11:39:43 +02:00
committed by Pedro M. Baeza
parent a80e867abd
commit 034eeac761
9 changed files with 160 additions and 74 deletions

View File

@@ -17,3 +17,4 @@
##############################################################################
from . import models
from . import wizard

View File

@@ -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,

View File

@@ -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

View File

@@ -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)

View File

@@ -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,

View File

@@ -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):

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<openerp>
<data>
<record model="ir.ui.view" id="mrp_config_settings_costs">
<field name="name">mrp.config.settings.costs</field>
<field name="model">mrp.config.settings</field>
<field name="inherit_id" ref="mrp.view_mrp_config" />
<field name="arch" type="xml">
<xpath expr="//field[@name='module_mrp_repair']/.." position="after">
<div>
<field name="final_product_analytic_cost" class="oe_inline"/>
<label for="final_product_analytic_cost"/>
</div>
</xpath>
</field>
</record>
</data>
</openerp>

View File

@@ -0,0 +1,6 @@
# -*- coding: utf-8 -*-
##############################################################################
# For copyright and license notices, see __openerp__.py file in root directory
##############################################################################
from . import mrp_product_produce

View File

@@ -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