[IMP] Implement comments on pull request

This commit is contained in:
Josse Colpaert 2014-09-09 19:06:26 +02:00
parent ec8703b38b
commit ae2eb43e30
13 changed files with 83 additions and 121 deletions

View File

@ -230,7 +230,7 @@ class mrp_bom(osv.osv):
}
_order = "sequence"
def _bom_find(self, cr, uid, product_uom, product_tmpl_id=None, product_id=None, properties=None):
def _bom_find(self, cr, uid, product_uom, product_tmpl_id=None, product_id=None, properties=None, context=None):
""" Finds BoM for particular product and product uom.
@param product_tmpl_id: Selected product.
@param product_uom: Unit of measure of a product.
@ -241,7 +241,7 @@ class mrp_bom(osv.osv):
properties = []
if product_id:
if not product_tmpl_id:
product_tmpl_id = self.pool['product.product'].browse(cr, uid, product_id).product_tmpl_id.id
product_tmpl_id = self.pool['product.product'].browse(cr, uid, product_id, context=context).product_tmpl_id.id
domain = [
'|',
('product_id', '=', product_id),
@ -255,21 +255,21 @@ class mrp_bom(osv.osv):
# neither product nor template, makes no sense to search
return False
if product_uom:
domain += [('product_uom','=',product_uom)]
domain += [('product_uom','=',product_uom)]
domain = domain + [ '|', ('date_start', '=', False), ('date_start', '<=', time.strftime(DEFAULT_SERVER_DATETIME_FORMAT)),
'|', ('date_stop', '=', False), ('date_stop', '>=', time.strftime(DEFAULT_SERVER_DATETIME_FORMAT))]
# order to prioritize bom with product_id over the one without
ids = self.search(cr, uid, domain, order='product_id')
for bom in self.pool.get('mrp.bom').browse(cr, uid, ids):
if not set(map(int,bom.property_ids or [])) - set(properties or []):
if not set(map(int, bom.property_ids or [])) - set(properties or []):
return bom.id
return False
def _bom_explode(self, cr, uid, bom, product, factor, properties=None, level=0, routing_id=False, previous_products=None, master_bom=None):
def _bom_explode(self, cr, uid, bom, product, factor, properties=None, level=0, routing_id=False, previous_products=None, master_bom=None, context=None):
""" Finds Products and Work Centers for related BoM for manufacturing order.
@param bom: BoM of particular product template.
@param product: Select a particular variant of the BoM. If False use BoM without variants.
@param factor: Factor of product UoM.
@param factor: Factor represents the quantity, but in UoM of the BoM, taking into account the numbers produced by the BoM
@param properties: A List of properties Ids.
@param level: Depth level to find BoM lines starts from 10.
@param previous_products: List of product previously use by bom explore to avoid recursion
@ -312,9 +312,6 @@ class mrp_bom(osv.osv):
if bom_line_id.date_start and bom_line_id.date_start > time.strftime(DEFAULT_SERVER_DATETIME_FORMAT) or \
bom_line_id.date_stop and bom_line_id.date_stop > time.strftime(DEFAULT_SERVER_DATETIME_FORMAT):
continue
# check properties
if set(map(int,bom_line_id.property_ids or [])) - set(properties or []):
continue
# all bom_line_id variant values must be in the product
if bom_line_id.attribute_value_ids:
if not product or (set(map(int,bom_line_id.attribute_value_ids or [])) - set(map(int,product.attribute_value_ids))):
@ -323,26 +320,25 @@ class mrp_bom(osv.osv):
if bom_line_id.product_id.id in all_prod:
raise osv.except_osv(_('Invalid Action!'), _('BoM "%s" contains a BoM line with a product recursion: "%s".') % (master_bom.name,bom_line_id.product_id.name_get()[0][1]))
all_prod.append(bom_line_id.product_id.id)
quantity = _factor(bom_line_id.product_qty * factor, bom_line_id.product_efficiency, bom_line_id.product_rounding)
bom2 = None
bom_id = self._bom_find(cr, uid, bom_line_id.product_uom.id, product_id=bom_line_id.product_id.id, properties=properties)
if bom_id:
bom2 = self.browse(cr, uid, bom_id)
if bom_line_id.type != "phantom" and (not bom2 or bom2.type != "phantom"):
bom_id = self._bom_find(cr, uid, bom_line_id.product_uom.id, product_id=bom_line_id.product_id.id, properties=properties, context=context)
#If BoM should not behave like PhantoM, just add the product, otherwise explode further
if bom_line_id.type != "phantom" and (not bom_id or self.browse(cr, uid, bom_id, context=context).type != "phantom"):
result.append({
'name': bom_line_id.product_id.name,
'product_id': bom_line_id.product_id.id,
'product_qty': quantity,
'product_qty': bom_line_id.product_qty * factor,
'product_uom': bom_line_id.product_uom.id,
'product_uos_qty': bom_line_id.product_uos and bom_line_id.product_uos_qty * factor or False,
'product_uos': bom_line_id.product_uos and bom_line_id.product_uos.id or False,
})
elif bom2:
elif bom_id:
bom2 = self.browse(cr, uid, bom_id, context=context)
quantity = _factor(bom_line_id.product_qty * factor, bom_line_id.product_efficiency, bom_line_id.product_rounding)
res = self._bom_explode(cr, uid, bom2, bom_line_id.product_id, quantity,
properties=properties, level=level + 10, previous_products=all_prod, master_bom=master_bom)
properties=properties, level=level + 10, previous_products=all_prod, master_bom=master_bom, context=context)
result = result + res[0]
result2 = result2 + res[1]
else:
@ -646,7 +642,7 @@ class mrp_production(osv.osv):
}}
bom_obj = self.pool.get('mrp.bom')
product = self.pool.get('product.product').browse(cr, uid, product_id, context=context)
bom_id = bom_obj._bom_find(cr, uid, product.uom_id and product.uom_id.id, product_id=product.id, properties=[])
bom_id = bom_obj._bom_find(cr, uid, product.uom_id and product.uom_id.id, product_id=product.id, properties=[], context=context)
routing_id = False
if bom_id:
bom_point = bom_obj.browse(cr, uid, bom_id, context=context)
@ -695,7 +691,7 @@ class mrp_production(osv.osv):
bom_point = production.bom_id
bom_id = production.bom_id.id
if not bom_point:
bom_id = bom_obj._bom_find(cr, uid, production.product_uom.id, product_id=production.product_id.id, properties=properties)
bom_id = bom_obj._bom_find(cr, uid, production.product_uom.id, product_id=production.product_id.id, properties=properties, context=context)
if bom_id:
bom_point = bom_obj.browse(cr, uid, bom_id)
routing_id = bom_point.routing_id.id or False
@ -707,7 +703,7 @@ class mrp_production(osv.osv):
# get components and workcenter_lines from BoM structure
factor = uom_obj._compute_qty(cr, uid, production.product_uom.id, production.product_qty, bom_point.product_uom.id)
# product_lines, workcenter_lines
results, results2 = bom_obj._bom_explode(cr, uid, bom_point, production.product_id, factor / bom_point.product_qty, properties, routing_id=production.routing_id.id)
results, results2 = bom_obj._bom_explode(cr, uid, bom_point, production.product_id, factor / bom_point.product_qty, properties, routing_id=production.routing_id.id, context=context)
# reset product_lines in production order
for line in results:
line['production_id'] = production.id
@ -1063,9 +1059,6 @@ class mrp_production(osv.osv):
return "make_to_order"
return "make_to_stock"
def _create_previous_move(self, cr, uid, move_id, product, source_location_id, dest_location_id, context=None):
'''
When the routing gives a different location than the raw material location of the production order,
@ -1077,17 +1070,15 @@ class mrp_production(osv.osv):
stock_move = self.pool.get('stock.move')
type_obj = self.pool.get('stock.picking.type')
# Need to search for a picking type
src_loc = loc_obj.browse(cr, uid, source_location_id, context=context)
dest_loc = loc_obj.browse(cr, uid, dest_location_id, context=context)
code = 'internal'
check_loc = dest_loc
if src_loc.usage == 'internal' and dest_loc.usage != 'internal':
code = 'outgoing'
check_loc = src_loc
if src_loc.usage != 'internal' and dest_loc.usage == 'internal':
code = 'incoming'
move = stock_move.browse(cr, uid, move_id, context=context)
code = stock_move.get_code_from_locs(cr, uid, move, context=context)
if code == 'outgoing':
check_loc_id = source_location_id
else:
check_loc_id = dest_location_id
check_loc = loc_obj.browse(cr, uid, check_loc_id, context=context)
wh = loc_obj.get_warehouse(cr, uid, check_loc, context=context)
domain = [('code','=', code)]
domain = [('code', '=', code)]
if wh:
domain += [('warehouse_id', '=', wh)]
types = type_obj.search(cr, uid, domain, context=context)

View File

@ -63,7 +63,7 @@ class procurement_order(osv.osv):
for procurement in self.browse(cr, uid, ids, context=context):
properties = [x.id for x in procurement.property_ids]
bom_id = self.pool.get('mrp.bom')._bom_find(cr, uid, procurement.product_uom.id,
product_id=procurement.product_id.id, properties=properties)
product_id=procurement.product_id.id, properties=properties, context=context)
if not bom_id:
return False
return True
@ -85,7 +85,7 @@ class procurement_order(osv.osv):
else:
properties = [x.id for x in procurement.property_ids]
bom_id = bom_obj._bom_find(cr, uid, procurement.product_uom.id,
product_id=procurement.product_id.id, properties=properties)
product_id=procurement.product_id.id, properties=properties, context=context)
bom = bom_obj.browse(cr, uid, bom_id, context=context)
routing_id = bom.routing_id.id

View File

@ -144,7 +144,7 @@ class report_custom(report_rml):
for product in product_pool.browse(cr, uid, ids, context=context):
product_uom_name = to_xml(product.uom_id.name)
bom_id = bom_pool._bom_find(cr, uid, product.uom_id.id, product_id=product.id)
bom_id = bom_pool._bom_find(cr, uid, product.uom_id.id, product_id=product.id, context=context)
title = "<title>%s</title>" %(_("Cost Structure"))
title += "<title>%s</title>" % (to_xml(product.name))
xml += "<lines style='header'>" + title + prod_header + "</lines>"
@ -168,7 +168,7 @@ class report_custom(report_rml):
else:
bom = bom_pool.browse(cr, uid, bom_id, context=context)
factor = number * product.uom_id.factor / bom.product_uom.factor
sub_boms = bom_pool._bom_explode(cr, uid, bom, product, factor / bom.product_qty)
sub_boms = bom_pool._bom_explode(cr, uid, bom, product, factor / bom.product_qty, context=context)
total = 0
total_strd = 0
parent_bom = {

View File

@ -73,7 +73,7 @@ class StockMove(osv.osv):
if bis:
factor = move.product_qty
bom_point = bom_obj.browse(cr, SUPERUSER_ID, bis[0], context=context)
res = bom_obj._bom_explode(cr, SUPERUSER_ID, bom_point, move.product_id, factor, [])
res = bom_obj._bom_explode(cr, SUPERUSER_ID, bom_point, move.product_id, factor, [], context=context)
state = 'confirmed'
if move.state == 'assigned':

View File

@ -78,7 +78,7 @@ class change_production_qty(osv.osv_memory):
bom_point = prod.bom_id
bom_id = prod.bom_id.id
if not bom_point:
bom_id = bom_obj._bom_find(cr, uid, prod.product_uom.id, product_id=prod.product_id.id)
bom_id = bom_obj._bom_find(cr, uid, prod.product_uom.id, product_id=prod.product_id.id, context=context)
if not bom_id:
raise osv.except_osv(_('Error!'), _("Cannot find bill of material for this product."))
prod_obj.write(cr, uid, [prod.id], {'bom_id': bom_id})
@ -89,7 +89,7 @@ class change_production_qty(osv.osv_memory):
factor = prod.product_qty * prod.product_uom.factor / bom_point.product_uom.factor
product_details, workcenter_details = \
bom_obj._bom_explode(cr, uid, bom_point, prod.product_id, factor / bom_point.product_qty, [])
bom_obj._bom_explode(cr, uid, bom_point, prod.product_id, factor / bom_point.product_qty, [], context=context)
for r in product_details:
if r['product_id'] == move.product_id.id:
move_obj.write(cr, uid, [move.id], {'product_uom_qty': r['product_qty']})

View File

@ -1190,46 +1190,7 @@ class product_supplierinfo(osv.osv):
'delay': 1,
'company_id': lambda self,cr,uid,c: self.pool.get('res.company')._company_default_get(cr, uid, 'product.supplierinfo', context=c),
}
def price_get(self, cr, uid, supplier_ids, product_id, product_qty=1, context=None):
"""
Calculate price from supplier pricelist.
@param supplier_ids: Ids of res.partner object.
@param product_id: Id of product.
@param product_qty: specify quantity to purchase.
"""
if type(supplier_ids) in (int,long,):
supplier_ids = [supplier_ids]
res = {}
product_pool = self.pool.get('product.product')
partner_pool = self.pool.get('res.partner')
pricelist_pool = self.pool.get('product.pricelist')
currency_pool = self.pool.get('res.currency')
currency_id = self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id.currency_id.id
# Compute price from standard price of product
product_price = product_pool.price_get(cr, uid, [product_id], 'standard_price', context=context)[product_id]
product = product_pool.browse(cr, uid, product_id, context=context)
for supplier in partner_pool.browse(cr, uid, supplier_ids, context=context):
price = product_price
# Compute price from Purchase pricelist of supplier
#FIXME: property_product_pricelist_purchase is defined in purchase
pricelist_id = supplier.property_product_pricelist_purchase.id
if pricelist_id:
price = pricelist_pool.price_get(cr, uid, [pricelist_id], product_id, product_qty, context=context).setdefault(pricelist_id, 0)
price = currency_pool.compute(cr, uid, pricelist_pool.browse(cr, uid, pricelist_id).currency_id.id, currency_id, price)
# Compute price from supplier pricelist which are in Supplier Information
supplier_info_ids = self.search(cr, uid, [('name','=',supplier.id),('product_tmpl_id','=',product.product_tmpl_id.id)])
if supplier_info_ids:
cr.execute('SELECT * ' \
'FROM pricelist_partnerinfo ' \
'WHERE suppinfo_id IN %s' \
'AND min_quantity <= %s ' \
'ORDER BY min_quantity DESC LIMIT 1', (tuple(supplier_info_ids),product_qty,))
res2 = cr.dictfetchone()
if res2:
price = res2['price']
res[supplier.id] = price
return res
_order = 'sequence'

View File

@ -673,10 +673,9 @@ class purchase_order(osv.osv):
return False
def wkf_action_cancel(self, cr, uid, ids, context=None):
self.write(cr, uid, ids, {'state': 'cancel'})
self.write(cr, uid, ids, {'state': 'cancel'}, context=context)
self.set_order_line_status(cr, uid, ids, 'cancel', context=context)
def action_cancel(self, cr, uid, ids, context=None):
for purchase in self.browse(cr, uid, ids, context=context):
for pick in purchase.picking_ids:

View File

@ -71,10 +71,10 @@ class stock_move(osv.osv):
return purchase_order.partner_id, purchase_order.create_uid.id, purchase_order.currency_id.id
else:
partner = move.picking_id and move.picking_id.partner_id or False
if partner:
if partner.property_product_pricelist_purchase and move.location_id.usage != 'internal' and move.location_dest_id.usage == 'internal':
currency = partner.property_product_pricelist_purchase.currency_id.id
return partner, uid, currency
code = self.get_code_from_locs(cr, uid, move, context=context)
if partner and partner.property_product_pricelist_purchase and code == 'incoming':
currency = partner.property_product_pricelist_purchase.currency_id.id
return partner, uid, currency
return super(stock_move, self)._get_master_data(cr, uid, move, company, context=context)
@ -91,7 +91,8 @@ class stock_move(osv.osv):
"""
Attribute price to move, important in inter-company moves or receipts with only one partner
"""
if not move.purchase_line_id and move.location_id.usage != 'internal' and move.location_dest_id.usage == 'internal' and not move.price_unit:
code = self.get_code_from_locs(cr, uid, move, context=context)
if not move.purchase_line_id and code == 'incoming' and not move.price_unit:
partner = move.picking_id and move.picking_id.partner_id or False
price = False
# If partner given, search price in its purchase pricelist
@ -104,12 +105,10 @@ class stock_move(osv.osv):
'date': move.date,
})[pricelist]
if price:
self.write(cr, uid, [move.id], {'price_unit': price}, context=context)
return True
return self.write(cr, uid, [move.id], {'price_unit': price}, context=context)
super(stock_move, self).attribute_price(cr, uid, move, context=context)
class stock_picking(osv.osv):
_inherit = 'stock.picking'
@ -167,7 +166,6 @@ class stock_warehouse(osv.osv):
'route_id': buy_route_id,
'action': 'buy',
'picking_type_id': warehouse.in_type_id.id,
'propagate': False,
'warehouse_id': warehouse.id,
}

View File

@ -288,6 +288,7 @@ class sale_order_line(osv.osv):
product_uom_obj = self.pool.get('product.uom')
product_obj = self.pool.get('product.product')
warning = {}
#UoM False due to hack which makes sure uom changes price, ... in product_id_change
res = self.product_id_change(cr, uid, ids, pricelist, product, qty=qty,
uom=False, qty_uos=qty_uos, uos=uos, name=name, partner_id=partner_id,
lang=lang, update_tax=update_tax, date_order=date_order, packaging=packaging, fiscal_position=fiscal_position, flag=flag, context=context)

View File

@ -84,8 +84,10 @@
<separator/>
<filter name="real_stock_available" string="Available Products" domain="[('qty_available','&gt;',0)]"/>
<filter name="virtual_stock_available" string="Forecast Available Products" domain="[('virtual_available','&gt;',0)]"/>
<filter name="real_stock_negative" string="Exhausted Stock" domain="[('qty_available','&lt;=',0)]"/>
<filter name="virtual_stock_negative" string="Forecast Exhausted Stock" domain="[('virtual_available','&lt;=',0)]"/>
<filter name="real_stock_exhausted" string="Exhausted Stock" domain="[('qty_available','&lt;=',0)]"/>
<filter name="virtual_stock_exhausted" string="Forecast Exhausted Stock" domain="[('virtual_available','&lt;=',0)]"/>
<filter name="real_stock_negative" string="Negative Stock" domain="[('qty_available','&lt;',0)]"/>
<filter name="virtual_stock_negative" string="Forecast Negative Stock" domain="[('virtual_available','&lt;',0)]"/>
</field>
<filter name="consumable" position="before">
<filter string="Products" icon="terp-accessories-archiver" domain="[('type','=','product')]" help="Stockable products"/>
@ -249,21 +251,5 @@
</xpath>
</field>
</record>
<act_window
context="{'location': active_id}"
domain="[('type','&lt;&gt;','service')]"
id="act_product_location_open"
name="Products"
res_model="product.product"
src_model="stock.location"/>
<record id="ir_act_product_location_open" model="ir.values">
<field name="key2">tree_but_open</field>
<field name="model">stock.location</field>
<field name="name">Products</field>
<field eval="'ir.actions.act_window,%d'%act_product_location_open" name="value"/>
</record>
</data>
</openerp>

View File

@ -2032,7 +2032,6 @@ class stock_move(osv.osv):
price = move.product_id.standard_price
self.write(cr, uid, [move.id], {'price_unit': price})
def action_confirm(self, cr, uid, ids, context=None):
""" Confirms stock move or put it in waiting if it's linked to another move.
@return: List of ids.
@ -2443,6 +2442,21 @@ class stock_move(osv.osv):
return self.action_confirm(cr, uid, [new_move], context=context)[0]
def get_code_from_locs(self, cr, uid, move, context=None):
"""
Returns the code the picking type should have. This can easily be used
to check if a move is internal or not
"""
code = 'internal'
src_loc = move.location_id
dest_loc = move.location_dest_id
if src_loc.usage == 'internal' and dest_loc.usage != 'internal':
code = 'outgoing'
if src_loc.usage != 'internal' and dest_loc.usage == 'internal':
code = 'incoming'
return code
class stock_inventory(osv.osv):
_name = "stock.inventory"
_description = "Inventory"
@ -3531,7 +3545,6 @@ class stock_location_path(osv.osv):
'push_rule_id': rule.id,
'warehouse_id': rule.warehouse_id and rule.warehouse_id.id or False,
}
def _apply(self, cr, uid, rule, move, context=None):
move_obj = self.pool.get('stock.move')

View File

@ -306,6 +306,14 @@
<field name="res_model">stock.quant</field>
</record>
<act_window
context="{'location': active_id, 'search_default_real_stock_available': 1, 'search_default_virtual_stock_available': 1,
'search_default_virtual_stock_negative': 1, 'search_default_real_stock_negative': 1}"
id="act_product_location_open"
name="Products"
res_model="product.product"
src_model="stock.location"/>
<record id="view_location_form" model="ir.ui.view">
<field name="name">stock.location.form</field>
<field name="model">stock.location</field>
@ -316,6 +324,11 @@
class="oe_stat_button"
icon="fa-building-o" name="%(location_open_quants)d" type="action"
context="{'search_default_internal_loc': 1}"/>
<button string="Products"
class="oe_stat_button"
icon="fa-filter" name="%(act_product_location_open)d" type="action"
context="{'location_id': active_id}"
/>
</div>
<label for="name" class="oe_edit_only"/>
<h1><field name="name"/></h1>

View File

@ -99,7 +99,8 @@ class stock_move(osv.osv):
currency = company.currency_id.id
partner = move.picking_id and move.picking_id.partner_id
if partner:
if partner.property_product_pricelist and move.location_id.usage == 'internal' and move.location_dest_id.usage != 'internal':
code = self.get_code_from_locs(cr, uid, move, context=context)
if partner.property_product_pricelist and code == 'outgoing':
currency = partner.property_product_pricelist.currency_id.id
return partner, uid, currency
@ -115,13 +116,7 @@ class stock_move(osv.osv):
if context is None:
context = {}
if type in ('in_invoice', 'in_refund'):
if move_line.price_unit:
return move_line.price_unit
else:
# Take the company of the move line
product = move_line.product_id.with_context(company_id=move_line.company_id.id)
amount_unit = product.price_get('standard_price')[move_line.product_id.id]
return amount_unit
return move_line.price_unit
else:
# If partner given, search price in its sale pricelist
if move_line.partner_id and move_line.partner_id.property_product_pricelist:
@ -192,7 +187,11 @@ class stock_picking(osv.osv):
res.append(move.picking_id.id)
return res
def _set_inv_state(self, cr, uid, picking_id, name, value, arg, context=None):
pick = self.browse(cr, uid, picking_id, context=context)
moves = [x.id for x in pick.move_lines]
move_obj= self.pool.get("stock.move")
move_obj.write(cr, uid, moves, {'invoice_state': pick.invoice_state})
_columns = {
'invoice_state': fields.function(__get_invoice_state, type='selection', selection=[
@ -200,6 +199,7 @@ class stock_picking(osv.osv):
("2binvoiced", "To Be Invoiced"),
("none", "Not Applicable")
], string="Invoice Control", required=True,
fnct_inv = _set_inv_state,
store={
'stock.picking': (lambda self, cr, uid, ids, c={}: ids, ['state'], 10),
'stock.move': (__get_picking_move, ['picking_id', 'invoice_state'], 10),