[FIX] stock, sale_stock: changed the way the procurements look for a suitable rule => Added a m2o field warehouse_id on procurement.order, procurement.rule and stock.move. There was a problem with MTO products because they weren't following the route of the chosen warehouse at all (since all warehouse were creating their rule in the same route, there was no garantee that the route chosen was included in the warehouse selected on the SO)

bzr revid: qdp-launchpad@openerp.com-20131022120605-3dj65nm5yc96sj5r
This commit is contained in:
Quentin (OpenERP) 2013-10-22 14:06:05 +02:00
parent 52cfccf2ce
commit 441d0bc009
4 changed files with 32 additions and 21 deletions

View File

@ -90,10 +90,9 @@ class sale_order(osv.osv):
location_id = order.partner_shipping_id.property_stock_customer.id location_id = order.partner_shipping_id.property_stock_customer.id
vals['location_id'] = location_id vals['location_id'] = location_id
routes = [] routes = line.route_id and [(4, line.route_id.id)] or []
routes += order.warehouse_id and [(4, x.id) for x in order.warehouse_id.route_ids] or [] #route_ids
routes += line.route_id and [(4, line.route_id.id)] or [] #route_id
vals['route_ids'] = routes vals['route_ids'] = routes
vals['warehouse_id'] = order.warehouse_id and order.warehouse_id.id or False
return vals return vals
_columns = { _columns = {

View File

@ -82,6 +82,7 @@ class procurement_rule(osv.osv):
'delay': fields.integer('Number of Days'), 'delay': fields.integer('Number of Days'),
'partner_address_id': fields.many2one('res.partner', 'Partner Address'), 'partner_address_id': fields.many2one('res.partner', 'Partner Address'),
'propagate': fields.boolean('Propagate cancel and split', help='If checked, when the previous move of the move (which was generated by a next procurement) is cancelled or split, the move generated by this move will too'), 'propagate': fields.boolean('Propagate cancel and split', help='If checked, when the previous move of the move (which was generated by a next procurement) is cancelled or split, the move generated by this move will too'),
'warehouse_id': fields.many2one('stock.warehouse', 'Warehouse'),
} }
_defaults = { _defaults = {
@ -99,7 +100,7 @@ class procurement_order(osv.osv):
'move_ids': fields.one2many('stock.move', 'procurement_id', 'Moves', help="Moves created by the procurement"), 'move_ids': fields.one2many('stock.move', 'procurement_id', 'Moves', help="Moves created by the procurement"),
'move_dest_id': fields.many2one('stock.move', 'Destination Move', help="Move which caused (created) the procurement"), 'move_dest_id': fields.many2one('stock.move', 'Destination Move', help="Move which caused (created) the procurement"),
'route_ids': fields.many2many('stock.location.route', 'stock_location_route_procurement', 'procurement_id', 'route_id', 'Followed Route', help="Preferred route to be followed by the procurement order"), 'route_ids': fields.many2many('stock.location.route', 'stock_location_route_procurement', 'procurement_id', 'route_id', 'Followed Route', help="Preferred route to be followed by the procurement order"),
'warehouse_id': fields.many2one('stock.warehouse', 'Warehouse', help="Warehouse to consider for the route selection"),
} }
def propagate_cancel(self, cr, uid, procurement, context=None): def propagate_cancel(self, cr, uid, procurement, context=None):
@ -125,10 +126,18 @@ class procurement_order(osv.osv):
res.append(location.id) res.append(location.id)
return res return res
def change_warehouse_id(self, cr, uid, ids, warehouse_id, context=None):
if warehouse_id:
warehouse = self.pool.get('stock.warehouse').browse(cr, uid, warehouse_id, context=context)
return {'value': {'location_id': warehouse.lot_stock_id.id}}
return {}
def _search_suitable_rule(self, cr, uid, procurement, domain, context=None): def _search_suitable_rule(self, cr, uid, procurement, domain, context=None):
'''we try to first find a rule among the ones defined on the procurement order group and if none is found, we try on the routes defined for the product, and finally we fallback on the default behavior''' '''we try to first find a rule among the ones defined on the procurement order group and if none is found, we try on the routes defined for the product, and finally we fallback on the default behavior'''
if procurement.warehouse_id:
domain += [('warehouse_id', '=', procurement.warehouse_id.id)]
product_route_ids = [x.id for x in procurement.product_id.route_ids + procurement.product_id.categ_id.total_route_ids] product_route_ids = [x.id for x in procurement.product_id.route_ids + procurement.product_id.categ_id.total_route_ids]
procurement_route_ids = [x.id for x in procurement.route_ids] procurement_route_ids = [x.id for x in procurement.route_ids] + [x.id for x in procurement.warehouse_id.route_ids]
res = self.pool.get('procurement.rule').search(cr, uid, domain + [('route_id', 'in', product_route_ids)], order = 'route_sequence, sequence', context=context) res = self.pool.get('procurement.rule').search(cr, uid, domain + [('route_id', 'in', product_route_ids)], order = 'route_sequence, sequence', context=context)
if not res: if not res:
res = self.pool.get('procurement.rule').search(cr, uid, domain + [('route_id', 'in', procurement_route_ids)], order = 'route_sequence, sequence', context=context) res = self.pool.get('procurement.rule').search(cr, uid, domain + [('route_id', 'in', procurement_route_ids)], order = 'route_sequence, sequence', context=context)
@ -171,6 +180,7 @@ class procurement_order(osv.osv):
'picking_type_id': procurement.rule_id.picking_type_id.id, 'picking_type_id': procurement.rule_id.picking_type_id.id,
'group_id': procurement.group_id and procurement.group_id.id or False, 'group_id': procurement.group_id and procurement.group_id.id or False,
'route_ids': [(4, x.id) for x in procurement.route_ids], 'route_ids': [(4, x.id) for x in procurement.route_ids],
'warehouse_id': procurement.rule_id.warehouse_id.id,
} }
if procurement.rule_id: if procurement.rule_id:
newdate = (datetime.strptime(procurement.date_planned, '%Y-%m-%d %H:%M:%S') - relativedelta(days=procurement.rule_id.delay or 0)).strftime('%Y-%m-%d %H:%M:%S') newdate = (datetime.strptime(procurement.date_planned, '%Y-%m-%d %H:%M:%S') - relativedelta(days=procurement.rule_id.delay or 0)).strftime('%Y-%m-%d %H:%M:%S')

View File

@ -1356,6 +1356,7 @@ class stock_move(osv.osv):
'restrict_partner_id': fields.many2one('res.partner', 'Owner ', help="Technical field used to depict a restriction on the ownership of quants to consider when marking this move as 'done'"), 'restrict_partner_id': fields.many2one('res.partner', 'Owner ', help="Technical field used to depict a restriction on the ownership of quants to consider when marking this move as 'done'"),
'putaway_ids': fields.one2many('stock.move.putaway', 'move_id', 'Put Away Suggestions'), 'putaway_ids': fields.one2many('stock.move.putaway', 'move_id', 'Put Away Suggestions'),
'route_ids': fields.many2many('stock.location.route', 'stock_location_route_move', 'move_id', 'route_id', 'Destination route', help="Preferred route to be followed by the procurement order"), 'route_ids': fields.many2many('stock.location.route', 'stock_location_route_move', 'move_id', 'route_id', 'Destination route', help="Preferred route to be followed by the procurement order"),
'warehouse_id': fields.many2one('stock.warehouse', 'Warehouse', help="Technical field depicting the warehouse to consider for the route selection on the next procurement (if any)."),
} }
def copy(self, cr, uid, id, default=None, context=None): def copy(self, cr, uid, id, default=None, context=None):
@ -1420,6 +1421,7 @@ class stock_move(osv.osv):
'move_dest_id': move.id, 'move_dest_id': move.id,
'group_id': move.group_id and move.group_id.id or False, 'group_id': move.group_id and move.group_id.id or False,
'route_ids' : [(4, x.id) for x in move.route_ids], 'route_ids' : [(4, x.id) for x in move.route_ids],
'warehouse_id': move.warehouse_id and move.warehouse_id.id or False,
} }
def _push_apply(self, cr, uid, moves, context): def _push_apply(self, cr, uid, moves, context):
@ -1429,7 +1431,10 @@ class stock_move(osv.osv):
routes = [x.id for x in move.product_id.route_ids + move.product_id.categ_id.total_route_ids] routes = [x.id for x in move.product_id.route_ids + move.product_id.categ_id.total_route_ids]
routes = routes or [x.id for x in move.route_ids] routes = routes or [x.id for x in move.route_ids]
if routes: if routes:
rules = push_obj.search(cr, uid, [('route_id', 'in', routes), ('location_from_id', '=', move.location_dest_id.id)], context=context) domain = [('route_id', 'in', routes), ('location_from_id', '=', move.location_dest_id.id)]
if move.warehouse_id:
domain += [('warehouse_id', '=', move.warehouse_id.id)]
rules = push_obj.search(cr, uid, domain, context=context)
if rules: if rules:
rule = push_obj.browse(cr, uid, rules[0], context=context) rule = push_obj.browse(cr, uid, rules[0], context=context)
push_obj._apply(cr, uid, rule, move, context=context) push_obj._apply(cr, uid, rule, move, context=context)
@ -2225,6 +2230,7 @@ class stock_warehouse(osv.osv):
'name': fields.char('Name', size=128, required=True, select=True), 'name': fields.char('Name', size=128, required=True, select=True),
'company_id': fields.many2one('res.company', 'Company', required=True, select=True), 'company_id': fields.many2one('res.company', 'Company', required=True, select=True),
'partner_id': fields.many2one('res.partner', 'Address'), 'partner_id': fields.many2one('res.partner', 'Address'),
'view_location_id': fields.many2one('stock.location', 'View Location', required=True, domain=[('usage', '=', 'view')]),
'lot_stock_id': fields.many2one('stock.location', 'Location Stock', required=True, domain=[('usage', '=', 'internal')]), 'lot_stock_id': fields.many2one('stock.location', 'Location Stock', required=True, domain=[('usage', '=', 'internal')]),
'code': fields.char('Short Name', size=5, required=True, help="Short name used to identify your warehouse"), 'code': fields.char('Short Name', size=5, required=True, help="Short name used to identify your warehouse"),
'route_ids': fields.many2many('stock.location.route', 'stock_route_warehouse', 'warehouse_id', 'route_id', 'Routes', domain="[('warehouse_selectable', '=', True)]", help='Defaults routes through the warehouse'), 'route_ids': fields.many2many('stock.location.route', 'stock_route_warehouse', 'warehouse_id', 'route_id', 'Routes', domain="[('warehouse_selectable', '=', True)]", help='Defaults routes through the warehouse'),
@ -2382,6 +2388,7 @@ class stock_warehouse(osv.osv):
'auto': 'manual', 'auto': 'manual',
'picking_type_id': pick_type_id, 'picking_type_id': pick_type_id,
'active': active, 'active': active,
'warehouse_id': warehouse.id,
}) })
pull_rules_list.append({ pull_rules_list.append({
'name': self._format_rulename(cr, uid, warehouse, from_loc, dest_loc, context=context), 'name': self._format_rulename(cr, uid, warehouse, from_loc, dest_loc, context=context),
@ -2392,6 +2399,7 @@ class stock_warehouse(osv.osv):
'picking_type_id': pick_type_id, 'picking_type_id': pick_type_id,
'procure_method': first_rule is True and 'make_to_stock' or 'make_to_order', 'procure_method': first_rule is True and 'make_to_stock' or 'make_to_order',
'active': active, 'active': active,
'warehouse_id': warehouse.id,
}) })
first_rule = False first_rule = False
return push_rules_list, pull_rules_list return push_rules_list, pull_rules_list
@ -2416,6 +2424,7 @@ class stock_warehouse(osv.osv):
'picking_type_id': pick_type_id, 'picking_type_id': pick_type_id,
'procure_method': 'make_to_order', 'procure_method': 'make_to_order',
'active': True, 'active': True,
'warehouse_id': warehouse.id,
} }
def _get_crossdock_route(self, cr, uid, warehouse, route_name, context=None): def _get_crossdock_route(self, cr, uid, warehouse, route_name, context=None):
@ -2546,6 +2555,7 @@ class stock_warehouse(osv.osv):
'usage': 'view', 'usage': 'view',
'location_id': data_obj.get_object_reference(cr, uid, 'stock', 'stock_location_locations')[1] 'location_id': data_obj.get_object_reference(cr, uid, 'stock', 'stock_location_locations')[1]
}, context=context) }, context=context)
vals['view_location_id'] = wh_loc_id
#create all location #create all location
reception_steps = vals.get('reception_steps', False) reception_steps = vals.get('reception_steps', False)
delivery_steps = vals.get('delivery_steps', False) delivery_steps = vals.get('delivery_steps', False)
@ -2834,6 +2844,7 @@ class stock_location_path(osv.osv):
'stock.location.route': (_get_route, ['active'], 20), 'stock.location.route': (_get_route, ['active'], 20),
'stock.location.path': (lambda self, cr, uid, ids, c={}: ids, ['route_id'], 20),}, 'stock.location.path': (lambda self, cr, uid, ids, c={}: ids, ['route_id'], 20),},
help="If the active field is set to False, it will allow you to hide the rule without removing it." ), help="If the active field is set to False, it will allow you to hide the rule without removing it." ),
'warehouse_id': fields.many2one('stock.warehouse', 'Warehouse'),
} }
_defaults = { _defaults = {
'auto': 'auto', 'auto': 'auto',
@ -2865,6 +2876,7 @@ class stock_location_path(osv.osv):
'picking_type_id': rule.picking_type_id and rule.picking_type_id.id or False, 'picking_type_id': rule.picking_type_id and rule.picking_type_id.id or False,
'rule_id': rule.id, 'rule_id': rule.id,
'propagate': rule.propagate, 'propagate': rule.propagate,
'warehouse_id': rule.warehouse_id and rule.warehouse_id.id or False,
}) })
move_obj.write(cr, uid, [move.id], { move_obj.write(cr, uid, [move.id], {
'move_dest_id': move_id, 'move_dest_id': move_id,

View File

@ -1667,7 +1667,8 @@
<field name="inherit_id" ref="procurement.procurement_form_view"/> <field name="inherit_id" ref="procurement.procurement_form_view"/>
<field name="arch" type="xml"> <field name="arch" type="xml">
<xpath expr="//field[@name='origin']" position="after"> <xpath expr="//field[@name='origin']" position="after">
<field name="location_id"/> <field name="warehouse_id" on_change="change_warehouse_id(warehouse_id, context)"/>
<field name="location_id" domain="[('usage', '=', 'internal')]"/>
</xpath> </xpath>
<xpath expr="//field[@name='rule_id']" position="after"> <xpath expr="//field[@name='rule_id']" position="after">
<field name="route_ids" widget="many2many_tags"/> <field name="route_ids" widget="many2many_tags"/>
@ -2129,17 +2130,6 @@
<menuitem action="action_routes_form" id="menu_stock_routes" <menuitem action="action_routes_form" id="menu_stock_routes"
parent="stock.menu_stock_configuration" sequence="11" /> parent="stock.menu_stock_configuration" sequence="11" />
<record id="procurement_form_view_inherit" model="ir.ui.view">
<field name="name">procurement.order.form.view.inherit</field>
<field name="inherit_id" ref="procurement.procurement_form_view"/>
<field name="model">procurement.order</field>
<field name="arch" type="xml">
<xpath expr="//field[@name='rule_id']" position="after">
<field name="route_ids" widget="many2many_tags" />
</xpath>
</field>
</record>
<record id="view_product_procurement_rule_form" model="ir.ui.view"> <record id="view_product_procurement_rule_form" model="ir.ui.view">
<field name="name">product.template.procurement.rule.inherit</field> <field name="name">product.template.procurement.rule.inherit</field>
<field name="model">product.product</field> <field name="model">product.product</field>