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

« back to all changes in this revision

Viewing changes to mission_stock/mission_stock.py

  • Committer: matthieu.choplin at msf
  • Date: 2012-08-30 07:48:00 UTC
  • mto: This revision was merged to the branch mainline in revision 1118.
  • Revision ID: matthieu.choplin@geneva.msf.org-20120830074800-l442bu42mt0yzutn
[uf-1374]- change the write and create by an _sql_constraint on the financing contract check dates

Show diffs side-by-side

added added

removed removed

Lines of Context:
27
27
import pooler
28
28
import time
29
29
import threading
30
 
import logging
31
 
 
32
 
REPLACE_DICT = {'cell': 'Cell',
33
 
                'row': 'Row',
34
 
                'data': 'Data'}
35
 
 
36
 
def replace_all(text):
37
 
    for i, j in REPLACE_DICT.iteritems():
38
 
        text = text.replace(i, j)
39
 
    return text
40
30
 
41
31
 
42
32
class stock_mission_report(osv.osv):
43
33
    _name = 'stock.mission.report'
44
34
    _description = 'Mission stock report'
45
 
 
 
35
    
46
36
    def _get_local_report(self, cr, uid, ids, field_name, args, context=None):
47
37
        '''
48
38
        Check if the mission stock report is a local report or not
49
39
        '''
50
40
        if isinstance(ids, (int, long)):
51
41
            ids = [ids]
52
 
 
 
42
        
53
43
        res = {}
54
 
 
 
44
        
55
45
        local_instance_id = self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id.instance_id.id
56
 
 
57
 
        for report in self.read(cr, uid, ids, ['instance_id'], context=context):
58
 
            res[report['id']] = False
59
 
            if report['instance_id'] \
60
 
                and report['instance_id'][0] == local_instance_id:
61
 
                res[report['id']] = True
62
 
 
 
46
        
 
47
        for report in self.browse(cr, uid, ids, context=context):
 
48
            res[report.id] = False
 
49
            if report.instance_id.id == local_instance_id:
 
50
                res[report.id] = True
 
51
                
63
52
        return res
64
 
 
 
53
    
65
54
    def _src_local_report(self, cr, uid, obj, name, args, context=None):
66
55
        '''
67
56
        Returns the local or not report mission according to args
68
57
        '''
69
58
        res = []
70
 
 
 
59
        
71
60
        local_instance_id = self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id.instance_id.id
72
 
 
 
61
        
73
62
        for arg in args:
74
63
            if len(arg) > 2 and arg[0] == 'local_report':
75
64
                if (arg[1] == '=' and arg[2] in ('True', 'true', 't', 1)) or \
80
69
                    res.append(('instance_id', '!=', local_instance_id))
81
70
                else:
82
71
                    raise osv.except_osv(_('Error'), _('Bad operator'))
83
 
 
 
72
                
84
73
        return res
85
 
 
 
74
    
86
75
    _columns = {
87
76
        'name': fields.char(size=128, string='Name', required=True),
88
77
        'instance_id': fields.many2one('msf.instance', string='Instance', required=True),
89
78
        'full_view': fields.boolean(string='Is a full view report ?'),
90
 
        'local_report': fields.function(_get_local_report, fnct_search=_src_local_report,
 
79
        'local_report': fields.function(_get_local_report, fnct_search=_src_local_report, 
91
80
                                        type='boolean', method=True, store=False,
92
81
                                        string='Is a local report ?', help='If the report is a local report, it will be updated periodically'),
93
82
        'report_line': fields.one2many('stock.mission.report.line', 'mission_report_id', string='Lines'),
94
83
        'last_update': fields.datetime(string='Last update'),
95
 
        'move_ids': fields.many2many('stock.move', 'mission_move_rel', 'mission_id', 'move_id', string='Noves'),
96
 
        'export_ok': fields.boolean(string='Export file possible ?'),
97
 
        'ns_nv_vals': fields.text(string='XML values'),
98
 
        's_nv_vals': fields.text(string='XML values'),
99
 
        'ns_v_vals': fields.text(string='XML values'),
100
 
        's_v_vals': fields.text(string='XML values'),
101
84
    }
102
 
 
103
 
    def __init__(self, pool, cr):
104
 
        a = super(stock_mission_report, self).__init__(pool, cr)
105
 
        for col in ['ns_nv_vals', 's_nv_vals', 'ns_v_vals', 's_v_vals']:
106
 
            self._columns[col]._prefetch = False
107
 
        return a
108
 
 
 
85
    
109
86
    _defaults = {
110
87
        'full_view': lambda *a: False,
111
 
        #'export_ok': False,
112
88
    }
113
 
 
 
89
    
114
90
    def create(self, cr, uid, vals, context=None):
115
91
        '''
116
92
        Create lines at report creation
117
93
        '''
118
94
        res = super(stock_mission_report, self).create(cr, uid, vals, context=context)
119
 
 
 
95
        
120
96
        local_instance_id = self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id.instance_id.id
121
 
 
 
97
        
122
98
        # Not update lines for full view or non local reports
123
 
        if vals.get('instance_id', False) and vals['instance_id'] == local_instance_id and not vals.get('full_view', False):
 
99
        if (vals.get('instance_id', False) and vals['instance_id'] != local_instance_id) or not vals.get('full_view', False):
124
100
            if not context.get('no_update', False):
125
101
                self.update(cr, uid, res, context=context)
126
 
 
 
102
        
127
103
        return res
128
 
 
 
104
    
129
105
    def background_update(self, cr, uid, ids, context=None):
130
106
        """
131
 
        Run the update of local stock report in background
 
107
        Run the update of local stock report in background 
132
108
        """
133
109
        if not ids:
134
110
            ids = []
135
 
 
 
111
        
136
112
        threaded_calculation = threading.Thread(target=self.update_newthread, args=(cr, uid, ids, context))
137
113
        threaded_calculation.start()
138
114
        return {'type': 'ir.actions.act_window_close'}
139
 
 
 
115
    
140
116
    def update_newthread(self, cr, uid, ids=[], context=None):
141
 
        # Open a new cursor : Don't forget to close it at the end of method
 
117
        # Open a new cursor : Don't forget to close it at the end of method   
142
118
        cr = pooler.get_db(cr.dbname).cursor()
143
119
        try:
144
120
            self.update(cr, uid, ids=[], context=None)
145
121
            cr.commit()
146
 
        except Exception:
147
 
            cr.rollback()
148
122
        finally:
149
 
            cr.close(True)
 
123
            cr.close()
150
124
 
151
125
    def update(self, cr, uid, ids=[], context=None):
152
126
        '''
154
128
        '''
155
129
        if not context:
156
130
            context = {}
157
 
 
 
131
            
158
132
        if isinstance(ids, (int, long)):
159
133
            ids = [ids]
160
 
 
 
134
        
161
135
        line_obj = self.pool.get('stock.mission.report.line')
162
 
 
 
136
        
 
137
        product_ids = self.pool.get('product.product').search(cr, uid, [], context=context)
163
138
        report_ids = self.search(cr, uid, [('local_report', '=', True)], context=context)
164
139
        full_report_ids = self.search(cr, uid, [('full_view', '=', True)], context=context)
165
140
        instance_id = self.pool.get('res.users').browse(cr, uid, uid).company_id.instance_id
166
141
        line_ids = []
167
 
 
168
 
        # Create a local report if no exist
 
142
        
169
143
        if not report_ids and context.get('update_mode', False) not in ('update', 'init') and instance_id:
170
144
            c = context.copy()
171
145
            c.update({'no_update': True})
173
147
                                               'instance_id': instance_id.id,
174
148
                                               'full_view': False}, context=c)]
175
149
 
176
 
        # Create a full view report if no exist
177
150
        if not full_report_ids and context.get('update_mode', False) not in ('update', 'init') and instance_id:
178
151
            c = context.copy()
179
152
            c.update({'no_update': True})
181
154
                                               'instance_id': instance_id.id,
182
155
                                               'full_view': True}, context=c)]
183
156
 
184
 
        cr.commit()
185
 
 
186
157
        if context.get('update_full_report'):
187
158
            report_ids = full_report_ids
188
 
 
189
 
        product_ids = self.pool.get('product.product').search(cr, uid, [], context=context)
190
 
        product_values = {}
191
 
        for product in self.pool.get('product.product').read(cr, uid, product_ids, ['product_amc', 'reviewed_consumption'], context=context):
192
 
            product_values.setdefault(product['id'], {})
193
 
            product_values[product['id']].setdefault('product_amc', product['product_amc'])
194
 
            product_values[product['id']].setdefault('reviewed_consumption', product['reviewed_consumption'])
195
 
 
 
159
            
196
160
 
197
161
        # Check in each report if new products are in the database and not in the report
198
 
        for report in self.read(cr, uid, report_ids, ['local_report', 'full_view'], context=context):
199
 
            #self.write(cr, uid, [report.id], {'export_ok': False}, context=context)
200
 
            # Create one line by product
201
 
            cr.execute('''SELECT id FROM product_product
202
 
                        EXCEPT
203
 
                          SELECT product_id FROM stock_mission_report_line WHERE mission_report_id = %s''' % report['id'])
204
 
            for product in cr.fetchall():
205
 
                line_ids.append(line_obj.create(cr, uid, {'product_id': product, 'mission_report_id': report['id']}, context=context))
206
 
 
 
162
        for report in self.browse(cr, uid, report_ids, context=context):
207
163
            # Don't update lines for full view or non local reports
208
 
            if not report['local_report']:
 
164
            if not report.local_report:
209
165
                continue
210
 
 
 
166
            
 
167
            product_in_report = []
 
168
            if report.report_line:
 
169
                for line in report.report_line:
 
170
                    line_ids.append(line.id)
 
171
                    product_in_report.append(line.product_id.id)
 
172
        
 
173
            # Difference between product list and products in report
 
174
            product_diff = filter(lambda x:x not in product_in_report, product_ids)
 
175
            for product in product_diff:
 
176
                line_ids.append(line_obj.create(cr, uid, {'product_id': product, 'mission_report_id': report.id}, context=context))
 
177
        
211
178
            # Update the update date on report
212
 
            self.write(cr, uid, [report['id']], {'last_update': time.strftime('%Y-%m-%d %H:%M:%S'),
213
 
                                              'export_ok': False}, context=context)
214
 
 
215
 
            if context.get('update_full_report'):
216
 
                full_view = self.search(cr, uid, [('full_view', '=', True)])
217
 
                if full_view:
218
 
                    line_ids = line_obj.search(cr, uid, [('mission_report_id', 'in', full_view)])
219
 
                    line_obj.update_full_view_line(cr, uid, line_ids, context=context)
220
 
            elif not report['full_view']:
221
 
                # Update all lines
222
 
                self.update_lines(cr, uid, [report['id']])
223
 
 
224
 
            self._get_export_csv(cr, uid, report['id'], product_values, context=context)
 
179
            self.write(cr, uid, [report.id], {'last_update': time.strftime('%Y-%m-%d %H:%M:%S')}, context=context)
 
180
               
 
181
        if context.get('update_full_report'):
 
182
            line_obj.update_full_view_line(cr, uid, line_ids, context=context)
 
183
        else:
 
184
            # Update all lines
 
185
            line_obj.update(cr, uid, line_ids, context=context)
 
186
 
225
187
 
226
188
        # After update of all normal reports, update the full view report
227
189
        if not context.get('update_full_report'):
230
192
            self.update(cr, uid, [], context=c)
231
193
 
232
194
        return True
233
 
 
234
 
    def update_lines(self, cr, uid, ids, context=None):
235
 
        location_obj = self.pool.get('stock.location')
236
 
        data_obj = self.pool.get('ir.model.data')
237
 
        line_obj = self.pool.get('stock.mission.report.line')
238
 
        product_obj = self.pool.get('product.product')
239
 
        # Search considered SLocation
240
 
        stock_location_id = data_obj.get_object_reference(cr, uid, 'stock', 'stock_location_stock')
241
 
        if stock_location_id:
242
 
            stock_location_id = stock_location_id[1]
243
 
        internal_loc = location_obj.search(cr, uid, [('usage', '=', 'internal')], context=context)
244
 
        central_loc = location_obj.search(cr, uid, [('central_location_ok', '=', True)], context=context)
245
 
        cross_loc = location_obj.search(cr, uid, [('cross_docking_location_ok', '=', True)], context=context)
246
 
        stock_loc = location_obj.search(cr, uid, [('location_id', 'child_of', stock_location_id),
247
 
                                                  ('id', 'not in', cross_loc),
248
 
                                                  ('central_location_ok', '=', False)], context=context)
249
 
        cu_loc = location_obj.search(cr, uid, [('usage', '=', 'internal'), ('location_category', '=', 'consumption_unit')], context=context)
250
 
        secondary_location_id = data_obj.get_object_reference(cr, uid, 'msf_config_locations', 'stock_location_intermediate_client_view')
251
 
        if secondary_location_id:
252
 
            secondary_location_id = secondary_location_id[1]
253
 
        secondary_location_ids = location_obj.search(cr, uid, [('location_id', 'child_of', secondary_location_id)], context=context)
254
 
 
255
 
        cu_loc = location_obj.search(cr, uid, [('location_id', 'child_of', cu_loc)], context=context)
256
 
        central_loc = location_obj.search(cr, uid, [('location_id', 'child_of', central_loc)], context=context)
257
 
 
258
 
        # Check if the instance is a coordination or a project
259
 
        coordo_id = False
260
 
        company = self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id
261
 
        coordo = self.pool.get('msf.instance').search(cr, uid, [('level', '=', 'coordo')], context=context)
262
 
        if company.instance_id.level == 'project' and coordo:
263
 
            coordo_id = self.pool.get('msf.instance').browse(cr, uid, coordo[0], context=context).instance
264
 
 
265
 
        for id in ids:
266
 
            # In-Pipe moves
267
 
            cr.execute('''SELECT m.product_id, m.product_qty, m.product_uom, p.name, m.id
268
 
                          FROM stock_move m
269
 
                              LEFT JOIN stock_picking s ON m.picking_id = s.id
270
 
                              LEFT JOIN res_partner p ON s.partner_id2 = p.id
271
 
                          WHERE s.type = 'in' AND m.state in ('confirmed', 'waiting', 'assigned')''')
272
 
 
273
 
            in_pipe_moves = cr.fetchall()
274
 
            for product_id, qty, uom, partner, move_id in in_pipe_moves:
275
 
                line_id = line_obj.search(cr, uid, [('product_id', '=', product_id),
276
 
                                                    ('mission_report_id', '=', id)])
277
 
                if line_id:
278
 
                    line = line_obj.browse(cr, uid, line_id[0])
279
 
                    if uom != line.product_id.uom_id.id:
280
 
                        qty = self.pool.get('product.uom')._compute_qty(cr, uid, uom, qty, line.product_id.uom_id.id)
281
 
 
282
 
                    vals = {'in_pipe_qty': 0.00,
283
 
                            'in_pipe_coor_qty': 0.00,
284
 
                            'updated': True}
285
 
 
286
 
                    vals['in_pipe_qty'] = vals['in_pipe_qty'] + qty
287
 
 
288
 
                    if partner == coordo_id:
289
 
                        vals['in_pipe_coor_qty'] = vals['in_pipe_coor_qty'] + qty
290
 
 
291
 
                    line_obj.write(cr, uid, line.id, vals)
292
 
 
293
 
            # All other moves
294
 
            cr.execute('''
295
 
                        SELECT id, product_id, product_uom, product_qty, location_id, location_dest_id
296
 
                        FROM stock_move
297
 
                        WHERE state = 'done'
298
 
                        AND id not in (SELECT move_id FROM mission_move_rel WHERE mission_id = %s)
299
 
            ''' % (id))
300
 
            res = cr.fetchall()
301
 
            for move in res:
302
 
                cr.execute('INSERT INTO mission_move_rel VALUES (%s, %s)' % (id, move[0]))
303
 
                product = product_obj.browse(cr, uid, move[1])
304
 
                line_id = line_obj.search(cr, uid, [('product_id', '=', move[1]),
305
 
                                                    ('mission_report_id', '=', id)])
306
 
                if line_id:
307
 
                    line = line_obj.browse(cr, uid, line_id[0])
308
 
                    qty = self.pool.get('product.uom')._compute_qty(cr, uid, move[2], move[3], product.uom_id.id)
309
 
                    vals = {'internal_qty': line.internal_qty or 0.00,
310
 
                            'stock_qty': line.stock_qty or 0.00,
311
 
                            'central_qty': line.central_qty or 0.00,
312
 
                            'cross_qty': line.cross_qty or 0.00,
313
 
                            'secondary_qty': line.secondary_qty or 0.00,
314
 
                            'cu_qty': line.cu_qty or 0.00,
315
 
                            'updated': True}
316
 
 
317
 
                    if move[4] in internal_loc:
318
 
                        vals['internal_qty'] = vals['internal_qty'] - qty
319
 
                    if move[4] in stock_loc:
320
 
                        vals['stock_qty'] = vals['stock_qty'] - qty
321
 
                    if move[4] in central_loc:
322
 
                        vals['central_qty'] = vals['central_qty'] - qty
323
 
                    if move[4] in cross_loc:
324
 
                        vals['cross_qty'] = vals['cross_qty'] - qty
325
 
                    if move[4] in secondary_location_ids:
326
 
                        vals['secondary_qty'] = vals['secondary_qty'] - qty
327
 
                    if move[4] in cu_loc:
328
 
                        vals['cu_qty'] = vals['cu_qty'] - qty
329
 
 
330
 
                    if move[5] in internal_loc:
331
 
                        vals['internal_qty'] = vals['internal_qty'] + qty
332
 
                    if move[5] in stock_loc:
333
 
                        vals['stock_qty'] = vals['stock_qty'] + qty
334
 
                    if move[5] in central_loc:
335
 
                        vals['central_qty'] = vals['central_qty'] + qty
336
 
                    if move[5] in cross_loc:
337
 
                        vals['cross_qty'] = vals['cross_qty'] + qty
338
 
                    if move[5] in secondary_location_ids:
339
 
                        vals['secondary_qty'] = vals['secondary_qty'] + qty
340
 
                    if move[5] in cu_loc:
341
 
                        vals['cu_qty'] = vals['cu_qty'] + qty
342
 
 
343
 
                    vals.update({'internal_val': vals['internal_qty'] * product.standard_price})
344
 
                    line_obj.write(cr, uid, line.id, vals)
345
 
 
346
 
        return True
347
 
 
348
 
    def _get_export_csv(self, cr, uid, ids, product_values, context=None):
349
 
        '''
350
 
        Get the XML files of the stock mission report.
351
 
        This method generates 4 files (according to option set) :
352
 
            * 1 file with no split of WH and no valuation
353
 
            * 1 file with no split of WH and valuation
354
 
            * 1 file with split of WH and valuation
355
 
            * 1 file with split aof WH and valuation
356
 
        '''
357
 
        context = context or {}
358
 
        if isinstance(ids, (int, long)):
359
 
            ids = [ids]
360
 
 
361
 
        def set_data(request, report_id, line, data_name,):
362
 
            data = ''
363
 
            cr.execute(request, (report_id, line['id']))
364
 
            try:
365
 
                product_amc = line['product_id'][0] in product_values and product_values[line['product_id'][0]]['product_amc'] or 0.00
366
 
                reviewed_consumption = line['product_id'][0] in product_values and product_values[line['product_id'][0]]['reviewed_consumption'] or 0.00
367
 
                for r in cr.dictfetchall():
368
 
                    data += r[data_name] % (product_amc, reviewed_consumption)
369
 
            except Exception, e:
370
 
                logging.getLogger('Mission stock report').warning("""An error is occured when compute the consumption values for product at mission stock report file generation. Data: \n %s""" % data_name)
371
 
 
372
 
            data += '\n'
373
 
            return data
374
 
 
375
 
#        for report in self.browse(cr, uid, ids, context=context):
376
 
        for report_id in ids:
377
 
            # No split, no valuation
378
 
            ns_nv_data = ''
379
 
            # No split, valuation
380
 
            ns_v_data = ''
381
 
            # Split, no valuation
382
 
            s_nv_data = ''
383
 
            # Split, valuation
384
 
            s_v_data = ''
385
 
 
386
 
            request = '''SELECT
387
 
                l.product_id AS product_id,
388
 
                xmlelement(name Row,
389
 
 
390
 
                xmlelement(name Cell, xmlattributes('ssBorder' as "ss:StyleID"),
391
 
                xmlelement(name Data, xmlattributes('String' as "ss:Type"),
392
 
                replace(l.default_code, '%%', '%%%%'))),
393
 
 
394
 
                xmlelement(name Cell, xmlattributes('ssBorder' as "ss:StyleID"),
395
 
                xmlelement(name Data, xmlattributes('String' as "ss:Type"),
396
 
                replace(pt.name, '%%', '%%%%'))),
397
 
 
398
 
                xmlelement(name Cell, xmlattributes('ssBorder' as "ss:StyleID"),
399
 
                xmlelement(name Data, xmlattributes('String' as "ss:Type"),
400
 
                replace(pu.name, '%%', '%%%%'))),
401
 
 
402
 
                xmlelement(name Cell, xmlattributes('ssBorder' as "ss:StyleID"),
403
 
                xmlelement(name Data, xmlattributes('Number' as "ss:Type"),
404
 
                trim(to_char(l.internal_qty, '999999999999.999')))),
405
 
 
406
 
                xmlelement(name Cell, xmlattributes('ssBorder' as "ss:StyleID"),
407
 
                xmlelement(name Data, xmlattributes('Number' as "ss:Type"),
408
 
                trim(to_char(l.wh_qty, '999999999999.999')))),
409
 
 
410
 
                xmlelement(name Cell, xmlattributes('ssBorder' as "ss:StyleID"),
411
 
                xmlelement(name Data, xmlattributes('Number' as "ss:Type"),
412
 
                trim(to_char(l.cross_qty, '999999999999.999')))),
413
 
 
414
 
                xmlelement(name Cell, xmlattributes('ssBorder' as "ss:StyleID"),
415
 
                xmlelement(name Data, xmlattributes('Number' as "ss:Type"),
416
 
                trim(to_char(l.secondary_qty, '999999999999.999')))),
417
 
 
418
 
                xmlelement(name Cell, xmlattributes('ssBorder' as "ss:StyleID"),
419
 
                xmlelement(name Data, xmlattributes('Number' as "ss:Type"),
420
 
                trim(to_char(l.cu_qty, '999999999999.999')))),
421
 
 
422
 
                xmlelement(name Cell, xmlattributes('ssBorder' as "ss:StyleID"),
423
 
                xmlelement(name Data, xmlattributes('Number' as "ss:Type"),
424
 
                '%%s')),
425
 
 
426
 
                xmlelement(name Cell, xmlattributes('ssBorder' as "ss:StyleID"),
427
 
                xmlelement(name Data, xmlattributes('Number' as "ss:Type"),
428
 
                '%%s')),
429
 
 
430
 
                xmlelement(name Cell, xmlattributes('ssBorder' as "ss:StyleID"),
431
 
                xmlelement(name Data, xmlattributes('Number' as "ss:Type"),
432
 
                trim(to_char(l.in_pipe_qty, '999999999999.999'))))
433
 
                ) AS ns_nv_data,
434
 
                xmlelement(name Row,
435
 
 
436
 
                xmlelement(name Cell, xmlattributes('ssBorder' as "ss:StyleID"),
437
 
                xmlelement(name Data, xmlattributes('String' as "ss:Type"),
438
 
                replace(l.default_code, '%%', '%%%%'))),
439
 
 
440
 
                xmlelement(name Cell, xmlattributes('ssBorder' as "ss:StyleID"),
441
 
                xmlelement(name Data, xmlattributes('String' as "ss:Type"),
442
 
                replace(pt.name, '%%', '%%%%'))),
443
 
 
444
 
                xmlelement(name Cell, xmlattributes('ssBorder' as "ss:StyleID"),
445
 
                xmlelement(name Data, xmlattributes('String' as "ss:Type"),
446
 
                replace(pu.name, '%%', '%%%%'))),
447
 
 
448
 
                xmlelement(name Cell, xmlattributes('ssBorder' as "ss:StyleID"),
449
 
                xmlelement(name Data, xmlattributes('Number' as "ss:Type"),
450
 
                trim(to_char(l.internal_qty, '999999999999.999')))),
451
 
 
452
 
                xmlelement(name Cell, xmlattributes('ssBorder' as "ss:StyleID"),
453
 
                xmlelement(name Data, xmlattributes('Number' as "ss:Type"),
454
 
                trim(to_char(l.stock_qty, '999999999999.999')))),
455
 
 
456
 
                xmlelement(name Cell, xmlattributes('ssBorder' as "ss:StyleID"),
457
 
                xmlelement(name Data, xmlattributes('Number' as "ss:Type"),
458
 
                trim(to_char(l.central_qty, '999999999999.999')))),
459
 
 
460
 
                xmlelement(name Cell, xmlattributes('ssBorder' as "ss:StyleID"),
461
 
                xmlelement(name Data, xmlattributes('Number' as "ss:Type"),
462
 
                trim(to_char(l.cross_qty, '999999999999.999')))),
463
 
 
464
 
                xmlelement(name Cell, xmlattributes('ssBorder' as "ss:StyleID"),
465
 
                xmlelement(name Data, xmlattributes('Number' as "ss:Type"),
466
 
                trim(to_char(l.secondary_qty, '999999999999.999')))),
467
 
 
468
 
                xmlelement(name Cell, xmlattributes('ssBorder' as "ss:StyleID"),
469
 
                xmlelement(name Data, xmlattributes('Number' as "ss:Type"),
470
 
                trim(to_char(l.cu_qty, '999999999999.999')))),
471
 
 
472
 
                xmlelement(name Cell, xmlattributes('ssBorder' as "ss:StyleID"),
473
 
                xmlelement(name Data, xmlattributes('Number' as "ss:Type"),
474
 
                '%%s')),
475
 
 
476
 
                xmlelement(name Cell, xmlattributes('ssBorder' as "ss:StyleID"),
477
 
                xmlelement(name Data, xmlattributes('Number' as "ss:Type"),
478
 
                '%%s')),
479
 
 
480
 
                xmlelement(name Cell, xmlattributes('ssBorder' as "ss:StyleID"),
481
 
                xmlelement(name Data, xmlattributes('Number' as "ss:Type"),
482
 
                trim(to_char(l.in_pipe_qty, '999999999999.999'))))
483
 
                ) AS s_nv_data,
484
 
                xmlelement(name Row,
485
 
 
486
 
                xmlelement(name Cell, xmlattributes('ssBorder' as "ss:StyleID"),
487
 
                xmlelement(name Data, xmlattributes('String' as "ss:Type"),
488
 
                replace(l.default_code, '%%', '%%%%'))),
489
 
 
490
 
                xmlelement(name Cell, xmlattributes('ssBorder' as "ss:StyleID"),
491
 
                xmlelement(name Data, xmlattributes('String' as "ss:Type"),
492
 
                replace(pt.name, '%%', '%%%%'))),
493
 
 
494
 
                xmlelement(name Cell, xmlattributes('ssBorder' as "ss:StyleID"),
495
 
                xmlelement(name Data, xmlattributes('String' as "ss:Type"),
496
 
                replace(pu.name, '%%', '%%%%'))),
497
 
 
498
 
                xmlelement(name Cell, xmlattributes('ssBorder' as "ss:StyleID"),
499
 
                xmlelement(name Data, xmlattributes('Number' as "ss:Type"),
500
 
                trim(to_char(pt.standard_price, '999999999999.999')))),
501
 
 
502
 
                xmlelement(name Cell, xmlattributes('ssBorder' as "ss:StyleID"),
503
 
                xmlelement(name Data, xmlattributes('String' as "ss:Type"),
504
 
                rc.name)),
505
 
 
506
 
                xmlelement(name Cell, xmlattributes('ssBorder' as "ss:StyleID"),
507
 
                xmlelement(name Data, xmlattributes('Number' as "ss:Type"),
508
 
                trim(to_char(l.internal_qty, '999999999999.999')))),
509
 
 
510
 
                xmlelement(name Cell, xmlattributes('ssBorder' as "ss:StyleID"),
511
 
                xmlelement(name Data, xmlattributes('Number' as "ss:Type"),
512
 
                trim(to_char((l.internal_qty * pt.standard_price), '999999999999.999')))),
513
 
 
514
 
                xmlelement(name Cell, xmlattributes('ssBorder' as "ss:StyleID"),
515
 
                xmlelement(name Data, xmlattributes('Number' as "ss:Type"),
516
 
                trim(to_char(l.wh_qty, '999999999999.999')))),
517
 
 
518
 
                xmlelement(name Cell, xmlattributes('ssBorder' as "ss:StyleID"),
519
 
                xmlelement(name Data, xmlattributes('Number' as "ss:Type"),
520
 
                trim(to_char(l.cross_qty, '999999999999.999')))),
521
 
 
522
 
                xmlelement(name Cell, xmlattributes('ssBorder' as "ss:StyleID"),
523
 
                xmlelement(name Data, xmlattributes('Number' as "ss:Type"),
524
 
                trim(to_char(l.secondary_qty, '999999999999.999')))),
525
 
 
526
 
                xmlelement(name Cell, xmlattributes('ssBorder' as "ss:StyleID"),
527
 
                xmlelement(name Data, xmlattributes('Number' as "ss:Type"),
528
 
                trim(to_char(l.cu_qty, '999999999999.999')))),
529
 
 
530
 
                xmlelement(name Cell, xmlattributes('ssBorder' as "ss:StyleID"),
531
 
                xmlelement(name Data, xmlattributes('Number' as "ss:Type"),
532
 
                '%%s')),
533
 
 
534
 
                xmlelement(name Cell, xmlattributes('ssBorder' as "ss:StyleID"),
535
 
                xmlelement(name Data, xmlattributes('Number' as "ss:Type"),
536
 
                '%%s')),
537
 
 
538
 
                xmlelement(name Cell, xmlattributes('ssBorder' as "ss:StyleID"),
539
 
                xmlelement(name Data, xmlattributes('Number' as "ss:Type"),
540
 
                trim(to_char(l.in_pipe_qty, '999999999999.999'))))
541
 
                ) AS ns_v_data,
542
 
                xmlelement(name Row,
543
 
 
544
 
                xmlelement(name Cell, xmlattributes('ssBorder' as "ss:StyleID"),
545
 
                xmlelement(name Data, xmlattributes('String' as "ss:Type"),
546
 
                replace(l.default_code, '%%', '%%%%'))),
547
 
 
548
 
                xmlelement(name Cell, xmlattributes('ssBorder' as "ss:StyleID"),
549
 
                xmlelement(name Data, xmlattributes('String' as "ss:Type"),
550
 
                replace(pt.name, '%%', '%%%%'))),
551
 
 
552
 
                xmlelement(name Cell, xmlattributes('ssBorder' as "ss:StyleID"),
553
 
                xmlelement(name Data, xmlattributes('String' as "ss:Type"),
554
 
                replace(pu.name, '%%', '%%%%'))),
555
 
 
556
 
                xmlelement(name Cell, xmlattributes('ssBorder' as "ss:StyleID"),
557
 
                xmlelement(name Data, xmlattributes('Number' as "ss:Type"),
558
 
                trim(to_char((l.internal_qty * pt.standard_price), '999999999999.999')))),
559
 
 
560
 
                xmlelement(name Cell, xmlattributes('ssBorder' as "ss:StyleID"),
561
 
                xmlelement(name Data, xmlattributes('String' as "ss:Type"),
562
 
                rc.name)),
563
 
 
564
 
                xmlelement(name Cell, xmlattributes('ssBorder' as "ss:StyleID"),
565
 
                xmlelement(name Data, xmlattributes('Number' as "ss:Type"),
566
 
                trim(to_char(l.internal_qty, '999999999999.999')))),
567
 
 
568
 
                xmlelement(name Cell, xmlattributes('ssBorder' as "ss:StyleID"),
569
 
                xmlelement(name Data, xmlattributes('Number' as "ss:Type"),
570
 
                trim(to_char((l.internal_qty * pt.standard_price), '999999999999.999')))),
571
 
 
572
 
                xmlelement(name Cell, xmlattributes('ssBorder' as "ss:StyleID"),
573
 
                xmlelement(name Data, xmlattributes('Number' as "ss:Type"),
574
 
                trim(to_char(l.stock_qty, '999999999999.999')))),
575
 
 
576
 
                xmlelement(name Cell, xmlattributes('ssBorder' as "ss:StyleID"),
577
 
                xmlelement(name Data, xmlattributes('Number' as "ss:Type"),
578
 
                trim(to_char(l.central_qty, '999999999999.999')))),
579
 
 
580
 
                xmlelement(name Cell, xmlattributes('ssBorder' as "ss:StyleID"),
581
 
                xmlelement(name Data, xmlattributes('Number' as "ss:Type"),
582
 
                trim(to_char(l.cross_qty, '999999999999.999')))),
583
 
 
584
 
                xmlelement(name Cell, xmlattributes('ssBorder' as "ss:StyleID"),
585
 
                xmlelement(name Data, xmlattributes('Number' as "ss:Type"),
586
 
                trim(to_char(l.secondary_qty, '999999999999.999')))),
587
 
 
588
 
                xmlelement(name Cell, xmlattributes('ssBorder' as "ss:StyleID"),
589
 
                xmlelement(name Data, xmlattributes('Number' as "ss:Type"),
590
 
                trim(to_char(l.cu_qty, '999999999999.999')))),
591
 
 
592
 
                xmlelement(name Cell, xmlattributes('ssBorder' as "ss:StyleID"),
593
 
                xmlelement(name Data, xmlattributes('Number' as "ss:Type"),
594
 
                '%%s')),
595
 
 
596
 
                xmlelement(name Cell, xmlattributes('ssBorder' as "ss:StyleID"),
597
 
                xmlelement(name Data, xmlattributes('Number' as "ss:Type"),
598
 
                '%%s')),
599
 
 
600
 
                xmlelement(name Cell, xmlattributes('ssBorder' as "ss:StyleID"),
601
 
                xmlelement(name Data, xmlattributes('Number' as "ss:Type"),
602
 
                trim(to_char(l.in_pipe_qty, '999999999999.999'))))
603
 
                ) AS s_v_data
604
 
            FROM stock_mission_report_line l
605
 
                 LEFT JOIN product_product pp ON l.product_id = pp.id
606
 
                 LEFT JOIN product_template pt ON pp.product_tmpl_id = pt.id
607
 
                 LEFT JOIN product_uom pu ON pt.uom_id = pu.id
608
 
                 LEFT JOIN res_currency rc ON pp.currency_id = rc.id
609
 
            WHERE l.mission_report_id = %s'''
610
 
 
611
 
            cr.execute(request, (report_id, ))
612
 
            res = cr.dictfetchall()
613
 
            for line in res:
614
 
                try:
615
 
                    product_amc = line['product_id'] in product_values and product_values[line['product_id']]['product_amc'] or 0.00
616
 
                    reviewed_consumption = line['product_id'] in product_values and product_values[line['product_id']]['reviewed_consumption'] or 0.00
617
 
                    ns_nv_data += replace_all(line['ns_nv_data'] % (product_amc, reviewed_consumption))
618
 
                    ns_v_data  += replace_all(line['ns_v_data'] % (product_amc, reviewed_consumption))
619
 
                    s_nv_data  += replace_all(line['s_nv_data'] % (product_amc, reviewed_consumption))
620
 
                    s_v_data   += replace_all(line['s_v_data'] % (product_amc, reviewed_consumption))
621
 
                except Exception, e:
622
 
                    logging.getLogger('Mission stock report').warning("""An error is occured when generate the mission stock report file. Data: \n %s""" % line)
623
 
 
624
 
            for data, field in [(ns_nv_data, 'ns_nv_vals'), (ns_v_data, 'ns_v_vals'), (s_nv_data, 's_nv_vals'), (s_v_data, 's_v_vals')]:
625
 
                self.write(cr, uid, [report_id], {field: data}, context=context)
626
 
 
627
 
            self.write(cr, uid, [report_id], {'export_ok': True}, context=context)
628
 
 
629
 
        return True
630
 
 
 
195
                
 
196
    
631
197
stock_mission_report()
632
198
 
633
199
 
634
200
class stock_mission_report_line(osv.osv):
635
201
    _name = 'stock.mission.report.line'
636
202
    _description = 'Mission stock report line'
637
 
    _order = 'default_code'
638
 
 
 
203
    
639
204
    def _get_product_type_selection(self, cr, uid, context=None):
640
205
        return self.pool.get('product.template').PRODUCT_TYPE
641
 
 
 
206
    
642
207
    def _get_product_subtype_selection(self, cr, uid, context=None):
643
208
        return self.pool.get('product.template').PRODUCT_SUBTYPE
644
 
 
 
209
    
645
210
    def onChangeSearchNomenclature(self, cr, uid, id, position, type, nomen_manda_0, nomen_manda_1, nomen_manda_2, nomen_manda_3, num=True, context=None):
646
211
        return self.pool.get('product.product').onChangeSearchNomenclature(cr, uid, id, position, type, nomen_manda_0, nomen_manda_1, nomen_manda_2, nomen_manda_3, num=num, context=context)
647
 
 
 
212
    
648
213
    def _get_nomen_s(self, cr, uid, ids, fields, *a, **b):
649
214
        value = {}
650
215
        for f in fields:
654
219
        for id in ids:
655
220
            ret[id] = value
656
221
        return ret
657
 
 
 
222
    
658
223
    def _search_nomen_s(self, cr, uid, obj, name, args, context=None):
659
224
        # Some verifications
660
225
        if context is None:
661
226
            context = {}
662
 
 
 
227
            
663
228
        if not args:
664
229
            return []
665
230
        narg = []
666
231
        for arg in args:
667
232
            el = arg[0].split('_')
668
233
            el.pop()
669
 
            narg = [('_'.join(el), arg[1], arg[2])]
670
 
 
 
234
            narg=[('_'.join(el), arg[1], arg[2])]
 
235
        
671
236
        return narg
672
 
 
 
237
    
673
238
    def _get_template(self, cr, uid, ids, context=None):
674
239
        return self.pool.get('stock.mission.report.line').search(cr, uid, [('product_id.product_tmpl_id', 'in', ids)], context=context)
675
 
 
676
 
    def _get_wh_qty(self, cr, uid, ids, field_name, args, context=None):
677
 
        res = {}
678
 
        for line in self.browse(cr, uid, ids, context=context):
679
 
            res[line.id] = line.stock_qty + line.central_qty
680
 
 
681
 
        return res
682
 
 
683
 
    def _get_internal_val(self, cr, uid, ids, field_name, args, context=None):
684
 
        res = {}
685
 
        for line in self.browse(cr, uid, ids, context=context):
686
 
            res[line.id] = line.internal_qty * line.cost_price
687
 
 
688
 
        return res
689
 
 
 
240
    
690
241
    _columns = {
691
 
        'product_id': fields.many2one('product.product', string='Name', required=True, ondelete="cascade"),
692
 
        'default_code': fields.related('product_id', 'default_code', string='Reference', type='char', size=64, store=True),
 
242
        'product_id': fields.many2one('product.product', string='Name', required=True),
 
243
        'default_code': fields.related('product_id', 'default_code', string='Reference', type='char'),
693
244
        'old_code': fields.related('product_id', 'old_code', string='Old Code', type='char'),
694
245
        'name': fields.related('product_id', 'name', string='Name', type='char'),
695
246
        'categ_id': fields.related('product_id', 'categ_id', string='Category', type='many2one', relation='product.category',
696
 
                                   store={'product.template': (_get_template, ['type'], 10),
697
 
                                          'stock.mission.report.line': (lambda self, cr, uid, ids, c={}: ids, ['product_id'], 10)}),
698
 
        'type': fields.related('product_id', 'type', string='Type', type='selection', selection=_get_product_type_selection,
699
 
                               store={'product.template': (_get_template, ['type'], 10),
700
 
                                      'stock.mission.report.line': (lambda self, cr, uid, ids, c={}: ids, ['product_id'], 10)}),
701
 
        'subtype': fields.related('product_id', 'subtype', string='Subtype', type='selection', selection=_get_product_subtype_selection,
702
 
                                  store={'product.template': (_get_template, ['subtype'], 10),
703
 
                                         'stock.mission.report.line': (lambda self, cr, uid, ids, c={}: ids, ['product_id'], 10)}),
 
247
                                   store={'product.template': (_get_template, ['type'], 10)}),
 
248
        'type': fields.related('product_id', 'type', string='Type', type='selection', selection=_get_product_type_selection, 
 
249
                               store={'product.template': (_get_template, ['type'], 10)}),
 
250
        'subtype': fields.related('product_id', 'subtype', string='Subtype', type='selection', selection=_get_product_subtype_selection),
704
251
        # mandatory nomenclature levels
705
252
        'nomen_manda_0': fields.related('product_id', 'nomen_manda_0', type='many2one', relation='product.nomenclature', string='Main Type'),
706
253
        'nomen_manda_1': fields.related('product_id', 'nomen_manda_1', type='many2one', relation='product.nomenclature', string='Group'),
723
270
        'nomen_sub_3_s': fields.function(_get_nomen_s, method=True, type='many2one', relation='product.nomenclature', string='Sub Class 4', fnct_search=_search_nomen_s, multi="nom_s"),
724
271
        'nomen_sub_4_s': fields.function(_get_nomen_s, method=True, type='many2one', relation='product.nomenclature', string='Sub Class 5', fnct_search=_search_nomen_s, multi="nom_s"),
725
272
        'nomen_sub_5_s': fields.function(_get_nomen_s, method=True, type='many2one', relation='product.nomenclature', string='Sub Class 6', fnct_search=_search_nomen_s, multi="nom_s"),
726
 
        'product_amc': fields.related('product_id', 'product_amc', type='float', string='AMC'),
727
 
        'reviewed_consumption': fields.related('product_id', 'reviewed_consumption', type='float', string='FMC'),
 
273
        'product_amc': fields.float(digits=(16,2), string='AMC'),
 
274
        'reviewed_consumption': fields.float(digits=(16,2), string='FMC'),
728
275
        'currency_id': fields.related('product_id', 'currency_id', type='many2one', relation='res.currency', string='Func. cur.'),
729
 
        'cost_price': fields.related('product_id', 'standard_price', type='float', string='Cost price'),
730
276
        'uom_id': fields.related('product_id', 'uom_id', type='many2one', relation='product.uom', string='UoM',
731
 
                                store={
732
 
                                    'product.template': (_get_template, ['type'], 10),
733
 
                                    'stock.mission.report.line': (lambda self, cr, uid, ids, c=None: ids, ['product_id'], 10),
734
 
                                }),
 
277
                                store={'product.template': (_get_template, ['type'], 10)}),
735
278
        'mission_report_id': fields.many2one('stock.mission.report', string='Mission Report', required=True),
736
 
        'internal_qty': fields.float(digits=(16,2), string='Instance Stock'),
737
 
        'internal_val': fields.function(_get_internal_val, method=True, type='float', string='Instance Stock Val.'),
738
 
        #'internal_val': fields.float(digits=(16,2), string='Instance Stock Val.'),
 
279
        'internal_qty': fields.float(digits=(16,2), string='Internal Qty.'),
 
280
        'internal_val': fields.float(digits=(16,2), string='Internal Val.'),
739
281
        'stock_qty': fields.float(digits=(16,2), string='Stock Qty.'),
740
282
        'stock_val': fields.float(digits=(16,2), string='Stock Val.'),
741
 
        'central_qty': fields.float(digits=(16,2), string='Unallocated Stock Qty.'),
742
 
        'central_val': fields.float(digits=(16,2), string='Unallocated Stock Val.'),
743
 
        'wh_qty': fields.function(_get_wh_qty, method=True, type='float', string='Warehouse stock',
744
 
                                  store={'stock.mission.report.line': (lambda self, cr, uid, ids, c=None: ids, ['stock_qty', 'central_qty'], 10),}),
 
283
        'central_qty': fields.float(digits=(16,2), string='Central Stock Qty.'),
 
284
        'central_val': fields.float(digits=(16,2), string='Central Stock Val.'),
745
285
        'cross_qty': fields.float(digits=(16,3), string='Cross-docking Qty.'),
746
286
        'cross_val': fields.float(digits=(16,3), string='Cross-docking Val.'),
747
287
        'secondary_qty': fields.float(digits=(16,2), string='Secondary Stock Qty.'),
754
294
        'in_pipe_coor_val': fields.float(digits=(16,2), string='In Pipe from Coord.'),
755
295
        'updated': fields.boolean(string='Updated'),
756
296
        'full_view': fields.related('mission_report_id', 'full_view', string='Full view', type='boolean', store=True),
757
 
        'move_ids': fields.many2many('stock.move', 'mission_line_move_rel', 'line_id', 'move_id', string='Noves'),
758
 
    }
759
 
 
760
 
    _defaults = {
761
 
        'internal_qty': 0.00,
762
 
        'internal_val': 0.00,
763
 
        'stock_qty': 0.00,
764
 
        'stock_val': 0.00,
765
 
        'wh_qty': 0.00,
766
 
        'central_qty': 0.00,
767
 
        'central_val': 0.00,
768
 
        'cross_qty': 0.00,
769
 
        'cross_val': 0.00,
770
 
        'secondary_qty': 0.00,
771
 
        'secondary_val': 0.00,
772
 
        'cu_qty': 0.00,
773
 
        'cu_val': 0.00,
774
 
        'in_pipe_qty': 0.00,
775
 
        'in_pipe_val': 0.00,
776
 
        'in_pipe_coor_qty': 0.00,
777
 
        'in_pipe_coor_val': 0.00,
778
 
    }
 
297
    }
 
298
    
 
299
    def _get_request(self, cr, uid, location_ids, product_id):
 
300
        '''
 
301
        Browse the good values and give the result
 
302
        '''
 
303
        obj = self.pool.get('report.stock.move')
 
304
        
 
305
        if isinstance(location_ids, (int, long)):
 
306
            location_ids = [location_ids]
 
307
            
 
308
        if not isinstance(product_id, (int, long)):
 
309
            raise osv.except_osv(_('Error'), _('You can\'t build the request for some products !'))
 
310
        
 
311
        minus_ids = obj.search(cr, uid, [('location_id', 'in', location_ids), 
 
312
                                         ('product_id', '=', product_id), 
 
313
                                         ('state', '=', 'done')])
 
314
        
 
315
        plus_ids = obj.search(cr, uid, [('location_dest_id', 'in', location_ids), 
 
316
                                        ('product_id', '=', product_id), 
 
317
                                        ('state', '=', 'done')])
 
318
        
 
319
        res = 0.00
 
320
        for r in obj.browse(cr, uid, plus_ids):
 
321
            res += r.product_qty
 
322
        for r in obj.browse(cr, uid, minus_ids):
 
323
            res -= r.product_qty
 
324
            
 
325
        return res
779
326
 
780
327
    def update_full_view_line(self, cr, uid, ids, context=None):
781
 
        is_project = False
782
 
        if self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id.instance_id.level == 'project':
783
 
            is_project = True
784
 
 
785
 
 
786
 
        request = '''SELECT l.product_id AS product_id,
787
 
                            sum(l.internal_qty) AS internal_qty,
788
 
                            sum(l.stock_qty) AS stock_qty,
789
 
                            sum(l.central_qty) AS central_qty,
790
 
                            sum(l.cross_qty) AS cross_qty,
791
 
                            sum(l.secondary_qty) AS secondary_qty,
792
 
                            sum(l.cu_qty) AS cu_qty,
793
 
                            sum(l.in_pipe_qty) AS in_pipe_qty,
794
 
                            sum(l.in_pipe_coor_qty) AS in_pipe_coor_qty,
795
 
                            sum(l.internal_qty)*t.standard_price AS internal_val
796
 
                     FROM stock_mission_report_line l
797
 
                       LEFT JOIN
798
 
                          stock_mission_report m
799
 
                       ON l.mission_report_id = m.id
800
 
                       LEFT JOIN
801
 
                          product_product p
802
 
                       ON l.product_id = p.id
803
 
                       LEFT JOIN
804
 
                          product_template t
805
 
                       ON p.product_tmpl_id = t.id
806
 
                     WHERE m.full_view = False
807
 
                       AND (l.internal_qty != 0.00
808
 
                       OR l.stock_qty != 0.00
809
 
                       OR l.central_qty != 0.00
810
 
                       OR l.cross_qty != 0.00
811
 
                       OR l.secondary_qty != 0.00
812
 
                       OR l.cu_qty != 0.00
813
 
                       OR l.in_pipe_qty != 0.00
814
 
                       OR l.in_pipe_coor_qty != 0.00)
815
 
                     GROUP BY l.product_id, t.standard_price'''
816
 
 
817
 
        cr.execute(request)
818
 
 
819
 
        vals = cr.fetchall()
820
 
        mission_report_id = self.pool.get('stock.mission.report').search(cr, uid, [('full_view', '=', True)], context=context)
821
 
        for line in vals:
822
 
            line_ids = self.search(cr, uid, [('mission_report_id.full_view', '=', True), ('product_id', '=', line[0])], context=context)
823
 
            if not line_ids:
824
 
                if not mission_report_id:
825
 
                    continue
826
 
                line_id = self.create(cr, uid, {'mission_report_id': mission_report_id[0],
827
 
                                                'product_id': line[0]}, context=context)
828
 
            else:
829
 
                line_id = line_ids[0]
830
 
 
831
 
            in_pipe = line[7] or 0.00
 
328
        for line in self.browse(cr, uid, ids, context=context):
 
329
            line_ids = self.search(cr, uid, [('mission_report_id', '!=', line.mission_report_id.id), ('product_id', '=', line.product_id.id)], context=context)
 
330
            lines = self.browse(cr, uid, line_ids, context=context)
 
331
    
 
332
            internal_qty = 0.00
 
333
            internal_val = 0.00
 
334
            stock_qty = 0.00
 
335
            stock_val = 0.00
 
336
            central_qty = 0.00
 
337
            central_val = 0.00
 
338
            cross_qty = 0.00
 
339
            cross_val = 0.00
 
340
            secondary_qty = 0.00
 
341
            secondary_val = 0.00
 
342
            cu_qty = 0.00
 
343
            cu_val = 0.00
 
344
            in_pipe_qty = 0.00
 
345
            in_pipe_val = 0.00
 
346
            in_pipe_not_coor_qty = 0.00
 
347
            in_pipe_not_coor_val = 0.00
 
348
 
 
349
            is_project = False
 
350
            if self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id.instance_id.level == 'project':
 
351
                is_project = True
 
352
    
 
353
            for l in lines:
 
354
                internal_qty += l.internal_qty
 
355
                internal_val += l.internal_val
 
356
                stock_qty += l.stock_qty
 
357
                stock_val += l.stock_val
 
358
                central_qty += l.central_qty
 
359
                central_val += l.central_val
 
360
                cross_qty += l.cross_qty
 
361
                cross_val += l.cross_val
 
362
                secondary_qty += l.secondary_qty
 
363
                secondary_val += l.secondary_val
 
364
                cu_qty += l.cu_qty
 
365
                cu_val += l.cu_val
 
366
                in_pipe_qty += l.in_pipe_qty
 
367
                in_pipe_val += l.in_pipe_val
 
368
                in_pipe_not_coor_qty += l.in_pipe_coor_qty
 
369
                in_pipe_not_coor_val += l.in_pipe_coor_qty
 
370
 
832
371
            if not is_project:
833
 
                in_pipe = (line[7] or 0.00) - (line[8] or 0.00)
834
 
 
835
 
            self.write(cr, uid, [line_id], {'internal_qty': line[1] or 0.00,
836
 
                                            'internal_val': line[9] or 0.00,
837
 
                                            'stock_qty': line[2] or 0.00,
838
 
                                            'central_qty': line[3] or 0.00,
839
 
                                            'cross_qty': line[4] or 0.00,
840
 
                                            'secondary_qty': line[5] or 0.00,
841
 
                                            'cu_qty': line[6] or 0.00,
842
 
                                            'in_pipe_qty': line[7] or 0.00,
843
 
                                            'in_pipe_coor_qty': line[8] or 0.00,}, context=context)
844
 
 
845
 
        return True
846
 
 
 
372
                in_pipe_qty = in_pipe_qty - in_pipe_not_coor_qty
 
373
                in_pipe_val = in_pipe_val - in_pipe_not_coor_val
 
374
 
 
375
            self.write(cr, uid, [line.id], {'product_amc': line.product_id.product_amc,
 
376
                                            'reviewed_consumption': line.product_id.reviewed_consumption,
 
377
                                            'internal_qty': internal_qty,
 
378
                                            'internal_val': internal_val,
 
379
                                            'stock_qty': stock_qty,
 
380
                                            'stock_val': stock_val,
 
381
                                            'central_qty': central_qty,
 
382
                                            'central_val': central_val,
 
383
                                            'cross_qty': cross_qty,
 
384
                                            'cross_val': cross_val,
 
385
                                            'secondary_qty': secondary_qty,
 
386
                                            'secondary_val': secondary_val,
 
387
                                            'cu_qty': cu_qty,
 
388
                                            'cu_val': cu_val,
 
389
                                            'in_pipe_qty': in_pipe_qty,
 
390
                                            'in_pipe_val': in_pipe_val,
 
391
                                            'in_pipe_coor_qty': in_pipe_not_coor_qty,
 
392
                                            'in_pipe_coor_val': in_pipe_not_coor_val}, context=context)
 
393
            
 
394
        return True
 
395
    
 
396
    def update(self, cr, uid, ids, context=None):
 
397
        '''
 
398
        Update line values
 
399
        '''
 
400
        if not context:
 
401
            context = {}
 
402
            
 
403
        if isinstance(ids, (int, long)):
 
404
            ids = [ids]
 
405
        
 
406
        location_obj = self.pool.get('stock.location')
 
407
        data_obj = self.pool.get('ir.model.data')
 
408
        
 
409
        stock_location_id = data_obj.get_object_reference(cr, uid, 'stock', 'stock_location_stock')
 
410
        if stock_location_id:
 
411
            stock_location_id = stock_location_id[1]
 
412
            
 
413
        # Check if the instance is a coordination or a project
 
414
        coordo_id = False
 
415
        company = self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id
 
416
        coordo = self.pool.get('msf.instance').search(cr, uid, [('level', '=', 'coordo')], context=context)
 
417
        if company.instance_id.level == 'project' and coordo:
 
418
            coordo_id = self.pool.get('msf.instance').browse(cr, uid, coordo[0], context=context).instance
 
419
        
 
420
        # Search considered SLocation
 
421
        internal_loc = location_obj.search(cr, uid, [('usage', '=', 'internal')], context=context)
 
422
        central_loc = location_obj.search(cr, uid, [('central_location_ok', '=', True)], context=context)
 
423
        cross_loc = location_obj.search(cr, uid, [('cross_docking_location_ok', '=', True)], context=context)
 
424
        stock_loc = location_obj.search(cr, uid, [('location_id', 'child_of', stock_location_id),
 
425
                                                  ('id', 'not in', cross_loc), 
 
426
                                                  ('central_location_ok', '=', False)], context=context)
 
427
        cu_loc = location_obj.search(cr, uid, [('usage', '=', 'internal'), ('location_category', '=', 'consumption_unit')], context=context)
 
428
        secondary_location_id = data_obj.get_object_reference(cr, uid, 'msf_config_locations', 'stock_location_intermediate_client_view')
 
429
        if secondary_location_id:
 
430
            secondary_location_id = secondary_location_id[1]
 
431
        secondary_location_ids = location_obj.search(cr, uid, [('location_id', 'child_of', secondary_location_id)], context=context)
 
432
        
 
433
        for line in self.browse(cr, uid, ids, context=context):
 
434
            # In case of full report
 
435
            if line.mission_report_id.full_view:
 
436
                continue
 
437
            
 
438
            standard_price = line.product_id.standard_price
 
439
            # Internal locations
 
440
            internal_qty = 0.00
 
441
            internal_val = 0.00
 
442
            if internal_loc:
 
443
                internal_qty = self._get_request(cr, uid, internal_loc, line.product_id.id)
 
444
                internal_val = internal_qty*standard_price
 
445
            
 
446
            # Stock locations
 
447
            stock_qty = 0.00
 
448
            stock_val = 0.00
 
449
            if stock_loc:
 
450
                stock_qty = self._get_request(cr, uid, stock_loc, line.product_id.id)
 
451
                stock_val = stock_qty*standard_price                                                    
 
452
            
 
453
            # Central stock locations
 
454
            central_qty = 0.00
 
455
            central_val = 0.00
 
456
            if central_loc:
 
457
                central_loc = location_obj.search(cr, uid, [('location_id', 'child_of', central_loc)], context=context)
 
458
                central_qty = self._get_request(cr, uid, central_loc, line.product_id.id)
 
459
                central_val = central_qty*standard_price
 
460
            
 
461
            # Cross-docking locations
 
462
            cross_qty = 0.00
 
463
            cross_val = 0.00
 
464
            if cross_loc:
 
465
                cross_loc = location_obj.search(cr, uid, [('location_id', 'child_of', cross_loc)], context=context)
 
466
                cross_qty = self._get_request(cr, uid, cross_loc, line.product_id.id)
 
467
                cross_val = cross_qty*standard_price
 
468
 
 
469
            # Secondary stock locations
 
470
            secondary_qty = 0.00
 
471
            secondary_val = 0.00
 
472
            if secondary_location_ids != False:
 
473
                secondary_qty = self._get_request(cr, uid, secondary_location_ids, line.product_id.id)
 
474
                secondary_val = secondary_qty*standard_price
 
475
                
 
476
            # Consumption unit locations
 
477
            cu_qty = 0.00
 
478
            cu_val = 0.00
 
479
            if cu_loc:
 
480
                cu_loc = location_obj.search(cr, uid, [('location_id', 'child_of', cu_loc)], context=context)
 
481
                cu_qty = self._get_request(cr, uid, cu_loc, line.product_id.id)
 
482
                cu_val = cu_qty*standard_price
 
483
                
 
484
            # In Pipe
 
485
            in_pipe_qty = 0.00
 
486
            in_pipe_not_coord_qty = 0.00
 
487
            cr.execute('''SELECT m.product_qty, m.product_uom, p.name
 
488
                          FROM stock_move m 
 
489
                              LEFT JOIN stock_picking s ON m.picking_id = s.id
 
490
                              LEFT JOIN res_partner p ON s.partner_id2 = p.id
 
491
                          WHERE m.type = 'in' AND m.state in ('confirmed', 'waiting', 'assigned')
 
492
                              AND m.product_id = %s''' % line.product_id.id)
 
493
            moves = cr.fetchall()
 
494
            for qty, uom, partner in moves:
 
495
                if uom != line.product_id.uom_id.id:
 
496
                    qty = self.pool.get('product.uom')._compute_qty(cr, uid, uom, qty, line.product_id.uom_id.id)
 
497
                
 
498
                in_pipe_qty += qty
 
499
                if partner == coordo_id:
 
500
                    in_pipe_not_coord_qty += qty
 
501
            
 
502
            in_pipe_val = in_pipe_qty*standard_price
 
503
            in_pipe_not_coord_val = in_pipe_not_coord_qty*standard_price
 
504
            
 
505
            values = {'product_amc': line.product_id.product_amc,
 
506
                      'reviewed_consumption': line.product_id.reviewed_consumption,
 
507
                      'internal_qty': internal_qty,
 
508
                      'internal_val': internal_val,
 
509
                      'stock_qty': stock_qty,
 
510
                      'stock_val': stock_val,
 
511
                      'central_qty': central_qty,
 
512
                      'central_val': central_val,
 
513
                      'cross_qty': cross_qty,
 
514
                      'cross_val': cross_val,
 
515
                      'secondary_qty': secondary_qty,
 
516
                      'secondary_val': secondary_val,
 
517
                      'cu_qty': cu_qty,
 
518
                      'cu_val': cu_val,
 
519
                      'in_pipe_qty': in_pipe_qty,
 
520
                      'in_pipe_val': in_pipe_val,
 
521
                      'in_pipe_coor_qty': in_pipe_not_coord_qty,
 
522
                      'in_pipe_coor_val': in_pipe_not_coord_val,
 
523
                      'updated': False}
 
524
            
 
525
            line_read = self.read(cr, uid, line.id, values.keys(), context=context)
 
526
            for k in values.keys():
 
527
                if line_read[k] != values[k]:
 
528
                    values.update({'updated': True})
 
529
            
 
530
            self.write(cr, uid, [line.id], values, context=context)
 
531
        return True
 
532
    
847
533
stock_mission_report_line()