Skip to content

Commit

Permalink
[IMP] product_cost_incl_bom, product_get_cost_field, sale_markup: ext…
Browse files Browse the repository at this point in the history
…racted code to new modules

          
          extracted the bits about the computation of product cost with BoM from sale_markup to product_cost_incl_bom
(lp:c2c-addons/6.1  rev 40.1.13)
  • Loading branch information
gurneyalex committed May 15, 2012
1 parent fcec4e9 commit a08e3b5
Show file tree
Hide file tree
Showing 23 changed files with 75 additions and 1,263 deletions.
7 changes: 2 additions & 5 deletions product_cost_incl_bom/__openerp__.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,11 @@
'version' : '0.1',
'author' : 'Camptocamp',
'maintainer': 'Camptocamp',
'category': 'Products',
'category': 'Hidden',
'complexity': "normal", # easy, normal, expert
'depends' : ['product_get_cost_field',
'mrp'],
'description': """
Compute product cost price by recursively summing parts cost prices according to product BOM. It takes into
account the BoM costing (cost per cycle and so...). If no BOM define for a product, the cost_price is always
equal to the standard_price field of the product, so we always have a value to base our reporting on.
'description': """Compute product base price by recursively summing parts base prices according to product BOM
""",
'website': 'http://www.camptocamp.com/',
'init_xml': [],
Expand Down
91 changes: 51 additions & 40 deletions product_cost_incl_bom/product_cost_incl_bom.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,25 @@
class Product(Model):
_inherit = 'product.product'

## def get_cost_field(self):
## """overriden from product_get_cost_field"""
## return self.standard_price # XXX or a string?



def _compute_purchase_price(self, cursor, user, ids,
pricelist=None,
product_uom=None,
bom_properties=None,
context=None):
bom_properties=None):
'''
Compute the purchase price, taking into account sub products and routing
Compute the purchase price
As it explodes the sub product on 1 level
This is not implemented for BoM having sub BoM producing more than 1
product qty.
Rewrite _compute_purchase_price and remove mrp constraint to fix this.
'''
if context is None:
context = {}
if bom_properties is None:
bom_properties = []
bom_obj = self.pool.get('mrp.bom')
Expand All @@ -48,51 +58,52 @@ def _compute_purchase_price(self, cursor, user, ids,
# Workaround for first loading in V5 as some columns are not created
#if not hasattr(pr, 'standard_price'): return False
bom_id = bom_obj._bom_find(cursor, user, pr.id, product_uom=None, properties=bom_properties)
if not bom_id: # no BoM: use standard_price

if bom_id:
bom = bom_obj.browse(cursor, user, bom_id)

sub_products, routes = bom_obj._bom_explode(cursor, user, bom,
factor=1,
properties=bom_properties,
addthis=True)

res[pr.id] = 0.0
for sub_prod_dict in sub_products:
sub_product = self.browse(cursor, user, sub_product_dict['product_id'])
std_price = sub_product.standard_price
qty = uom_obj._compute_qty(cursor, user,
from_uom_id = sub_product_dict['product_uom'],
qty = sub_product_dict['product_qty'],
to_uom_id = sub_product.uom_po_id.id)

res[pr.id] += std_price * qty
# TODO alf use routes to compute cost of manufacturing (following is from product_extended)
## if bom.routing_id:
## for wline in bom.routing_id.workcenter_lines:
## wc = wline.workcenter_id
## cycle = wline.cycle_nbr
## hour = (wc.time_start + wc.time_stop + cycle * wc.time_cycle) * (wc.time_efficiency or 1.0)
## price += wc.costs_cycle * cycle + wc.costs_hour * hour
## price = self.pool.get('product.uom')._compute_price(cr,uid,bom.product_uom.id,price,bom.product_id.uom_id.id)

else:
res[pr.id] = pr.standard_price
continue
bom = bom_obj.browse(cursor, user, bom_id)
sub_products, routes = bom_obj._bom_explode(cursor, user, bom,
factor=1,
properties=bom_properties,
addthis=True)
price = 0.
for sub_product_dict in sub_products:
sub_product = self.browse(cursor, user, sub_product_dict['product_id'])
std_price = sub_product.standard_price
qty = uom_obj._compute_qty(cursor, user,
from_uom_id = sub_product_dict['product_uom'],
qty = sub_product_dict['product_qty'],
to_uom_id = sub_product.uom_po_id.id)
price += std_price * qty
if bom.routing_id:
for wline in bom.routing_id.workcenter_lines:
wc = wline.workcenter_id
cycle = wline.cycle_nbr
hour = (wc.time_start + wc.time_stop + cycle * wc.time_cycle) * (wc.time_efficiency or 1.0)
price += wc.costs_cycle * cycle + wc.costs_hour * hour
price /= bom.product_qty
price = uom_obj._compute_price(cursor, user, bom.product_uom.id, price, bom.product_id.uom_id.id)
res[pr.id] = price

return res

def get_cost_field(self, cr, uid, ids, context=None):
return self._cost_price(cr, uid, ids, '', [], context)

def _cost_price(self, cr, uid, ids, field_name, arg, context=None):
def _cost_price(self, cr, uid, ids, context=None):
if context is None:
context = {}
pricelist = context.get('pricelist')
product_uom = context.get('product_uom')
bom_properties = context.get('properties')
res = self._compute_purchase_price(cr, uid, ids, product_uom, bom_properties)
return res

return _compute_purchase_price(cr, uid, ids, pricelist, product_uom, bom_properties)

_columns = {
'cost_price': fields.function(_cost_price,
method=True,
methode=True,
string='Cost Price (incl. BoM)',
digits_compute = dp.get_precision('Sale Price'),
help="The cost price is the standard price or, if the product has a bom, "
"the sum of all standard price of its components. it take also care of the "
"bom costing like cost per cylce.")
help="The cost is the standard price")
}
2 changes: 1 addition & 1 deletion product_get_cost_field/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Author: Alexandre Fayolle, Joel Grand-Guillaume
# Author: Alexandre Fayolle
# Copyright 2012 Camptocamp SA
#
# This program is free software: you can redistribute it and/or modify
Expand Down
18 changes: 6 additions & 12 deletions product_get_cost_field/__openerp__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Author: Alexandre Fayolle, Joel Grand-Guillaume
# Author: Alexandre Fayolle
# Copyright 2012 Camptocamp SA
#
# This program is free software: you can redistribute it and/or modify
Expand All @@ -22,23 +22,17 @@
'version' : '0.1',
'author' : 'Camptocamp',
'maintainer': 'Camptocamp',
'category': 'Products',
'category': 'Hidden',
'complexity': "normal", # easy, normal, expert
'depends' : ['product',
],
'description': """
Provides an overridable method on product which compute the cost_price field of a product.
By default it just return the value of standard_price field, but using the product_cost_incl_bom
module, it will return the costing from the bom.
As it is a generic module, you can also setup your own way of computing the cost_price for your
product.
All our modules to compute margin are based on it, so you'll ba able to use them in your own way.
'description': """Provides an overridable method on product which returns the name of
the field used to compute the product cost, allowing for customization
of product cost computation.
""",
'website': 'http://www.camptocamp.com/',
'init_xml': [],
'update_xml': ['product_view.xml'],
'update_xml': [],
'demo_xml': [],
'tests': [],
'installable': True,
Expand Down
21 changes: 9 additions & 12 deletions product_get_cost_field/product_get_cost_field.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,33 +18,30 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
import logging

from openerp.osv.orm import Model
from openerp.osv import fields
import decimal_precision as dp


class Product(Model):
_inherit = 'product.product'

def _cost_price(self, cr, uid, ids, field_name, arg, context=None):
if context is None:
context = {}
logger = logging.getLogger('product.get_cost_field')
logger.debug("get cost field _cost_price %s, %s, %s", field_name, arg, context)
## def get_cost_field(self):
## """override in subclass if you need to setup a custom way of computing the standard price"""
## " XXX fonction statique qui renvoie le prix standard en fonction d'une liste d'id de product"
## return self.standard_price # XXX or a string?


def _cost_price(self, cr, uid, ids, context=None):
res = {}
for product in self.browse(cr, uid, ids):
res[product.id] = product.standard_price
return res

def get_cost_field(self, cr, uid, ids, context=None):
return self._cost_price(cr, uid, ids, '', [], context)

_columns = {
'cost_price': fields.function(_cost_price,
method=True,
methode=True,
string='Cost Price',
digits_compute = dp.get_precision('Sale Price'),
help="The cost price is the standard price unless you install the product_cost_incl_bom module.")
help="The cost is the standard price")
}
10 changes: 6 additions & 4 deletions product_get_cost_field/product_view.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,21 @@
<field name="inherit_id" ref="product.product_normal_form_view" />
<field name="arch" type="xml">
<field name="list_price" position="after">
<field name="cost_price"/> <!-- FIXME groups setting! -->
<field name="cost_price"
groups="sale.group_sale_manager"/>
</field>
</field>
</record>

<record model="ir.ui.view" id="product_get_cost_field_tree">
<field name="name">product.get_cost_field.view.tree</field>
<field name="type">tree</field>
<field name="model">product.product</field>
<field name="inherit_id" ref="product.product_product_tree_view" />
<field name="arch" type="xml">
<field name="standard_price" position="replace">
<field name="cost_price"/><!-- FIXME groups setting! -->
<field name="standard_price" position="after">
<field name="cost_price"
groups="sale.group_sale_manager"/>
</field>
</field>
</record>
Expand Down
24 changes: 0 additions & 24 deletions product_historical_margin/__init__.py

This file was deleted.

65 changes: 0 additions & 65 deletions product_historical_margin/__openerp__.py

This file was deleted.

Loading

0 comments on commit a08e3b5

Please sign in to comment.