mirror of
https://github.com/OCA/manufacture.git
synced 2025-01-28 16:37:15 +02:00
[ADD] product_variant_cost: Module for cost at variant level
This commit is contained in:
committed by
Oihane Crucelaegui
parent
31589bb887
commit
03cd3f8895
@@ -36,6 +36,7 @@
|
||||
"mrp",
|
||||
"mrp_operations_extension",
|
||||
"mrp_project_link",
|
||||
"product_variant_cost"
|
||||
],
|
||||
"data": [
|
||||
"data/analytic_journal_data.xml",
|
||||
|
||||
@@ -24,7 +24,7 @@ class MrpBom(models.Model):
|
||||
_inherit = "mrp.bom"
|
||||
|
||||
product_standard_price = fields.Float(string="Product Standard Price",
|
||||
related="product_id.standard_price")
|
||||
related="product_id.cost_price")
|
||||
product_manual_standard_price = fields.Float(
|
||||
string="Product Manual Standard Price",
|
||||
related="product_id.manual_standard_cost")
|
||||
|
||||
@@ -63,7 +63,7 @@ class MrpProduction(models.Model):
|
||||
string="Product Manual Cost",
|
||||
related="product_id.manual_standard_cost")
|
||||
product_cost = fields.Float(
|
||||
string="Product Cost", related="product_id.standard_price")
|
||||
string="Product Cost", related="product_id.cost_price")
|
||||
analytic_line_ids = fields.One2many(
|
||||
comodel_name="account.analytic.line", inverse_name="mrp_production_id",
|
||||
string="Cost Lines")
|
||||
@@ -148,6 +148,39 @@ class MrpProduction(models.Model):
|
||||
'context': self.env.context
|
||||
}
|
||||
|
||||
def _prepare_cost_analytic_line(self, journal, name, production, product,
|
||||
general_account=None, workorder=None,
|
||||
qty=1, amount=0, estim_std=0, estim_avg=0):
|
||||
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 self.analytic_account_id:
|
||||
raise exceptions.Warning(
|
||||
_('You must define one Analytic Account for this MO: %s') %
|
||||
(production.name))
|
||||
vals = {
|
||||
'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 and product.uom_id.id or False,
|
||||
'general_account_id': general_account.id,
|
||||
'estim_std_cost': estim_std,
|
||||
'estim_avg_cost': estim_avg,
|
||||
}
|
||||
return vals
|
||||
|
||||
@api.multi
|
||||
def calculate_production_estimated_cost(self):
|
||||
analytic_line_obj = self.env['account.analytic.line']
|
||||
@@ -161,9 +194,12 @@ class MrpProduction(models.Model):
|
||||
raise exceptions.Warning(
|
||||
_("One consume line has no product assigned."))
|
||||
name = _('%s-%s' % (record.name, line.work_order.name or ''))
|
||||
vals = record._prepare_estim_cost_analytic_line(
|
||||
journal, name, record, line.work_order, line.product_id,
|
||||
line.product_qty)
|
||||
product = line.product_id
|
||||
qty = line.product_qty
|
||||
vals = record._prepare_cost_analytic_line(
|
||||
journal, name, record, product, workorder=line.work_order,
|
||||
qty=qty, estim_std=-(qty * product.manual_standard_cost),
|
||||
estim_avg=-(qty * product.cost_price))
|
||||
analytic_line_obj.create(vals)
|
||||
journal = record.env.ref('mrp_production_project_estimated_cost.'
|
||||
'analytic_journal_machines', False)
|
||||
@@ -175,20 +211,26 @@ class MrpProduction(models.Model):
|
||||
if (wc.time_start and line.workcenter_id.pre_op_product):
|
||||
name = (_('%s-%s Pre-operation') %
|
||||
(record.name, line.workcenter_id.name))
|
||||
vals = record._prepare_estim_cost_analytic_line(
|
||||
journal, name, record, line,
|
||||
line.workcenter_id.pre_op_product, wc.time_start)
|
||||
amount = line.workcenter_id.pre_op_product.standard_price
|
||||
vals['amount'] = amount
|
||||
product = line.workcenter_id.pre_op_product
|
||||
amount = product.cost_price * wc.time_start
|
||||
qty = wc.time_start
|
||||
vals = record._prepare_cost_analytic_line(
|
||||
journal, name, record, product, workorder=line,
|
||||
qty=qty, amount=-amount,
|
||||
estim_std=-(qty * product.manual_standard_cost),
|
||||
estim_avg=-(amount))
|
||||
analytic_line_obj.create(vals)
|
||||
if (wc.time_stop and line.workcenter_id.post_op_product):
|
||||
name = (_('%s-%s Post-operation') %
|
||||
(record.name, line.workcenter_id.name))
|
||||
vals = record._prepare_estim_cost_analytic_line(
|
||||
journal, name, record, line,
|
||||
line.workcenter_id.post_op_product, wc.time_stop)
|
||||
amount = line.workcenter_id.post_op_product.standard_price
|
||||
vals['amount'] = amount
|
||||
product = line.workcenter_id.post_op_product
|
||||
amount = product.cost_price * wc.time_stop
|
||||
qty = wc.time_stop
|
||||
vals = record._prepare_cost_analytic_line(
|
||||
journal, name, record, product, workorder=line,
|
||||
qty=qty, amount=-amount,
|
||||
estim_std=-(qty * product.manual_standard_cost),
|
||||
estim_avg=-(amount))
|
||||
analytic_line_obj.create(vals)
|
||||
if line.cycle and line.workcenter_id.costs_cycle:
|
||||
if not line.workcenter_id.product_id:
|
||||
@@ -198,12 +240,12 @@ class MrpProduction(models.Model):
|
||||
name = (_('%s-%s-C-%s') %
|
||||
(record.name, line.routing_wc_line.operation.code,
|
||||
line.workcenter_id.name))
|
||||
vals = record._prepare_estim_cost_analytic_line(
|
||||
journal, name, record, line,
|
||||
line.workcenter_id.product_id, line.cycle)
|
||||
cost = line.workcenter_id.costs_cycle
|
||||
vals['estim_avg_cost'] = line.cycle * cost
|
||||
vals['estim_std_cost'] = vals['estim_avg_cost']
|
||||
product = line.workcenter_id.product_id
|
||||
estim_cost = -(line.workcenter_id.costs_cycle * line.cycle)
|
||||
vals = record._prepare_cost_analytic_line(
|
||||
journal, name, record, product, workorder=line,
|
||||
qty=line.cycle, estim_std=estim_cost,
|
||||
estim_avg=estim_cost)
|
||||
analytic_line_obj.create(vals)
|
||||
if line.hour and line.workcenter_id.costs_hour:
|
||||
if not line.workcenter_id.product_id:
|
||||
@@ -218,67 +260,38 @@ class MrpProduction(models.Model):
|
||||
hour += wc.time_stop
|
||||
if wc.time_start and not line.workcenter_id.pre_op_product:
|
||||
hour += wc.time_start
|
||||
vals = record._prepare_estim_cost_analytic_line(
|
||||
journal, name, record, line,
|
||||
line.workcenter_id.product_id, hour)
|
||||
cost = line.workcenter_id.costs_hour
|
||||
vals['estim_avg_cost'] = hour * cost
|
||||
vals['estim_std_cost'] = vals['estim_avg_cost']
|
||||
estim_cost = -(hour * line.workcenter_id.costs_hour)
|
||||
vals = record._prepare_cost_analytic_line(
|
||||
journal, name, record, line.workcenter_id.product_id,
|
||||
workorder=line, qty=hour,
|
||||
estim_std=estim_cost, estim_avg=estim_cost)
|
||||
analytic_line_obj.create(vals)
|
||||
if wc.op_number > 0 and line.hour:
|
||||
if not line.workcenter_id.product_id:
|
||||
raise exceptions.Warning(
|
||||
_("There is at least this workcenter without "
|
||||
"product: %s") % line.workcenter_id.name)
|
||||
journal_wk = record.env.ref(
|
||||
journal = record.env.ref(
|
||||
'mrp_production_project_estimated_cost.analytic_'
|
||||
'journal_operators', False)
|
||||
name = (_('%s-%s-%s') %
|
||||
(record.name, line.routing_wc_line.operation.code,
|
||||
line.workcenter_id.product_id.name))
|
||||
vals = record._prepare_estim_cost_analytic_line(
|
||||
journal_wk, name, record, line,
|
||||
line.workcenter_id.product_id,
|
||||
line.hour * wc.op_number)
|
||||
vals['estim_avg_cost'] = (wc.op_number * wc.op_avg_cost *
|
||||
line.hour)
|
||||
vals['estim_std_cost'] = vals['estim_avg_cost']
|
||||
estim_cost = -(wc.op_number * wc.op_avg_cost * line.hour)
|
||||
qty = line.hour * wc.op_number
|
||||
vals = record._prepare_cost_analytic_line(
|
||||
journal, name, record, line.workcenter_id.product_id,
|
||||
workorder=line, qty=qty, estim_std=estim_cost,
|
||||
estim_avg=estim_cost)
|
||||
analytic_line_obj.create(vals)
|
||||
|
||||
def _prepare_estim_cost_analytic_line(self, journal, name, production,
|
||||
workorder, product, qty):
|
||||
analytic_line_obj = self.env['account.analytic.line']
|
||||
general_account = (product.property_account_income or
|
||||
product.categ_id.property_account_income_categ or
|
||||
False)
|
||||
if not general_account:
|
||||
raise exceptions.Warning(
|
||||
_('You must define Income account in the product "%s", or in'
|
||||
' the product category') % (product.name))
|
||||
if not self.analytic_account_id:
|
||||
raise exceptions.Warning(
|
||||
_('You must define one Analytic Account for this MO: %s') %
|
||||
(production.name))
|
||||
vals = {
|
||||
'name': name,
|
||||
'mrp_production_id': production.id,
|
||||
'workorder': workorder.id,
|
||||
'account_id': self.analytic_account_id.id,
|
||||
'journal_id': journal.id,
|
||||
'user_id': self._uid,
|
||||
'date': analytic_line_obj._get_default_date(),
|
||||
'product_id': product.id,
|
||||
'unit_amount': qty,
|
||||
'product_uom_id': product.uom_id.id,
|
||||
'general_account_id': general_account.id,
|
||||
'estim_std_cost': qty * product.manual_standard_cost,
|
||||
'estim_avg_cost': qty * product.standard_price,
|
||||
}
|
||||
return vals
|
||||
|
||||
@api.multi
|
||||
def load_product_std_price(self):
|
||||
for record in self:
|
||||
product = record.product_id
|
||||
if record.unit_std_cost:
|
||||
product.manual_standard_cost = record.unit_std_cost
|
||||
|
||||
@api.multi
|
||||
def _get_min_qty_for_production(self, routing=False):
|
||||
return 1
|
||||
|
||||
@@ -20,6 +20,9 @@
|
||||
<field name="model">account.analytic.line</field>
|
||||
<field name="inherit_id" ref="account.view_account_analytic_line_tree"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="journal_id" position="before">
|
||||
<field name="product_id"/>
|
||||
</field>
|
||||
<field name="journal_id" position="after">
|
||||
<field name="estim_std_cost" />
|
||||
<field name="estim_avg_cost" />
|
||||
@@ -36,6 +39,7 @@
|
||||
<field name="date"/>
|
||||
<field name="ref"/>
|
||||
<field name="name"/>
|
||||
<field name="product_id"/>
|
||||
<field name="journal_id"/>
|
||||
<field name="estim_avg_cost"/>
|
||||
<field name="estim_std_cost"/>
|
||||
@@ -49,5 +53,19 @@
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="action_show_production_anaytic_lines" model="ir.actions.act_window">
|
||||
<field name="name">Production Analytic Lines</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">account.analytic.line</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="view_id" eval="estimated_cost_list_view"/>
|
||||
<field name="context">{'default_mrp_production_id': active_id,
|
||||
'search_default_group_production': 1,
|
||||
'search_default_group_workorder': 1,
|
||||
'search_default_group_journal': 1}</field>
|
||||
<field name="domain">[('mrp_production_id','=',active_id)]</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
|
||||
@@ -83,10 +83,16 @@
|
||||
<div name="buttons" position="inside">
|
||||
<button class="oe_inline oe_stat_button"
|
||||
type="object"
|
||||
string="Estim. Costs"
|
||||
string="Costs analysis"
|
||||
name="action_show_estimated_costs"
|
||||
icon="fa-bar-chart">
|
||||
</button>
|
||||
<button class="oe_inline oe_stat_button"
|
||||
type="action"
|
||||
string="Production Costs"
|
||||
name="%(action_show_production_anaytic_lines)d"
|
||||
icon="fa-list">
|
||||
</button>
|
||||
</div>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
@@ -9,7 +9,7 @@ class WizCreateFictitiousOf(models.TransientModel):
|
||||
_name = "wiz.create.fictitious.of"
|
||||
|
||||
date_planned = fields.Datetime(
|
||||
string='Scheduled Date', required=True, default=fields.Datetime.now())
|
||||
string='Scheduled Date', required=True, default=fields.Datetime.now)
|
||||
load_on_product = fields.Boolean("Load cost on product")
|
||||
project_id = fields.Many2one("project.project", string="Project")
|
||||
|
||||
@@ -17,6 +17,7 @@ class WizCreateFictitiousOf(models.TransientModel):
|
||||
def do_create_fictitious_of(self):
|
||||
production_obj = self.env['mrp.production']
|
||||
product_obj = self.env['product.product']
|
||||
routing_obj = self.env['mrp.routing']
|
||||
self.ensure_one()
|
||||
active_ids = self.env.context['active_ids']
|
||||
active_model = self.env.context['active_model']
|
||||
@@ -34,8 +35,21 @@ class WizCreateFictitiousOf(models.TransientModel):
|
||||
'user_id': self._uid,
|
||||
'active': False,
|
||||
'product_uom': product.uom_id.id,
|
||||
'project_id': self.project_id.id
|
||||
'project_id': self.project_id.id,
|
||||
'analytic_account_id': (
|
||||
self.project_id.analytic_account_id.id)
|
||||
}
|
||||
prod_vals = production_obj.product_id_change(product.id,
|
||||
1)['value']
|
||||
vals.update(prod_vals)
|
||||
if 'routing_id' in vals:
|
||||
routing = routing_obj.browse(vals['routing_id'])
|
||||
product_qty = production_obj._get_min_qty_for_production(
|
||||
routing)
|
||||
vals['product_qty'] = product_qty
|
||||
prod_vals = production_obj.product_id_change(
|
||||
product.id, product_qty)['value']
|
||||
vals.update(prod_vals)
|
||||
new_production = production_obj.create(vals)
|
||||
new_production.action_compute()
|
||||
production_list.append(new_production.id)
|
||||
|
||||
Reference in New Issue
Block a user