From 4ec8db1671e6f0f294e45f2b0e47414dd850a8ff Mon Sep 17 00:00:00 2001 From: "Quentin (OpenERP)" Date: Wed, 2 Oct 2013 16:56:07 +0200 Subject: [PATCH 01/13] [IMP] stock_location: warehouse configuration improved/fixed + main warehouse data updated as if it was ran through the config as well bzr revid: qdp-launchpad@openerp.com-20131002145607-cmjs2sh1e7casvx0 --- addons/stock/procurement.py | 3 + addons/stock/stock.py | 4 +- addons/stock/stock_data.xml | 14 +- addons/stock_location/stock_location.py | 607 ++++++++---------- addons/stock_location/stock_location_data.xml | 280 ++------ 5 files changed, 346 insertions(+), 562 deletions(-) diff --git a/addons/stock/procurement.py b/addons/stock/procurement.py index a42cfcd1919..36635287a27 100644 --- a/addons/stock/procurement.py +++ b/addons/stock/procurement.py @@ -47,6 +47,9 @@ class procurement_rule(osv.osv): return res def _get_route(self, cr, uid, ids, context=None): + #WARNING TODO route_id is not required, so a field related seems a bad idea >-< + if context is None: + context = {} result = {} if context is None: context = {} diff --git a/addons/stock/stock.py b/addons/stock/stock.py index 1fe5dba331f..fbf71f1bf63 100644 --- a/addons/stock/stock.py +++ b/addons/stock/stock.py @@ -147,7 +147,7 @@ class stock_location_route(osv.osv): } _defaults = { - 'sequence': lambda self,cr,uid,ctx: 0, + 'sequence': lambda self, cr, uid, ctx: 0, 'active': True, } @@ -2653,6 +2653,7 @@ class stock_picking_type(osv.osv): 'code_id': fields.selection([('incoming', 'Suppliers'), ('outgoing', 'Customers'), ('internal', 'Internal')], 'Picking type code', required=True), 'return_picking_type_id': fields.many2one('stock.picking.type', 'Picking Type for Returns'), 'warehouse_id': fields.many2one('stock.warehouse', 'Warehouse'), + 'active': fields.boolean('Active'), # Statistics for the kanban view 'weekly_picking': fields.function(_get_picking_data, @@ -2687,5 +2688,6 @@ class stock_picking_type(osv.osv): } _defaults = { 'warehouse_id': _default_warehouse, + 'active': True, } diff --git a/addons/stock/stock_data.xml b/addons/stock/stock_data.xml index 880bc1b6839..6b21224889c 100644 --- a/addons/stock/stock_data.xml +++ b/addons/stock/stock_data.xml @@ -80,22 +80,22 @@ - Picking in - IN + WH Picking in + WH\IN 5 - Picking out - OUT + WH Picking out + WH\OUT 5 - Picking internal - INT + WH Picking internal + WH\INT 5 @@ -228,7 +228,7 @@ watch your stock valuation, and track production lots upstream and downstream (b - Main + WH diff --git a/addons/stock_location/stock_location.py b/addons/stock_location/stock_location.py index 0df162489a6..aeff85edd3f 100644 --- a/addons/stock_location/stock_location.py +++ b/addons/stock_location/stock_location.py @@ -50,228 +50,225 @@ class stock_warehouse(osv.osv): ('ship_only', 'Ship directly from stock (Ship only)'), ('pick_ship', 'Bring goods to output location before shipping (Pick + Ship)'), ('pick_pack_ship', 'Make packages into a dedicated location, then bring them to the output location for shipping (Pick + Pack + Ship)')], 'Outgoing Shippings', required=True), - 'wh_input_stock_loc_id': fields.many2one('stock.location', 'Input Location'), 'wh_qc_stock_loc_id': fields.many2one('stock.location', 'Quality Control Location'), 'wh_output_stock_loc_id': fields.many2one('stock.location', 'Output Location'), 'wh_pack_stock_loc_id': fields.many2one('stock.location', 'Packing Location'), - 'ship_route_mto': fields.many2one('stock.location.route', 'ship MTO route'), - 'pick_ship_route_mto': fields.many2one('stock.location.route', 'pick-ship MTO route'), - 'pick_pack_ship_route_mto': fields.many2one('stock.location.route', 'pick-pack-ship MTO route'), - + 'mto_pull_id': fields.many2one('procurement.rule', 'MTO rule'), + 'pick_type_id': fields.many2one('stock.picking.type', 'Pick Type'), + 'pack_type_id': fields.many2one('stock.picking.type', 'Pack Type'), + 'out_type_id': fields.many2one('stock.picking.type', 'Out Type'), + 'in_type_id': fields.many2one('stock.picking.type', 'In Type'), + 'int_type_id': fields.many2one('stock.picking.type', 'Internal Type'), + 'crossdock_route_id': fields.many2one('stock.location.route', 'Crossdock Route'), + 'reception_route_id': fields.many2one('stock.location.route', 'Reception Route'), + 'delivery_route_id': fields.many2one('stock.location.route', 'Delivery Route'), } + _defaults = { 'reception_steps': 'one_step', 'delivery_steps': 'ship_only', } + def _get_partner_locations(self, cr, uid, ids, context=None): + ''' returns a tuple made of the browse record of customer location and the browse record of supplier location''' + data_obj = self.pool.get('ir.model.data') + location_obj = self.pool.get('stock.location') + try: + customer_loc = data_obj.get_object_reference(cr, uid, 'stock', 'stock_location_customers')[1] + supplier_loc = data_obj.get_object_reference(cr, uid, 'stock', 'stock_location_suppliers')[1] + except: + customer_loc = location_obj.search(cr, uid, [('usage', '=', 'customer')], context=context) + customer_loc = customer_loc and customer_loc[0] or False + supplier_loc = location_obj.search(cr, uid, [('usage', '=', 'supplier')], context=context) + supplier_loc = supplier_loc and supplier_loc[0] or False + if not (customer_loc and supplier_loc): + raise osv.except_osv(_('Error!'), _('Can\'t find any customer or supplier location.')) + return location_obj.browse(cr, uid, [customer_loc, supplier_loc], context=context) + def switch_location(self, cr, uid, ids, warehouse, new_reception_step=False, new_delivery_step=False, context=None): location_obj = self.pool.get('stock.location') - wh_view_location_id = warehouse.lot_stock_id.location_id.id - wh_stock_loc = warehouse.lot_stock_id - wh_input_stock_loc = wh_output_stock_loc = wh_pack_stock_loc = wh_qc_stock_loc = wh_stock_loc new_reception_step = new_reception_step or warehouse.reception_steps new_delivery_step = new_delivery_step or warehouse.delivery_steps if warehouse.reception_steps != new_reception_step: location_obj.write(cr, uid, [warehouse.wh_input_stock_loc_id.id, warehouse.wh_qc_stock_loc_id.id], {'active': False}, context=context) if new_reception_step != 'one_step': - location_obj.write(cr, uid, warehouse.wh_input_stock_loc_id.id, {'active': True}, context=context) + location_obj.write(cr, uid, warehouse.wh_input_stock_loc_id.id, {'active': True}, context=context) if new_reception_step == 'three_steps': location_obj.write(cr, uid, warehouse.wh_qc_stock_loc_id.id, {'active': True}, context=context) - + if warehouse.delivery_steps != new_delivery_step: location_obj.write(cr, uid, [warehouse.wh_output_stock_loc_id.id, warehouse.wh_pack_stock_loc_id.id], {'active': False}, context=context) if new_delivery_step != 'ship_only': - location_obj.write(cr, uid, warehouse.wh_output_stock_loc_id.id, {'active': True}, context=context) + location_obj.write(cr, uid, warehouse.wh_output_stock_loc_id.id, {'active': True}, context=context) if new_delivery_step == 'pick_pack_ship': - location_obj.write(cr, uid, warehouse.wh_pack_stock_loc_id.id, {'active': True}, context=context) - + location_obj.write(cr, uid, warehouse.wh_pack_stock_loc_id.id, {'active': True}, context=context) return True - def create_route(self, cr, uid, ids, warehouse, context=None): - default_route_ids = [] - data_obj = self.pool.get('ir.model.data') - route_obj = self.pool.get('stock.location.route') - pull_obj = self.pool.get('procurement.rule') - push_obj = self.pool.get('stock.location.path') - keys = ('two_steps', 'three_steps') - routes_dict = self.get_routes_dict(cr, uid, ids, warehouse, warehouse.reception_steps, warehouse.delivery_steps, write=False, context=context) - for reception in keys: - active = False - route_name, values = routes_dict[reception] - if reception == warehouse.reception_steps: - active = True - new_route_id = route_obj.create(cr, uid, vals={ - 'name': self._format_routename(cr, uid, warehouse, route_name, context=context), - 'product_categ_selectable': True, - 'product_selectable': False, - 'active': active - }, context=context) - default_route_ids.append((4, new_route_id)) - first_rule = True - for from_loc, dest_loc, pick_type_id in values: - push_data = { - 'name': self._format_rulename(cr, uid, warehouse, from_loc, dest_loc, context=context), - 'location_from_id': from_loc.id, - 'location_dest_id': dest_loc.id, - 'route_id': new_route_id, - 'auto': 'manual', - 'picking_type_id': pick_type_id, - 'active': active, - } - push_obj.create(cr, uid, vals=push_data, context=context) - pull_obj.create(cr, uid, { - 'name': self._format_rulename(cr, uid, warehouse, from_loc, dest_loc, context=context), - 'location_src_id': from_loc.id, - 'location_id': dest_loc.id, - 'route_id': new_route_id, - 'action': 'move', - 'picking_type_id': pick_type_id, - 'procure_method': first_rule is True and 'make_to_stock' or 'make_to_order', - 'active': active, - }, context=context) - first_rule = False + def _get_reception_delivery_route(self, cr, uid, warehouse, route_name, context=None): + return { + 'name': self._format_routename(cr, uid, warehouse, route_name, context=context), + 'product_categ_selectable': True, + 'product_selectable': False, + } - - keys = {'ship_only': 'ship_route_mto', 'pick_ship': 'pick_ship_route_mto', 'pick_pack_ship': 'pick_pack_ship_route_mto'} - for delivery, field in keys.items(): - active = False - #create pull rules for delivery, which include all routes in MTS on the warehouse and a specific route MTO to be set on the product - route_name, values = routes_dict[delivery] - if delivery == warehouse.delivery_steps: - active = True - route_id = route_obj.create(cr, uid, vals={ - 'name': self._format_routename(cr, uid, warehouse, route_name, context=context), - 'warehouse_selectable': True, - 'product_selectable': False, - 'active': active, - }, context=context) - default_route_ids.append((4, route_id)) - - mto_route_id = route_obj.create(cr, uid, vals={ - 'name': self._format_routename(cr, uid, warehouse, route_name, context=context) + _(' (MTO)'), - 'warehouse_selectable': False, - 'product_selectable': True, + def _get_push_pull_rules(self, cr, uid, warehouse, active, values, new_route_id, context=None): + first_rule = True + push_rules_list = [] + pull_rules_list = [] + for from_loc, dest_loc, pick_type_id in values: + push_rules_list.append({ + 'name': self._format_rulename(cr, uid, warehouse, from_loc, dest_loc, context=context), + 'location_from_id': from_loc.id, + 'location_dest_id': dest_loc.id, + 'route_id': new_route_id, + 'auto': 'manual', + 'picking_type_id': pick_type_id, 'active': active, }) - self.write(cr, uid, warehouse.id, {field: mto_route_id}, context=context) - first_rule = True - for from_loc, dest_loc, pick_type_id in values: - pull_obj.create(cr, uid, { - 'name': self._format_rulename(cr, uid, warehouse, from_loc, dest_loc, context=context), - 'location_src_id': from_loc.id, - 'location_id': dest_loc.id, - 'route_id': route_id, - 'action': 'move', - 'picking_type_id': pick_type_id, - 'procure_method': first_rule is True and 'make_to_stock' or 'make_to_order', - 'active': active, - }, context=context) - if first_rule: - pull_obj.create(cr, uid, { - 'name': self._format_rulename(cr, uid, warehouse, from_loc, dest_loc, context=context), - 'location_src_id': from_loc.id, - 'location_id': dest_loc.id, - 'route_id': mto_route_id, - 'action': 'move', - 'picking_type_id': pick_type_id, - 'procure_method': 'make_to_order', - 'sequence': 10, - 'active': active, - }, context=context) - first_rule = False + pull_rules_list.append({ + 'name': self._format_rulename(cr, uid, warehouse, from_loc, dest_loc, context=context), + 'location_src_id': from_loc.id, + 'location_id': dest_loc.id, + 'route_id': new_route_id, + 'action': 'move', + 'picking_type_id': pick_type_id, + 'procure_method': first_rule is True and 'make_to_stock' or 'make_to_order', + 'active': active, + }) + first_rule = False + return push_rules_list, pull_rules_list - #create a route for cross dock operations, that can be set on products and product categories - route_name, values = routes_dict['crossdock'] - crossdock_route_id = route_obj.create(cr, uid, vals={ + def _get_mto_pull_rule(self, cr, uid, warehouse, values, context=None): + data_obj = self.pool.get('ir.model.data') + try: + mto_route_id = data_obj.get_object_reference(cr, uid, 'stock', 'route_warehouse0_mto')[1] + except: + mto_route_id = route_obj.search(cr, uid, [('name', 'like', _('MTO'))], context=context) + mto_route_id = mto_route_id and mto_route_id[0] or False + if not mto_route_id: + raise osv.except_osv(_('Error!'), _('Can\'t find any generic MTO route.')) + + from_loc, dest_loc, pick_type_id = values[0] + return { + 'name': self._format_rulename(cr, uid, warehouse, from_loc, dest_loc, context=context) + _(' MTO'), + 'location_src_id': from_loc.id, + 'location_id': dest_loc.id, + 'route_id': mto_route_id, + 'action': 'move', + 'picking_type_id': pick_type_id, + 'procure_method': 'make_to_order', + 'active': True, + } + + def _get_crossdock_route(self, cr, uid, warehouse, route_name, context=None): + return { 'name': self._format_routename(cr, uid, warehouse, route_name, context=context), 'warehouse_selectable': False, 'product_selectable': True, 'product_categ_selectable': True, - }) - default_route_ids.append((4, crossdock_route_id)) - first_rule = True - for from_loc, dest_loc, pick_type_id in values: - pull_obj.create(cr, uid, { - 'name': self._format_rulename(cr, uid, warehouse, from_loc, dest_loc, context=context), - 'location_src_id': from_loc.id, - 'location_id': dest_loc.id, - 'route_id': crossdock_route_id, - 'action': 'move', - 'picking_type_id': pick_type_id, - 'procure_method': first_rule is True and 'make_to_stock' or 'make_to_order', - 'sequence': 10, - }, context=context) - first_rule = False + 'active': warehouse.delivery_steps != 'ship_only' and warehouse.reception_steps != 'one_step', + } - #set defaut delivery route on warehouse according to option choosen - self.write(cr, uid, warehouse.id, {'route_ids': default_route_ids}, context=context) + def create_routes(self, cr, uid, ids, warehouse, context=None): + wh_route_ids = [] + route_obj = self.pool.get('stock.location.route') + pull_obj = self.pool.get('procurement.rule') + push_obj = self.pool.get('stock.location.path') + routes_dict = self.get_routes_dict(cr, uid, ids, warehouse, context=context) + #create reception route and rules + route_name, values = routes_dict[warehouse.reception_steps] + route_vals = self._get_reception_delivery_route(cr, uid, warehouse, route_name, context=context) + reception_route_id = route_obj.create(cr, uid, route_vals, context=context) + wh_route_ids.append((4, reception_route_id)) + push_rules_list, pull_rules_list = self._get_push_pull_rules(cr, uid, warehouse, True, values, reception_route_id, context=context) + #create the push/pull rules + for push_rule in push_rules_list: + push_obj.create(cr, uid, vals=push_rule, context=context) + for pull_rule in pull_rules_list: + pull_obj.create(cr, uid, vals=pull_rule, context=context) - return default_route_ids + #create MTS route and pull rules for delivery a specific route MTO to be set on the product + route_name, values = routes_dict[warehouse.delivery_steps] + route_vals = self._get_reception_delivery_route(cr, uid, warehouse, route_name, context=context) + #create the route and its pull rules + delivery_route_id = route_obj.create(cr, uid, route_vals, context=context) + wh_route_ids.append((4, delivery_route_id)) + dummy, pull_rules_list = self._get_push_pull_rules(cr, uid, warehouse, True, values, delivery_route_id, context=context) + for pull_rule in pull_rules_list: + pull_obj.create(cr, uid, vals=pull_rule, context=context) + #create MTO pull rule and link it to the generic MTO route + mto_pull_vals = self._get_mto_pull_rule(cr, uid, warehouse, values, context=context) + mto_pull_id = pull_obj.create(cr, uid, mto_pull_vals, context=context) + + #create a route for cross dock operations, that can be set on products and product categories + route_name, values = routes_dict['crossdock'] + crossdock_route_vals = self._get_crossdock_route(cr, uid, warehouse, route_name, context=context) + crossdock_route_id = route_obj.create(cr, uid, vals=crossdock_route_vals, context=context) + wh_route_ids.append((4, crossdock_route_id)) + dummy, pull_rules_list = self._get_push_pull_rules(cr, uid, warehouse, warehouse.delivery_steps != 'ship_only' and warehouse.reception_steps != 'one_step', values, crossdock_route_id, context=context) + for pull_rule in pull_rules_list: + pull_obj.create(cr, uid, vals=pull_rule, context=context) + + #set routes and mto pull rule on warehouse + return self.write(cr, uid, warehouse.id, { + 'route_ids': wh_route_ids, + 'mto_pull_id': mto_pull_id, + 'reception_route_id': reception_route_id, + 'delivery_route_id': delivery_route_id, + 'crossdock_route_id': crossdock_route_id, + }, context=context) def change_route(self, cr, uid, ids, warehouse, new_reception_step=False, new_delivery_step=False, context=None): + picking_type_obj = self.pool.get('stock.picking.type') pull_obj = self.pool.get('procurement.rule') + push_obj = self.pool.get('stock.location.path') route_obj = self.pool.get('stock.location.route') new_reception_step = new_reception_step or warehouse.reception_steps new_delivery_step = new_delivery_step or warehouse.delivery_steps - reception_name = False - routes_dict = self.get_routes_dict(cr, uid, ids, warehouse, new_reception_step, new_delivery_step, write=True, context=context) - delivery_name, values = routes_dict[new_delivery_step] - delivery_name = self._format_routename(cr, uid, warehouse, delivery_name, context=context) - crossdock_name, values = routes_dict['crossdock'] - crossdock_name = self._format_routename(cr, uid, warehouse, crossdock_name, context=context) - if new_reception_step != 'one_step': - reception_name, values = routes_dict[new_reception_step] - reception_name = self._format_routename(cr, uid, warehouse, reception_name, context=context) - - set_active_route_ids = [] - set_inactive_route_ids = [] - for route in warehouse.route_ids: - #put active route that are associated to reception and delivery method choosen if it's not already the case - if route.name == reception_name or route.name == delivery_name: - if not route.active: - set_active_route_ids.append(route.id) - #put previous active route that are no longer needed to active=False - elif route.active and route.name != crossdock_name: - set_inactive_route_ids.append(route.id) - #change pull rules input/output destination on crossdock route - elif route.name == crossdock_name: - route_name, values = routes_dict['crossdock'] - first_rule = True - i=0 - if len(route.pull_ids) == len(values): - for from_loc, dest_loc, pick_type_id in values: - pull_obj.write(cr, uid, route.pull_ids[i].id, vals={ - 'name': self._format_rulename(cr, uid, warehouse, from_loc, dest_loc, context=context), - 'location_src_id': from_loc.id, - 'location_id': dest_loc.id, - 'route_id': route.id, - 'action': 'move', - 'picking_type_id': pick_type_id, - 'procure_method': first_rule is True and 'make_to_stock' or 'make_to_order', - 'sequence': 10, - }, context=context) - first_rule = False - i+=1 - continue - #deactivate previous mto route - if warehouse.ship_route_mto.active: - set_inactive_route_ids.append(warehouse.ship_route_mto.id) - if warehouse.pick_ship_route_mto.active: - set_inactive_route_ids.append(warehouse.pick_ship_route_mto.id) - if warehouse.pick_pack_ship_route_mto.active: - set_inactive_route_ids.append(warehouse.pick_pack_ship_route_mto.id) - #activate new mto route + #change the default source and destination location and (de)activate picking types + input_loc = warehouse.wh_input_stock_loc_id + if new_reception_step == 'one_step': + input_loc = warehouse.lot_stock_id + output_loc = warehouse.wh_output_stock_loc_id if new_delivery_step == 'ship_only': - set_active_route_ids.append(warehouse.ship_route_mto.id) - elif new_delivery_step == 'pick_ship': - set_active_route_ids.append(warehouse.pick_ship_route_mto.id) - elif new_delivery_step == 'pick_pack_ship': - set_active_route_ids.append(warehouse.pick_pack_ship_route_mto.id) - route_obj.write(cr, uid, set_inactive_route_ids, {'active': False}, context=context) - route_obj.write(cr, uid, set_active_route_ids, {'active': True}, context=context) + output_loc = warehouse.lot_stock_id + picking_type_obj.write(cr, uid, warehouse.in_type_id.id, {'default_location_dest_id': input_loc.id}, context=context) + picking_type_obj.write(cr, uid, warehouse.out_type_id.id, {'default_location_src_id': output_loc.id}, context=context) + picking_type_obj.write(cr, uid, warehouse.int_type_id.id, {'active': new_reception_step != 'one_step'}, context=context) + picking_type_obj.write(cr, uid, warehouse.pick_type_id.id, {'active': new_delivery_step != 'ship_only'}, context=context) + picking_type_obj.write(cr, uid, warehouse.pack_type_id.id, {'active': new_delivery_step == 'pick_pack_ship'}, context=context) + + routes_dict = self.get_routes_dict(cr, uid, ids, warehouse, context=context) + #update delivery route and rules: unlink the existing rules of the warehouse delivery route and recreate it + pull_obj.unlink(cr, uid, [pu.id for pu in warehouse.delivery_route_id.pull_ids], context=context) + route_name, values = routes_dict[new_delivery_step] + route_obj.write(cr, uid, warehouse.delivery_route_id.id, {'name': self._format_routename(cr, uid, warehouse, route_name, context=context)}, context=context) + dummy, pull_rules_list = self._get_push_pull_rules(cr, uid, warehouse, True, values, warehouse.delivery_route_id.id, context=context) + #create the pull rules + for pull_rule in pull_rules_list: + pull_obj.create(cr, uid, vals=pull_rule, context=context) + + #update reception route and rules: unlink the existing rules of the warehouse reception route and recreate it + pull_obj.unlink(cr, uid, [pu.id for pu in warehouse.reception_route_id.pull_ids], context=context) + push_obj.unlink(cr, uid, [pu.id for pu in warehouse.reception_route_id.push_ids], context=context) + route_name, values = routes_dict[new_reception_step] + route_obj.write(cr, uid, warehouse.reception_route_id.id, {'name': self._format_routename(cr, uid, warehouse, route_name, context=context)}, context=context) + push_rules_list, pull_rules_list = self._get_push_pull_rules(cr, uid, warehouse, True, values, warehouse.reception_route_id.id, context=context) + #create the push/pull rules + for push_rule in push_rules_list: + push_obj.create(cr, uid, vals=push_rule, context=context) + for pull_rule in pull_rules_list: + pull_obj.create(cr, uid, vals=pull_rule, context=context) + + route_obj.write(cr, uid, warehouse.crossdock_route_id.id, {'active': new_reception_step != 'one_step' and new_delivery_step != 'ship_only'}, context=context) + + #change MTO rule + dummy, values = routes_dict[new_delivery_step] + mto_pull_vals = self._get_mto_pull_rule(cr, uid, warehouse, values, context=context) + pull_obj.write(cr, uid, warehouse.mto_pull_id.id, mto_pull_vals, context=context) return True def create(self, cr, uid, vals, context=None): @@ -283,7 +280,6 @@ class stock_warehouse(osv.osv): seq_obj = self.pool.get('ir.sequence') picking_type_obj = self.pool.get('stock.picking.type') location_obj = self.pool.get('stock.location') - route_obj = self.pool.get('stock.location.route') #create view location for warehouse wh_loc_id = location_obj.create(cr, uid, { @@ -291,84 +287,54 @@ class stock_warehouse(osv.osv): 'usage': 'view', 'location_id': data_obj.get_object_reference(cr, uid, 'stock', 'stock_location_locations')[1] }, context=context) - wh_stock_loc_id = location_obj.create(cr, uid, { - 'name': _('Stock'), - 'usage': 'internal', - 'location_id': wh_loc_id - }, context=context) - vals['lot_stock_id'] = wh_stock_loc_id - context_with_inactive = context.copy() - context_with_inactive['active_test']=False #create all location reception_steps = vals.get('reception_steps', False) delivery_steps = vals.get('delivery_steps', False) - wh_input_stock_loc_id = location_obj.create(cr, uid, { - 'name': _('Input'), + context_with_inactive = context.copy() + context_with_inactive['active_test'] = False + sub_locations = [ + {'name': _('Stock'), 'active': True, 'field': 'lot_stock_id'}, + {'name': _('Input'), 'active': reception_steps != 'one_step', 'field': 'wh_input_stock_loc_id'}, + {'name': _('Quality Control'), 'active': reception_steps == 'three_steps', 'field': 'wh_qc_stock_loc_id'}, + {'name': _('Output'), 'active': delivery_steps != 'ship_only', 'field': 'wh_output_stock_loc_id'}, + {'name': _('Packing Zone'), 'active': delivery_steps == 'pick_pack_ship', 'field': 'wh_pack_stock_loc_id'}, + ] + for values in sub_locations: + location_id = location_obj.create(cr, uid, { + 'name': values['name'], 'usage': 'internal', 'location_id': wh_loc_id, - 'active': reception_steps != 'one_step' and True or False, + 'active': values['active'], }, context=context_with_inactive) - vals['wh_input_stock_loc_id'] = wh_input_stock_loc_id - wh_qc_stock_loc_id = location_obj.create(cr, uid, { - 'name': _('Quality Control'), - 'usage': 'internal', - 'location_id': wh_loc_id, - 'active': reception_steps == 'three_steps' and True or False, - }, context=context_with_inactive) - vals['wh_qc_stock_loc_id'] = wh_qc_stock_loc_id - wh_output_stock_loc_id = location_obj.create(cr, uid, { - 'name': _('Output'), - 'usage': 'internal', - 'location_id': wh_loc_id, - 'active': delivery_steps != 'ship_only' and True or False, - }, context=context_with_inactive) - vals['wh_output_stock_loc_id'] = wh_output_stock_loc_id - wh_pack_stock_loc_id = location_obj.create(cr, uid, { - 'name': _('Packing Zone'), - 'usage': 'internal', - 'location_id': wh_loc_id, - 'active': delivery_steps == 'pick_pack_ship' and True or False, - }, context=context_with_inactive) - vals['wh_pack_stock_loc_id'] = wh_pack_stock_loc_id + vals[values['field']] = location_id + + #create new sequences + in_seq_id = seq_obj.create(cr, uid, values={'name': vals.get('name', '') + _(' Sequence in'), 'prefix': vals.get('code', '') + '\IN\\', 'padding': 5}, context=context) + out_seq_id = seq_obj.create(cr, uid, values={'name': vals.get('name', '') + _(' Sequence out'), 'prefix': vals.get('code', '') + '\OUT\\', 'padding': 5}, context=context) + pack_seq_id = seq_obj.create(cr, uid, values={'name': vals.get('name', '') + _(' Sequence packing'), 'prefix': vals.get('code', '') + '\PACK\\', 'padding': 5}, context=context) + pick_seq_id = seq_obj.create(cr, uid, values={'name': vals.get('name', '') + _(' Sequence picking'), 'prefix': vals.get('code', '') + '\PICK\\', 'padding': 5}, context=context) + int_seq_id = seq_obj.create(cr, uid, values={'name': vals.get('name', '') + _(' Sequence internal'), 'prefix': vals.get('code', '') + '\INT\\', 'padding': 5}, context=context) #create WH new_id = super(stock_warehouse, self).create(cr, uid, vals=vals, context=context) - #create sequences and picking type warehouse = self.browse(cr, uid, new_id, context=context) wh_stock_loc = warehouse.lot_stock_id - wh_input_stock_loc = location_obj.browse(cr, uid, wh_input_stock_loc_id, context=context) - wh_qc_stock_loc = location_obj.browse(cr, uid, wh_qc_stock_loc_id, context=context) - wh_output_stock_loc = location_obj.browse(cr, uid, wh_output_stock_loc_id, context=context) - wh_pack_stock_loc = location_obj.browse(cr, uid, wh_pack_stock_loc_id, context=context) - + wh_input_stock_loc = warehouse.wh_input_stock_loc_id + wh_output_stock_loc = warehouse.wh_output_stock_loc_id + wh_pack_stock_loc = warehouse.wh_pack_stock_loc_id + #fetch customer and supplier locations, for references - try: - customer_loc = data_obj.get_object_reference(cr, uid, 'stock', 'stock_location_customers')[1] - supplier_loc = data_obj.get_object_reference(cr, uid, 'stock', 'stock_location_suppliers')[1] - except: - customer_loc = location_obj.search(cr, uid, [('usage', '=', 'customer')], context=context) - customer_loc = customer_loc and customer_loc[0] or False - supplier_loc = location_obj.search(cr, uid, [('usage', '=', 'supplier')], context=context) - supplier_loc = supplier_loc and supplier_loc[0] or False - if not (customer_loc and supplier_loc): - raise osv.except_osv(_('Error!'), _('Can\'t find any customer or supplier location.')) - customer_loc = location_obj.browse(cr, uid, customer_loc, context=context) - supplier_loc = location_obj.browse(cr, uid, supplier_loc, context=context) + customer_loc, supplier_loc = self._get_partner_locations(cr, uid, new_id, context=context) #create in, out, internal picking types for warehouse - #First create new sequence - in_seq_id = seq_obj.create(cr, uid, values={'name': warehouse.name + _(' Picking in'), 'prefix': warehouse.code + '\IN\\', 'padding': 5}, context=context) - out_seq_id = seq_obj.create(cr, uid, values={'name': warehouse.name + _(' Picking out'), 'prefix': warehouse.code + '\OUT\\', 'padding': 5}, context=context) - internal_seq_id = seq_obj.create(cr, uid, values={'name': warehouse.name + _(' Picking internal'), 'prefix': warehouse.code + '\INT\\', 'padding': 5}, context=context) - #then create picking_types input_loc = wh_input_stock_loc if warehouse.reception_steps == 'one_step': input_loc = wh_stock_loc output_loc = wh_output_stock_loc if warehouse.delivery_steps == 'ship_only': output_loc = wh_stock_loc - in_picking_type_id = picking_type_obj.create(cr, uid, vals={ + in_type_id = picking_type_obj.create(cr, uid, vals={ 'name': _('Receptions'), 'warehouse_id': new_id, 'code_id': 'incoming', @@ -376,7 +342,7 @@ class stock_warehouse(osv.osv): 'sequence_id': in_seq_id, 'default_location_src_id': supplier_loc.id, 'default_location_dest_id': input_loc.id}, context=context) - out_picking_type_id = picking_type_obj.create(cr, uid, vals={ + out_type_id = picking_type_obj.create(cr, uid, vals={ 'name': _('Delivery Orders'), 'warehouse_id': new_id, 'code_id': 'outgoing', @@ -384,18 +350,47 @@ class stock_warehouse(osv.osv): 'delivery': True, 'default_location_src_id': output_loc.id, 'default_location_dest_id': customer_loc.id}, context=context) - internal_picking_type_id = picking_type_obj.create(cr, uid, vals={ + int_type_id = picking_type_obj.create(cr, uid, vals={ 'name': _('Internal Transfers'), 'warehouse_id': new_id, 'code_id': 'internal', - 'sequence_id': internal_seq_id, + 'sequence_id': int_seq_id, 'default_location_src_id': wh_stock_loc.id, 'default_location_dest_id': wh_stock_loc.id, - 'pack': True,}, context=context) + 'active': reception_steps != 'one_step', + 'pack': False}, context=context) + pack_type_id = picking_type_obj.create(cr, uid, vals={ + 'name': _('Pack'), + 'warehouse_id': new_id, + 'code_id': 'internal', + 'sequence_id': pack_seq_id, + 'default_location_src_id': wh_pack_stock_loc.id, + 'default_location_dest_id': output_loc.id, + 'active': delivery_steps == 'pick_pack_ship', + 'pack': True}, context=context) + pick_type_id = picking_type_obj.create(cr, uid, vals={ + 'name': _('Pick'), + 'warehouse_id': new_id, + 'code_id': 'internal', + 'sequence_id': pick_seq_id, + 'default_location_src_id': wh_stock_loc.id, + 'default_location_dest_id': wh_pack_stock_loc.id, + 'active': delivery_steps != 'ship_only', + 'pack': False}, context=context) + + #write picking types on WH + vals = { + 'in_type_id': in_type_id, + 'out_type_id': out_type_id, + 'pack_type_id': pack_type_id, + 'pick_type_id': pick_type_id, + 'int_type_id': int_type_id, + } + super(stock_warehouse, self).write(cr, uid, new_id, vals=vals, context=context) + warehouse.refresh() #create routes and push/pull rules - default_route_id = self.create_route(cr, uid, new_id, warehouse, context=context) - + self.create_routes(cr, uid, new_id, warehouse, context=context) return new_id def _format_rulename(self, cr, uid, obj, from_loc, dest_loc, context=None): @@ -404,54 +399,23 @@ class stock_warehouse(osv.osv): def _format_routename(self, cr, uid, obj, name, context=None): return obj.name + ': ' + name - def get_routes_dict(self, cr, uid, ids, warehouse, reception_steps=False, delivery_steps=False, write=False, context=None): - picking_type_obj = self.pool.get('stock.picking.type') - data_obj = self.pool.get('ir.model.data') - location_obj = self.pool.get('stock.location') - #fetch various location - wh_input_stock_loc = warehouse.wh_input_stock_loc_id - wh_qc_stock_loc = warehouse.wh_qc_stock_loc_id - wh_output_stock_loc = warehouse.wh_output_stock_loc_id - wh_pack_stock_loc = warehouse.wh_pack_stock_loc_id - wh_stock_loc = warehouse.lot_stock_id + def get_routes_dict(self, cr, uid, ids, warehouse, context=None): #fetch customer and supplier locations, for references - try: - customer_loc = data_obj.get_object_reference(cr, uid, 'stock', 'stock_location_customers')[1] - supplier_loc = data_obj.get_object_reference(cr, uid, 'stock', 'stock_location_suppliers')[1] - except: - customer_loc = location_obj.search(cr, uid, [('usage', '=', 'customer')], context=context) - customer_loc = customer_loc and customer_loc[0] or False - supplier_loc = location_obj.search(cr, uid, [('usage', '=', 'supplier')], context=context) - supplier_loc = supplier_loc and supplier_loc[0] or False - if not (customer_loc and supplier_loc): - raise osv.except_osv(_('Error!'), _('Can\'t find any customer or supplier location.')) - customer_loc = location_obj.browse(cr, uid, customer_loc, context=context) - supplier_loc = location_obj.browse(cr, uid, supplier_loc, context=context) - #update route on picking type - input_loc = wh_input_stock_loc - if reception_steps == 'one_step': - input_loc = wh_stock_loc - output_loc = wh_output_stock_loc - if delivery_steps == 'ship_only': - output_loc = wh_stock_loc - in_picking_type_id = picking_type_obj.search(cr, uid, [('warehouse_id', '=', warehouse.id), ('code_id', '=', 'incoming')], context=context)[0] - out_picking_type_id = picking_type_obj.search(cr, uid, [('warehouse_id', '=', warehouse.id), ('code_id', '=', 'outgoing')], context=context)[0] - internal_picking_type_id = picking_type_obj.search(cr, uid, [('warehouse_id', '=', warehouse.id), ('code_id', '=', 'internal')], context=context)[0] - #in case we need to update picking location - if write: - picking_type_obj.write(cr, uid, in_picking_type_id, {'default_location_dest_id': input_loc.id}, context=context) - picking_type_obj.write(cr, uid, out_picking_type_id, {'default_location_src_id': output_loc.id}, context=context) - + customer_loc, supplier_loc = self._get_partner_locations(cr, uid, ids, context=context) + return { - 'two_steps': (_('Reception in 2 steps'), [(wh_input_stock_loc, wh_stock_loc, internal_picking_type_id)]), - 'three_steps': (_('Reception in 3 steps'), [(wh_input_stock_loc, wh_qc_stock_loc, internal_picking_type_id), (wh_qc_stock_loc, wh_stock_loc, internal_picking_type_id)]), - 'crossdock': (_('Cross-Dock'), [(input_loc, output_loc, internal_picking_type_id), (output_loc, customer_loc, out_picking_type_id)]), - 'ship_only': (_('Ship Only'), [(wh_stock_loc, customer_loc, out_picking_type_id)]), - 'pick_ship': (_('Pick + Ship'), [(wh_stock_loc, wh_output_stock_loc, internal_picking_type_id), (wh_output_stock_loc, customer_loc, out_picking_type_id)]), - 'pick_pack_ship': (_('Pick + Pack + Ship'), [(wh_stock_loc, wh_pack_stock_loc, internal_picking_type_id), (wh_pack_stock_loc, wh_output_stock_loc, internal_picking_type_id), (wh_output_stock_loc, customer_loc, out_picking_type_id)]), + 'one_step': (_('Reception in 1 step'), []), + 'two_steps': (_('Reception in 2 steps'), [(warehouse.wh_input_stock_loc_id, warehouse.lot_stock_id, warehouse.int_type_id.id)]), + 'three_steps': (_('Reception in 3 steps'), [(warehouse.wh_input_stock_loc_id, warehouse.wh_qc_stock_loc_id, warehouse.int_type_id.id), (warehouse.wh_qc_stock_loc_id, warehouse.lot_stock_id, warehouse.int_type_id.id)]), + 'crossdock': (_('Cross-Dock'), [(warehouse.wh_input_stock_loc_id, warehouse.wh_output_stock_loc_id, warehouse.int_type_id.id), (warehouse.wh_output_stock_loc_id, customer_loc, warehouse.out_type_id.id)]), + 'ship_only': (_('Ship Only'), [(warehouse.lot_stock_id, customer_loc, warehouse.out_type_id.id)]), + 'pick_ship': (_('Pick + Ship'), [(warehouse.lot_stock_id, warehouse.wh_output_stock_loc_id, warehouse.pick_type_id.id), (warehouse.wh_output_stock_loc_id, customer_loc, warehouse.out_type_id.id)]), + 'pick_pack_ship': (_('Pick + Pack + Ship'), [(warehouse.lot_stock_id, warehouse.wh_pack_stock_loc_id, warehouse.int_type_id.id), (warehouse.wh_pack_stock_loc_id, warehouse.wh_output_stock_loc_id, warehouse.pack_type_id.id), (warehouse.wh_output_stock_loc_id, customer_loc, warehouse.out_type_id.id)]), } def write(self, cr, uid, ids, vals, context=None): + if context is None: + context = {} if isinstance(ids, (int, long)): ids = [ids] if context is None: @@ -463,50 +427,36 @@ class stock_warehouse(osv.osv): push_obj = self.pool.get('stock.location.path') context_with_inactive = context.copy() - context_with_inactive['active_test']=False + context_with_inactive['active_test'] = False for warehouse in self.browse(cr, uid, ids, context=context_with_inactive): - name = warehouse.name - rename = False - if vals.get('code') or vals.get('name'): - #use previous name to find informations - #rename sequence - if vals.get('name'): - rename = True - name = vals.get('name') - in_seq = seq_obj.search(cr, uid, [('name', '=', name + _(' Picking in'))], context=context) - out_seq = seq_obj.search(cr, uid, [('name', '=', name + _(' Picking out'))], context=context) - internal_seq = seq_obj.search(cr, uid, [('name', '=', name + _(' Picking internal'))], context=context) - seq_obj.write(cr, uid, in_seq, {'name': name, 'prefix': vals.get('code', warehouse.code) + '\IN\\'}, context=context) - seq_obj.write(cr, uid, out_seq, {'name': name, 'prefix': vals.get('code', warehouse.code) + '\OUT\\'}, context=context) - seq_obj.write(cr, uid, internal_seq, {'name': name, 'prefix': vals.get('code', warehouse.code) + '\INT\\'}, context=context) #first of all, check if we need to delete and recreate route if vals.get('reception_steps') or vals.get('delivery_steps'): #activate and deactivate location according to reception and delivery option self.switch_location(cr, uid, warehouse.id, warehouse, vals.get('reception_steps', False), vals.get('delivery_steps', False), context=context) # switch between route self.change_route(cr, uid, ids, warehouse, vals.get('reception_steps', False), vals.get('delivery_steps', False), context=context_with_inactive) - - if rename: - #rename location - location_id = warehouse.lot_stock_id.location_id.id - location_obj.write(cr, uid, location_id, {'name': name}, context=context_with_inactive) - #rename route and push-pull rules - for route in warehouse.route_ids: - route_obj.write(cr, uid, route.id, {'name': route.name.replace(warehouse.name, name, 1)}, context=context_with_inactive) - for pull in route.pull_ids: - pull_obj.write(cr, uid, pull.id, {'name': pull.name.replace(warehouse.name, name, 1)}, context=context_with_inactive) - for push in route.push_ids: - push_obj.write(cr, uid, push.id, {'name': pull.name.replace(warehouse.name, name, 1)}, context=context_with_inactive) - #change the 3 mto route name - route_obj.write(cr, uid, warehouse.ship_route_mto.id, {'name': warehouse.ship_route_mto.name.replace(warehouse.name, name, 1)}, context=context_with_inactive) - for pull in warehouse.ship_route_mto.pull_ids: - pull_obj.write(cr, uid, pull.id, {'name': pull.name.replace(warehouse.name, name, 1)}, context=context_with_inactive) - route_obj.write(cr, uid, warehouse.pick_ship_route_mto.id, {'name': warehouse.pick_ship_route_mto.name.replace(warehouse.name, name, 1)}, context=context_with_inactive) - for pull in warehouse.pick_ship_route_mto.pull_ids: - pull_obj.write(cr, uid, pull.id, {'name': pull.name.replace(warehouse.name, name, 1)}, context=context_with_inactive) - route_obj.write(cr, uid, warehouse.pick_pack_ship_route_mto.id, {'name': warehouse.pick_pack_ship_route_mto.name.replace(warehouse.name, name, 1)}, context=context_with_inactive) - for pull in warehouse.pick_pack_ship_route_mto.pull_ids: - pull_obj.write(cr, uid, pull.id, {'name': pull.name.replace(warehouse.name, name, 1)}, context=context_with_inactive) + if vals.get('code') or vals.get('name'): + name = warehouse.name + #rename sequence + if vals.get('name'): + name = vals.get('name') + #rename location + location_id = warehouse.lot_stock_id.location_id.id + location_obj.write(cr, uid, location_id, {'name': name}, context=context_with_inactive) + #rename route and push-pull rules + for route in warehouse.route_ids: + route_obj.write(cr, uid, route.id, {'name': route.name.replace(warehouse.name, name, 1)}, context=context_with_inactive) + for pull in route.pull_ids: + pull_obj.write(cr, uid, pull.id, {'name': pull.name.replace(warehouse.name, name, 1)}, context=context_with_inactive) + for push in route.push_ids: + push_obj.write(cr, uid, push.id, {'name': pull.name.replace(warehouse.name, name, 1)}, context=context_with_inactive) + #change the mto pull rule name + pull_obj.write(cr, uid, warehouse.mto_pull_id.id, {'name': warehouse.mto_pull_id.name.replace(warehouse.name, name, 1)}, context=context_with_inactive) + seq_obj.write(cr, uid, warehouse.in_type_id.sequence_id.id, {'name': name + _(' Sequence in'), 'prefix': vals.get('code', warehouse.code) + '\IN\\'}, context=context) + seq_obj.write(cr, uid, warehouse.out_type_id.sequence_id.id, {'name': name + _(' Sequence out'), 'prefix': vals.get('code', warehouse.code) + '\OUT\\'}, context=context) + seq_obj.write(cr, uid, warehouse.pack_type_id.sequence_id.id, {'name': name + _(' Sequence packing'), 'prefix': vals.get('code', warehouse.code) + '\PACK\\'}, context=context) + seq_obj.write(cr, uid, warehouse.pick_type_id.sequence_id.id, {'name': name + _(' Sequence picking'), 'prefix': vals.get('code', warehouse.code) + '\PICK\\'}, context=context) + seq_obj.write(cr, uid, warehouse.int_type_id.sequence_id.id, {'name': name + _(' Sequence internal'), 'prefix': vals.get('code', warehouse.code) + '\INT\\'}, context=context) return super(stock_warehouse, self).write(cr, uid, ids, vals=vals, context=context) def unlink(self, cr, uid, ids, context=None): @@ -519,6 +469,9 @@ class stock_location_path(osv.osv): _order = "name" def _get_route(self, cr, uid, ids, context=None): + #WARNING TODO route_id is not required, so a field related seems a bad idea >-< + if context is None: + context = {} result = {} if context is None: context = {} @@ -672,16 +625,17 @@ class product_removal_strategy(osv.osv): 'location_id': fields.many2one('stock.location', 'Locations', required=True), } + class product_product(osv.osv): _inherit = 'product.product' _columns = { 'route_ids': fields.many2many('stock.location.route', 'stock_route_product', 'product_id', 'route_id', 'Routes', domain="[('product_selectable', '=', True)]"), #Adds domain } + class product_category(osv.osv): _inherit = 'product.category' - def calculate_total_routes(self, cr, uid, ids, name, args, context=None): res = {} route_obj = self.pool.get("stock.location.route") @@ -700,7 +654,6 @@ class product_category(osv.osv): 'putaway_strategy_ids': fields.one2many('product.putaway', 'product_categ_id', 'Put Away Strategies'), 'total_route_ids': fields.function(calculate_total_routes, relation='stock.location.route', type='many2many', string='Total routes', readonly=True), } - class stock_move_putaway(osv.osv): @@ -716,13 +669,12 @@ class stock_move_putaway(osv.osv): class stock_quant(osv.osv): _inherit = "stock.quant" + def check_preferred_location(self, cr, uid, move, context=None): - # moveputaway_obj = self.pool.get('stock.move.putaway') if move.putaway_ids and move.putaway_ids[0]: #Take only first suggestion for the moment return move.putaway_ids[0].location_id - else: - return super(stock_quant, self).check_preferred_location(cr, uid, move, context=context) + return super(stock_quant, self).check_preferred_location(cr, uid, move, context=context) class stock_move(osv.osv): @@ -818,5 +770,4 @@ class stock_location(osv.osv): return pr.browse(cr, uid, result[0], context=context).method return super(stock_location, self).get_removal_strategy(cr, uid, location, product, context=context) - # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/stock_location/stock_location_data.xml b/addons/stock_location/stock_location_data.xml index d085e19aba0..5cbb9d863e4 100644 --- a/addons/stock_location/stock_location_data.xml +++ b/addons/stock_location/stock_location_data.xml @@ -4,7 +4,6 @@ - Packing zone @@ -18,20 +17,50 @@ internal - - - - - - internal - Quality Control - + + + Quality Control + + internal + + + + Main warehouse: Pack + WH\PACK + 5 + + + + Pack Operations + + + + internal + + + + + + Main warehouse: Pick + WH\PICK + 5 + + + + + Pick Operations + + + + internal + + + - Your Company: Ship only 20 @@ -39,7 +68,6 @@ - Your Company: Stock → Customers move @@ -50,34 +78,6 @@ - - - - - Your company: Ship only (MTO) - 10 - - - - - Your Company: Stock → Customers - move - - - make_to_order - - - - Your Company: Cross-Dock 9 @@ -106,203 +106,31 @@ - - Your Company: Pick + Ship - 15 - - - - - - - Your Company: Pick + Ship (MTO) - 10 - - - - - Your Company: Stock → Output - move - - - make_to_stock - - - - - - - Your Company: Output → Customers - move - - - make_to_order - - - - - - - - Your Company: Stock → Output - move - - - make_to_order - - - - - - - - - Your Company: Pick + Pack + Ship - 20 - - - - - - - Your Company: Pick + Pack + Ship (MTO) - 12 - - - - - - Your Company: Stock → Packing Zone - move - - - make_to_stock - - - - - - - Your Company: Output → Customers - move - - - make_to_order - - - - - - - Your Company: Packing Zone → Output - move - - - make_to_order - - - - - - - Your Company: Stock → Packing Zone - move - - - make_to_order - - - - - - - - Your Company: Reception in 2 steps + + + 1-step Receival 20 - - - Your Company: Input → Stock - - - - - - - - Your Company: Input → Stock - move - - - make_to_stock - - - - - - - - Your Company: Reception in 3 steps - 22 - - - - - - - Your Company: Input → Quality Control - - - - - - - - - Your Company: Quality Control → Stock - - - - - - - - - Your Company: Quality Control → Stock - move - - - make_to_order - - - - - - - Your Company: Input → Quality Control - move - - - make_to_stock - - - - - - + + - + - - - - + + + + + + + + + From 4deb9c8605a5fb72a1773a5e6c3979faca6ea9c0 Mon Sep 17 00:00:00 2001 From: "Quentin (OpenERP)" Date: Wed, 2 Oct 2013 17:11:22 +0200 Subject: [PATCH 02/13] [FIX] stock: get_picking_for_packing_ui now filters on the picking type bzr revid: qdp-launchpad@openerp.com-20131002151122-y10jyz46hxqx3ryb --- addons/stock/stock.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/stock/stock.py b/addons/stock/stock.py index fbf71f1bf63..3651a55aad8 100644 --- a/addons/stock/stock.py +++ b/addons/stock/stock.py @@ -1007,7 +1007,7 @@ class stock_picking(osv.osv): # Methods for the barcode UI def get_picking_for_packing_ui(self, cr, uid, context=None): - return self.search(cr, uid, [('state', 'in', ('confirmed', 'assigned'))], context=context) + return self.search(cr, uid, [('state', 'in', ('confirmed', 'assigned')), ('picking_type_id', '=', context.get('default_picking_type_id'))], context=context) def action_done_from_packing_ui(self, cr, uid, picking_id, only_split_lines=False, context=None): self.do_partial(cr, uid, picking_id, only_split_lines, context=context) From 9835f6fee6d3068d820b10712c93094872b79f91 Mon Sep 17 00:00:00 2001 From: "Quentin (OpenERP)" Date: Wed, 2 Oct 2013 17:25:38 +0200 Subject: [PATCH 03/13] [FIX] stock_location: demo data was badly merged in previous revision bzr revid: qdp-launchpad@openerp.com-20131002152538-8tpm0p53yz96iae9 --- addons/stock_location/stock_location_demo_cpu1.xml | 8 ++++---- addons/stock_location/test/stock_location_push_flow.yml | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/addons/stock_location/stock_location_demo_cpu1.xml b/addons/stock_location/stock_location_demo_cpu1.xml index d49e1730261..c44e4f738c9 100644 --- a/addons/stock_location/stock_location_demo_cpu1.xml +++ b/addons/stock_location/stock_location_demo_cpu1.xml @@ -4,7 +4,7 @@ This product is configured with example of push/pull flows - + True @@ -14,12 +14,12 @@ none Receptions to Quality Control - + - + manual none @@ -67,4 +67,4 @@ - \ No newline at end of file + diff --git a/addons/stock_location/test/stock_location_push_flow.yml b/addons/stock_location/test/stock_location_push_flow.yml index bf17692a399..59ccc6e2da2 100644 --- a/addons/stock_location/test/stock_location_push_flow.yml +++ b/addons/stock_location/test/stock_location_push_flow.yml @@ -31,13 +31,13 @@ push_ids: - name: 'stock -> quality test' invoice_state: none - location_dest_id: stock_location.stock_location_qualitytest0 + location_dest_id: stock_location.stock_location_quality location_from_id: stock.stock_location_stock picking_type_id: stock.picking_type_internal - name: 'quality test -> components' invoice_state: none location_dest_id: stock.stock_location_components - location_from_id: stock_location.stock_location_qualitytest0 + location_from_id: stock_location.stock_location_quality picking_type_id: stock.picking_type_internal - !record {model: product.product, id: product_product_hpcdwriters01}: From 08dbf986bfe9bf216f1466e227ce1f604f534780 Mon Sep 17 00:00:00 2001 From: "Quentin (OpenERP)" Date: Wed, 2 Oct 2013 18:02:02 +0200 Subject: [PATCH 04/13] [] stock_complex_routes/test/dropship.yml: added debug statement bzr revid: qdp-launchpad@openerp.com-20131002160202-uwdasv8g31lucdjk --- addons/stock_complex_routes/test/dropship.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/addons/stock_complex_routes/test/dropship.yml b/addons/stock_complex_routes/test/dropship.yml index 37e6670f6ca..0cc159169b5 100644 --- a/addons/stock_complex_routes/test/dropship.yml +++ b/addons/stock_complex_routes/test/dropship.yml @@ -50,6 +50,7 @@ sale_record = self.pool.get("sale.order").browse(cr, uid, ref('sale_order_drp_shpng')) procurement_order = self.pool.get("procurement.group").browse(cr, uid, sale_record.procurement_group_id.id).procurement_ids[0] print 'procurement_order', procurement_order.state + print 'test', procurement_order.purchase_line_id.order_id purchase_id = procurement_order.purchase_line_id.order_id.id wf_service = netsvc.LocalService('workflow') From 8530fc623a1bced5a4a214007816463fcf0b6071 Mon Sep 17 00:00:00 2001 From: "Quentin (OpenERP)" Date: Wed, 2 Oct 2013 21:42:37 +0200 Subject: [PATCH 05/13] [FIX] attempt to fix the runbot bzr revid: qdp-launchpad@openerp.com-20131002194237-hggdv3git151p09d --- addons/purchase/purchase.py | 2 ++ addons/stock_complex_routes/test/dropship.yml | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/addons/purchase/purchase.py b/addons/purchase/purchase.py index 5a969154cc7..f72394cd34c 100644 --- a/addons/purchase/purchase.py +++ b/addons/purchase/purchase.py @@ -1135,7 +1135,9 @@ class procurement_order(osv.osv): return rule_id def _run(self, cr, uid, procurement, context=None): + print "dans le _run de purchase", procurement.rule_id.name if procurement.rule_id and procurement.rule_id.action == 'buy': + print "go pour make_po" #make a purchase order for the procurement return self.make_po(cr, uid, [procurement.id], context=context)[procurement.id] return super(procurement_order, self)._run(cr, uid, procurement, context=context) diff --git a/addons/stock_complex_routes/test/dropship.yml b/addons/stock_complex_routes/test/dropship.yml index 0cc159169b5..d9d70cc83ba 100644 --- a/addons/stock_complex_routes/test/dropship.yml +++ b/addons/stock_complex_routes/test/dropship.yml @@ -42,6 +42,11 @@ !python {model: procurement.group}: | sale_record = self.pool.get("sale.order").browse(cr, uid, ref('sale_order_drp_shpng')) assert self.browse(cr, uid, sale_record.procurement_group_id.id).procurement_ids[0].product_qty == 200 +- + I run scheduler. +- + !python {model: procurement.order}: | + self.run_scheduler(cr, uid) - Check a quotation was created to a certain supplier and confirm so it becomes a confirmed purchase order - From 66652b2fd59fa204e583b068b8fcd07892492cf6 Mon Sep 17 00:00:00 2001 From: "Quentin (OpenERP)" Date: Wed, 2 Oct 2013 22:14:25 +0200 Subject: [PATCH 06/13] [DEBUG] debug statement bzr revid: qdp-launchpad@openerp.com-20131002201425-ti74znmwqiefmkjx --- addons/purchase/purchase.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/purchase/purchase.py b/addons/purchase/purchase.py index f72394cd34c..68469ded48e 100644 --- a/addons/purchase/purchase.py +++ b/addons/purchase/purchase.py @@ -1135,7 +1135,7 @@ class procurement_order(osv.osv): return rule_id def _run(self, cr, uid, procurement, context=None): - print "dans le _run de purchase", procurement.rule_id.name + print "dans le _run de purchase", procurement.rule_id and procurement.rule_id.name or 'pas de rule' if procurement.rule_id and procurement.rule_id.action == 'buy': print "go pour make_po" #make a purchase order for the procurement From 15765de7d00cae8d214865c2bd78634b8ee11cde Mon Sep 17 00:00:00 2001 From: "Quentin (OpenERP)" Date: Wed, 2 Oct 2013 22:46:24 +0200 Subject: [PATCH 07/13] [DEBUG] debug statement bzr revid: qdp-launchpad@openerp.com-20131002204624-g1h9lylck0cx8bww --- addons/purchase/purchase.py | 2 +- addons/sale_stock_location/sale_stock_location.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/addons/purchase/purchase.py b/addons/purchase/purchase.py index 68469ded48e..66b67961a22 100644 --- a/addons/purchase/purchase.py +++ b/addons/purchase/purchase.py @@ -1135,7 +1135,7 @@ class procurement_order(osv.osv): return rule_id def _run(self, cr, uid, procurement, context=None): - print "dans le _run de purchase", procurement.rule_id and procurement.rule_id.name or 'pas de rule' + print "dans le run de purchase", procurement.rule_id and procurement.rule_id.name or 'pas de rule' if procurement.rule_id and procurement.rule_id.action == 'buy': print "go pour make_po" #make a purchase order for the procurement diff --git a/addons/sale_stock_location/sale_stock_location.py b/addons/sale_stock_location/sale_stock_location.py index 4107af9e261..ac08fd21547 100644 --- a/addons/sale_stock_location/sale_stock_location.py +++ b/addons/sale_stock_location/sale_stock_location.py @@ -40,6 +40,7 @@ class sale_order(osv.osv): routes += route_ids route_id = line.route_id and [(4, line.route_id.id)] or [] routes += route_id + print 'toutes les routes sur le procurement', routes res.update({ 'route_ids': routes }) From 25ead5971309fb43f851f878639f1a8ce70832a8 Mon Sep 17 00:00:00 2001 From: "Quentin (OpenERP)" Date: Wed, 2 Oct 2013 23:10:40 +0200 Subject: [PATCH 08/13] [DEBUG] debug statement bzr revid: qdp-launchpad@openerp.com-20131002211040-s5tglavh3g8hok6w --- addons/purchase/purchase.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/addons/purchase/purchase.py b/addons/purchase/purchase.py index 66b67961a22..317b542e103 100644 --- a/addons/purchase/purchase.py +++ b/addons/purchase/purchase.py @@ -1135,7 +1135,10 @@ class procurement_order(osv.osv): return rule_id def _run(self, cr, uid, procurement, context=None): - print "dans le run de purchase", procurement.rule_id and procurement.rule_id.name or 'pas de rule' + print "dans le run de purchase" + print procurement + a = procurement.rule_id and procurement.rule_id.name or 'pas de rule' + print a if procurement.rule_id and procurement.rule_id.action == 'buy': print "go pour make_po" #make a purchase order for the procurement From 380a64b6b4559965cf79db9308acd58df721e2da Mon Sep 17 00:00:00 2001 From: "Quentin (OpenERP)" Date: Wed, 2 Oct 2013 23:31:41 +0200 Subject: [PATCH 09/13] [DEBUG] debug statement bzr revid: qdp-launchpad@openerp.com-20131002213141-m7uu4yga6hlzp4lt --- addons/purchase/purchase.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/addons/purchase/purchase.py b/addons/purchase/purchase.py index 317b542e103..f3e2bd23b9f 100644 --- a/addons/purchase/purchase.py +++ b/addons/purchase/purchase.py @@ -1137,8 +1137,9 @@ class procurement_order(osv.osv): def _run(self, cr, uid, procurement, context=None): print "dans le run de purchase" print procurement - a = procurement.rule_id and procurement.rule_id.name or 'pas de rule' - print a + print procurement.rule_id + #a = procurement.rule_id and procurement.rule_id.name or 'pas de rule' + #print a if procurement.rule_id and procurement.rule_id.action == 'buy': print "go pour make_po" #make a purchase order for the procurement From db0b40111e956d037347f9a3c657a1ae301e401f Mon Sep 17 00:00:00 2001 From: "Quentin (OpenERP)" Date: Wed, 2 Oct 2013 23:57:45 +0200 Subject: [PATCH 10/13] [DEBUG] debug statement bzr revid: qdp-launchpad@openerp.com-20131002215745-9l5spf55ec6nr6ti --- addons/purchase/purchase.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/addons/purchase/purchase.py b/addons/purchase/purchase.py index f3e2bd23b9f..30a55bd3e45 100644 --- a/addons/purchase/purchase.py +++ b/addons/purchase/purchase.py @@ -1138,6 +1138,9 @@ class procurement_order(osv.osv): print "dans le run de purchase" print procurement print procurement.rule_id + if procurement.rule_id: + print procurement.rule_id.action + print procurement.rule_id.name #a = procurement.rule_id and procurement.rule_id.name or 'pas de rule' #print a if procurement.rule_id and procurement.rule_id.action == 'buy': From b1d9c439d2d64d70d043847c70b83f06686190e7 Mon Sep 17 00:00:00 2001 From: "Quentin (OpenERP)" Date: Thu, 3 Oct 2013 09:17:33 +0200 Subject: [PATCH 11/13] [DEBUG] debug statement bzr revid: qdp-launchpad@openerp.com-20131003071733-ubx5ejm3n430hb5t --- addons/purchase/purchase.py | 1 - addons/stock_complex_routes/test/dropship.yml | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/purchase/purchase.py b/addons/purchase/purchase.py index 30a55bd3e45..e23ee0431ac 100644 --- a/addons/purchase/purchase.py +++ b/addons/purchase/purchase.py @@ -1140,7 +1140,6 @@ class procurement_order(osv.osv): print procurement.rule_id if procurement.rule_id: print procurement.rule_id.action - print procurement.rule_id.name #a = procurement.rule_id and procurement.rule_id.name or 'pas de rule' #print a if procurement.rule_id and procurement.rule_id.action == 'buy': diff --git a/addons/stock_complex_routes/test/dropship.yml b/addons/stock_complex_routes/test/dropship.yml index d9d70cc83ba..598a4c6a2b9 100644 --- a/addons/stock_complex_routes/test/dropship.yml +++ b/addons/stock_complex_routes/test/dropship.yml @@ -56,6 +56,7 @@ procurement_order = self.pool.get("procurement.group").browse(cr, uid, sale_record.procurement_group_id.id).procurement_ids[0] print 'procurement_order', procurement_order.state print 'test', procurement_order.purchase_line_id.order_id + print 'test rule name', procurement_order.rule_id.name purchase_id = procurement_order.purchase_line_id.order_id.id wf_service = netsvc.LocalService('workflow') From 11fa96bbbd6d1108f737283e942e03419f7e8ad1 Mon Sep 17 00:00:00 2001 From: "Quentin (OpenERP)" Date: Thu, 3 Oct 2013 11:17:09 +0200 Subject: [PATCH 12/13] [FIX] fixed find_suitable_rule, fixed data for main warehouse and added debug statement for crashing yaml test bzr revid: qdp-launchpad@openerp.com-20131003091709-q4boyc5dwz2ec7ho --- addons/mrp/procurement.py | 8 ------- addons/purchase/purchase.py | 8 ------- addons/stock_complex_routes/test/dropship.yml | 5 ++++ addons/stock_location/stock_location.py | 23 ++++++++++++------- addons/stock_location/stock_location_data.xml | 13 +++++++---- 5 files changed, 28 insertions(+), 29 deletions(-) diff --git a/addons/mrp/procurement.py b/addons/mrp/procurement.py index 4971d849227..df80ac2ea9f 100644 --- a/addons/mrp/procurement.py +++ b/addons/mrp/procurement.py @@ -40,14 +40,6 @@ class procurement_order(osv.osv): 'production_id': fields.many2one('mrp.production', 'Manufacturing Order'), } - def _find_suitable_rule(self, cr, uid, procurement, context=None): - rule_id = super(procurement_order, self)._find_suitable_rule(cr, uid, procurement, context=context) - if not rule_id: - #if there isn't any specific procurement.rule defined for the product, we try to directly supply it from a supplier - rule_id = self._search_suitable_rule(cr, uid, procurement, [('action', '=', 'manufacture'), ('location_id', '=', procurement.location_id.id)], context=context) - rule_id = rule_id and rule_id[0] or False - return rule_id - def _run(self, cr, uid, procurement, context=None): if procurement.rule_id and procurement.rule_id.action == 'manufacture': #make a manufacturing order for the procurement diff --git a/addons/purchase/purchase.py b/addons/purchase/purchase.py index e23ee0431ac..c2c5a053eab 100644 --- a/addons/purchase/purchase.py +++ b/addons/purchase/purchase.py @@ -1126,14 +1126,6 @@ class procurement_order(osv.osv): 'purchase_line_id': fields.many2one('purchase.order.line', 'Purchase Order'), } - def _find_suitable_rule(self, cr, uid, procurement, context=None): - rule_id = super(procurement_order, self)._find_suitable_rule(cr, uid, procurement, context=context) - if not rule_id: - #if there isn't any specific procurement.rule defined for the product, we try to directly supply it from a supplier - rule_id = self._search_suitable_rule(cr, uid, procurement, [('action', '=', 'buy'), ('location_id', '=', procurement.location_id.id)], context=context) - rule_id = rule_id and rule_id[0] or False - return rule_id - def _run(self, cr, uid, procurement, context=None): print "dans le run de purchase" print procurement diff --git a/addons/stock_complex_routes/test/dropship.yml b/addons/stock_complex_routes/test/dropship.yml index 598a4c6a2b9..a9790ea5c9c 100644 --- a/addons/stock_complex_routes/test/dropship.yml +++ b/addons/stock_complex_routes/test/dropship.yml @@ -57,6 +57,11 @@ print 'procurement_order', procurement_order.state print 'test', procurement_order.purchase_line_id.order_id print 'test rule name', procurement_order.rule_id.name + print 'test route sequence', [(r.name, r.sequence) for r in procurement_order.route_ids] + rule_seq = [] + for route in procurement_order.route_ids: + rule_seq += [(ru.name, ru.route_sequence, ru.sequence) for ru in route.pull_ids] + print '####RULES SEQ####', rule_seq purchase_id = procurement_order.purchase_line_id.order_id.id wf_service = netsvc.LocalService('workflow') diff --git a/addons/stock_location/stock_location.py b/addons/stock_location/stock_location.py index aeff85edd3f..6c1892bc18f 100644 --- a/addons/stock_location/stock_location.py +++ b/addons/stock_location/stock_location.py @@ -581,27 +581,34 @@ class procurement_order(osv.osv): }) return d + def _find_parent_locations(self, cr, uid, procurement, context=None): + location = procurement.location_id + res = [location.id] + while location.location_id: + location = location.location_id + res.append(location.id) + return res + def _find_suitable_rule(self, cr, uid, procurement, context=None): rule_id = super(procurement_order, self)._find_suitable_rule(cr, uid, procurement, context=context) if not rule_id: - rule_id = self._search_suitable_rule(cr, uid, procurement, [('location_id', '=', procurement.location_id.id)], context=context) #action=move + #a rule defined on 'Stock' is suitable for a procurement in 'Stock\Bin A' + all_parent_location_ids = self._find_parent_locations(cr, uid, procurement, context=context) + rule_id = self._search_suitable_rule(cr, uid, procurement, [('location_id', 'in', all_parent_location_ids)], context=context) rule_id = rule_id and rule_id[0] or False return rule_id 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''' - categ_obj = self.pool.get("product.category") - categ_id = procurement.product_id.categ_id.id - route_ids1 = [x.id for x in procurement.product_id.route_ids + procurement.product_id.categ_id.total_route_ids] - route_ids2 = [x.id for x in procurement.route_ids] - res = self.pool.get('procurement.rule').search(cr, uid, domain + [('route_id', 'in', route_ids1)], order = 'route_sequence, sequence', context=context) + 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] + 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: - res = self.pool.get('procurement.rule').search(cr, uid, domain + [('route_id', 'in', route_ids2)], 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) if not res: res = self.pool.get('procurement.rule').search(cr, uid, domain + [('route_id', '=', False)], order='sequence', context=context) return res - class product_putaway_strategy(osv.osv): _name = 'product.putaway' _description = 'Put Away Strategy' diff --git a/addons/stock_location/stock_location_data.xml b/addons/stock_location/stock_location_data.xml index 5cbb9d863e4..cc83be2dc85 100644 --- a/addons/stock_location/stock_location_data.xml +++ b/addons/stock_location/stock_location_data.xml @@ -84,26 +84,29 @@ + - Your Company: Stock → Customers + Your Company: Output → Customers move - + make_to_order + - Your Company: Stock → Stock + Your Company: Input → Output move - - + + make_to_stock + From 5e5fc75451e166fa60d28aa5a23bb1dcf0bc636c Mon Sep 17 00:00:00 2001 From: "Quentin (OpenERP)" Date: Thu, 3 Oct 2013 11:47:17 +0200 Subject: [PATCH 13/13] [DEBUg] debug statement bzr revid: qdp-launchpad@openerp.com-20131003094717-5kdd7r59ysvoq6gk --- addons/stock_complex_routes/test/dropship.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/stock_complex_routes/test/dropship.yml b/addons/stock_complex_routes/test/dropship.yml index a9790ea5c9c..276d6b33bbd 100644 --- a/addons/stock_complex_routes/test/dropship.yml +++ b/addons/stock_complex_routes/test/dropship.yml @@ -56,7 +56,7 @@ procurement_order = self.pool.get("procurement.group").browse(cr, uid, sale_record.procurement_group_id.id).procurement_ids[0] print 'procurement_order', procurement_order.state print 'test', procurement_order.purchase_line_id.order_id - print 'test rule name', procurement_order.rule_id.name + print 'test rule', procurement_order.rule_id.action print 'test route sequence', [(r.name, r.sequence) for r in procurement_order.route_ids] rule_seq = [] for route in procurement_order.route_ids: