[IMP] Compute price wizard with options
bzr revid: jco@openerp.com-20130606144835-8qdjlj1t0rmf5v1l
This commit is contained in:
parent
fbaa0995f2
commit
54d89d7266
|
@ -33,7 +33,7 @@ Product extension. This module adds:
|
||||||
""",
|
""",
|
||||||
"init_xml" : [],
|
"init_xml" : [],
|
||||||
"demo_xml" : [],
|
"demo_xml" : [],
|
||||||
"update_xml" : ["product_extended_view.xml","product_extended_wizard.xml","mrp_view.xml"],
|
"update_xml" : ["product_extended_wizard.xml","product_extended_view.xml","mrp_view.xml"],
|
||||||
"active": False,
|
"active": False,
|
||||||
"installable": True
|
"installable": True
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,66 +28,74 @@ from openerp.osv import osv
|
||||||
class product_product(osv.osv):
|
class product_product(osv.osv):
|
||||||
_name = 'product.product'
|
_name = 'product.product'
|
||||||
_inherit = 'product.product'
|
_inherit = 'product.product'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
_columns = {
|
def compute_price(self, cr, uid, ids, recursive=False, test=False, real_time_accounting = False, context=None):
|
||||||
'calculate_price': fields.boolean('Compute standard price', help="Check this box if the standard price must be computed from the BoM."),
|
'''
|
||||||
}
|
Will return test dict when the test = False
|
||||||
|
Multiple ids at once?
|
||||||
_defaults = {
|
testdict is used to inform the user about the changes to be made
|
||||||
'calculate_price': lambda w,x,y,z: False,
|
'''
|
||||||
}
|
testdict = {}
|
||||||
|
|
||||||
def compute_price(self, cr, uid, ids, *args):
|
|
||||||
proxy = self.pool.get('mrp.bom')
|
|
||||||
for prod_id in ids:
|
for prod_id in ids:
|
||||||
bom_ids = proxy.search(cr, uid, [('product_id', '=', prod_id)])
|
bom_obj = self.pool.get('mrp.bom')
|
||||||
|
bom_ids = bom_obj.search(cr, uid, [('bom_id', '=', False), ('product_id','=', prod_id), ('bom_lines', '!=', False)], context=context)
|
||||||
if bom_ids:
|
if bom_ids:
|
||||||
for bom in proxy.browse(cr, uid, bom_ids):
|
bom_id = bom_ids[0]
|
||||||
self._calc_price(cr, uid, bom)
|
# In recursive mode, it will first compute the prices of child boms
|
||||||
return True
|
if recursive:
|
||||||
|
#Search the products that are components of this bom of prod_id
|
||||||
def _calc_price(self, cr, uid, bom):
|
boms = bom_obj.search(cr, uid, [('bom_id', '=', bom_id)], context=context)
|
||||||
if not bom.product_id.calculate_price:
|
#Call compute_price on these subproducts
|
||||||
return bom.product_id.standard_price
|
prod_set = set([x.product_id.id for x in bom_obj.browse(cr, uid, boms, context=context)])
|
||||||
|
res = self.compute_price(cr, uid, list(prod_set), recursive=recursive, test=test, real_time_accounting = real_time_accounting, context=context)
|
||||||
|
if test:
|
||||||
|
testdict.update(res)
|
||||||
|
#Use calc price to calculate and put the price on the product of the BoM if necessary
|
||||||
|
price = self._calc_price(cr, uid, bom_obj.browse(cr, uid, bom_id, context=context), test=test, real_time_accounting = real_time_accounting, context=context)
|
||||||
|
if test:
|
||||||
|
testdict.update({prod_id : price})
|
||||||
|
if test:
|
||||||
|
print testdict
|
||||||
|
return testdict
|
||||||
else:
|
else:
|
||||||
price = 0
|
return True
|
||||||
if bom.bom_lines:
|
|
||||||
for sbom in bom.bom_lines:
|
|
||||||
my_qty = sbom.bom_lines and 1.0 or sbom.product_qty
|
def _calc_price(self, cr, uid, bom, test = False, real_time_accounting=False, context=None):
|
||||||
price += self._calc_price(cr, uid, sbom) * my_qty
|
if context is None:
|
||||||
else:
|
context={}
|
||||||
bom_obj = self.pool.get('mrp.bom')
|
price = 0
|
||||||
no_child_bom = bom_obj.search(cr, uid, [('product_id', '=', bom.product_id.id), ('bom_id', '=', False)])
|
uom_obj = self.pool.get("product.uom")
|
||||||
if no_child_bom and bom.id not in no_child_bom:
|
if bom.bom_lines:
|
||||||
other_bom = bom_obj.browse(cr, uid, no_child_bom)[0] #TODO zero before?
|
for sbom in bom.bom_lines:
|
||||||
if not other_bom.product_id.calculate_price:
|
my_qty = sbom.bom_lines and 1.0 or sbom.product_qty
|
||||||
price += self._calc_price(cr, uid, other_bom) * other_bom.product_qty
|
price += uom_obj._compute_price(cr, uid, sbom.product_id.uom_id.id, sbom.product_id.standard_price, sbom.product_uom.id) * my_qty
|
||||||
else:
|
|
||||||
# price += other_bom.product_qty * other_bom.product_id.standard_price
|
if bom.routing_id:
|
||||||
price += other_bom.product_id.standard_price
|
for wline in bom.routing_id.workcenter_lines:
|
||||||
else:
|
wc = wline.workcenter_id
|
||||||
# price += bom.product_qty * bom.product_id.standard_price
|
cycle = wline.cycle_nbr
|
||||||
price += bom.product_id.standard_price
|
hour = (wc.time_start + wc.time_stop + cycle * wc.time_cycle) * (wc.time_efficiency or 1.0)
|
||||||
# if no_child_bom:
|
price += wc.costs_cycle * cycle + wc.costs_hour * hour
|
||||||
# other_bom = bom_obj.browse(cr, uid, no_child_bom)[0]
|
price = self.pool.get('product.uom')._compute_price(cr,uid,bom.product_uom.id, price, bom.product_id.uom_id.id)
|
||||||
# price += bom.product_qty * self._calc_price(cr, uid, other_bom)
|
|
||||||
# else:
|
#Convert on product UoM quantities
|
||||||
# price += bom.product_qty * bom.product_id.standard_price
|
if price > 0:
|
||||||
|
price = uom_obj._compute_price(cr, uid, bom.product_uom.id, price / bom.product_qty, bom.product_id.uom_id.id)
|
||||||
|
product = self.pool.get("product.product").browse(cr, uid, bom.product_id.id, context=context)
|
||||||
|
if not test:
|
||||||
|
if (product.valuation != "real_time" or not real_time_accounting):
|
||||||
|
self.write(cr, uid, [bom.product_id.id], {'standard_price' : price}, context=context)
|
||||||
|
else:
|
||||||
|
#Call wizard function here
|
||||||
|
wizard_obj = self.pool.get("stock.change.standard.price")
|
||||||
|
ctx = context.copy()
|
||||||
|
ctx.update({'active_id': bom.product_id.id})
|
||||||
|
wiz_id = wizard_obj.create(cr, uid, {'new_price': price}, context=ctx)
|
||||||
|
wizard_obj.change_price(cr, uid, [wiz_id], context=context)
|
||||||
|
return price
|
||||||
|
|
||||||
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)
|
|
||||||
if bom.bom_lines:
|
|
||||||
self.write(cr, uid, [bom.product_id.id], {'standard_price' : price/bom.product_qty})
|
|
||||||
if bom.product_uom.id != bom.product_id.uom_id.id:
|
|
||||||
price = self.pool.get('product.uom')._compute_price(cr,uid,bom.product_uom.id,price,bom.product_id.uom_id.id)
|
|
||||||
return price
|
|
||||||
product_product()
|
product_product()
|
||||||
|
|
||||||
class product_bom(osv.osv):
|
class product_bom(osv.osv):
|
||||||
|
|
|
@ -21,8 +21,9 @@
|
||||||
<field name="inherit_id" ref="product.product_normal_form_view" />
|
<field name="inherit_id" ref="product.product_normal_form_view" />
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<field name="standard_price" position="after">
|
<field name="standard_price" position="after">
|
||||||
<field name="calculate_price" />
|
<button name="%(action_view_compute_price_wizard)d" string="Recompute price from BoM"
|
||||||
<button name="compute_price" attrs="{'invisible': [('cost_method', '!=', 'standard')]}" type="object" string="Compute standard price"/>
|
type="action" attrs="{'invisible': [('cost_method', '!=', 'standard')]}"
|
||||||
|
groups="product.group_costing_method"/>
|
||||||
</field>
|
</field>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
|
@ -1,11 +1,35 @@
|
||||||
<?xml version="1.0" ?>
|
<?xml version="1.0" ?>
|
||||||
<openerp>
|
<openerp>
|
||||||
<data>
|
<data>
|
||||||
<wizard
|
<record id="view_compute_price_wizard" model="ir.ui.view">
|
||||||
string="Compute standard price"
|
<field name="name">Compute Price as Sum of BoM Components and Routing</field>
|
||||||
model="mrp.bom"
|
<field name="model">wizard.price</field>
|
||||||
name="product_extended.compute_price"
|
<field name="arch" type="xml">
|
||||||
menu="True"
|
<form string="Change Standard Price" version="7.0">
|
||||||
id="id_compute_price"/>
|
<separator string="Change Price"/>
|
||||||
|
<group>
|
||||||
|
<field name="info_field"/>
|
||||||
|
<field name="real_time_accounting"/>
|
||||||
|
<field name="recursive"/>
|
||||||
|
</group>
|
||||||
|
<footer>
|
||||||
|
<button name="compute_from_bom" string="Set price on BoM" type="object" class="oe_highlight"/>
|
||||||
|
or
|
||||||
|
<button string="Cancel" class="oe_link" special="cancel" />
|
||||||
|
</footer>
|
||||||
|
</form>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record id="action_view_compute_price_wizard" model="ir.actions.act_window">
|
||||||
|
<field name="name">Compute Price Wizard</field>
|
||||||
|
<field name="type">ir.actions.act_window</field>
|
||||||
|
<field name="res_model">wizard.price</field>
|
||||||
|
<field name="view_type">form</field>
|
||||||
|
<field name="view_mode">form</field>
|
||||||
|
<field name="view_id" ref="view_compute_price_wizard"/>
|
||||||
|
<field name="target">new</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
</data>
|
</data>
|
||||||
</openerp>
|
</openerp>
|
||||||
|
|
|
@ -23,27 +23,36 @@
|
||||||
|
|
||||||
from openerp.osv import fields, osv
|
from openerp.osv import fields, osv
|
||||||
|
|
||||||
def _compute_price(self, cr, uid, data, context):
|
|
||||||
bom_obj = self.pool.get('mrp.bom')
|
|
||||||
|
|
||||||
for bom in bom_obj.browse(cr, uid, data['ids'], context=context):
|
|
||||||
bom.product_id.compute_price(cr, uid, bom.product_id.id)
|
|
||||||
return {}
|
|
||||||
|
|
||||||
|
|
||||||
class wizard_price(osv.osv):
|
class wizard_price(osv.osv):
|
||||||
_name = "wizard.price"
|
_name = "wizard.price"
|
||||||
_description = "Compute price wizard"
|
_description = "Compute price wizard"
|
||||||
states = {
|
_columns = {
|
||||||
'init' : {
|
'info_field': fields.text('Info', readonly=True),
|
||||||
'actions' : [],
|
'real_time_accounting': fields.boolean("Generate accounting entries when real-time"),
|
||||||
'result' : {
|
'recursive': fields.boolean("Change prices of child BoMs too"),
|
||||||
'type' : 'action',
|
}
|
||||||
'action' : _compute_price,
|
|
||||||
'state' : 'end'
|
def default_get(self, cr, uid, fields, context=None):
|
||||||
}
|
res = super(wizard_price, self).default_get(cr, uid, fields, context=context)
|
||||||
},
|
product_pool = self.pool.get('product.product')
|
||||||
}
|
product_obj = product_pool.browse(cr, uid, context.get('active_id', False))
|
||||||
|
if context is None:
|
||||||
|
context = {}
|
||||||
|
rec_id = context and context.get('active_id', False)
|
||||||
|
assert rec_id, _('Active ID is not set in Context.')
|
||||||
|
res['info_field'] = str(product_pool.compute_price(cr, uid, [product_obj.id], test=True, context=context))
|
||||||
|
return res
|
||||||
|
|
||||||
|
def compute_from_bom(self, cr, uid, ids, context=None):
|
||||||
|
assert len(ids) == 1
|
||||||
|
if context is None:
|
||||||
|
context = {}
|
||||||
|
rec_id = context and context.get('active_id', False)
|
||||||
|
assert rec_id, _('Active ID is not set in Context.')
|
||||||
|
prod_obj = self.pool.get('product.product')
|
||||||
|
res = self.browse(cr, uid, ids, context=context)
|
||||||
|
prod = prod_obj.browse(cr, uid, rec_id, context=context)
|
||||||
|
prod_obj.compute_price(cr, uid, [prod.id], real_time_accounting=res[0].real_time_accounting, recursive=res[0].recursive, test=False, context=context)
|
||||||
|
|
||||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue