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

« back to all changes in this revision

Viewing changes to sourcing/sourcing.py

UF-358 [ADD] Initial creation : backup of this day

Show diffs side-by-side

added added

removed removed

Lines of Context:
28
28
import netsvc
29
29
import pooler
30
30
import time
31
 
import re
32
31
 
33
32
from order_types import ORDER_PRIORITY, ORDER_CATEGORY
34
 
from sale_override import SALE_ORDER_STATE_SELECTION
35
33
 
36
34
_SELECTION_PO_CFT = [
37
35
                     ('po', 'Purchase Order'),
38
 
                     ('dpo', 'Direct Purchase Order'),
39
 
                     ('cft', 'Tender'),
 
36
                     ('cft', 'Call for Tender'),
40
37
                     ]
41
38
 
42
39
class sourcing_line(osv.osv):
46
43
    sourcing lines are generated when a Sale Order is created
47
44
    (overriding of create method of sale_order)
48
45
    '''
49
 
    
50
 
    def get_sale_order_states(self, cr, uid, context=None):
51
 
        '''
52
 
        Returns all states values for a sale.order object
53
 
        '''
54
 
        return self.pool.get('sale.order')._columns['state'].selection
55
 
    
56
 
    def get_sale_order_line_states(self, cr, uid, context=None):
57
 
        '''
58
 
        Returns all states values for a sale.order.line object
59
 
        '''
60
 
        return self.pool.get('sale.order.line')._columns['state'].selection
61
 
        
62
 
 
63
46
    _SELECTION_TYPE = [
64
47
                       ('make_to_stock', 'from stock'),
65
48
                       ('make_to_order', 'on order'),
66
49
                       ]
67
50
    
68
 
    _SELECTION_SALE_ORDER_STATE = get_sale_order_states
 
51
    _SELECTION_SALE_ORDER_STATE = [
 
52
                                   ('procurement', 'Internal Supply Requirement'),
 
53
                                   ('proc_progress', 'In Progress'),
 
54
                                   ('proc_cancel', 'Cancelled'),
 
55
                                   ('proc_done', 'Done'),
 
56
                                   ('draft', 'Quotation'),
 
57
                                   ('waiting_date', 'Waiting Schedule'),
 
58
                                   ('manual', 'Manual In Progress'),
 
59
                                   ('progress', 'In Progress'),
 
60
                                   ('shipping_except', 'Shipping Exception'),
 
61
                                   ('invoice_except', 'Invoice Exception'),
 
62
                                   ('done', 'Done'),
 
63
                                   ('cancel', 'Cancelled'),
 
64
                                   ]
69
65
    
70
 
    _SELECTION_SALE_ORDER_LINE_STATE = get_sale_order_line_states
 
66
    _SELECTION_SALE_ORDER_LINE_STATE = [
 
67
                                        ('draft', 'Draft'),
 
68
                                        ('confirmed', 'Confirmed'),
 
69
                                        ('done', 'Done'),
 
70
                                        ('cancel', 'Cancelled'),
 
71
                                        ('exception', 'Exception'),
 
72
                                        ]
71
73
    
72
74
    def unlink(self, cr, uid, ids, context=None):
73
75
        '''
79
81
            raise osv.except_osv(_('Invalid action !'), _('Cannot delete Sale Order Line(s) from the sourcing tool !'))
80
82
        # delete the sourcing line
81
83
        return super(sourcing_line, self).unlink(cr, uid, ids, context)
82
 
 
83
 
    def _getAvailableStock(self, cr, uid, ids, field_names=None, arg=False, context=None):
84
 
        '''
85
 
        get available stock for the product of the corresponding sourcing line
86
 
        '''
87
 
        result = {}
88
 
        productObj = self.pool.get('product.product')
89
 
        # for each sourcing line
90
 
        for sl in self.browse(cr, uid, ids, context):
91
 
            product_context = context
92
 
            if sl.product_id:
93
 
                real_stock = sl.product_id.qty_available
94
 
                product_context = context
95
 
                product_context.update({'states': ('assigned',), 'what': ('out',)})
96
 
                productId = productObj.get_product_available(cr, uid, [sl.product_id.id], context=product_context)
97
 
                res = real_stock + productId.get(sl.product_id.id, 0.00)
98
 
            else:
99
 
                res = 0.00
100
 
 
101
 
            result[sl.id] = res
102
 
            
103
 
        return result
104
84
    
105
85
    def _getVirtualStock(self, cr, uid, ids, field_names=None, arg=False, context=None):
106
86
        '''
109
89
        '''
110
90
        result = {}
111
91
        productObj = self.pool.get('product.product')
112
 
 
113
 
        # UF-1411 : Compute the virtual stock on Stock + Input locations
114
 
        location_ids = []
115
 
        wids = self.pool.get('stock.warehouse').search(cr, uid, [], context=context)
116
 
        for w in self.pool.get('stock.warehouse').browse(cr, uid, wids, context=context):
117
 
            location_ids.append(w.lot_stock_id.id)
118
 
            location_ids.append(w.lot_input_id.id)
119
 
 
120
92
        # for each sourcing line
121
93
        for sl in self.browse(cr, uid, ids, context):
122
 
            product_context = context
123
 
            rts = sl.rts < time.strftime('%Y-%m-%d') and time.strftime('%Y-%m-%d') or sl.rts
124
 
            product_context.update({'location': location_ids, 'to_date': '%s 23:59:59' % rts})
125
 
            if sl.product_id:
126
 
                product_virtual = productObj.browse(cr, uid, sl.product_id.id, context=product_context)
127
 
                res = product_virtual.virtual_available
 
94
            rts = sl.rts
 
95
            productId = sl.product_id.id
 
96
            if productId:
 
97
                productList = [productId]
128
98
            else:
129
 
                res = 0.00
130
 
 
131
 
            result[sl.id] = res
 
99
                productList = []
 
100
            res = productObj.get_product_available(cr, uid, productList, context={'states': ('confirmed','waiting','assigned','done'),
 
101
                                                                                  'what': ('in', 'out'),
 
102
                                                                                  'to_date': rts})
 
103
            result[sl.id] = res.get(productId, 0.0)
132
104
            
133
105
        return result
134
106
    
135
107
    _name = 'sourcing.line'
136
108
    _description = 'Sourcing Line'
137
 
    
138
 
    def _get_sourcing_vals(self, cr, uid, ids, fields, arg, context=None):
139
 
        '''
140
 
        returns the value from the sale.order
141
 
        '''
142
 
        if isinstance(fields, str):
143
 
            fields = [fields]
144
 
        result = {}
145
 
        for obj in self.browse(cr, uid, ids, context=context):
146
 
            result[obj.id] = {}
147
 
            for f in fields:
148
 
                result[obj.id].update({f: False,})
149
 
            # gather procurement_request boolean
150
 
            result[obj.id]['procurement_request'] = obj.sale_order_id and obj.sale_order_id.procurement_request or False
151
 
            # gather sale order line state
152
 
            result[obj.id]['state'] = obj.sale_order_line_id and obj.sale_order_line_id.state or False
153
 
            # display confirm button - display if state == draft and not proc or state == progress and proc
154
 
            result[obj.id]['display_confirm_button'] = (obj.state == 'draft' and obj.sale_order_id.state == 'validated')
155
 
            # sale_order_state
156
 
            result[obj.id]['sale_order_state'] = False
157
 
            if obj.sale_order_id:
158
 
                result[obj.id]['sale_order_state'] = obj.sale_order_id.state
159
 
                if obj.sale_order_id.state == 'done' and obj.sale_order_id.split_type_sale_order == 'original_sale_order':
160
 
                    result[obj.id]['sale_order_state'] = 'split_so'
161
 
        
162
 
        return result
163
 
    
164
 
    def _get_sale_order_ids(self, cr, uid, ids, context=None):
165
 
        '''
166
 
        self represents sale.order
167
 
        ids represents the ids of sale.order objects for which procurement_request has changed
168
 
        
169
 
        return the list of ids of sourcing.line object which need to get their procurement_request field updated
170
 
        '''
171
 
        if isinstance(ids, (int, long)):
172
 
            ids = [ids]
173
 
        # list of sourcing lines having sale_order_id within ids
174
 
        result = self.pool.get('sourcing.line').search(cr, uid, [('sale_order_id', 'in', ids)], context=context)
175
 
        return result
176
 
    
177
 
    def _get_sale_order_line_ids(self, cr, uid, ids, context=None):
178
 
        '''
179
 
        self represents sale.order.line
180
 
        ids represents the ids of sale.order.line objects for which state has changed
181
 
        
182
 
        return the list of ids of sourcing.line object which need to get their state field updated
183
 
        '''
184
 
        if isinstance(ids, (int, long)):
185
 
            ids = [ids]
186
 
        # list of sourcing lines having sale_order_line_id within ids
187
 
        result = self.pool.get('sourcing.line').search(cr, uid, [('sale_order_line_id', 'in', ids)], context=context)
188
 
        return result
189
 
    
190
 
    def _get_souring_lines_ids(self, cr, uid, ids, context=None):
191
 
        '''
192
 
        self represents sourcing.line
193
 
        ids represents the ids of sourcing.line objects for which a field has changed
194
 
        
195
 
        return the list of ids of sourcing.line object which need to get their field updated
196
 
        '''
197
 
        if isinstance(ids, (int, long)):
198
 
            ids = [ids]
199
 
        
200
 
        result = ids
201
 
        return result
202
 
    
203
 
    def _get_fake(self, cr, uid, ids, fields, arg, context=None):
204
 
        if isinstance(ids, (int, long)):
205
 
            ids = [ids]
206
 
        result = {}
207
 
        for id in ids:
208
 
            result[id] = False
209
 
        return result
210
 
 
211
 
    def _search_need_sourcing(self, cr, uid, obj, name, args, context=None):
212
 
        if not args:
213
 
            return []
214
 
 
215
 
        if args[0][1] != '=' or not args[0][2]:
216
 
            raise osv.except_osv(_('Error !'), _('Filter not implemented'))
217
 
 
218
 
        return [('state', '=', 'draft'), ('sale_order_state', '=', 'validated')]
219
 
 
220
 
    def _search_sale_order_state(self, cr, uid, obj, name, args, context=None):
221
 
        if not args:
222
 
            return []
223
 
        newargs = []
224
 
 
225
 
        for arg in args:
226
 
            if arg[1] != '=':
227
 
                raise osv.except_osv(_('Error !'), _('Filter not implemented'))
228
 
 
229
 
            if arg[2] == 'progress':
230
 
                newargs.append(('sale_order_state', 'in', ['progress', 'manual']))
231
 
            else:
232
 
                newargs.append(('sale_order_state', arg[1], arg[2]))
233
 
        return newargs
234
 
 
235
 
    def _get_date(self, cr, uid, ids, field_name, args, context=None):
236
 
        res = {}
237
 
        
238
 
        for line in self.browse(cr, uid, ids, context=context):
239
 
            res[line.id] = {'estimated_delivery_date': False,
240
 
                            'rts': False}
241
 
            if line.supplier:
242
 
                delay = self.onChangeSupplier(cr, uid, [line.id], line.supplier.id, context=context).get('value', {}).get('estimated_delivery_date', False)
243
 
                res[line.id]['estimated_delivery_date'] = line.cf_estimated_delivery_date and line.state in ('done', 'confirmed') and line.cf_estimated_delivery_date or delay
244
 
            
245
 
##            tr_lt = line.sale_order_id and line.sale_order_id.est_transport_lead_time or 0.00
246
 
#            ship_lt = self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id.shipment_lead_time
247
 
#            res[line.id]['rts'] = datetime.strptime(line.sale_order_line_id.date_planned, '%Y-%m-%d') - relativedelta(days=int(tr_lt)) - relativedelta(days=int(ship_lt))
248
 
#            res[line.id]['rts'] = res[line.id]['rts'].strftime('%Y-%m-%d')
249
 
            res[line.id]['rts'] = line.sale_order_id.ready_to_ship_date
250
 
 
251
 
        return res
252
 
 
253
109
    _columns = {
254
110
        # sequence number
255
111
        'name': fields.char('Name', size=128),
256
 
        'sale_order_id': fields.many2one('sale.order', 'Order', on_delete='cascade', readonly=True),
257
 
        'sale_order_line_id': fields.many2one('sale.order.line', 'Order Line', on_delete='cascade', readonly=True),
258
 
        'customer': fields.many2one('res.partner', 'Customer', readonly=True),
 
112
        'sale_order_id': fields.many2one('sale.order', 'Sale Order', on_delete='cascade', readonly=True),
 
113
        'sale_order_line_id': fields.many2one('sale.order.line', 'Sale Order Line', on_delete='cascade', readonly=True),
259
114
        'reference': fields.related('sale_order_id', 'name', type='char', size=128, string='Reference', readonly=True),
260
 
#        'state': fields.related('sale_order_line_id', 'state', type="selection", selection=_SELECTION_SALE_ORDER_LINE_STATE, readonly=True, string="State", store=False),
261
 
        'state': fields.function(_get_sourcing_vals, method=True, type='selection', selection=_SELECTION_SALE_ORDER_LINE_STATE, string='State', multi='get_vals_sourcing',
262
 
                                  store={'sale.order.line': (_get_sale_order_line_ids, ['state'], 10),
263
 
                                         'sourcing.line': (_get_souring_lines_ids, ['sale_order_line_id'], 10)}),
 
115
        'state': fields.related('sale_order_line_id', 'state', type="selection", selection=_SELECTION_SALE_ORDER_LINE_STATE, readonly=True, string="State", store=False), 
264
116
        'priority': fields.selection(ORDER_PRIORITY, string='Priority', readonly=True),
265
117
        'categ': fields.selection(ORDER_CATEGORY, string='Category', readonly=True),
266
 
        # I do not directly set the store on state_hidden_sale_order because I did not find definitive clue that dynamic store could be used in cascade
267
 
        'sale_order_state': fields.function(_get_sourcing_vals, method=True, readonly=True, type='selection', selection=_SELECTION_SALE_ORDER_STATE, string='Order State', multi='get_vals_sourcing',
268
 
                                            store={'sale.order': (_get_sale_order_ids, ['state', 'split_type_sale_order'], 10),
269
 
                                                   'sourcing.line': (_get_souring_lines_ids, ['sale_order_id'], 10)}),
270
 
#        'sale_order_state': fields.selection(_SELECTION_SALE_ORDER_STATE, string="Order State", readonly=True),
271
 
        'sale_order_state_search': fields.function(_get_fake, string="Order State", type='selection', method=True, selection=[x for x in SALE_ORDER_STATE_SELECTION if x[0] != 'manual'], fnct_search=_search_sale_order_state),
 
118
        'sale_order_state': fields.selection(_SELECTION_SALE_ORDER_STATE, string="Order State", readonly=True),
272
119
        'line_number': fields.integer(string='Line', readonly=True),
273
120
        'product_id': fields.many2one('product.product', string='Product', readonly=True),
274
121
        'qty': fields.related('sale_order_line_id', 'product_uom_qty', type='float', string='Quantity', readonly=True),
275
122
        'uom_id': fields.related('sale_order_line_id', 'product_uom', relation='product.uom', type='many2one', string='UoM', readonly=True),
276
 
        #'rts': fields.related('sale_order_id', 'ready_to_ship_date', type='date', string='RTS', readonly=True),
277
 
        'rts': fields.function(_get_date, type='date', method=True, string='RTS', readonly=True, store=False, multi='dates'),
 
123
        'rts': fields.related('sale_order_id', 'delivery_requested_date', type='date', string='RTS', readonly=True),
278
124
        'sale_order_line_state': fields.related('sale_order_line_id', 'state', type="selection", selection=_SELECTION_SALE_ORDER_LINE_STATE, readonly=True, store=False),
279
125
        'type': fields.selection(_SELECTION_TYPE, string='Procurement Method', readonly=True, states={'draft': [('readonly', False)]}),
280
126
        'po_cft': fields.selection(_SELECTION_PO_CFT, string='PO/CFT', readonly=True, states={'draft': [('readonly', False)]}),
281
127
        'real_stock': fields.related('product_id', 'qty_available', type='float', string='Real Stock', readonly=True),
 
128
        'available_stock': fields.float('Available Stock', readonly=True),
282
129
        'virtual_stock': fields.function(_getVirtualStock, method=True, type='float', string='Virtual Stock', digits_compute=dp.get_precision('Product UoM'), readonly=True),
283
 
        'available_stock': fields.function(_getAvailableStock, method=True, type='float', string='Available Stock', digits_compute=dp.get_precision('Product UoM'), readonly=True),
284
130
        'supplier': fields.many2one('res.partner', 'Supplier', readonly=True, states={'draft': [('readonly', False)]}, domain=[('supplier', '=', True)]),
285
 
        'cf_estimated_delivery_date': fields.date(string='Estimated DD', readonly=True),
286
 
        'estimated_delivery_date': fields.function(_get_date, type='date', method=True, store=False, string='Estimated DD', readonly=True, multi='dates'),
287
 
        'company_id': fields.many2one('res.company','Company',select=1),
288
 
        'procurement_request': fields.function(_get_sourcing_vals, method=True, type='boolean', string='Procurement Request', multi='get_vals_sourcing',
289
 
                                               store={'sale.order': (_get_sale_order_ids, ['procurement_request'], 10),
290
 
                                                      'sourcing.line': (_get_souring_lines_ids, ['sale_order_id'], 10)}),
291
 
        'display_confirm_button': fields.function(_get_sourcing_vals, method=True, type='boolean', string='Display Button', multi='get_vals_sourcing',),
292
 
        'need_sourcing': fields.function(_get_fake, method=True, type='boolean', string='Only for filtering', fnct_search=_search_need_sourcing),
 
131
        'estimated_delivery_date': fields.date(string='Estimated DD', readonly=True),
293
132
    }
294
133
    _order = 'sale_order_id desc, line_number'
295
134
    _defaults = {
296
135
             'name': lambda self, cr, uid, context=None: self.pool.get('ir.sequence').get(cr, uid, 'sourcing.line'),
297
 
             'company_id': lambda obj, cr, uid, context: obj.pool.get('res.users').browse(cr, uid, uid, context=context).company_id.id,
298
136
    }
299
137
    
300
 
    def _check_line_conditions(self, cr, uid, ids, context=None):
301
 
        '''
302
 
        Check if the line have good values
303
 
        '''
304
 
        if not context:
305
 
            context = {}
306
 
        if context.get('no_check_line', False):
307
 
            return True
308
 
        
309
 
        if isinstance(ids, (int, long)):
310
 
            ids = [ids]
311
 
        for line in self.browse(cr, uid, ids, context=context):
312
 
            if line.type == 'make_to_order' and line.po_cft not in ['cft'] and not line.product_id and \
313
 
               line.sale_order_id.procurement_request and line.supplier and line.supplier.partner_type not in ['internal', 'section', 'intermission']:
314
 
                raise osv.except_osv(_('Warning'), _("""For an Internal Request with a procurement method 'On Order' and without product, the supplier must be either in 'Internal', 'Inter-section' or 'Intermission type."""))
315
 
 
316
 
            if not line.product_id:
317
 
                if line.po_cft == 'cft':
318
 
                    raise osv.except_osv(_('Warning'), _("You can't source with 'Tender' if you don't have product."))
319
 
                if line.type == 'make_to_stock':
320
 
                    raise osv.except_osv(_('Warning'), _("You can't Source 'from stock' if you don't have product."))
321
 
                if line.supplier and line.supplier.partner_type in ('external', 'esc'):
322
 
                    raise osv.except_osv(_('Warning'), _("You can't Source to an '%s' partner if you don't have product.") % (line.supplier.partner_type == 'external' and 'External' or 'ESC'))
323
 
 
324
 
        return True
325
 
 
326
 
    def open_split_wizard(self, cr, uid, ids, context=None):
327
 
        '''
328
 
        Open the split line wizard
329
 
        '''
330
 
        line = self.browse(cr, uid, ids[0], context=context)
331
 
        return self.pool.get('sale.order.line').open_split_wizard(cr, uid, [line.sale_order_line_id.id], context=context)
332
 
    
333
138
    def check_supplierinfo(self, cr, uid, ids, partner_id, context=None):
334
139
        '''
335
140
        return the value of delay if the corresponding supplier is in supplier info the product
338
143
        '''
339
144
        for sourcing_line in self.browse(cr, uid, ids, context=context):
340
145
            delay = -1
341
 
            return sourcing_line.supplier and sourcing_line.supplier.supplier_lt or delay
 
146
            for suppinfo in sourcing_line.product_id.seller_ids:
 
147
                if suppinfo.name.id == partner_id:
 
148
                    delay = suppinfo.delay
 
149
                    
 
150
            return delay
342
151
    
343
152
    def write(self, cr, uid, ids, values, context=None):
344
153
        '''
351
160
        to sale order line
352
161
        '''
353
162
        if not context:
354
 
            context = {}
 
163
            context={}
355
164
        if isinstance(ids, (int, long)):
356
165
            ids = [ids]
357
 
            
358
 
        # Remove the saved estimated DD on cancellation of the FO line
359
 
        if 'state' in values and values['state'] == 'cancel':
360
 
            self.write(cr, uid, ids, {'cf_estimated_delivery_date': False}, context=context)
361
 
            
362
166
        if 'fromOrderLine' not in context and 'fromOrder' not in context:
363
167
            context['fromSourcingLine'] = True
364
168
            for sourcingLine in self.browse(cr, uid, ids, context=context):
377
181
                    if 'po_cft' in values:
378
182
                        pocft = values['po_cft']
379
183
                        vals.update({'po_cft': pocft})
380
 
                        if pocft == 'cft':
381
 
                            # no supplier for tender
382
 
                            values.update({'supplier': False})
383
 
                            vals.update({'supplier': False})
384
184
                else:
385
185
                    # if make to stock, reset anyway to False
386
186
                    pocft = False
387
 
                    values.update({'po_cft': pocft, 'supplier': False})
388
 
                    vals.update({'po_cft': pocft, 'supplier': False})
 
187
                    vals.update({'po_cft': pocft})
389
188
                
390
189
                # partner_id
391
190
                if 'supplier' in values:
410
209
                    else:
411
210
                        # no partner is selected, erase the date
412
211
                        values.update({'estimated_delivery_date': False})
413
 
                    
414
212
                # update sourcing line
415
213
                self.pool.get('sale.order.line').write(cr, uid, solId, vals, context=context)
416
214
        
417
 
        res = super(sourcing_line, self).write(cr, uid, ids, values, context=context)
418
 
        self._check_line_conditions(cr, uid, ids, context)
419
 
        return res
420
 
    
421
 
    def onChangePoCft(self, cr, uid, id, po_cft, order_id=False, context=None):
422
 
        '''
423
 
        '''
424
 
        warning = {}
425
 
        value = {}
426
 
            
427
 
        if order_id:
428
 
            order = self.pool.get('sale.order').browse(cr, uid, order_id, context=context)
429
 
            if order.procurement_request and po_cft == 'dpo':
430
 
                warning = {'title': 'DPO for IR',
431
 
                           'message': 'You cannot choose Direct Purchase Order as method to source an Internal Request line.'}
432
 
                value = {'po_cft': 'po'}
433
 
            if po_cft == 'cft':
434
 
                # tender does not allow supplier selection
435
 
                value = {'supplier': False}
436
 
        return {'warning': warning, 'value': value}
 
215
        return super(sourcing_line, self).write(cr, uid, ids, values, context=context)
437
216
    
438
217
    def onChangeType(self, cr, uid, id, type, context=None):
439
218
        '''
440
219
        if type == make to stock, change pocft to False
441
220
        '''
442
221
        value = {}
443
 
        message = {}
444
 
        if id:
445
 
            line = self.browse(cr, uid, id, context=context)[0]
446
 
            if line.product_id.type in ('consu', 'service', 'service_recep') and type == 'make_to_stock':
447
 
                product_type = line.product_id.type=='consu' and 'non stockable' or 'service'
448
 
                value.update({'type': 'make_to_order'})
449
 
                message.update({'title': _('Warning'),
450
 
                                'message': _('You cannot choose \'from stock\' as method to source a %s product !') % product_type})
451
 
 
452
222
        if type == 'make_to_stock':
453
223
            value.update({'po_cft': False})
454
224
    
455
 
        return {'value': value, 'warning': message}
 
225
        return {'value': value}
456
226
    
457
227
    def onChangeSupplier(self, cr, uid, id, supplier, context=None):
458
228
        '''
459
229
        supplier changes, we update 'estimated_delivery_date' with corresponding delivery lead time
460
 
        we add a domain for the IR line on the supplier
461
230
        '''
462
 
        result = {'value':{}, 'domain':{}}
 
231
        result = {'value':{}}
463
232
        
464
233
        if not supplier:
465
 
            for sl in self.browse(cr, uid, id, context):
466
 
                if not sl.product_id and sl.sale_order_id.procurement_request and sl.type == 'make_to_order':
467
 
                    result['domain'].update({'supplier': [('partner_type', 'in', ['internal', 'section', 'intermission'])]})
468
234
            return result
469
235
        
470
236
        partner = self.pool.get('res.partner').browse(cr, uid, supplier, context)
473
239
        # otherwise we take the default value from product form
474
240
        if delay < 0:
475
241
            delay = partner.default_delay
476
 
 
 
242
        
477
243
        daysToAdd = delay
478
244
        estDeliveryDate = date.today()
479
245
        estDeliveryDate = estDeliveryDate + relativedelta(days=int(daysToAdd))
480
246
        
481
247
        result['value'].update({'estimated_delivery_date': estDeliveryDate.strftime('%Y-%m-%d')})
482
 
 
 
248
        
483
249
        return result
484
250
    
485
251
    def copy(self, cr, uid, id, default=None, context=None):
493
259
        '''
494
260
        create method from sourcing_line
495
261
        '''
496
 
        res = super(sourcing_line, self).create(cr, uid, vals, context)
497
 
        self._check_line_conditions(cr, uid, res, context)
498
 
        return res
 
262
        result = super(sourcing_line, self).create(cr, uid, vals, context)
 
263
        return result
499
264
    
500
265
    def copy_data(self, cr, uid, id, default=None, context=None):
501
266
        '''
514
279
#            default.update({'sale_order_id': soId,})
515
280
            
516
281
        return super(sourcing_line, self).copy_data(cr, uid, id, default, context=context)
517
 
 
 
282
    
518
283
    def confirmLine(self, cr, uid, ids, context=None):
519
284
        '''
520
285
        set the corresponding line's state to 'confirmed'
523
288
        wf_service = netsvc.LocalService("workflow")
524
289
        result = []
525
290
        for sl in self.browse(cr, uid, ids, context):
526
 
            # check if the line has a product for a Field Order (and not for an Internal Request)
527
 
            if not sl.product_id and not sl.sale_order_id.procurement_request:
528
 
                raise osv.except_osv(_('Warning'), _("""The product must be chosen before sourcing the line.
529
 
                Please select it within the lines of the associated Field Order (through the "Field Orders" menu).
530
 
                """))
531
 
            # corresponding state for the lines: IR: confirmed, FO: sourced
532
 
            state_to_use = sl.sale_order_id.procurement_request and 'confirmed' or 'sourced'
533
 
            # check if it is in On Order and if the Supply info is valid, if it's empty, just exit the action
534
 
            
535
 
            if sl.type == 'make_to_order' and not sl.po_cft in ['cft']:
536
 
                if not sl.supplier:
537
 
                    raise osv.except_osv(_('Warning'), _("The supplier must be chosen before sourcing the line"))
538
 
                # an Internal Request without product can only have Internal, Intersection or Intermission partners.
539
 
                elif sl.supplier and not sl.product_id and sl.sale_order_id.procurement_request and sl.supplier.partner_type not in ['internal', 'section', 'intermission']:
540
 
                    raise osv.except_osv(_('Warning'), _("""For an Internal Request with a procurement method 'On Order' and without product,
541
 
                    the supplier must be either in 'Internal', 'Inter-Section' or 'Intermission' type.
542
 
                    """))
543
 
            
544
291
            # set the corresponding sale order line to 'confirmed'
545
 
            result.append((sl.id, sl.sale_order_line_id.write({'state': state_to_use}, context)))
 
292
            result.append((sl.id, sl.sale_order_line_id.write({'state':'confirmed'}, context)))
546
293
            # check if all order lines have been confirmed
547
294
            linesConfirmed = True
548
295
            for ol in sl.sale_order_id.order_line:
549
 
                if ol.state != state_to_use:
 
296
                if ol.state != 'confirmed':
550
297
                    linesConfirmed = False
551
 
                    break
552
 
            # the line reads estimated_dd, after trg_validate, the lines are deleted, so all read/write must be performed before
553
 
            self.write(cr, uid, [sl.id], {'cf_estimated_delivery_date': sl.estimated_delivery_date}, context=context)
554
298
            # if all lines have been confirmed, we confirm the sale order
555
299
            if linesConfirmed:
556
 
                if sl.sale_order_id.procurement_request:
557
 
                    wf_service.trg_validate(uid, 'sale.order', sl.sale_order_id.id, 'procurement_confirm', cr)
558
 
                else:
559
 
                    wf_service.trg_validate(uid, 'sale.order', sl.sale_order_id.id, 'order_confirm', cr)
 
300
                wf_service.trg_validate(uid, 'sale.order', sl.sale_order_id.id, 'order_confirm', cr)
560
301
                
561
302
        return result
562
303
    
573
314
        
574
315
sourcing_line()
575
316
 
576
 
 
577
317
class sale_order(osv.osv):
578
318
    
579
319
    _inherit = 'sale.order'
602
342
            ids = [ids]
603
343
   
604
344
        context['fromOrder'] = True
605
 
        context['no_check_line'] = True
606
 
        
607
345
        values = {}
608
346
        if 'priority' in vals:
609
347
            values.update({'priority': vals['priority']})
610
348
        if 'categ' in vals:
611
349
            values.update({'categ': vals['categ']})
612
 
#        if 'state' in vals:
613
 
#            values.update({'sale_order_state': vals['state']})
614
 
#        if 'state_hidden_sale_order' in vals:
615
 
#            values.update({'sale_order_state': vals['state_hidden_sale_order']})
 
350
        if 'state' in vals:
 
351
            values.update({'sale_order_state': vals['state']})
616
352
        
617
353
        # for each sale order
618
354
        for so in self.browse(cr, uid, ids, context):
621
357
                # update the sourcing line
622
358
                for sl in sol.sourcing_line_ids:
623
359
                    self.pool.get('sourcing.line').write(cr, uid, sl.id, values, context)
624
 
                    if vals.get('partner_id') and vals.get('partner_id') != so.partner_id.id:
625
 
                        self.pool.get('sourcing.line').write(cr, uid, sl.id, {'customer': so.partner_id.id}, context)
626
360
        
627
361
        return super(sale_order, self).write(cr, uid, ids, vals, context)
628
362
        
634
368
        dont copy sourcing lines, they are generated at sale order lines creation
635
369
        '''
636
370
        if not default:
637
 
            default = {}
 
371
            default={}
638
372
            
639
373
        default['sourcing_line_ids']=[]
640
374
        
664
398
        
665
399
        return super(sale_order, self).unlink(cr, uid, ids, context)
666
400
    
667
 
    def _hook_ship_create_procurement_order(self, cr, uid, ids, context=None, *args, **kwargs):
668
 
        '''
669
 
        Please copy this to your module's method also.
670
 
        This hook belongs to the action_ship_create method from sale>sale.py
671
 
        
672
 
        - allow to modify the data for procurement order creation
673
 
        '''
674
 
        result = super(sale_order, self)._hook_ship_create_procurement_order(cr, uid, ids, context=context, *args, **kwargs)
675
 
        proc_data = kwargs['proc_data']
676
 
        line = kwargs['line']
677
 
        
678
 
        # new field representing selected partner from sourcing tool
679
 
        result['supplier'] = line.supplier and line.supplier.id or False
680
 
        if line.po_cft:
681
 
            result.update({'po_cft': line.po_cft})
682
 
        # uf-583 - the location defined for the procurementis input instead of stock if the procurement is on order
683
 
        # if from stock, the procurement search from products in the default location: Stock
684
 
        order = kwargs['order']
685
 
        if line.type == 'make_to_order':
686
 
            result['location_id'] = order.shop_id.warehouse_id.lot_input_id.id,
687
 
 
688
 
        return result
689
 
 
690
 
    def _hook_procurement_create_line_condition(self, cr, uid, ids, context=None, *args, **kwargs):
691
 
        '''
692
 
        Please copy this to your module's method also.
693
 
        This hook belongs to the action_ship_create method from sale>sale.py
694
 
             
695
 
        - allow to customize the execution condition
696
 
        '''
697
 
        line = kwargs['line']
698
 
        result = super(sale_order, self)._hook_procurement_create_line_condition(cr, uid, ids, context=context, *args, **kwargs)
699
 
        
700
 
        # if make_to_stock and procurement_request, no procurement is created
701
 
        return result and not(line.type == 'make_to_stock' and line.order_id.procurement_request)
702
 
    
703
 
    def do_order_confirm_method(self, cr, uid, ids, context=None):
704
 
        '''
705
 
        trigger the workflow
706
 
        '''
707
 
        # Some verifications
708
 
        if context is None:
709
 
            context = {}
710
 
        if isinstance(ids, (int, long)):
711
 
            ids = [ids]
712
 
            
713
 
        # objects
714
 
        wf_service = netsvc.LocalService("workflow")
715
 
        sol_obj = self.pool.get('sale.order.line')
716
 
        
717
 
        # we confirm (validation in unifield) the sale order
718
 
        # we set all line state to 'sourced' of the original Fo
719
 
        for obj in self.browse(cr, uid, ids, context=context):
720
 
            for line in obj.order_line:
721
 
                sol_obj.write(cr, uid, [line.id], {'state': 'sourced'}, context=context)
722
 
            # trigger workflow signal
723
 
            wf_service.trg_validate(uid, 'sale.order', obj.id, 'order_confirm', cr)
724
 
        
725
 
        return True
726
 
        return {'name':_("Field Orders"),
727
 
                'view_mode': 'form,tree',
728
 
                'view_type': 'form',
729
 
                'res_model': 'sale.order',
730
 
                'res_id': ids[0],
731
 
                'type': 'ir.actions.act_window',
732
 
                'target': 'dummy',
733
 
                'domain': [],
734
 
                'context': {},
735
 
                }
 
401
    def _hook_ship_create_procurement_order(self, cr, uid, ids, procurement_data, order_line, *args, **kwargs):
 
402
        # new field representing selected supplierinfo from sourcing tool
 
403
        procurement_data['supplier'] = order_line.supplier and order_line.supplier.id or False
 
404
        return super(sale_order, self)._hook_ship_create_procurement_order(cr, uid, ids, procurement_data, order_line, *args, **kwargs)
736
405
 
737
406
sale_order()
738
407
 
739
 
 
740
408
class sale_order_line(osv.osv):
741
409
    '''
742
410
    override of sale_order_line class
773
441
        'tax_id': [(6, 0, [])], 
774
442
        'type': 'make_to_stock', 
775
443
        'price_unit': 450.0, 
776
 
        'address_allotment_id': False,
777
 
        'customer': partner_id,
 
444
        'address_allotment_id': False
778
445
        }
779
446
        '''
780
447
        if not context:
798
465
            else:
799
466
                deliveryDate = product.delay_for_supplier 
800
467
 
801
 
        # if type is missing, set to make_to_stock and po_cft to False
 
468
        # type
802
469
        if not vals.get('type'):
803
470
            vals['type'] = 'make_to_stock'
804
 
            vals['po_cft'] = False
805
 
        
806
 
        if vals.get('product_id',False):
807
 
            bropro = self.pool.get('product.product').browse(cr,uid,vals['product_id'])
808
 
            if bropro.type in ('consu', 'service', 'service_recep'):
809
 
                vals['type'] = 'make_to_order'
810
 
        
811
 
        # fill po/cft : by default, if mto -> po and po_cft is not specified in data, if mts -> False
812
 
        if not vals.get('po_cft', False) and vals.get('type', False) == 'make_to_order':
813
 
            vals['po_cft'] = 'po'
814
 
        elif vals.get('type', False) == 'make_to_stock':
815
 
            vals['po_cft'] = False
816
 
        
817
 
        # fill the supplier
 
471
        
 
472
        # fill po/cft : by default, if mto -> po, if mts -> False
 
473
        pocft = False
 
474
        if vals['type'] == 'make_to_order':
 
475
            pocft = 'po'
 
476
        
 
477
        # fill the default pocft and supplier
 
478
        vals.update({'po_cft': pocft})
818
479
        vals.update({'supplier': sellerId})
819
480
        
820
481
        # create the new sale order line
825
486
        if deliveryDate:
826
487
            daysToAdd = deliveryDate
827
488
            estDeliveryDate = date.today()
828
 
            estDeliveryDate = estDeliveryDate + relativedelta(days=int(daysToAdd))
 
489
            estDeliveryDate = estDeliveryDate + relativedelta(days=daysToAdd)
829
490
            estDeliveryDate = estDeliveryDate.strftime('%Y-%m-%d')
830
491
        
831
492
        # order state
832
493
        order = self.pool.get('sale.order').browse(cr, uid, vals['order_id'], context)
833
 
        orderState = order.state_hidden_sale_order
 
494
        orderState = order.state
834
495
        orderPriority = order.priority
835
496
        orderCategory = order.categ
836
 
        customer_id = order.partner_id.id
837
497
        
838
 
        if sellerId:
839
 
            seller = self.pool.get('res.partner').browse(cr,uid,sellerId)
840
 
            if seller.partner_type and not order.procurement_request and not seller.partner_type in ['external','esc']:
841
 
                sellerId = False
842
 
 
843
498
        values = {
844
499
                  'sale_order_id': vals['order_id'],
845
500
                  'sale_order_line_id': result,
846
 
                  'customer_id': customer_id,
847
501
                  'supplier': sellerId,
848
 
                  'po_cft': vals['po_cft'],
 
502
                  'po_cft': pocft,
849
503
                  'estimated_delivery_date': estDeliveryDate,
850
504
                  'rts': time.strftime('%Y-%m-%d'),
851
505
                  'type': vals['type'],
852
506
                  'line_number': vals['line_number'],
853
 
                  'product_id': vals.get('product_id', False),
 
507
                  'product_id': vals['product_id'],
854
508
                  'priority': orderPriority,
855
509
                  'categ': orderCategory,
856
 
#                  'sale_order_state': orderState,
857
 
                  'state': self.browse(cr, uid, result, context=context).state
 
510
                  'sale_order_state': orderState,
858
511
                  }
859
 
 
860
 
        sourcing_line_id = self.pool.get('sourcing.line').create(cr, uid, values, context=context)
861
 
        # update sourcing line - trigger update of fields.function values -- OPENERP BUG ? with empty values
862
 
        self.pool.get('sourcing.line').write(cr, uid, [sourcing_line_id], {}, context=context)
 
512
        
 
513
        self.pool.get('sourcing.line').create(cr, uid, values, context=context)
863
514
            
864
515
        return result
865
516
    
896
547
         - product_id
897
548
        ''' 
898
549
        if not context:
899
 
            context = {}
 
550
            context={}
900
551
        if isinstance(ids, (int, long)):
901
552
            ids = [ids]
902
553
 
903
 
        if vals.get('product_id',False):
904
 
            bropro = self.pool.get('product.product').browse(cr,uid,vals['product_id'])
905
 
            if bropro.type in ('consu', 'service', 'service_recep'):
906
 
                vals['type'] = 'make_to_order'
907
 
 
908
554
        # update the corresponding sourcing line if not called from a sourcing line updated
909
555
        if 'fromSourcingLine' not in context:
910
556
            context['fromOrderLine'] = True
911
557
            values = {}
912
 
            if 'state' in vals:
913
 
                values.update({'state': vals['state']})
914
558
            if 'supplier' in vals:
915
559
                values.update({'supplier': vals['supplier']})
916
560
            if 'po_cft' in vals:
919
563
                values.update({'type': vals['type']})
920
564
                if vals['type'] == 'make_to_stock':
921
565
                    values.update({'po_cft': False})
922
 
                    vals.update({'po_cft': False})
923
566
                    values.update({'supplier': False})
924
 
                    vals.update({'supplier': False})
925
567
            if 'product_id' in vals:
926
568
                values.update({'product_id': vals['product_id']})
927
 
            if 'line_number' in vals:
928
 
                values.update({'line_number': vals['line_number']})
929
569
                
930
570
            # for each sale order line
931
571
            for sol in self.browse(cr, uid, ids, context):
953
593
        idsToDelete = []
954
594
        for orderLine in self.browse(cr, uid, ids, context):
955
595
            for sourcingLine in orderLine.sourcing_line_ids:
956
 
                idsToDelete.append(sourcingLine.id)
 
596
                    idsToDelete.append(sourcingLine.id)
957
597
        # delete sourcing lines
958
598
        self.pool.get('sourcing.line').unlink(cr, uid, idsToDelete, context)
959
599
        
1001
641
    _description = "Procurement"
1002
642
    _columns = {
1003
643
        'supplier': fields.many2one('res.partner', 'Supplier'),
1004
 
        'po_cft': fields.selection(_SELECTION_PO_CFT, string="PO/CFT"),
1005
644
    }
1006
645
    
1007
 
    def po_line_values_hook(self, cr, uid, ids, context=None, *args, **kwargs):
1008
 
        '''
1009
 
        Please copy this to your module's method also.
1010
 
        This hook belongs to the make_po method from purchase>purchase.py>procurement_order
1011
 
        
1012
 
        - allow to modify the data for purchase order line creation
1013
 
        '''
1014
 
        line = super(procurement_order, self).po_line_values_hook(cr, uid, ids, context=context, *args, **kwargs)
1015
 
        if 'procurement' in kwargs:
1016
 
            order_line_ids = self.pool.get('sale.order.line').search(cr, uid, [('procurement_id', '=', kwargs['procurement'].id)])
1017
 
            if order_line_ids:
1018
 
                origin = self.pool.get('sale.order.line').browse(cr, uid, order_line_ids[0]).order_id.name
1019
 
                line.update({'origin': origin})
1020
 
        if line.get('price_unit', False) == False:
1021
 
            st_price = self.pool.get('product.product').browse(cr, uid, line['product_id']).standard_price
1022
 
            if 'pricelist' in kwargs:
1023
 
                cur_id = self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id.currency_id.id
1024
 
                st_price = self.pool.get('res.currency').compute(cr, uid, cur_id, kwargs['pricelist'].currency_id.id, st_price, round=False, context=context)
1025
 
            line.update({'price_unit': st_price})
1026
 
        return line
1027
 
    
1028
 
    def action_check_finished(self, cr, uid, ids):
1029
 
        res = super(procurement_order, self).action_check_finished(cr, uid, ids)
1030
 
        
1031
 
        # If the procurement has been generated from an internal request, close the order
1032
 
        for order in self.browse(cr, uid, ids):
1033
 
            line_ids = self.pool.get('sale.order.line').search(cr, uid, [('procurement_id', '=', order.id)])
1034
 
            for line in self.pool.get('sale.order.line').browse(cr, uid, line_ids):
1035
 
                if line.order_id.procurement_request:
1036
 
                    return True
1037
 
        
1038
 
        return res
1039
 
 
1040
 
    def create_po_hook(self, cr, uid, ids, context=None, *args, **kwargs):
1041
 
        '''
1042
 
        if a purchase order for the same supplier and the same requested date,
1043
 
        don't create a new one
1044
 
        '''
1045
 
        po_obj = self.pool.get('purchase.order')
1046
 
        procurement = kwargs['procurement']
1047
 
        values = kwargs['values']
1048
 
        # Make the line as price changed manually to do not raise an error on purchase order line creation
1049
 
#        if 'order_line' in values and len(values['order_line']) > 0 and len(values['order_line'][0]) > 2 and 'price_unit' in values['order_line'][0][2]:
1050
 
#            values['order_line'][0][2].update({'change_price_manually': True})
1051
 
 
1052
 
        partner = self.pool.get('res.partner').browse(cr, uid, values['partner_id'], context=context)
1053
 
        
1054
 
        purchase_domain = [('partner_id', '=', partner.id),
1055
 
                           ('state', '=', 'draft'),
1056
 
                           ('rfq_ok', '=', False),
1057
 
                           ('delivery_requested_date', '=', values.get('delivery_requested_date'))]
1058
 
        
1059
 
        if procurement.po_cft == 'dpo':
1060
 
            purchase_domain.append(('order_type', '=', 'direct'))
1061
 
        else:
1062
 
            purchase_domain.append(('order_type', '!=', 'direct'))
1063
 
        
1064
 
        if partner.po_by_project == 'project' or procurement.po_cft == 'dpo':
1065
 
            sale_line_ids = self.pool.get('sale.order.line').search(cr, uid, [('procurement_id', '=', procurement.id)], context=context)
1066
 
            if sale_line_ids:
1067
 
                line = self.pool.get('sale.order.line').browse(cr, uid, sale_line_ids[0], context=context)
1068
 
                if line.procurement_request:
1069
 
                    customer_id = self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id.partner_id.id
1070
 
                else:
1071
 
                    customer_id = line.order_id.partner_id.id 
1072
 
                values.update({'customer_id': customer_id})
1073
 
                purchase_domain.append(('customer_id', '=', customer_id))
1074
 
        
1075
 
        # if we are updating the sale order from the corresponding on order purchase order
1076
 
        # the purchase order to merge the new line to is locked and provided in the procurement
1077
 
        if procurement.so_back_update_dest_po_id_procurement_order:
1078
 
            purchase_ids = [procurement.so_back_update_dest_po_id_procurement_order.id]
1079
 
        else:
1080
 
            # search for purchase order according to defined domain
1081
 
            purchase_ids = po_obj.search(cr, uid, purchase_domain, context=context)
1082
 
        
1083
 
        # Set the origin of the line with the origin of the Procurement order
1084
 
        if procurement.origin:
1085
 
            values['order_line'][0][2].update({'origin': procurement.origin})
1086
 
            
1087
 
        if procurement.tender_id:
1088
 
            if values.get('origin'):
1089
 
                values['origin'] = '%s;%s' % (values['origin'], procurement.tender_id.name)
1090
 
            else:
1091
 
                values['origin'] = procurement.tender_id.name
1092
 
        
1093
 
        # Set the analytic distribution on PO line if an analytic distribution is on SO line or SO    
1094
 
        sol_ids = self.pool.get('sale.order.line').search(cr, uid, [('procurement_id', '=', procurement.id)], context=context)
1095
 
        location_id = False
1096
 
        if sol_ids:
1097
 
            sol = self.pool.get('sale.order.line').browse(cr, uid, sol_ids[0], context=context)
1098
 
            if sol.analytic_distribution_id:
1099
 
                new_analytic_distribution_id = self.pool.get('analytic.distribution').copy(cr, uid, 
1100
 
                                                    sol.analytic_distribution_id.id, context=context)
1101
 
                values['order_line'][0][2].update({'analytic_distribution_id': new_analytic_distribution_id})
1102
 
            elif sol.order_id.analytic_distribution_id:
1103
 
                new_analytic_distribution_id = self.pool.get('analytic.distribution').copy(cr, 
1104
 
                                                    uid, sol.order_id.analytic_distribution_id.id, context=context)
1105
 
                values['order_line'][0][2].update({'analytic_distribution_id': new_analytic_distribution_id})
1106
 
        elif procurement.product_id:
1107
 
            if procurement.product_id.type == 'consu':
1108
 
                location_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'stock_override', 'stock_location_non_stockable')[1]
1109
 
            elif procurement.product_id.type == 'service_recep':
1110
 
                location_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'msf_config_locations', 'stock_location_service')[1]
1111
 
            else:
1112
 
                wh_ids = self.pool.get('stock.warehouse').search(cr, uid, [])
1113
 
                if wh_ids:
1114
 
                    location_id = self.pool.get('stock.warehouse').browse(cr, uid, wh_ids[0]).lot_input_id.id
1115
 
                else:
1116
 
                    location_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'msf_config_locations', 'stock_location_service')[1]
1117
 
 
1118
 
        if purchase_ids:
1119
 
            line_values = values['order_line'][0][2]
1120
 
            line_values.update({'order_id': purchase_ids[0],'origin': procurement.origin})
1121
 
            po = self.pool.get('purchase.order').browse(cr, uid, purchase_ids[0], context=context)
1122
 
            # Update the origin of the PO with the origin of the procurement 
1123
 
            # and tender name if exist
1124
 
            origins = set([po.origin, procurement.origin, procurement.tender_id and procurement.tender_id.name])
1125
 
            # Add different origin on 'Source document' field if the origin is nat already listed
1126
 
            origin = ';'.join(o for o in list(origins) if o and (not po.origin or o == po.origin or o not in po.origin))
1127
 
            self.pool.get('purchase.order').write(cr, uid, purchase_ids[0], {'origin': origin}, context=context)
1128
 
            
1129
 
            if location_id:
1130
 
                self.pool.get('purchase.order').write(cr, uid, purchase_ids[0], {'location_id': location_id, 'cross_docking_ok': False}, context=context)
1131
 
            self.pool.get('purchase.order.line').create(cr, uid, line_values, context=context)
1132
 
            return purchase_ids[0]
1133
 
        else:
1134
 
            if procurement.po_cft == 'dpo':
1135
 
                sol_ids = self.pool.get('sale.order.line').search(cr, uid, [('procurement_id', '=', procurement.id)], context=context)
1136
 
                if sol_ids:
1137
 
                    sol = self.pool.get('sale.order.line').browse(cr, uid, sol_ids[0], context=context)
1138
 
                    if not sol.procurement_request:
1139
 
                        values.update({'order_type': 'direct', 
1140
 
                                       'dest_partner_id': sol.order_id.partner_id.id, 
1141
 
                                       'dest_address_id': sol.order_id.partner_shipping_id.id})
1142
 
 
1143
 
                # Force the destination location of the Po to Input location
1144
 
                company_id = self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id.id
1145
 
                warehouse_id = self.pool.get('stock.warehouse').search(cr, uid, [('company_id', '=', company_id)], context=context)
1146
 
                if warehouse_id:
1147
 
                    input_id = self.pool.get('stock.warehouse').browse(cr, uid, warehouse_id[0], context=context).lot_input_id.id
1148
 
                    values.update({'location_id': input_id,})
1149
 
            purchase_id = super(procurement_order, self).create_po_hook(cr, uid, ids, context=context, *args, **kwargs)
1150
 
            return purchase_id
1151
 
    
1152
646
    def write(self, cr, uid, ids, vals, context=None):
1153
647
        '''
1154
648
        override for workflow modification
1155
649
        '''
1156
650
        return super(procurement_order, self).write(cr, uid, ids, vals, context)
1157
651
 
1158
 
    def _partner_check_hook(self, cr, uid, ids, context=None, *args, **kwargs):
1159
 
        '''
1160
 
        check the if supplier is available or not
1161
 
        
1162
 
        the new selection field does not exist when the procurement has been produced by
1163
 
        an order_point (minimum stock rules). in this case we take the default supplier from product
1164
 
        
1165
 
        same cas if no supplier were selected in the sourcing tool
1166
 
        
1167
 
        return True if a supplier is available
1168
 
        '''
1169
 
        procurement = kwargs['procurement']
1170
 
        # add supplier check in procurement object from sourcing tool
1171
 
        result = procurement.supplier or super(procurement_order, self)._partner_check_hook(cr, uid, ids, context=context, *args, **kwargs)
1172
 
        return result
1173
 
    
1174
 
    def _partner_get_hook(self, cr, uid, ids, context=None, *args, **kwargs):
1175
 
        '''
1176
 
        returns the partner from procurement or suppinfo
1177
 
        
1178
 
        the new selection field does not exist when the procurement has been produced by
1179
 
        an order_point (minimum stock rules). in this case we take the default supplier from product
1180
 
        
1181
 
        same cas if no supplier were selected in the sourcing tool
1182
 
        '''
1183
 
        procurement = kwargs['procurement']
1184
 
        # the specified supplier in sourcing tool has priority over suppinfo
1185
 
        partner = procurement.supplier or super(procurement_order, self)._partner_get_hook(cr, uid, ids, context=context, *args, **kwargs)
1186
 
        if partner.id == self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id.id:
1187
 
            cr.execute('update procurement_order set message=%s where id=%s',
1188
 
                           (_('Impossible to make a Purchase Order to your own company !'), procurement.id))
1189
 
        return partner
1190
 
    
1191
 
    def get_delay_qty(self, cr, uid, ids, partner, product, context=None):
1192
 
        '''
1193
 
        find corresponding values for seller_qty and seller_delay from product supplierinfo or default values
1194
 
        '''
1195
 
        result = {}
1196
 
        # if the supplier is present in product seller_ids, we take that quantity from supplierinfo
1197
 
        # otherwise 1
1198
 
        # seller_qty default value
1199
 
        seller_qty = 1
1200
 
        seller_delay = -1
1201
 
        for suppinfo in product.seller_ids:
1202
 
            if suppinfo.name.id == partner.id:
1203
 
                seller_qty = suppinfo.qty
1204
 
                seller_delay = int(suppinfo.delay)
1205
 
        
1206
 
        # if not, default delay from supplier (partner.default_delay)
1207
 
        if seller_delay < 0:
1208
 
            seller_delay = partner.default_delay
1209
 
        
1210
 
        result.update(seller_qty=seller_qty,
1211
 
                      seller_delay=seller_delay,)
 
652
    # @@@override procurement.py > procurement.order > check_buy
 
653
    def check_buy(self, cr, uid, ids):
 
654
        """ Checks product type.
 
655
        @return: True or Product Id.
 
656
        """
 
657
        user = self.pool.get('res.users').browse(cr, uid, uid)
 
658
        partner_obj = self.pool.get('res.partner')
 
659
        for procurement in self.browse(cr, uid, ids):
 
660
            if procurement.product_id.product_tmpl_id.supply_method <> 'buy':
 
661
                return False
 
662
            # use new selection field instead
 
663
            # the new selection field does not exist when the procurement has been produced by
 
664
            # an order_point (minimum stock rules). in this case we take the default supplier from product
 
665
            #if not procurement.product_id.seller_ids:
 
666
            if not procurement.supplier and not procurement.product_id.seller_ids:
 
667
                cr.execute('update procurement_order set message=%s where id=%s',
 
668
                        (_('No supplier defined for this product !'), procurement.id))
 
669
                return False
 
670
            # use new selection field instead, **FIRST** the new one, and if not exist, from product
 
671
            # the new selection field does not exist when the procurement has been produced by
 
672
            # an order_point (minimum stock rules). in this case we take the default supplier from product
 
673
            #partner = procurement.product_id.seller_id #Taken Main Supplier of Product of Procurement.
 
674
            partner = procurement.supplier or procurement.product_id.seller_id
 
675
 
 
676
            if user.company_id and user.company_id.partner_id:
 
677
                if partner.id == user.company_id.partner_id.id:
 
678
                    return False
 
679
            address_id = partner_obj.address_get(cr, uid, [partner.id], ['delivery'])['delivery']
 
680
            if not address_id:
 
681
                cr.execute('update procurement_order set message=%s where id=%s',
 
682
                        (_('No address defined for the supplier'), procurement.id))
 
683
                return False
 
684
        return True
 
685
    # @@@override end
 
686
 
 
687
    # @@@override purchase>purchase.py>procurement_order
 
688
    def make_po(self, cr, uid, ids, context=None):
 
689
        """ Make purchase order from procurement
 
690
        @return: New created Purchase Orders procurement wise
 
691
        """
 
692
        res = {}
 
693
        if context is None:
 
694
            context = {}
 
695
        company = self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id
 
696
        partner_obj = self.pool.get('res.partner')
 
697
        uom_obj = self.pool.get('product.uom')
 
698
        pricelist_obj = self.pool.get('product.pricelist')
 
699
        prod_obj = self.pool.get('product.product')
 
700
        acc_pos_obj = self.pool.get('account.fiscal.position')
 
701
        po_obj = self.pool.get('purchase.order')
 
702
        for procurement in self.browse(cr, uid, ids, context=context):
 
703
            res_id = procurement.move_id.id
 
704
            # use new selection field instead, **FIRST** the new one, and if not exist, from product
 
705
            # the new selection field does not exist when the procurement has been produced by
 
706
            # an order_point (minimum stock rules). in this case we take the default supplier from product
 
707
            if procurement.supplier:
 
708
                partner = procurement.supplier
 
709
                # if the supplier is present in product seller_ids, we take that quantity from supplierinfo
 
710
                # otherwise 1
 
711
                seller_qty = -1
 
712
                seller_delay = -1
 
713
                for suppinfo in procurement.product_id.seller_ids:
 
714
                    if suppinfo.name.id == partner.id:
 
715
                        seller_qty = suppinfo.qty
 
716
                        seller_delay = int(suppinfo.delay)
 
717
                
 
718
                if seller_qty < 0:
 
719
                    seller_qty = 1
 
720
                
 
721
                # if not, default delay from supplier (partner.default_delay)
 
722
                if seller_delay < 0:
 
723
                    seller_delay = partner.default_delay
 
724
                
 
725
            else:
 
726
                partner = procurement.product_id.seller_id # Taken Main Supplier of Product of Procurement.
 
727
                seller_qty = procurement.product_id.seller_qty
 
728
                seller_delay = int(procurement.product_id.seller_delay)
1212
729
            
1213
 
        return result
1214
 
    
1215
 
    def get_partner_hook(self, cr, uid, ids, context=None, *args, **kwargs):
1216
 
        '''
1217
 
        get data from supplier
1218
 
        
1219
 
        return also the price_unit
1220
 
        '''
1221
 
        tender_line_obj = self.pool.get('tender_line')
1222
 
        # get default values
1223
 
        result = super(procurement_order, self).get_partner_hook(cr, uid, ids, context=context, *args, **kwargs)
1224
 
        procurement = kwargs['procurement']
1225
 
        
1226
 
        # this is kept here and not moved in the tender_flow module
1227
 
        # because we have no control on the order of inherited function call (do we?)
1228
 
        # and if we have tender and supplier defined and supplier code is ran after
1229
 
        # tender one, the supplier will be use while tender has priority
1230
 
        if procurement.is_tender:
1231
 
            # tender line -> search for info about this product in the corresponding tender
1232
 
            # if nothing found, we keep default values from super
1233
 
            for sol in procurement.sale_order_line_ids:
1234
 
                for tender_line in sol.tender_line_ids:
1235
 
                    # if a tender rfq has been selected for this sale order line
1236
 
                    if tender_line.purchase_order_line_id:
1237
 
                        partner = tender_line.supplier_id
1238
 
                        price_unit = tender_line.price_unit
1239
 
                        # get corresponding delay and qty
1240
 
                        delay_qty = self.get_delay_qty(cr, uid, ids, partner, procurement.product_id, context=None)
1241
 
                        seller_delay = delay_qty['seller_delay']
1242
 
                        seller_qty = delay_qty['seller_qty']
1243
 
                        result.update(partner=partner,
1244
 
                                      seller_qty=seller_qty,
1245
 
                                      seller_delay=seller_delay,
1246
 
                                      price_unit=price_unit)
1247
 
                        
1248
 
        elif procurement.supplier:
1249
 
            # not tender, we might have a selected supplier from sourcing tool
1250
 
            # if not, we keep default values from super
1251
 
            partner = procurement.supplier
1252
 
            # get corresponding delay and qty
1253
 
            delay_qty = self.get_delay_qty(cr, uid, ids, partner, procurement.product_id, context=None)
1254
 
            seller_delay = delay_qty['seller_delay']
1255
 
            seller_qty = delay_qty['seller_qty']
1256
 
            result.update(partner=partner,
1257
 
                          seller_qty=seller_qty,
1258
 
                          seller_delay=seller_delay)
1259
 
        
1260
 
        return result
 
730
            partner_id = partner.id
 
731
            address_id = partner_obj.address_get(cr, uid, [partner_id], ['delivery'])['delivery']
 
732
            pricelist_id = partner.property_product_pricelist_purchase.id
 
733
 
 
734
            uom_id = procurement.product_id.uom_po_id.id
 
735
 
 
736
            qty = uom_obj._compute_qty(cr, uid, procurement.product_uom.id, procurement.product_qty, uom_id)
 
737
            if seller_qty:
 
738
                qty = max(qty,seller_qty)
 
739
 
 
740
            price = pricelist_obj.price_get(cr, uid, [pricelist_id], procurement.product_id.id, qty, partner_id, {'uom': uom_id})[pricelist_id]
 
741
 
 
742
            newdate = datetime.strptime(procurement.date_planned, '%Y-%m-%d %H:%M:%S')
 
743
            newdate = (newdate - relativedelta(days=company.po_lead)) - relativedelta(days=int(seller_delay))
 
744
 
 
745
            #Passing partner_id to context for purchase order line integrity of Line name
 
746
            context.update({'lang': partner.lang, 'partner_id': partner_id})
 
747
 
 
748
            product = prod_obj.browse(cr, uid, procurement.product_id.id, context=context)
 
749
 
 
750
            line = {
 
751
                'name': product.partner_ref,
 
752
                'product_qty': qty,
 
753
                'product_id': procurement.product_id.id,
 
754
                'product_uom': uom_id,
 
755
                'price_unit': price,
 
756
                'date_planned': newdate.strftime('%Y-%m-%d %H:%M:%S'),
 
757
                'move_dest_id': res_id,
 
758
                'notes': product.description_purchase,
 
759
            }
 
760
 
 
761
            taxes_ids = procurement.product_id.product_tmpl_id.supplier_taxes_id
 
762
            taxes = acc_pos_obj.map_tax(cr, uid, partner.property_account_position, taxes_ids)
 
763
            line.update({
 
764
                'taxes_id': [(6,0,taxes)]
 
765
            })
 
766
            purchase_id = po_obj.create(cr, uid, {
 
767
                'origin': procurement.origin,
 
768
                'partner_id': partner_id,
 
769
                'partner_address_id': address_id,
 
770
                'location_id': procurement.location_id.id,
 
771
                'pricelist_id': pricelist_id,
 
772
                'order_line': [(0,0,line)],
 
773
                'company_id': procurement.company_id.id,
 
774
                'fiscal_position': partner.property_account_position and partner.property_account_position.id or False
 
775
            })
 
776
            res[procurement.id] = purchase_id
 
777
            self.write(cr, uid, [procurement.id], {'state': 'running', 'purchase_id': purchase_id})
 
778
        return res
 
779
    # @@@override end
1261
780
 
1262
781
procurement_order()
1263
782
 
1268
787
    _inherit = "purchase.order"
1269
788
    _description = "Purchase Order"
1270
789
    
1271
 
    _columns = {
1272
 
        'customer_id': fields.many2one('res.partner', string='Customer', domain=[('customer', '=', True)]),
1273
 
    }
1274
 
    
1275
790
    def create(self, cr, uid, vals, context=None):
1276
791
        '''
1277
792
        override for debugging purpose
1278
793
        '''
1279
794
        return super(purchase_order, self).create(cr, uid, vals, context)
1280
 
 
1281
 
    def _check_order_type_and_partner(self, cr, uid, ids, context=None):
1282
 
        """
1283
 
        Check order type and partner type compatibilities.
1284
 
        """
1285
 
        compats = {
1286
 
            'regular':       ['internal', 'intermission', 'section', 'external', 'esc'],
1287
 
            'donation_st':   ['internal', 'intermission', 'section'],
1288
 
            'loan':          ['internal', 'intermission', 'section', 'external'],
1289
 
            'donation_exp':  ['internal', 'intermission', 'section'],
1290
 
            'in_kind':       ['external', 'esc'],
1291
 
            'direct':        ['external', 'esc'],
1292
 
            'purchase_list': ['external'],
1293
 
        }
1294
 
        # Browse PO
1295
 
        for po in self.browse(cr, uid, ids):
1296
 
            if po.order_type not in compats or po.partner_id.partner_type not in compats[po.order_type]:
1297
 
                return False
1298
 
        return True
1299
 
 
1300
 
    _constraints = [
1301
 
        (_check_order_type_and_partner, "Partner type and order type are incompatible! Please change either order type or partner.", ['order_type', 'partner_id']),
1302
 
    ]
1303
 
 
 
795
        
1304
796
purchase_order()
1305
797
 
1306
798
class product_template(osv.osv):
1339
831
        return false for each id
1340
832
        '''
1341
833
        if isinstance(ids,(long, int)):
1342
 
            ids = [ids]
 
834
           ids = [ids]
1343
835
        
1344
836
        result = {}
1345
837
        for id in ids:
1346
 
            result[id] = []
 
838
          result[id] = False
1347
839
        return result
1348
840
    
1349
 
    def _get_product_ids(self, cr, uid, obj, name, args, context=None):
 
841
    def _get_product_ids(self, cr, uid, obj, name, args, domain=None, context=None):
1350
842
        '''
1351
843
        from the product.template id returns the corresponding product.product
1352
844
        '''
1361
853
        # search filter on product_id of supplierinfo
1362
854
        return [('product_id', '=', templateId)]
1363
855
    
1364
 
    _columns = {'product_product_ids': fields.function(_get_false, method=True, type='one2many',relation='product.product', string="Products",fnct_search=_get_product_ids),
 
856
    _columns = {'product_product_ids': fields.function(_get_false, type='one2many',relation='product.product', string="Products",fnct_search=_get_product_ids),
1365
857
                }
1366
858
 
1367
859
    def name_get(self, cr, uid, ids, context=None):
1394
886
        return super(product_supplierinfo, self).create(cr, uid, values, context)
1395
887
        
1396
888
product_supplierinfo()
1397
 
 
1398
 
 
1399
 
class res_partner(osv.osv):
1400
 
    _name = 'res.partner'
1401
 
    _inherit = 'res.partner'
1402
 
    
1403
 
    def _get_available_for_dpo(self, cr, uid,ids, field_name, args, context=None):
1404
 
        '''
1405
 
        Return for each partner if he's available for DPO selection
1406
 
        '''
1407
 
        res = {}
1408
 
        company_id = self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id.partner_id.id
1409
 
        
1410
 
        for partner in self.browse(cr, uid, ids, context=context):
1411
 
            res[partner.id] = False
1412
 
            if partner.supplier and partner.id != company_id and partner.partner_type in ('external', 'esc'):
1413
 
                res[partner.id] = True
1414
 
        
1415
 
        return res
1416
 
    
1417
 
    def _src_available_for_dpo(self, cr, uid, obj, name, args, context=None):
1418
 
        '''
1419
 
        Returns all partners according to args
1420
 
        '''
1421
 
        res = []
1422
 
        for arg in args:
1423
 
            if len(arg) > 2 and arg[0] == 'available_for_dpo':
1424
 
                if arg[1] != '=':
1425
 
                    raise osv.except_osv(_('Error'), _('Bad operator'))
1426
 
                elif arg[2] == 'dpo':
1427
 
                    company_id = self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id.partner_id.id
1428
 
                    res.append(('id', '!=', company_id))
1429
 
                    res.append(('partner_type', 'in', ('external', 'esc')))
1430
 
                    res.append(('supplier', '=', True))
1431
 
                    
1432
 
        return res
1433
 
 
1434
 
    def _get_fake(self, cr, uid, ids, fields, arg, context=None):
1435
 
        if isinstance(ids, (int, long)):
1436
 
            ids = [ids]
1437
 
        result = {}
1438
 
        for id in ids:
1439
 
            result[id] = False
1440
 
        return result
1441
 
        
1442
 
    def _check_partner_type(self, cr, uid, obj, name, args, context=None):
1443
 
        if context is None:
1444
 
            context = {}
1445
 
        active_id = context.get('active_id', False)
1446
 
        if isinstance(active_id, (int, long)):
1447
 
            active_id = [active_id]
1448
 
        if not args:
1449
 
            return []
1450
 
        newargs = []
1451
 
        for arg in args:
1452
 
            if arg[0] == 'check_partner':
1453
 
                if arg[1] != '=' or not isinstance(arg[2], (int, long)):
1454
 
                    raise osv.except_osv(_('Error'), _('Filter check_partner different than (arg[0], =, id) not implemented.'))
1455
 
                if arg[2]:
1456
 
                    so = self.pool.get('sale.order').browse(cr, uid, arg[2])
1457
 
                    sl = self.pool.get('sourcing.line').browse(cr, uid, active_id)[0]
1458
 
                    if not so.procurement_request:
1459
 
                        newargs.append(('partner_type', 'in', ['external', 'esc']))
1460
 
                    elif so.procurement_request and not sl.product_id:
1461
 
                        newargs.append(('partner_type','in', ['internal', 'section', 'intermission']))
1462
 
            else:
1463
 
                newargs.append(args)
1464
 
        return newargs
1465
 
 
1466
 
    def _check_partner_type_rfq(self, cr, uid, obj, name, args, context=None):
1467
 
        if not args:
1468
 
            return []
1469
 
        newargs = []
1470
 
        for arg in args:
1471
 
            if arg[0] == 'check_partner_rfq':
1472
 
                if arg[1] != '=' or not isinstance(arg[2], (int, long)):
1473
 
                    raise osv.except_osv(_('Error'), _('Filter check_partner_rfq different than (arg[0], =, id) not implemented.'))
1474
 
                if arg[2]:
1475
 
                    tender = self.pool.get('tender').browse(cr, uid, arg[2])
1476
 
                    if tender.sale_order_id:
1477
 
                        newargs.append(('partner_type', 'in', ['external', 'esc']))
1478
 
            else:
1479
 
                newargs.append(args)
1480
 
        return newargs
1481
 
 
1482
 
    def _check_partner_type_ir(self, cr, uid, obj, name, args, context=None):
1483
 
        if context is None:
1484
 
            context = {}
1485
 
        active_ids = context.get('active_ids', False)
1486
 
        if isinstance(active_ids, (int, long)):
1487
 
            active_ids = [active_ids]
1488
 
        if not args:
1489
 
            return []
1490
 
        newargs = []
1491
 
        for arg in args:
1492
 
            if arg[0] == 'check_partner_ir':
1493
 
                if arg[1] != '=':
1494
 
                    raise osv.except_osv(_('Error'), _('Filter check_partner_ir different than (arg[0], =, id) not implemented.'))
1495
 
                if arg[2]:
1496
 
                    if active_ids:
1497
 
                        sol = self.pool.get('sale.order.line').browse(cr, uid, active_ids)[0]
1498
 
                        if not context.get('product_id', False) and sol.order_id.procurement_request:
1499
 
                            newargs.append(('partner_type','in', ['internal', 'section', 'intermission']))
1500
 
            else:
1501
 
                newargs.append(args)
1502
 
        return newargs
1503
 
 
1504
 
    def _check_partner_type_po(self, cr, uid, obj, name, args, context=None):
1505
 
        """
1506
 
        Create a domain on the field partner_id on the view id="purchase_move_buttons"
1507
 
        """
1508
 
        if context is None:
1509
 
            context = {}
1510
 
        if not args:
1511
 
            return []
1512
 
        newargs = []
1513
 
        partner_obj = self.pool.get('res.partner')
1514
 
        local_market = None
1515
 
        # Search the local market partner id
1516
 
        data_obj = self.pool.get('ir.model.data')
1517
 
        data_id = data_obj.search(cr, uid, [('module', '=', 'order_types'), ('model', '=', 'res.partner'), ('name', '=', 'res_partner_local_market')] )
1518
 
        if data_id:
1519
 
            local_market = data_obj.read(cr, uid, data_id, ['res_id'])[0]['res_id']
1520
 
        for arg in args:
1521
 
            if arg[0] == 'check_partner_po':
1522
 
                if arg[1] != '=' \
1523
 
                or arg[2]['order_type'] not in ['regular', 'donation_exp', 'donation_st', 'loan', 'in_kind', 'purchase_list', 'direct']\
1524
 
                or not isinstance(arg[2]['partner_id'], (int, long)):
1525
 
                    raise osv.except_osv(_('Error'), _('Filter check_partner_po different than (arg[0], =, %s) not implemented.') % arg[2])
1526
 
                partner_id = arg[2]['partner_id']
1527
 
                order_type = arg[2]['order_type']
1528
 
                # Added by UF-1660 to filter partners
1529
 
                # do nothing on partner_type for loan
1530
 
                p_list = []
1531
 
                if order_type == 'loan':
1532
 
                    p_list = ['internal', 'intermission', 'section', 'external']
1533
 
                elif order_type in ['direct', 'in_kind']:
1534
 
                    p_list = ['esc', 'external']
1535
 
                elif order_type in ['donation_st', 'donation_exp']:
1536
 
                    p_list = ['internal', 'intermission', 'section']
1537
 
                elif order_type in ['purchase_list']:
1538
 
                    p_list = ['external']
1539
 
                # show all supplier for non taken cases
1540
 
                else:
1541
 
                    pass
1542
 
                if p_list:
1543
 
                    newargs.append(('partner_type', 'in', p_list))
1544
 
                # Useless code because if we enter in direct case, we do not enter in this one
1545
 
#                elif partner_id and partner_id != local_market:
1546
 
#                    partner = partner_obj.browse(cr, uid, partner_id)
1547
 
#                    if partner.partner_type not in ('external', 'esc') and order_type == 'direct':
1548
 
#                        newargs.append(('partner_type', 'in', ['esc', 'external']))
1549
 
            else:
1550
 
                newargs.append(args)
1551
 
        return newargs
1552
 
 
1553
 
    _columns = {
1554
 
        'available_for_dpo': fields.function(_get_available_for_dpo, fnct_search=_src_available_for_dpo,
1555
 
                                             method=True, type='boolean', string='Available for DPO', store=False),
1556
 
        'check_partner': fields.function(_get_fake, method=True, type='boolean', string='Check Partner Type', fnct_search=_check_partner_type),
1557
 
        'check_partner_rfq': fields.function(_get_fake, method=True, type='boolean', string='Check Partner Type', fnct_search=_check_partner_type_rfq),
1558
 
        'check_partner_ir': fields.function(_get_fake, method=True, type='boolean', string='Check Partner Type On IR', fnct_search=_check_partner_type_ir),
1559
 
        'check_partner_po': fields.function(_get_fake, method=True, type='boolean', string='Check Partner Type On PO', fnct_search=_check_partner_type_po),
1560
 
    }
1561
 
    
1562
 
res_partner()