~unifield-team/unifield-wm/us-826

93.9.1 by chloups208
[UF-33] correction of asset which is now linked to stock.move in a wizard when processing the stock.picking
1
##############################################################################
2
#
3
#    OpenERP, Open Source Management Solution
4
#    Copyright (C) 2011 TeMPO Consulting, MSF
5
#
6
#    This program is free software: you can redistribute it and/or modify
7
#    it under the terms of the GNU Affero General Public License as
8
#    published by the Free Software Foundation, either version 3 of the
9
#    License, or (at your option) any later version.
10
#
11
#    This program is distributed in the hope that it will be useful,
12
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
13
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
#    GNU Affero General Public License for more details.
15
#
16
#    You should have received a copy of the GNU Affero General Public License
17
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
18
#
19
##############################################################################
20
21
from datetime import datetime
22
from dateutil.relativedelta import relativedelta
23
import time
24
from operator import itemgetter
25
from itertools import groupby
26
27
from osv import fields, osv
28
from tools.translate import _
29
import netsvc
30
import tools
31
import decimal_precision as dp
32
import logging
778.8.1 by jf
Data: loading order for yml test
33
from os import path
93.9.1 by chloups208
[UF-33] correction of asset which is now linked to stock.move in a wizard when processing the stock.picking
34
35
243.1.5 by Quentin THEURET
UF-370 [IMP] Added an overriding of procurement.order action_confirm method to give a default reason type when a stock move is created from a procurement order
36
#----------------------------------------------------------
37
# Procurement Order
38
#----------------------------------------------------------
39
class procurement_order(osv.osv):
40
    _name = 'procurement.order'
41
    _inherit = 'procurement.order'
409.3.25 by chloups208
uf-651 - adapt to give confirmed date a default value if object comes from workflow
42
    
43
    def create(self, cr, uid, vals, context=None):
44
        '''
45
        create method for filling flag from yml tests
46
        '''
47
        if context is None:
48
            context = {}
559.15.1 by jf
From yml
49
        if context.get('update_mode') in ['init', 'update'] and 'from_yml_test' not in vals:
409.3.25 by chloups208
uf-651 - adapt to give confirmed date a default value if object comes from workflow
50
            logging.getLogger('init').info('PRO: set from yml test to True')
51
            vals['from_yml_test'] = True
52
        return super(procurement_order, self).create(cr, uid, vals, context=context)
243.1.5 by Quentin THEURET
UF-370 [IMP] Added an overriding of procurement.order action_confirm method to give a default reason type when a stock move is created from a procurement order
53
54
    def action_confirm(self, cr, uid, ids, context=None):
55
        """ Confirms procurement and writes exception message if any.
56
        @return: True
57
        """
58
        move_obj = self.pool.get('stock.move')
59
        for procurement in self.browse(cr, uid, ids, context=context):
60
            if procurement.product_qty <= 0.00:
61
                raise osv.except_osv(_('Data Insufficient !'),
62
                    _('Please check the Quantity in Procurement Order(s), it should not be less than 1!'))
63
            if procurement.product_id.type in ('product', 'consu'):
64
                if not procurement.move_id:
65
                    source = procurement.location_id.id
66
                    reason_type_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'reason_types_moves', 'reason_type_other')[1]
67
                    if procurement.procure_method == 'make_to_order':
68
                        reason_type_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'reason_types_moves', 'reason_type_external_supply')[1]
69
                        source = procurement.product_id.product_tmpl_id.property_stock_procurement.id
70
                    id = move_obj.create(cr, uid, {
71
                        'name': procurement.name,
72
                        'location_id': source,
73
                        'location_dest_id': procurement.location_id.id,
74
                        'product_id': procurement.product_id.id,
75
                        'product_qty': procurement.product_qty,
76
                        'product_uom': procurement.product_uom.id,
77
                        'date_expected': procurement.date_planned,
78
                        'state': 'draft',
79
                        'company_id': procurement.company_id.id,
80
                        'auto_validate': True,
81
                        'reason_type_id': reason_type_id,
82
                    })
83
                    move_obj.action_confirm(cr, uid, [id], context=context)
84
                    self.write(cr, uid, [procurement.id], {'move_id': id, 'close_move': 1})
85
        self.write(cr, uid, ids, {'state': 'confirmed', 'message': ''})
86
        return True
87
    
892.7.24 by chloups208
uf-1050 work the state of sale order line, update copy methods to allow to set default value for state, the splitted fo has sourced lines, lines of original fo are done
88
    def copy_data(self, cr, uid, id, default=None, context=None):
89
        '''
90
        reset link to purchase order from update of on order purchase order
91
        '''
92
        if not default:
93
            default = {}
1105.3.4 by chloups208
uf-1191 split function for Purchase Order, taking into account full behavior of Field Order back update, added original on order purchase order line reference to get line number value during new purchase order line creation
94
        default.update({'so_back_update_dest_po_id_procurement_order': False,
95
                        'so_back_update_dest_pol_id_procurement_order': False})
892.7.24 by chloups208
uf-1050 work the state of sale order line, update copy methods to allow to set default value for state, the splitted fo has sourced lines, lines of original fo are done
96
        return super(procurement_order, self).copy_data(cr, uid, id, default, context=context)
97
    
409.3.25 by chloups208
uf-651 - adapt to give confirmed date a default value if object comes from workflow
98
    _columns = {'from_yml_test': fields.boolean('Only used to pass addons unit test', readonly=True, help='Never set this field to true !'),
892.7.23 by chloups208
uf-1050 added origin value in procurement and sale order line for merging new purchase order line in the source purchase order which originated the split with impact
99
                # this field is used when the po is modified during on order process, and the so must be modified accordingly
100
                # the resulting new purchase order line will be merged in specified po_id 
101
                'so_back_update_dest_po_id_procurement_order': fields.many2one('purchase.order', string='Destination of new purchase order line', readonly=True),
1105.3.4 by chloups208
uf-1191 split function for Purchase Order, taking into account full behavior of Field Order back update, added original on order purchase order line reference to get line number value during new purchase order line creation
102
                'so_back_update_dest_pol_id_procurement_order': fields.many2one('purchase.order.line', string='Original purchase order line', readonly=True),
409.3.25 by chloups208
uf-651 - adapt to give confirmed date a default value if object comes from workflow
103
                }
104
    
105
    _defaults = {'from_yml_test': lambda *a: False,
106
                 }
107
    
243.1.5 by Quentin THEURET
UF-370 [IMP] Added an overriding of procurement.order action_confirm method to give a default reason type when a stock move is created from a procurement order
108
procurement_order()
109
93.9.1 by chloups208
[UF-33] correction of asset which is now linked to stock.move in a wizard when processing the stock.picking
110
111
#----------------------------------------------------------
112
# Stock Picking
113
#----------------------------------------------------------
114
class stock_picking(osv.osv):
115
    _inherit = "stock.picking"
116
    _description = "Picking List"
584.11.3 by Quentin THEURET
UF-801 [FIX] Fixed log message by changing 'Done' to 'Closed'.
117
    
118
    def _hook_state_list(self, cr, uid, *args, **kwargs):
119
        '''
120
        Change terms into states list
121
        '''
122
        state_list = kwargs['state_list']
123
        
124
        state_list['done'] = _('is closed.')
125
        
126
        return state_list
374.5.1 by Quentin THEURET
UF-402 [IMP] Modified states values according to the naming convention
127
128
    _columns = {
129
        'state': fields.selection([
130
            ('draft', 'Draft'),
131
            ('auto', 'Waiting'),
132
            ('confirmed', 'Confirmed'),
133
            ('assigned', 'Available'),
134
            ('done', 'Closed'),
135
            ('cancel', 'Cancelled'),
136
            ], 'State', readonly=True, select=True,
137
            help="* Draft: not confirmed yet and will not be scheduled until confirmed\n"\
138
                 "* Confirmed: still waiting for the availability of products\n"\
139
                 "* Available: products reserved, simply waiting for confirmation.\n"\
140
                 "* Waiting: waiting for another move to proceed before it becomes automatically available (e.g. in Make-To-Order flows)\n"\
141
                 "* Closed: has been processed, can't be modified or cancelled anymore\n"\
142
                 "* Cancelled: has been cancelled, can't be confirmed anymore"),
509 by jf
UF-651 [MERGE] Order dates mechanism
143
        'from_yml_test': fields.boolean('Only used to pass addons unit test', readonly=True, help='Never set this field to true !'),
781.5.3 by Quentin THEURET
UF-956 [FIX] Made partner and address readonly when the picking is closed/cancelled
144
        'address_id': fields.many2one('res.partner.address', 'Delivery address', help="Address of partner", readonly=False, states={'done': [('readonly', True)], 'cancel': [('readonly', True)]}, domain="[('partner_id', '=', partner_id)]"),
781.5.1 by Quentin THEURET
[FIX] Made the partner not mandatory on internal picking
145
        'partner_id2': fields.many2one('res.partner', 'Partner', required=False),
878.4.4 by pierre-marie
UF-1060 - General picking documents modifications - End of second and third part
146
        'from_wkf': fields.boolean('From wkf'),
374.5.1 by Quentin THEURET
UF-402 [IMP] Modified states values according to the naming convention
147
    }
409.3.25 by chloups208
uf-651 - adapt to give confirmed date a default value if object comes from workflow
148
    
149
    _defaults = {'from_yml_test': lambda *a: False,
878.4.4 by pierre-marie
UF-1060 - General picking documents modifications - End of second and third part
150
                'from_wkf': lambda *a: False,
409.3.25 by chloups208
uf-651 - adapt to give confirmed date a default value if object comes from workflow
151
                 }
152
    
153
    def create(self, cr, uid, vals, context=None):
154
        '''
155
        create method for filling flag from yml tests
156
        '''
157
        if context is None:
158
            context = {}
878.4.5 by pierre-marie
UF-1060 - General picking documents modifications - End of second and third part
159
160
        if not context.get('active_id',False):
878.4.4 by pierre-marie
UF-1060 - General picking documents modifications - End of second and third part
161
            vals['from_wkf'] = True
1229.4.1 by matthieu.choplin at msf
[utp-122] in case we duplicate an internal moves coming from a workflow, we keep the product editable
162
        # in case me make a copy of a stock.picking coming from a workflow
163
        if context.get('not_workflow', False):
164
            vals['from_wkf'] = False
878.4.4 by pierre-marie
UF-1060 - General picking documents modifications - End of second and third part
165
    
559.15.2 by jf
yml_test for PICKING
166
        if context.get('update_mode') in ['init', 'update'] and 'from_yml_test' not in vals:
409.3.25 by chloups208
uf-651 - adapt to give confirmed date a default value if object comes from workflow
167
            logging.getLogger('init').info('PICKING: set from yml test to True')
168
            vals['from_yml_test'] = True
633.6.6 by Quentin THEURET
UF-855 [IMP] Add 3 addresses on OUT/PICK
169
            
170
        if not vals.get('partner_id2') and vals.get('address_id'):
171
            addr = self.pool.get('res.partner.address').browse(cr, uid, vals.get('address_id'), context=context)
172
            vals['partner_id2'] = addr.partner_id and addr.partner_id.id or False
173
            
174
        if not vals.get('address_id') and vals.get('partner_id2'):
175
            addr = self.pool.get('res.partner').address_get(cr, uid, vals.get('partner_id2'), ['delivery', 'default'])
176
            if not addr.get('delivery'):
177
                vals['address_id'] = addr.get('default')
178
            else:
179
                vals['address_id'] = addr.get('delivery')
409.3.25 by chloups208
uf-651 - adapt to give confirmed date a default value if object comes from workflow
180
        return super(stock_picking, self).create(cr, uid, vals, context=context)
93.9.1 by chloups208
[UF-33] correction of asset which is now linked to stock.move in a wizard when processing the stock.picking
181
    
706 by jf
[FIX] context None
182
    def write(self, cr, uid, ids, vals, context=None):
633.6.6 by Quentin THEURET
UF-855 [IMP] Add 3 addresses on OUT/PICK
183
        '''
184
        Update the partner or the address according to the other
185
        '''
186
        if not vals.get('address_id') and vals.get('partner_id2'):
187
            for pick in self.browse(cr, uid, ids, context=context):
188
                if pick.partner_id.id != vals.get('partner_id2'):
189
                    addr = self.pool.get('res.partner').address_get(cr, uid, vals.get('partner_id2'), ['delivery', 'default'])
190
                    if not addr.get('delivery'):
191
                        vals['address_id'] = addr.get('default')
192
                    else:
193
                        vals['address_id'] = addr.get('delivery')
194
                        
195
        if not vals.get('partner_id2') and vals.get('address_id'):
196
            for pick in self.browse(cr, uid, ids, context=context):
197
                if pick.address_id.id != vals.get('address_id'):
198
                    addr = self.pool.get('res.partner.address').browse(cr, uid, vals.get('address_id'), context=context)
199
                    vals['partner_id2'] = addr.partner_id and addr.partner_id.id or False
200
        
201
        return super(stock_picking, self).write(cr, uid, ids, vals, context=context)
202
    
706 by jf
[FIX] context None
203
    def on_change_partner(self, cr, uid, ids, partner_id, address_id, context=None):
633.6.6 by Quentin THEURET
UF-855 [IMP] Add 3 addresses on OUT/PICK
204
        '''
205
        Change the delivery address when the partner change.
206
        '''
207
        v = {}
208
        d = {}
209
        
210
        if not partner_id:
211
            v.update({'address_id': False})
212
        else:
1213.5.4 by Quentin THEURET
UF-1472 [IMP] Change document name in res.log when confirm a Picking ticket
213
            d.update({'address_id': [('partner_id', '=', partner_id)]})
633.6.6 by Quentin THEURET
UF-855 [IMP] Add 3 addresses on OUT/PICK
214
            
215
216
        if address_id:
217
            addr = self.pool.get('res.partner.address').browse(cr, uid, address_id, context=context)
218
        
219
        if not address_id or addr.partner_id.id != partner_id:
220
            addr = self.pool.get('res.partner').address_get(cr, uid, partner_id, ['delivery', 'default'])
221
            if not addr.get('delivery'):
222
                addr = addr.get('default')
223
            else:
224
                addr = addr.get('delivery')
225
                
226
            v.update({'address_id': addr})
227
            
228
        
229
        return {'value': v,
230
                'domain': d}
231
    
706 by jf
[FIX] context None
232
    def set_manually_done(self, cr, uid, ids, all_doc=True, context=None):
451.4.2 by Quentin THEURET
UF-631 [ADD] Added a report to documents done
233
        '''
234
        Set the picking to done
235
        '''
236
        move_ids = []
451.5.7 by Quentin THEURET
UF-631 [IMP] Removed the done state on workflows
237
238
        if isinstance(ids, (int, long)):
239
            ids = [ids]
240
451.4.2 by Quentin THEURET
UF-631 [ADD] Added a report to documents done
241
        for pick in self.browse(cr, uid, ids, context=context):
242
            for move in pick.move_lines:
451.4.12 by Quentin THEURET
UF-631 [IMP] Reworked stock move cancellation
243
                if move.state not in ('cancel', 'done'):
451.4.2 by Quentin THEURET
UF-631 [ADD] Added a report to documents done
244
                    move_ids.append(move.id)
245
246
        #Set all stock moves to done
559.27.7 by Quentin THEURET
UF-780 [FIX] Get a confirmation message on closing action
247
        self.pool.get('stock.move').set_manually_done(cr, uid, move_ids, all_doc=all_doc, context=context)
451.4.2 by Quentin THEURET
UF-631 [ADD] Added a report to documents done
248
249
        return True
93.9.1 by chloups208
[UF-33] correction of asset which is now linked to stock.move in a wizard when processing the stock.picking
250
    
778.7.8 by chloups208
uf-643 claim processing from incoming shipment
251
    def _do_partial_hook(self, cr, uid, ids, context=None, *args, **kwargs):
93.9.1 by chloups208
[UF-33] correction of asset which is now linked to stock.move in a wizard when processing the stock.picking
252
        '''
778.7.8 by chloups208
uf-643 claim processing from incoming shipment
253
        Please copy this to your module's method also.
254
        This hook belongs to the do_partial method from stock_override>stock.py>stock_picking
255
        
256
        - allow to modify the defaults data for move creation and copy
93.9.1 by chloups208
[UF-33] correction of asset which is now linked to stock.move in a wizard when processing the stock.picking
257
        '''
258
        defaults = kwargs.get('defaults')
259
        assert defaults is not None, 'missing defaults'
260
        
261
        return defaults
778.7.8 by chloups208
uf-643 claim processing from incoming shipment
262
    
263
    def _picking_done_cond(self, cr, uid, ids, context=None, *args, **kwargs):
264
        '''
265
        Please copy this to your module's method also.
266
        This hook belongs to the do_partial method from stock_override>stock.py>stock_picking
267
        
268
        - allow to conditionally execute the picking processing to done
269
        '''
270
        return True
271
    
272
    def _custom_code(self, cr, uid, ids, context=None, *args, **kwargs):
273
        '''
274
        Please copy this to your module's method also.
275
        This hook belongs to the do_partial method from stock_override>stock.py>stock_picking
276
        
277
        - allow to execute specific custom code before processing picking to done
278
        - no supposed to modify partial_datas
279
        '''
280
        return True
93.9.1 by chloups208
[UF-33] correction of asset which is now linked to stock.move in a wizard when processing the stock.picking
281
282
    # @@@override stock>stock.py>stock_picking>do_partial
283
    def do_partial(self, cr, uid, ids, partial_datas, context=None):
284
        """ Makes partial picking and moves done.
285
        @param partial_datas : Dictionary containing details of partial picking
286
                          like partner_id, address_id, delivery_date,
287
                          delivery moves with product_id, product_qty, uom
288
        @return: Dictionary of values
289
        """
290
        if context is None:
291
            context = {}
292
        else:
293
            context = dict(context)
294
        res = {}
295
        move_obj = self.pool.get('stock.move')
296
        product_obj = self.pool.get('product.product')
297
        currency_obj = self.pool.get('res.currency')
298
        uom_obj = self.pool.get('product.uom')
299
        sequence_obj = self.pool.get('ir.sequence')
300
        wf_service = netsvc.LocalService("workflow")
820.2.1 by jf
UF-1020 Avg cost price
301
947.3.4 by Quentin THEURET
UF-1067 [IMP] Product average cost computation : Don't compute with products qty in cross docking locations
302
        internal_loc_ids = self.pool.get('stock.location').search(cr, uid, [('usage','=','internal'), ('cross_docking_location_ok', '=', False)])
820.2.1 by jf
UF-1020 Avg cost price
303
        ctx_avg = context.copy()
304
        ctx_avg['location'] = internal_loc_ids
93.9.1 by chloups208
[UF-33] correction of asset which is now linked to stock.move in a wizard when processing the stock.picking
305
        for pick in self.browse(cr, uid, ids, context=context):
306
            new_picking = None
878.4.3 by pierre-marie
UF-1060 - General picking documents modifications - End of second an third part
307
            complete, too_many, too_few , not_aval = [], [], [], []
93.9.1 by chloups208
[UF-33] correction of asset which is now linked to stock.move in a wizard when processing the stock.picking
308
            move_product_qty = {}
309
            prodlot_ids = {}
310
            product_avail = {}
311
            for move in pick.move_lines:
312
                if move.state in ('done', 'cancel'):
313
                    continue
878.4.3 by pierre-marie
UF-1060 - General picking documents modifications - End of second an third part
314
                elif move.state in ('confirmed'):
315
                    not_aval.append(move)
316
                    continue
217 by jf
OEB-32 [FIX] @revno 4694 Partial shipment impossible
317
                partial_data = partial_datas.get('move%s'%(move.id), {})
318
                #Commented in order to process the less number of stock moves from partial picking wizard
319
                #assert partial_data, _('Missing partial picking data for move #%s') % (move.id)
320
                product_qty = partial_data.get('product_qty') or 0.0
93.9.1 by chloups208
[UF-33] correction of asset which is now linked to stock.move in a wizard when processing the stock.picking
321
                move_product_qty[move.id] = product_qty
217 by jf
OEB-32 [FIX] @revno 4694 Partial shipment impossible
322
                product_uom = partial_data.get('product_uom') or False
323
                product_price = partial_data.get('product_price') or 0.0
324
                product_currency = partial_data.get('product_currency') or False
325
                prodlot_id = partial_data.get('prodlot_id') or False
93.9.1 by chloups208
[UF-33] correction of asset which is now linked to stock.move in a wizard when processing the stock.picking
326
                prodlot_ids[move.id] = prodlot_id
451.3.3 by chloups208
uf-655
327
                if move.product_qty == product_qty:
93.9.1 by chloups208
[UF-33] correction of asset which is now linked to stock.move in a wizard when processing the stock.picking
328
                    complete.append(move)
329
                elif move.product_qty > product_qty:
330
                    too_few.append(move)
331
                else:
332
                    too_many.append(move)
333
334
                # Average price computation
947.3.2 by Quentin THEURET
UF-1067 [IMP] Average cost price : Don't recompute cost price if the destination location is a cross-docking location
335
                if (pick.type == 'in') and (move.product_id.cost_method == 'average') and not move.location_dest_id.cross_docking_location_ok:
820.2.1 by jf
UF-1020 Avg cost price
336
                    product = product_obj.browse(cr, uid, move.product_id.id, context=ctx_avg)
93.9.1 by chloups208
[UF-33] correction of asset which is now linked to stock.move in a wizard when processing the stock.picking
337
                    move_currency_id = move.company_id.currency_id.id
338
                    context['currency_id'] = move_currency_id
339
                    qty = uom_obj._compute_qty(cr, uid, product_uom, product_qty, product.uom_id.id)
340
341
                    if product.id in product_avail:
342
                        product_avail[product.id] += qty
343
                    else:
344
                        product_avail[product.id] = product.qty_available
345
346
                    if qty > 0:
347
                        new_price = currency_obj.compute(cr, uid, product_currency,
348
                                move_currency_id, product_price)
349
                        new_price = uom_obj._compute_price(cr, uid, product_uom, new_price,
350
                                product.uom_id.id)
351
                        if product.qty_available <= 0:
352
                            new_std_price = new_price
353
                        else:
354
                            # Get the standard price
355
                            amount_unit = product.price_get('standard_price', context)[product.id]
356
                            new_std_price = ((amount_unit * product_avail[product.id])\
357
                                + (new_price * qty))/(product_avail[product.id] + qty)
358
                        # Write the field according to price type field
359
                        product_obj.write(cr, uid, [product.id], {'standard_price': new_std_price})
360
361
                        # Record the values that were chosen in the wizard, so they can be
362
                        # used for inventory valuation if real-time valuation is enabled.
363
                        move_obj.write(cr, uid, [move.id],
364
                                {'price_unit': product_price,
365
                                 'price_currency_id': product_currency})
878.4.3 by pierre-marie
UF-1060 - General picking documents modifications - End of second an third part
366
            for move in not_aval:
367
                if not new_picking:
368
                    new_picking = self.copy(cr, uid, pick.id,
369
                            {
370
                                'name': sequence_obj.get(cr, uid, 'stock.picking.%s'%(pick.type)),
371
                                'move_lines' : [],
372
                                'state':'draft',
373
                            })
93.9.1 by chloups208
[UF-33] correction of asset which is now linked to stock.move in a wizard when processing the stock.picking
374
375
            for move in too_few:
376
                product_qty = move_product_qty[move.id]
377
                if not new_picking:
378
                    new_picking = self.copy(cr, uid, pick.id,
379
                            {
380
                                'name': sequence_obj.get(cr, uid, 'stock.picking.%s'%(pick.type)),
381
                                'move_lines' : [],
382
                                'state':'draft',
383
                            })
384
                if product_qty != 0:
385
                    defaults = {
386
                            'product_qty' : product_qty,
387
                            'product_uos_qty': product_qty, #TODO: put correct uos_qty
388
                            'picking_id' : new_picking,
389
                            'state': 'assigned',
390
                            'move_dest_id': False,
391
                            'price_unit': move.price_unit,
392
                    }
393
                    prodlot_id = prodlot_ids[move.id]
394
                    if prodlot_id:
395
                        defaults.update(prodlot_id=prodlot_id)
396
                    # override : call to hook added
397
                    defaults = self._do_partial_hook(cr, uid, ids, context, move=move, partial_datas=partial_datas, defaults=defaults)
398
                    move_obj.copy(cr, uid, move.id, defaults)
399
400
                move_obj.write(cr, uid, [move.id],
401
                        {
402
                            'product_qty' : move.product_qty - product_qty,
403
                            'product_uos_qty':move.product_qty - product_qty, #TODO: put correct uos_qty
404
                        })
405
406
            if new_picking:
407
                move_obj.write(cr, uid, [c.id for c in complete], {'picking_id': new_picking})
408
            for move in complete:
409
                # override : refactoring
410
                defaults = {}
411
                prodlot_id = prodlot_ids.get(move.id)
412
                if prodlot_id:
413
                    defaults.update(prodlot_id=prodlot_id)
414
                defaults = self._do_partial_hook(cr, uid, ids, context, move=move, partial_datas=partial_datas, defaults=defaults)
415
                move_obj.write(cr, uid, [move.id], defaults)
416
                # override : end
878.4.3 by pierre-marie
UF-1060 - General picking documents modifications - End of second an third part
417
93.9.1 by chloups208
[UF-33] correction of asset which is now linked to stock.move in a wizard when processing the stock.picking
418
            for move in too_many:
419
                product_qty = move_product_qty[move.id]
420
                defaults = {
421
                    'product_qty' : product_qty,
422
                    'product_uos_qty': product_qty, #TODO: put correct uos_qty
423
                }
424
                prodlot_id = prodlot_ids.get(move.id)
425
                if prodlot_ids.get(move.id):
426
                    defaults.update(prodlot_id=prodlot_id)
427
                if new_picking:
428
                    defaults.update(picking_id=new_picking)
429
                # override : call to hook added
430
                defaults = self._do_partial_hook(cr, uid, ids, context, move=move, partial_datas=partial_datas, defaults=defaults)
431
                move_obj.write(cr, uid, [move.id], defaults)
432
433
            # At first we confirm the new picking (if necessary)
434
            if new_picking:
778.7.15 by chloups208
uf-643
435
                self.write(cr, uid, [pick.id], {'backorder_id': new_picking})
778.7.8 by chloups208
uf-643 claim processing from incoming shipment
436
                # custom code execution
778.7.14 by chloups208
uf-643 claim registration during wizard process with backorder
437
                self._custom_code(cr, uid, ids, context=context, partial_datas=partial_datas, concerned_picking=self.browse(cr, uid, new_picking, context=context))
778.7.53 by chloups208
uf-643 confirm method in do_partial is performed after custom code, so name of the new picking if modified in custom code is taken into account for self.log messages + messages of assert partial_datas completed with location of call
438
                # we confirm the new picking after its name was possibly modified by custom code - so the link message (top message) is correct
439
                wf_service.trg_validate(uid, 'stock.picking', new_picking, 'button_confirm', cr)
93.9.1 by chloups208
[UF-33] correction of asset which is now linked to stock.move in a wizard when processing the stock.picking
440
                # Then we finish the good picking
778.7.8 by chloups208
uf-643 claim processing from incoming shipment
441
                if self._picking_done_cond(cr, uid, ids, context=context, partial_datas=partial_datas):
442
                    self.action_move(cr, uid, [new_picking])
443
                    wf_service.trg_validate(uid, 'stock.picking', new_picking, 'button_done', cr)
93.9.1 by chloups208
[UF-33] correction of asset which is now linked to stock.move in a wizard when processing the stock.picking
444
                wf_service.trg_write(uid, 'stock.picking', pick.id, cr)
445
                delivered_pack_id = new_picking
446
            else:
778.7.8 by chloups208
uf-643 claim processing from incoming shipment
447
                # custom code execution
448
                self._custom_code(cr, uid, ids, context=context, partial_datas=partial_datas, concerned_picking=pick)
449
                if self._picking_done_cond(cr, uid, ids, context=context, partial_datas=partial_datas):
450
                    self.action_move(cr, uid, [pick.id])
451
                    wf_service.trg_validate(uid, 'stock.picking', pick.id, 'button_done', cr)
93.9.1 by chloups208
[UF-33] correction of asset which is now linked to stock.move in a wizard when processing the stock.picking
452
                delivered_pack_id = pick.id
453
454
            delivered_pack = self.browse(cr, uid, delivered_pack_id, context=context)
455
            res[pick.id] = {'delivered_picking': delivered_pack.id or False}
456
457
        return res
458
    # @@@override end
459
1074.21.1 by Matthieu Dietrich
UF-687: Returns accounting
460
    # @@@override stock>stock.py>stock_picking>_get_invoice_type
461
    def _get_invoice_type(self, pick):
462
        src_usage = dest_usage = None
463
        inv_type = None
464
        if pick.invoice_state == '2binvoiced':
465
            if pick.move_lines:
466
                src_usage = pick.move_lines[0].location_id.usage
467
                dest_usage = pick.move_lines[0].location_dest_id.usage
468
            if pick.type == 'out' and dest_usage == 'supplier':
469
                inv_type = 'in_refund'
470
            elif pick.type == 'out' and dest_usage == 'customer':
471
                inv_type = 'out_invoice'
472
            elif (pick.type == 'in' and src_usage == 'supplier') or (pick.type == 'internal'):
473
                inv_type = 'in_invoice'
474
            elif pick.type == 'in' and src_usage == 'customer':
475
                inv_type = 'out_refund'
476
            else:
477
                inv_type = 'out_invoice'
478
        return inv_type
479
809.6.1 by Olivier DOSSMANN
UF-935 [ADD] Add invoice creation automation for stock picking @ done state
480
    def action_done(self, cr, uid, ids, context=None):
481
        """
482
        Create automatically invoice
483
        """
484
        res = super(stock_picking, self).action_done(cr, uid, ids, context=context)
485
        if res:
828 by jf
UF-935 [IMP] Automate supplier invoice creation
486
            if isinstance(ids, (int, long)):
487
                ids = [ids]
809.6.1 by Olivier DOSSMANN
UF-935 [ADD] Add invoice creation automation for stock picking @ done state
488
            for sp in self.browse(cr, uid, ids):
892.15.40 by matthieu.choplin at msf
[uf-1055] Merge with trunk and conflicts resolved
489
                # we do not create invoice for procurement_request (Internal Request)
490
                if not sp.sale_id.procurement_request and sp.subtype == 'standard':
892.15.32 by matthieu.choplin at msf
For the UF-1055: if the sale.order is an IR, we don't create invoice. The filter view of the sourcing tool was updated to see the splitted line. We update the workflow of the Internal move to have it in confirm state once the IR is confirmed.
491
                    sp_type = False
1074.21.3 by Matthieu Dietrich
UF-687: [MERGE] merged with latest unifield-wm
492
                    inv_type = self._get_invoice_type(sp)
892.15.32 by matthieu.choplin at msf
For the UF-1055: if the sale.order is an IR, we don't create invoice. The filter view of the sourcing tool was updated to see the splitted line. We update the workflow of the Internal move to have it in confirm state once the IR is confirmed.
493
                    if sp.type == 'in' or sp.type == 'internal':
1074.21.3 by Matthieu Dietrich
UF-687: [MERGE] merged with latest unifield-wm
494
                        if inv_type == 'out_refund':
495
                            sp_type = 'sale_refund'
496
                        else:
497
                            sp_type = 'purchase'
892.15.32 by matthieu.choplin at msf
For the UF-1055: if the sale.order is an IR, we don't create invoice. The filter view of the sourcing tool was updated to see the splitted line. We update the workflow of the Internal move to have it in confirm state once the IR is confirmed.
498
                    elif sp.type == 'out':
1074.21.3 by Matthieu Dietrich
UF-687: [MERGE] merged with latest unifield-wm
499
                        if inv_type == 'in_refund':
500
                            sp_type = 'purchase_refund'
501
                        else:
502
                            sp_type = 'sale'
892.15.32 by matthieu.choplin at msf
For the UF-1055: if the sale.order is an IR, we don't create invoice. The filter view of the sourcing tool was updated to see the splitted line. We update the workflow of the Internal move to have it in confirm state once the IR is confirmed.
503
                    # Journal type
504
                    journal_type = sp_type
505
                    # Disturb journal for invoice only on intermission partner type
506
                    if sp.partner_id.partner_type == 'intermission':
507
                        journal_type = 'intermission'
1193.21.1 by Matthieu Dietrich
UTP-193: [FIX] added instance criteria to journal search
508
                    journal_ids = self.pool.get('account.journal').search(cr, uid, [('type', '=', journal_type),
1249.11.1 by Matthieu Dietrich
UF-1525: [IMP] added is_current_instance attribute on journals and analytical journals, and simplified each search domain by using it
509
                                                                                    ('is_current_instance', '=', True)])
892.15.32 by matthieu.choplin at msf
For the UF-1055: if the sale.order is an IR, we don't create invoice. The filter view of the sourcing tool was updated to see the splitted line. We update the workflow of the Internal move to have it in confirm state once the IR is confirmed.
510
                    if not journal_ids:
511
                        raise osv.except_osv(_('Warning'), _('No %s journal found!') % (journal_type,))
512
                    # Create invoice
513
                    self.action_invoice_create(cr, uid, [sp.id], journal_ids[0], False, inv_type, {})
828 by jf
UF-935 [IMP] Automate supplier invoice creation
514
        return res
93.9.1 by chloups208
[UF-33] correction of asset which is now linked to stock.move in a wizard when processing the stock.picking
515
892.14.8 by Olivier DOSSMANN
UF-1091 [ADD] Intermission Voucher IN/OUT generation from picking
516
    def action_invoice_create(self, cr, uid, ids, journal_id=False, group=False, type='out_invoice', context=None):
517
        """
518
        Attach an intermission journal to the Intermission Voucher IN/OUT if partner type is intermission from the picking.
892.14.19 by Olivier DOSSMANN
UF-1091 [ADD] Automatic conversion in functional currency for intermission voucher IN/OUT
519
        Prepare intermission voucher IN/OUT
1149.1.3 by Olivier DOSSMANN
UTP-114 [FIX] Error with invoice created from picking and come from a PO that's purchase_list
520
        Change invoice purchase_list field to TRUE if this picking come from a PO which is 'purchase_list'
892.14.8 by Olivier DOSSMANN
UF-1091 [ADD] Intermission Voucher IN/OUT generation from picking
521
        """
522
        res = super(stock_picking, self).action_invoice_create(cr, uid, ids, journal_id, group, type, context)
1193.21.1 by Matthieu Dietrich
UTP-193: [FIX] added instance criteria to journal search
523
        intermission_journal_ids = self.pool.get('account.journal').search(cr, uid, [('type', '=', 'intermission'),
1249.11.1 by Matthieu Dietrich
UF-1525: [IMP] added is_current_instance attribute on journals and analytical journals, and simplified each search domain by using it
524
                                                                                     ('is_current_instance', '=', True)])
892.14.19 by Olivier DOSSMANN
UF-1091 [ADD] Automatic conversion in functional currency for intermission voucher IN/OUT
525
        company = self.pool.get('res.users').browse(cr, uid, uid, context).company_id
526
        intermission_default_account = company.intermission_default_counterpart
892.14.8 by Olivier DOSSMANN
UF-1091 [ADD] Intermission Voucher IN/OUT generation from picking
527
        for pick in self.browse(cr, uid, [x for x in res]):
1149.1.3 by Olivier DOSSMANN
UTP-114 [FIX] Error with invoice created from picking and come from a PO that's purchase_list
528
            # Check if PO and PO is purchase_list
529
            if pick.purchase_id and pick.purchase_id.order_type and pick.purchase_id.order_type == 'purchase_list':
530
                inv_id = res[pick.id]
531
                self.pool.get('account.invoice').write(cr, uid, [inv_id], {'purchase_list': True})
532
            # Check intermission
892.14.8 by Olivier DOSSMANN
UF-1091 [ADD] Intermission Voucher IN/OUT generation from picking
533
            if pick.partner_id.partner_type == 'intermission':
534
                inv_id = res[pick.id]
535
                if not intermission_journal_ids:
536
                    raise osv.except_osv(_('Error'), _('No Intermission journal found!'))
892.14.18 by Olivier DOSSMANN
UF-1091 [ADD] Always use default account for intermission Voucher IN/OUT
537
                if not intermission_default_account or not intermission_default_account.id:
538
                    raise osv.except_osv(_('Error'), _('Please configure a default intermission account in Company configuration.'))
539
                self.pool.get('account.invoice').write(cr, uid, [inv_id], {'journal_id': intermission_journal_ids[0], 
540
                    'is_intermission': True, 'account_id': intermission_default_account.id,})
892.14.19 by Olivier DOSSMANN
UF-1091 [ADD] Automatic conversion in functional currency for intermission voucher IN/OUT
541
                # Change currency for this invoice
542
                company_currency = company.currency_id and company.currency_id.id or False
543
                if not company_currency:
544
                    raise osv.except_osv(_('Warning'), _('No company currency found!'))
545
                wiz_account_change = self.pool.get('account.change.currency').create(cr, uid, {'currency_id': company_currency})
546
                self.pool.get('account.change.currency').change_currency(cr, uid, [wiz_account_change], context={'active_id': inv_id})
892.14.8 by Olivier DOSSMANN
UF-1091 [ADD] Intermission Voucher IN/OUT generation from picking
547
        return res
548
1074.5.2 by jf
UF-1336 [IMP] Picking / moves
549
    def action_confirm(self, cr, uid, ids, context=None):
550
        """
551
            stock.picking: action confirm
552
            if INCOMING picking: confirm and check availability
553
        """
554
        super(stock_picking, self).action_confirm(cr, uid, ids, context=context)
555
        move_obj = self.pool.get('stock.move')
1074.5.4 by jf
UF-1336 action_assing only on confirmed stock move
556
1074.5.2 by jf
UF-1336 [IMP] Picking / moves
557
        if isinstance(ids, (int, long)):
558
            ids = [ids]
1074.5.4 by jf
UF-1336 action_assing only on confirmed stock move
559
        for pick in self.browse(cr, uid, ids):
560
            if pick.move_lines and pick.type == 'in':
561
                not_assigned_move = [x.id for x in pick.move_lines if x.state == 'confirmed']
562
                if not_assigned_move:
563
                    move_obj.action_assign(cr, uid, not_assigned_move)
1074.5.2 by jf
UF-1336 [IMP] Picking / moves
564
        return True
565
93.9.1 by chloups208
[UF-33] correction of asset which is now linked to stock.move in a wizard when processing the stock.picking
566
stock_picking()
567
568
# ----------------------------------------------------
569
# Move
570
# ----------------------------------------------------
571
572
#
573
# Fields:
574
#   location_dest_id is only used for predicting futur stocks
575
#
576
class stock_move(osv.osv):
577
578
    _inherit = "stock.move"
579
    _description = "Stock Move with hook"
580
706 by jf
[FIX] context None
581
    def set_manually_done(self, cr, uid, ids, all_doc=True, context=None):
451.4.2 by Quentin THEURET
UF-631 [ADD] Added a report to documents done
582
        '''
583
        Set the stock move to manually done
584
        '''
451.4.12 by Quentin THEURET
UF-631 [IMP] Reworked stock move cancellation
585
        return self.write(cr, uid, ids, {'state': 'cancel'}, context=context)
93.9.1 by chloups208
[UF-33] correction of asset which is now linked to stock.move in a wizard when processing the stock.picking
586
809.11.1 by Quentin THEURET
UF-965 [IMP] Display a warning message when a DPO is confirmed with already confirmed stock moves
587
    def _get_from_dpo(self, cr, uid, ids, field_name, args, context=None):
588
        '''
589
        Return True if the move has a dpo_id
590
        '''
591
        res = {}
592
593
        for move in self.browse(cr, uid, ids, context=context):
594
            res[move.id] = False
595
            if move.dpo_id:
1041.1.15 by Quentin THEURET
UF-1040 [IMP] Set locations by default
596
                res[move.id] = True
809.11.1 by Quentin THEURET
UF-965 [IMP] Display a warning message when a DPO is confirmed with already confirmed stock moves
597
598
        return res
599
600
    def _search_from_dpo(self, cr, uid, obj, name, args, context=None):
601
        '''
602
        Returns the list of moves from or not from DPO
603
        '''
604
        for arg in args:
605
            if arg[0] == 'from_dpo' and arg[1] == '=':
606
                return [('dpo_id', '!=', False)]
607
            elif arg[0] == 'from_dpo' and arg[1] in ('!=', '<>'):
608
                return [('dpo_id', '=', False)]
609
        
610
        return []
1041.1.15 by Quentin THEURET
UF-1040 [IMP] Set locations by default
611
    
612
    def _default_location_destination(self, cr, uid, context=None):
613
        if not context:
614
            context = {}
615
        if context.get('picking_type') == 'out':
616
            wh_ids = self.pool.get('stock.warehouse').search(cr, uid, [])
617
            if wh_ids:
618
                return self.pool.get('stock.warehouse').browse(cr, uid, wh_ids[0]).lot_output_id.id
619
    
620
        return False
809.11.1 by Quentin THEURET
UF-965 [IMP] Display a warning message when a DPO is confirmed with already confirmed stock moves
621
374.5.1 by Quentin THEURET
UF-402 [IMP] Modified states values according to the naming convention
622
    _columns = {
623
        'state': fields.selection([('draft', 'Draft'), ('waiting', 'Waiting'), ('confirmed', 'Not Available'), ('assigned', 'Available'), ('done', 'Closed'), ('cancel', 'Cancelled')], 'State', readonly=True, select=True,
584.11.1 by Quentin THEURET
UF-800 [FIX] Rename 'Done' by 'Closed' on all supply documents
624
              help='When the stock move is created it is in the \'Draft\' state.\n After that, it is set to \'Not Available\' state if the scheduler did not find the products.\n When products are reserved it is set to \'Available\'.\n When the picking is done the state is \'Closed\'.\
374.5.1 by Quentin THEURET
UF-402 [IMP] Modified states values according to the naming convention
625
              \nThe state is \'Waiting\' if the move is waiting for another one.'),
781.5.3 by Quentin THEURET
UF-956 [FIX] Made partner and address readonly when the picking is closed/cancelled
626
        'address_id': fields.many2one('res.partner.address', 'Delivery address', help="Address of partner", readonly=False, states={'done': [('readonly', True)], 'cancel': [('readonly', True)]}, domain="[('partner_id', '=', partner_id)]"),
633.6.6 by Quentin THEURET
UF-855 [IMP] Add 3 addresses on OUT/PICK
627
        'partner_id2': fields.many2one('res.partner', 'Partner', required=False),
639.3.8 by Quentin THEURET
UF-846 [FIX] FIx creation of chaining move coming from a waiting move
628
        'already_confirmed': fields.boolean(string='Already confirmed'),
809.11.2 by Quentin THEURET
UF-965 [IMP] Change link between stock moves and DPO
629
        'dpo_id': fields.many2one('purchase.order', string='Direct PO', help='PO from where this stock move is sourced.'),
809.11.1 by Quentin THEURET
UF-965 [IMP] Display a warning message when a DPO is confirmed with already confirmed stock moves
630
        'from_dpo': fields.function(_get_from_dpo, fnct_search=_search_from_dpo, type='boolean', method=True, store=False, string='From DPO ?'),
1074.5.1 by jf
UF-1299 [IMP] Add a button to change the destination location of an INT: no wizard
631
        'from_wkf_line': fields.related('picking_id', 'from_wkf', type='boolean', string='Internal use: from wkf'),
632
        'fake_state': fields.related('state', type='char', store=False, string="Internal use"),
374.5.1 by Quentin THEURET
UF-402 [IMP] Modified states values according to the naming convention
633
    }
634
    
1041.1.15 by Quentin THEURET
UF-1040 [IMP] Set locations by default
635
    _defaults = {
636
        'location_dest_id': _default_location_destination,
637
    }
638
    
706 by jf
[FIX] context None
639
    def create(self, cr, uid, vals, context=None):
633.6.6 by Quentin THEURET
UF-855 [IMP] Add 3 addresses on OUT/PICK
640
        '''
641
        Update the partner or the address according to the other
642
        '''
643
        if not vals.get('partner_id2') and vals.get('address_id'):
644
            addr = self.pool.get('res.partner.address').browse(cr, uid, vals.get('address_id'), context=context)
645
            vals['partner_id2'] = addr.partner_id and addr.partner_id.id or False
646
        elif not vals.get('partner_id2'):
647
            vals['partner_id2'] = self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id.partner_id.id
648
            
649
        if not vals.get('address_id') and vals.get('partner_id2'):
650
            addr = self.pool.get('res.partner').address_get(cr, uid, vals.get('partner_id2'), ['delivery', 'default'])
651
            if not addr.get('delivery'):
652
                vals['address_id'] = addr.get('default')
653
            else:
654
                vals['address_id'] = addr.get('delivery')
655
        
656
        return super(stock_move, self).create(cr, uid, vals, context=context)
657
    
706 by jf
[FIX] context None
658
    def write(self, cr, uid, ids, vals, context=None):
633.6.6 by Quentin THEURET
UF-855 [IMP] Add 3 addresses on OUT/PICK
659
        '''
660
        Update the partner or the address according to the other
661
        '''
662
        if not vals.get('address_id') and vals.get('partner_id2'):
663
            for move in self.browse(cr, uid, ids, context=context):
664
                if move.partner_id.id != vals.get('partner_id'):
665
                    addr = self.pool.get('res.partner').address_get(cr, uid, vals.get('partner_id2'), ['delivery', 'default'])
666
                    if not addr.get('delivery'):
667
                        vals['address_id'] = addr.get('default')
668
                    else:
669
                        vals['address_id'] = addr.get('delivery')
670
                        
671
        if not vals.get('partner_id2') and vals.get('address_id'):
672
            for move in self.browse(cr, uid, ids, context=context):
673
                if move.address_id.id != vals.get('address_id'):
674
                    addr = self.pool.get('res.partner.address').browse(cr, uid, vals.get('address_id'), context=context)
675
                    vals['partner_id2'] = addr.partner_id and addr.partner_id.id or False
676
        
677
        return super(stock_move, self).write(cr, uid, ids, vals, context=context)
678
    
706 by jf
[FIX] context None
679
    def on_change_partner(self, cr, uid, ids, partner_id, address_id, context=None):
633.6.6 by Quentin THEURET
UF-855 [IMP] Add 3 addresses on OUT/PICK
680
        '''
681
        Change the delivery address when the partner change.
682
        '''
683
        v = {}
684
        d = {}
685
        
686
        if not partner_id:
687
            v.update({'address_id': False})
688
        else:
689
            d.update({'address_id': [('partner_id', '=', partner_id)]})
690
            
691
692
        if address_id:
693
            addr = self.pool.get('res.partner.address').browse(cr, uid, address_id, context=context)
694
        
695
        if not address_id or addr.partner_id.id != partner_id:
696
            addr = self.pool.get('res.partner').address_get(cr, uid, partner_id, ['delivery', 'default'])
697
            if not addr.get('delivery'):
698
                addr = addr.get('default')
699
            else:
700
                addr = addr.get('delivery')
701
                
702
            v.update({'address_id': addr})
703
            
704
        
705
        return {'value': v,
706
                'domain': d}
707
    
734 by jf
UF-846 [DEV] Stock refactoring
708
    def copy(self, cr, uid, id, default=None, context=None):
639.3.10 by Quentin THEURET
UF-846 [IMP] Remove already_confirmed flag on stock move copy
709
        '''
710
        Remove the already confirmed flag
711
        '''
734 by jf
UF-846 [DEV] Stock refactoring
712
        if default is None:
713
            default = {}
714
        default.update({'already_confirmed':False})
639.3.10 by Quentin THEURET
UF-846 [IMP] Remove already_confirmed flag on stock move copy
715
        
734 by jf
UF-846 [DEV] Stock refactoring
716
        return super(stock_move, self).copy(cr, uid, id, default, context=context)
639.3.10 by Quentin THEURET
UF-846 [IMP] Remove already_confirmed flag on stock move copy
717
    
734 by jf
UF-846 [DEV] Stock refactoring
718
    def action_confirm(self, cr, uid, ids, context=None):
639.3.8 by Quentin THEURET
UF-846 [FIX] FIx creation of chaining move coming from a waiting move
719
        '''
720
        Set the bool already confirmed to True
721
        '''
722
        res = super(stock_move, self).action_confirm(cr, uid, ids, context=context)
723
        
724
        self.write(cr, uid, ids, {'already_confirmed': True}, context=context)
725
        
726
        return res
727
    
728
    def _hook_confirmed_move(self, cr, uid, *args, **kwargs):
729
        '''
730
        Always return True
731
        '''
732
        move = kwargs['move']
733
        if not move.already_confirmed:
734
            self.action_confirm(cr, uid, [move.id])
735
        return True
736
    
639.3.5 by Quentin THEURET
UF-846 [IMP] Add a hook to cancel all chained move
737
    def _hook_move_cancel_state(self, cr, uid, *args, **kwargs):
738
        '''
739
        Change the state of the chained move
740
        '''
734 by jf
UF-846 [DEV] Stock refactoring
741
        if kwargs.get('context'):
742
            kwargs['context'].update({'call_unlink': True})
743
        return {'state': 'cancel'}, kwargs.get('context', {})
878.4.3 by pierre-marie
UF-1060 - General picking documents modifications - End of second an third part
744
745
    def _hook_write_state_stock_move(self, cr, uid, done, notdone, count):
746
        if done:
747
            count += len(done)
1182.2.1 by pierre-marie
UF-1421 Stock move is done when source = dest
748
749
            #If source location == dest location THEN stock move is done.
750
            for line in self.read(cr,uid,done,['location_id','location_dest_id']):
751
                if line.get('location_id') and line.get('location_dest_id') and line.get('location_id') == line.get('location_dest_id'):
752
                    self.write(cr, uid, [line['id']], {'state': 'done'})
753
                else:
754
                    self.write(cr, uid, [line['id']], {'state': 'assigned'})
755
878.4.3 by pierre-marie
UF-1060 - General picking documents modifications - End of second an third part
756
        if notdone:
757
            self.write(cr, uid, notdone, {'state': 'confirmed'})
758
        return count
1041.1.4 by Quentin THEURET
UF-1040 [IMP] Add hooks to manage non-stockable products like normal products
759
    
760
    def _hook_check_assign(self, cr, uid, *args, **kwargs):
761
        '''
762
        kwargs['move'] is the current move
763
        '''
764
        move = kwargs['move']
765
        return move.location_id.usage == 'supplier'
878.4.3 by pierre-marie
UF-1060 - General picking documents modifications - End of second an third part
766
767
    def _hook_copy_stock_move(self, cr, uid, res, move, done, notdone):
768
        while res:
769
            r = res.pop(0)
770
            move_id = self.copy(cr, uid, move.id, {'product_qty': r[0],'product_uos_qty': r[0] * move.product_id.uos_coeff,'location_id': r[1]})
771
            if r[2]:
772
                done.append(move_id)
773
            else:
774
                notdone.append(move_id)
775
        return done, notdone 
374.5.1 by Quentin THEURET
UF-402 [IMP] Modified states values according to the naming convention
776
93.9.1 by chloups208
[UF-33] correction of asset which is now linked to stock.move in a wizard when processing the stock.picking
777
    def _do_partial_hook(self, cr, uid, ids, context, *args, **kwargs):
778
        '''
779
        hook to update defaults data
780
        '''
781
        defaults = kwargs.get('defaults')
782
        assert defaults is not None, 'missing defaults'
783
        
784
        return defaults
785
786
787
    # @@@override stock>stock.py>stock_move>do_partial
788
    def do_partial(self, cr, uid, ids, partial_datas, context=None):
789
        """ Makes partial pickings and moves done.
790
        @param partial_datas: Dictionary containing details of partial picking
791
                          like partner_id, address_id, delivery_date, delivery
792
                          moves with product_id, product_qty, uom
793
        """
794
        res = {}
795
        picking_obj = self.pool.get('stock.picking')
796
        product_obj = self.pool.get('product.product')
797
        currency_obj = self.pool.get('res.currency')
798
        uom_obj = self.pool.get('product.uom')
799
        wf_service = netsvc.LocalService("workflow")
800
801
        if context is None:
802
            context = {}
803
804
        complete, too_many, too_few = [], [], []
805
        move_product_qty = {}
806
        prodlot_ids = {}
947.3.4 by Quentin THEURET
UF-1067 [IMP] Product average cost computation : Don't compute with products qty in cross docking locations
807
        internal_loc_ids = self.pool.get('stock.location').search(cr, uid, [('usage','=','internal'), ('cross_docking_location_ok', '=', False)])
820.2.1 by jf
UF-1020 Avg cost price
808
        ctx_avg = context.copy()
809
        ctx_avg['location'] = internal_loc_ids
93.9.1 by chloups208
[UF-33] correction of asset which is now linked to stock.move in a wizard when processing the stock.picking
810
        for move in self.browse(cr, uid, ids, context=context):
811
            if move.state in ('done', 'cancel'):
812
                continue
813
            partial_data = partial_datas.get('move%s'%(move.id), False)
814
            assert partial_data, _('Missing partial picking data for move #%s') % (move.id)
815
            product_qty = partial_data.get('product_qty',0.0)
816
            move_product_qty[move.id] = product_qty
817
            product_uom = partial_data.get('product_uom',False)
818
            product_price = partial_data.get('product_price',0.0)
819
            product_currency = partial_data.get('product_currency',False)
820
            prodlot_ids[move.id] = partial_data.get('prodlot_id')
821
            if move.product_qty == product_qty:
822
                complete.append(move)
823
            elif move.product_qty > product_qty:
824
                too_few.append(move)
825
            else:
826
                too_many.append(move)
827
828
            # Average price computation
947.3.2 by Quentin THEURET
UF-1067 [IMP] Average cost price : Don't recompute cost price if the destination location is a cross-docking location
829
            if (move.picking_id.type == 'in') and (move.product_id.cost_method == 'average') and not move.location_dest_id.cross_docking_location_ok:
820.2.1 by jf
UF-1020 Avg cost price
830
                product = product_obj.browse(cr, uid, move.product_id.id, context=ctx_avg)
93.9.1 by chloups208
[UF-33] correction of asset which is now linked to stock.move in a wizard when processing the stock.picking
831
                move_currency_id = move.company_id.currency_id.id
832
                context['currency_id'] = move_currency_id
833
                qty = uom_obj._compute_qty(cr, uid, product_uom, product_qty, product.uom_id.id)
834
                if qty > 0:
835
                    new_price = currency_obj.compute(cr, uid, product_currency,
836
                            move_currency_id, product_price)
837
                    new_price = uom_obj._compute_price(cr, uid, product_uom, new_price,
838
                            product.uom_id.id)
839
                    if product.qty_available <= 0:
840
                        new_std_price = new_price
841
                    else:
842
                        # Get the standard price
843
                        amount_unit = product.price_get('standard_price', context)[product.id]
844
                        new_std_price = ((amount_unit * product.qty_available)\
845
                            + (new_price * qty))/(product.qty_available + qty)
846
847
                    product_obj.write(cr, uid, [product.id],{'standard_price': new_std_price})
848
849
                    # Record the values that were chosen in the wizard, so they can be
850
                    # used for inventory valuation if real-time valuation is enabled.
851
                    self.write(cr, uid, [move.id],
852
                                {'price_unit': product_price,
853
                                 'price_currency_id': product_currency,
854
                                })
855
856
        for move in too_few:
857
            product_qty = move_product_qty[move.id]
858
            if product_qty != 0:
859
                defaults = {
860
                            'product_qty' : product_qty,
861
                            'product_uos_qty': product_qty,
862
                            'picking_id' : move.picking_id.id,
863
                            'state': 'assigned',
864
                            'move_dest_id': False,
865
                            'price_unit': move.price_unit,
866
                            }
867
                prodlot_id = prodlot_ids[move.id]
868
                if prodlot_id:
869
                    defaults.update(prodlot_id=prodlot_id)
870
                # override : call to hook added
871
                defaults = self._do_partial_hook(cr, uid, ids, context, move=move, partial_datas=partial_datas, defaults=defaults)
872
                new_move = self.copy(cr, uid, move.id, defaults)
873
                complete.append(self.browse(cr, uid, new_move))
874
            self.write(cr, uid, [move.id],
875
                    {
876
                        'product_qty' : move.product_qty - product_qty,
877
                        'product_uos_qty':move.product_qty - product_qty,
878
                    })
879
880
881
        for move in too_many:
882
            self.write(cr, uid, [move.id],
883
                    {
884
                        'product_qty': move.product_qty,
885
                        'product_uos_qty': move.product_qty,
886
                    })
887
            complete.append(move)
888
889
        for move in complete:
890
            # override : refactoring
891
            defaults = {}
892
            prodlot_id = prodlot_ids.get(move.id)
893
            if prodlot_id:
894
                defaults.update(prodlot_id=prodlot_id)
895
            defaults = self._do_partial_hook(cr, uid, ids, context, move=move, partial_datas=partial_datas, defaults=defaults)
896
            self.write(cr, uid, [move.id], defaults)
897
            # override : end
898
            self.action_done(cr, uid, [move.id], context=context)
899
            if  move.picking_id.id :
900
                # TOCHECK : Done picking if all moves are done
901
                cr.execute("""
902
                    SELECT move.id FROM stock_picking pick
903
                    RIGHT JOIN stock_move move ON move.picking_id = pick.id AND move.state = %s
904
                    WHERE pick.id = %s""",
905
                            ('done', move.picking_id.id))
906
                res = cr.fetchall()
907
                if len(res) == len(move.picking_id.move_lines):
908
                    picking_obj.action_move(cr, uid, [move.picking_id.id])
909
                    wf_service.trg_validate(uid, 'stock.picking', move.picking_id.id, 'button_done', cr)
910
911
        return [move.id for move in complete]
912
    # @@@override end
913
475.1.1 by duy.vo at msf
[ADD] uf-580: Added the destruction location report
914
    def _get_destruction_products(self, cr, uid, ids, product_ids=False, context=None, recursive=False):
915
        """ Finds the product quantity and price for particular location.
916
        """
917
        if context is None:
918
            context = {}
919
475.1.2 by duy.vo at msf
[FIX] uf-580: Minor fixed
920
        result = []
475.1.1 by duy.vo at msf
[ADD] uf-580: Added the destruction location report
921
        for move in self.browse(cr, uid, ids, context=context):
922
            # add this move into the list of result
923
            dg_check_flag = ''
924
            if move.dg_check:
925
                dg_check_flag = 'x'
926
                
927
            np_check_flag = ''
928
            if move.np_check:
929
                np_check_flag = 'x'
930
            sub_total = move.product_qty * move.product_id.standard_price
931
            
932
            currency = ''
933
            if move.purchase_line_id and move.purchase_line_id.currency_id:
934
                currency = move.purchase_line_id.currency_id.name
935
            elif move.sale_line_id and move.sale_line_id.currency_id:
936
                currency = move.sale_line_id.currency_id.name
937
            
938
            result.append({
939
                'prod_name': move.product_id.name,
940
                'prod_code': move.product_id.code,
941
                'prod_price': move.product_id.standard_price,
942
                'sub_total': sub_total,
943
                'currency': currency,
475.1.4 by duy.vo at msf
[FIX] uf-580: Some minor changes
944
                'origin': move.origin,
475.1.1 by duy.vo at msf
[ADD] uf-580: Added the destruction location report
945
                'expired_date': move.expired_date,
946
                'prodlot_id': move.prodlot_id.name,
947
                'dg_check': dg_check_flag,
948
                'np_check': np_check_flag,
949
                'uom': move.product_uom.name,
950
                'prod_qty': move.product_qty,
951
            })
952
        return result
953
1074.5.2 by jf
UF-1336 [IMP] Picking / moves
954
    def in_action_confirm(self, cr, uid, ids, context=None):
955
        """
956
            Incoming: draft or confirmed: validate and assign
957
        """
958
        if isinstance(ids, (int, long)):
959
            ids = [ids]
960
        self.action_confirm(cr, uid, ids, context)
961
        self.action_assign(cr, uid, ids, context)
962
        return True
963
93.9.1 by chloups208
[UF-33] correction of asset which is now linked to stock.move in a wizard when processing the stock.picking
964
stock_move()
431.10.1 by Quentin THEURET
UF-697 [IMP] Added a new chaining type based on product nomenclature
965
639.3.1 by Quentin THEURET
UF-846 [IMP] Add a new report in tree architecture to see the view locations with a total of their children
966
#-----------------------------------------
967
#   Stock location
968
#-----------------------------------------
431.10.1 by Quentin THEURET
UF-697 [IMP] Added a new chaining type based on product nomenclature
969
class stock_location(osv.osv):
970
    _name = 'stock.location'
971
    _inherit = 'stock.location'
639.3.1 by Quentin THEURET
UF-846 [IMP] Add a new report in tree architecture to see the view locations with a total of their children
972
    
778.8.1 by jf
Data: loading order for yml test
973
    def init(self, cr):
974
        """
975
        Load data.xml asap
976
        """
977
        if hasattr(super(stock_location, self), 'init'):
978
            super(stock_location, self).init(cr)
979
980
        mod_obj = self.pool.get('ir.module.module')
981
        logging.getLogger('init').info('HOOK: module stock_override: loading stock_data.xml')
982
        pathname = path.join('stock_override', 'stock_data.xml')
983
        file = tools.file_open(pathname)
984
        tools.convert_xml_import(cr, 'stock_override', file, {}, mode='init', noupdate=False)
985
    
639.3.1 by Quentin THEURET
UF-846 [IMP] Add a new report in tree architecture to see the view locations with a total of their children
986
    def _product_value(self, cr, uid, ids, field_names, arg, context=None):
987
        """Computes stock value (real and virtual) for a product, as well as stock qty (real and virtual).
988
        @param field_names: Name of field
989
        @return: Dictionary of values
990
        """
991
        result = super(stock_location, self)._product_value(cr, uid, ids, field_names, arg, context=context)
992
        
993
        product_product_obj = self.pool.get('product.product')
994
        currency_id = self.pool.get('res.users').browse(cr, uid, uid).company_id.currency_id.id
995
        currency_obj = self.pool.get('res.currency')
996
        currency = currency_obj.browse(cr, uid, currency_id, context=context)
997
        if context.get('product_id'):
998
            view_ids = self.search(cr, uid, [('usage', '=', 'view')], context=context)
999
            result.update(dict([(i, {}.fromkeys(field_names, 0.0)) for i in list(set([aaa for aaa in view_ids]))]))
1000
            for loc_id in view_ids:
1001
                c = (context or {}).copy()
1002
                c['location'] = loc_id
1003
                c['compute_child'] = True
1004
                for prod in product_product_obj.browse(cr, uid, [context.get('product_id')], context=c):
1005
                    for f in field_names:
1006
                        if f == 'stock_real':
1007
                            if loc_id not in result:
1008
                                result[loc_id] = {}
1009
                            result[loc_id][f] += prod.qty_available
1010
                        elif f == 'stock_virtual':
1011
                            result[loc_id][f] += prod.virtual_available
1012
                        elif f == 'stock_real_value':
1013
                            amount = prod.qty_available * prod.standard_price
1014
                            amount = currency_obj.round(cr, uid, currency, amount)
1015
                            result[loc_id][f] += amount
1016
                        elif f == 'stock_virtual_value':
1017
                            amount = prod.virtual_available * prod.standard_price
1018
                            amount = currency_obj.round(cr, uid, currency, amount)
1019
                            result[loc_id][f] += amount
639.3.14 by Quentin THEURET
UF-846 [IMP] Reorganize the stock location view
1020
                            
1021
        return result
431.10.1 by Quentin THEURET
UF-697 [IMP] Added a new chaining type based on product nomenclature
1022
840.1.3 by pierre-marie
UF-1040 - Non stockable product management - Correction
1023
    def _fake_get(self, cr, uid, ids, fields, arg, context=None):
1024
        result = {}
1041.1.1 by jf
[MERGE]
1025
        if isinstance(ids, (int, long)):
1026
            ids = [ids]
1027
        for id in ids:
1028
            result[id] = False
840.1.3 by pierre-marie
UF-1040 - Non stockable product management - Correction
1029
        return result
1030
1031
    def _prod_loc_search(self, cr, uid, ids, fields, arg, context=None):
1041.1.1 by jf
[MERGE]
1032
        if not arg or not arg[0] or not arg[0][2] or not arg[0][2][0]:
840.1.7 by pierre-marie
UF 1040 - Correction bug sur les OUT
1033
            return []
840.1.3 by pierre-marie
UF-1040 - Non stockable product management - Correction
1034
        if context is None:
1035
            context = {}
1041.1.30 by Quentin THEURET
Move declaration of the non-stockable locations to stock_override to be loaded at stock_override loading
1036
        id_nonstock = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'stock_override', 'stock_location_non_stockable')[1]
1041.1.1 by jf
[MERGE]
1037
        id_cross = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'msf_cross_docking', 'stock_location_cross_docking')[1]
1038
        prod_obj = self.pool.get('product.product').browse(cr, uid, arg[0][2][0])
840.1.7 by pierre-marie
UF 1040 - Correction bug sur les OUT
1039
        if prod_obj and prod_obj.type == 'consu':
840.1.11 by pierre-marie
Correction bug on INT location
1040
            if arg[0][2][1] == 'in':
1041
                id_virt = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'stock','stock_location_locations_virtual')[1]
1041.1.1 by jf
[MERGE]
1042
                ids_child = self.pool.get('stock.location').search(cr,uid,[('location_id', 'child_of', id_virt)])
1043
                return [('id', 'in', [id_nonstock, id_cross]+ids_child)]
840.1.11 by pierre-marie
Correction bug on INT location
1044
            else:
840.1.9 by pierre-marie
Correction du merge
1045
                return [('id', 'in', [id_cross])]
840.1.11 by pierre-marie
Correction bug on INT location
1046
840.1.7 by pierre-marie
UF 1040 - Correction bug sur les OUT
1047
        elif prod_obj and  prod_obj.type != 'consu':
840.1.11 by pierre-marie
Correction bug on INT location
1048
                if arg[0][2][1] == 'in':
1041.1.23 by Quentin THEURET
UF-1040 [FIX] Fix non initialized variable
1049
                    return [('id', 'in', ids_child)]
840.1.11 by pierre-marie
Correction bug on INT location
1050
                else:
1041.1.1 by jf
[MERGE]
1051
                    return [('id', 'not in', [id_nonstock]), ('usage', '=', 'internal')]
840.1.11 by pierre-marie
Correction bug on INT location
1052
1041.1.1 by jf
[MERGE]
1053
        return [('id', 'in', [])]
840.1.3 by pierre-marie
UF-1040 - Non stockable product management - Correction
1054
1055
    def _cd_search(self, cr, uid, ids, fields, arg, context=None):
1041.1.1 by jf
[MERGE]
1056
        id_cross = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'msf_cross_docking', 'stock_location_cross_docking')[1]
840.1.3 by pierre-marie
UF-1040 - Non stockable product management - Correction
1057
        if context is None:
1058
            context = {}
1059
        if arg[0][2]:
1041.1.1 by jf
[MERGE]
1060
            obj_pol = arg[0][2][0] and self.pool.get('purchase.order.line').browse(cr, uid, arg[0][2][0]) or False
1061
            if  (obj_pol and obj_pol.order_id.cross_docking_ok) or arg[0][2][1]:
840.1.3 by pierre-marie
UF-1040 - Non stockable product management - Correction
1062
                return [('id', 'in', [id_cross])]
1063
        return []
1064
840.1.9 by pierre-marie
Correction du merge
1065
    def _check_usage(self, cr, uid, ids, fields, arg, context=None):
1041.1.1 by jf
[MERGE]
1066
        if not arg or not arg[0][2]:
840.1.9 by pierre-marie
Correction du merge
1067
            return []
1068
        if context is None:
1069
            context = {}
1041.1.1 by jf
[MERGE]
1070
        prod_obj = self.pool.get('product.product').browse(cr, uid, arg[0][2])
1071
        if prod_obj.type == 'service_recep':
1072
            ids = self.pool.get('stock.location').search(cr, uid, [('usage','=', 'inventory')])
840.1.9 by pierre-marie
Correction du merge
1073
            return [('id', 'in', ids)]
1041.1.1 by jf
[MERGE]
1074
        elif prod_obj.type == 'consu':
840.1.9 by pierre-marie
Correction du merge
1075
            return []
1076
        else:
1041.1.1 by jf
[MERGE]
1077
            ids = self.pool.get('stock.location').search(cr, uid, [('usage','=', 'internal')])
840.1.9 by pierre-marie
Correction du merge
1078
            return [('id', 'in', ids)]
1079
        return []
1080
1081
431.10.1 by Quentin THEURET
UF-697 [IMP] Added a new chaining type based on product nomenclature
1082
    _columns = {
1083
        'chained_location_type': fields.selection([('none', 'None'), ('customer', 'Customer'), ('fixed', 'Fixed Location'), ('nomenclature', 'Nomenclature')],
1084
                                'Chained Location Type', required=True,
1085
                                help="Determines whether this location is chained to another location, i.e. any incoming product in this location \n" \
1086
                                     "should next go to the chained location. The chained location is determined according to the type :"\
1087
                                     "\n* None: No chaining at all"\
1088
                                     "\n* Customer: The chained location will be taken from the Customer Location field on the Partner form of the Partner that is specified in the Picking list of the incoming products." \
1089
                                     "\n* Fixed Location: The chained location is taken from the next field: Chained Location if Fixed." \
1090
                                     "\n* Nomenclature: The chained location is taken from the options field: Chained Location is according to the nomenclature level of product."\
1091
                                    ),
1092
        'chained_options_ids': fields.one2many('stock.location.chained.options', 'location_id', string='Chained options'),
431.10.8 by qt-tempo-consulting
UF-697 [IMP] Remove the location : See all documents which generates error on deletion
1093
        'optional_loc': fields.boolean(string='Is an optional location ?'),
639.3.1 by Quentin THEURET
UF-846 [IMP] Add a new report in tree architecture to see the view locations with a total of their children
1094
        'stock_real': fields.function(_product_value, method=True, type='float', string='Real Stock', multi="stock"),
1095
        'stock_virtual': fields.function(_product_value, method=True, type='float', string='Virtual Stock', multi="stock"),
1096
        'stock_real_value': fields.function(_product_value, method=True, type='float', string='Real Stock Value', multi="stock", digits_compute=dp.get_precision('Account')),
1097
        'stock_virtual_value': fields.function(_product_value, method=True, type='float', string='Virtual Stock Value', multi="stock", digits_compute=dp.get_precision('Account')),
840.1.3 by pierre-marie
UF-1040 - Non stockable product management - Correction
1098
        'check_prod_loc': fields.function(_fake_get, method=True, type='many2one', string='zz', fnct_search=_prod_loc_search),
1099
        'check_cd': fields.function(_fake_get, method=True, type='many2one', string='zz', fnct_search=_cd_search),
840.1.9 by pierre-marie
Correction du merge
1100
        'check_usage': fields.function(_fake_get, method=True, type='many2one', string='zz', fnct_search=_check_usage),
840.1.6 by pierre-marie
UF-1040 - Non stockable product mana - Correction
1101
        'virtual_location': fields.boolean(string='Virtual location'),
840.1.3 by pierre-marie
UF-1040 - Non stockable product management - Correction
1102
431.10.1 by Quentin THEURET
UF-697 [IMP] Added a new chaining type based on product nomenclature
1103
    }
1104
1105
    #####
1106
    # Chained location on nomenclature level
1107
    #####
734 by jf
UF-846 [DEV] Stock refactoring
1108
    def _hook_chained_location_get(self, cr, uid, context=None, *args, **kwargs):
431.10.1 by Quentin THEURET
UF-697 [IMP] Added a new chaining type based on product nomenclature
1109
        '''
1110
        Return the location according to nomenclature level
1111
        '''
1112
        location = kwargs['location']
1113
        product = kwargs['product']
1114
        result = kwargs['result']
1115
1116
        if location.chained_location_type == 'nomenclature':
1117
            for opt in location.chained_options_ids:
1118
                if opt.nomen_id.id == product.nomen_manda_0.id:
1119
                    return opt.dest_location_id
1120
1121
        return result
1122
878.4.7 by pierre-marie
UF-1060 - General picking documents modifications - Correction on the Check Avaibility split
1123
    def _hook_proct_reserve(self, cr, uid, product_qty, result, amount, id, ids ):
878.4.3 by pierre-marie
UF-1060 - General picking documents modifications - End of second an third part
1124
        result.append((amount, id, True))
1125
        product_qty -= amount
1126
        if product_qty <= 0.0:
1127
            return result
1128
        else:
1129
            result = []
1130
            result.append((amount, id, True))
878.4.7 by pierre-marie
UF-1060 - General picking documents modifications - Correction on the Check Avaibility split
1131
            if len(ids) >= 1:
1132
                result.append((product_qty, ids[0], False))
1133
            else:
1134
                result.append((product_qty, id, False))
878.4.3 by pierre-marie
UF-1060 - General picking documents modifications - End of second an third part
1135
            return result
1136
        return []
431.10.1 by Quentin THEURET
UF-697 [IMP] Added a new chaining type based on product nomenclature
1137
734 by jf
UF-846 [DEV] Stock refactoring
1138
    def on_change_location_type(self, cr, uid, ids, chained_location_type, context=None):
431.10.1 by Quentin THEURET
UF-697 [IMP] Added a new chaining type based on product nomenclature
1139
        '''
1140
        If the location type is changed to 'Nomenclature', set some other fields values
1141
        '''
1142
        if chained_location_type and chained_location_type == 'nomenclature':
1143
            return {'value': {'chained_auto_packing': 'transparent',
1144
                              'chained_picking_type': 'internal',
1145
                              'chained_delay': 0}}
1146
1147
        return {}
1148
1149
1150
stock_location()
1151
1152
class stock_location_chained_options(osv.osv):
1153
    _name = 'stock.location.chained.options'
1154
    _rec_name = 'location_id'
1155
    
1156
    _columns = {
1157
        'dest_location_id': fields.many2one('stock.location', string='Destination Location', required=True),
1158
        'nomen_id': fields.many2one('product.nomenclature', string='Nomenclature Level', required=True),
1159
        'location_id': fields.many2one('stock.location', string='Location', required=True),
1160
    }
1161
1162
stock_location_chained_options()
892.5.9 by Quentin THEURET
UF-1152 Update
1163
1016.9.1 by Quentin THEURET
UF-1066 [IMP] Start dev on initial inventory
1164
892.5.9 by Quentin THEURET
UF-1152 Update
1165
class ir_values(osv.osv):
1166
    _name = 'ir.values'
1167
    _inherit = 'ir.values'
1168
1169
    def get(self, cr, uid, key, key2, models, meta=False, context=None, res_id_req=False, without_user=True, key2_req=True):
1170
        if context is None:
1171
            context = {}
1172
        values = super(ir_values, self).get(cr, uid, key, key2, models, meta, context, res_id_req, without_user, key2_req)
1173
        new_values = values
1174
        
1175
        move_accepted_values = {'client_action_multi': [],
1176
                                    'client_print_multi': [],
1177
                                    'client_action_relate': ['act_relate_picking'],
1178
                                    'tree_but_action': [],
1179
                                    'tree_but_open': []}
892.5.19 by Quentin THEURET
UF-1152 [IMP] Stock moves view : Rename 'Reference' by 'Picking Ref.'
1180
        
892.5.30 by Quentin THEURET
UF-1152 [FIX] Incoming shipment: screen a bit wide.
1181
        incoming_accepted_values = {'client_action_multi': ['act_stock_return_picking', 'action_stock_invoice_onshipping'],
967.3.1 by pierre-marie
New branch Report Reception
1182
                                    'client_print_multi': ['Reception'],
892.5.19 by Quentin THEURET
UF-1152 [IMP] Stock moves view : Rename 'Reference' by 'Picking Ref.'
1183
                                    'client_action_relate': ['View_log_stock.picking'],
1184
                                    'tree_but_action': [],
1185
                                    'tree_but_open': []}
1186
        
1187
        internal_accepted_values = {'client_action_multi': [],
1188
                                    'client_print_multi': ['Labels'],
1189
                                    'client_action_relate': [],
1190
                                    'tree_but_action': [],
1191
                                    'tree_but_open': []}
1192
        
1193
        delivery_accepted_values = {'client_action_multi': [],
1194
                                    'client_print_multi': ['Labels'],
1195
                                    'client_action_relate': [''],
1196
                                    'tree_but_action': [],
1197
                                    'tree_but_open': []}
1198
        
1199
        picking_accepted_values = {'client_action_multi': [],
1200
                                    'client_print_multi': ['Picking Ticket', 'Pre-Packing List', 'Labels'],
1201
                                    'client_action_relate': [''],
1202
                                    'tree_but_action': [],
1203
                                    'tree_but_open': []}
1204
        
892.5.9 by Quentin THEURET
UF-1152 Update
1205
        if 'stock.move' in [x[0] for x in models]:
1206
            new_values = []
1207
            for v in values:
1208
                if key == 'action' and v[1] in move_accepted_values[key2]:
892.5.19 by Quentin THEURET
UF-1152 [IMP] Stock moves view : Rename 'Reference' by 'Picking Ref.'
1209
                    new_values.append(v)          
1282.11.1 by matthieu.choplin at msf
[uf-1558][FIX] the link to desctruction report was missing because it wasn't taken into account in the ir.values
1210
                elif context.get('_terp_view_name', False) == 'Destruction Report':
1211
                    new_values.append(v)
892.5.19 by Quentin THEURET
UF-1152 [IMP] Stock moves view : Rename 'Reference' by 'Picking Ref.'
1212
        elif context.get('picking_type', False) == 'incoming_shipment' and 'stock.picking' in [x[0] for x in models]:
1213
            new_values = []
1214
            for v in values:
1215
                if key == 'action' and v[1] in incoming_accepted_values[key2]:
1216
                    new_values.append(v)
1217
        elif context.get('picking_type', False) == 'internal_move' and 'stock.picking' in [x[0] for x in models]:
1218
            new_values = []
1219
            for v in values:
1220
                if key == 'action' and v[1] in internal_accepted_values[key2]:
1221
                    new_values.append(v)
1222
        elif context.get('picking_type', False) == 'delivery_order' and 'stock.picking' in [x[0] for x in models]:
1223
            new_values = []
1224
            for v in values:
1225
                if key == 'action' and v[1] in delivery_accepted_values[key2]:
1226
                    new_values.append(v)
1227
        elif context.get('picking_type', False) == 'picking_ticket' and 'stock.picking' in [x[0] for x in models]:
1228
            new_values = []
1229
            for v in values:
1230
                if key == 'action' and v[1] in picking_accepted_values[key2]:
892.5.9 by Quentin THEURET
UF-1152 Update
1231
                    new_values.append(v)
1232
 
1233
        return new_values
1234
892.14.37 by Olivier DOSSMANN
UF-1091 [ADD] Update context for invoice log() method for inkind, intermission and debit note
1235
ir_values()