1
# -*- coding: utf-8 -*-
2
##############################################################################
4
# OpenERP, Open Source Management Solution
5
# Copyright (C) 2011 NovaPoint Group LLC (<http://www.novapointgroup.com>)
6
# Copyright (C) 2004-2010 OpenERP SA (<http://www.openerp.com>)
8
# This program is free software: you can redistribute it and/or modify
9
# it under the terms of the GNU General Public License as published by
10
# the Free Software Foundation, either version 3 of the License, or
11
# (at your option) any later version.
13
# This program is distributed in the hope that it will be useful,
14
# but WITHOUT ANY WARRANTY; without even the implied warranty of
15
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
# GNU General Public License for more details.
18
# You should have received a copy of the GNU General Public License
19
# along with this program. If not, see <http://www.gnu.org/licenses/>
21
##############################################################################
23
from osv import fields, osv
26
class stock_move(osv.osv):
27
_inherit = "stock.move"
29
def _get_order_no(self, cr, uid, product):
31
for multi_loc in product.multi_location_ids:
32
if multi_loc.evaluation_order > eval:
33
eval = multi_loc.evaluation_order
36
def _get_storage_type(self, cr, uid, product):
37
for multi_loc in product.multi_location_ids:
38
if multi_loc.storage_type == 'primary':
42
def _create_multilocation(self, cr, uid, ids, vals, context=None):
43
if vals.get('move_dest_id', False) or (vals.get('state', False) and vals['state'] <> "cancel" ):
44
warehouse_obj = self.pool.get('stock.warehouse')
45
warehouse_ids = warehouse_obj.search(cr, uid, [], context=context)
47
for lot_stock_id in warehouse_obj.read(cr, uid, warehouse_ids, ['lot_stock_id']):
48
lot_stock_ids.append(lot_stock_id['lot_stock_id'][0])
49
if isinstance(ids, (int, long)):
51
for move in self.browse(cr, uid, ids, context=context):
52
if move.location_dest_id.usage != 'internal' or move.location_dest_id.id in lot_stock_ids:
54
multi_loc_obj = self.pool.get('stock.multi.location')
55
search_list = [('product_id', '=', move.product_id.id), ('location_name', '=', move.location_dest_id.id)]
56
if not multi_loc_obj.search(cr, uid, search_list, context=context):
58
storage_type = "overstock"
59
for multi_location in move.product_id.multi_location_ids:
60
if multi_location.evaluation_order >= evaluation_order:
61
evaluation_order = multi_location.evaluation_order + 1
62
multi_loc_obj.create(cr, uid, {
63
'valuation_order': evaluation_order,
64
'storage_type': storage_type,
65
'warehouse': multi_loc_obj._get_shop_id(cr, uid, [], context=context),
66
'location_name': move.location_dest_id.id,
67
'product_uom': move.product_uom.id,
71
'location_active': True,
72
'product_id':move.product_id.id,
76
def write(self, cr, uid, ids, vals, context=None):
77
if isinstance(ids, (int, long)):
79
res=super(stock_move, self).write(cr, uid, ids, vals, context=context)
81
self._create_multilocation(cr, uid, ids, vals, context)
84
def create(self, cr, uid, vals, context=None):
85
res=super(stock_move, self).create(cr, uid, vals, context)
87
self._create_multilocation(cr, uid, [res], vals, context)
90
def _stock_available(self, cr, uid, ids, name, arg, context=None):
92
for obj in self.browse(cr, uid, ids, context=context):
94
loc_obj = self.pool.get('stock.location')
95
stock_vals = loc_obj.read(cr, uid, obj.location_id.id, ['stock_real', 'stock_virtual'], context={'product_id': obj.product_id.id})
96
if obj.product_id.type != 'consu' and stock_vals['stock_real'] < qty:
103
'stock_available': fields.function(_stock_available, method=True, type='boolean', string='Stock Available')
106
def check_assign(self, cr, uid, ids, context=None):
108
move_data = self.read(cr, uid, ids, ['picking_id'], context=context)
109
for move in move_data:
110
picking_id = move['picking_id'] and move['picking_id'][0]
111
production_ids = self.pool.get('mrp.production').search(cr, uid, [('picking_id', '=', picking_id)], context=context)
112
if picking_id and not production_ids:
113
ret.append(move['id'])
116
ret.append(move['id'])
118
return super(stock_move, self).check_assign(cr, uid, ret, context=context)
120
def action_consume(self, cr, uid, ids, product_qty, location_id=False, context=None):
122
Consumed product with specific quatity from specific source location.
123
@param product_qty: Consumed product quantity
124
@param location_id: Source location
125
@return: Consumed lines
128
production_obj = self.pool.get('mrp.production')
129
wf_service = netsvc.LocalService("workflow")
130
for move in self.browse(cr, uid, ids, context=context):
131
new_moves = super(stock_move, self).action_consume(cr, uid, [move.id], product_qty, move.location_id.id, context=context)
132
production_ids = production_obj.search(cr, uid, [('move_lines', 'in', [move.id])])
133
for prod in production_obj.browse(cr, uid, production_ids, context=context):
134
if prod.state == 'confirmed':
135
production_obj.force_production(cr, uid, [prod.id])
136
wf_service.trg_validate(uid, 'mrp.production', prod.id, 'button_produce', cr)
137
for new_move in new_moves:
138
if new_move == move.id:
139
continue #This move is already there in move lines of production order
140
production_obj.write(cr, uid, production_ids, {'move_lines': [(4, new_move)]}, context=context)
146
class stock_picking(osv.osv):
147
_inherit = "stock.picking"
149
'explode_multi_locations': fields.boolean('Explode Multi Location')
153
'explode_multi_locations': True
156
def explode_multilocation(self, cr, uid, ids):
157
for pick in self.browse(cr, uid, ids):
158
if not (pick.explode_multi_locations and pick.type == "out"):
160
for move in pick.move_lines:
161
total_product = remaining_product = move.product_qty
162
if total_product < 0:
164
for multi_location in move.product_id.multi_location_ids:
165
multi_location_id = multi_location.location_name.location_id and multi_location.location_name.location_id.id or False
166
if remaining_product >0 and multi_location_id == move.location_id.id and multi_location.qty_available > 0:
168
'location_id': multi_location.location_name.id,
169
'product_qty': min(remaining_product, multi_location.qty_available),
170
'location_dest_id': move.location_dest_id.id,
171
'date_expected': move.date_expected,
174
remaining_product = remaining_product - min(remaining_product, multi_location.qty_available)
175
last_move_created_id = self.pool.get("stock.move").copy(cr, uid, move.id, default_vals)
176
if remaining_product > 0:
177
cr.execute("update stock_move set product_qty = %s where id = %s" %(str(remaining_product), str(move.id)))
179
cr.execute("update procurement_order set move_id = %s where move_id = %s" %(last_move_created_id, move.id))
180
cr.execute("delete from stock_move where id = %s" %str(move.id))
183
def action_assign(self, cr, uid, ids, *args):
184
self.explode_multilocation(cr, uid, ids)
185
ret = super(stock_picking, self).action_assign(cr, uid, ids, *args)
188
def draft_force_assign(self, cr, uid, ids, *args):
189
self.explode_multilocation(cr, uid, ids)
190
ret = super(stock_picking, self).draft_force_assign(cr, uid, ids, *args)
193
def draft_validate(self, cr, uid, ids, *args):
194
self.explode_multilocation(cr, uid, ids)
195
ret = super(stock_picking, self).draft_validate(cr, uid, ids, *args)
199
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
b'\\ No newline at end of file'