39
37
_name = 'sale.order.followup'
40
38
_description = 'Sales Order Followup'
42
def get_selection(self, cr, uid, o, field, context=None):
45
return self.pool.get('ir.model.fields').get_browse_selection(cr, uid, o, field, context)
40
def get_selection(self, cr, uid, o, field):
43
sel = self.pool.get(o._name).fields_get(cr, uid, [field])
44
res = dict(sel[field]['selection']).get(getattr(o,field),getattr(o,field))
45
name = '%s,%s' % (o._name, field)
46
tr_ids = self.pool.get('ir.translation').search(cr, uid, [('type', '=', 'selection'), ('name', '=', name),('src', '=', res)])
48
return self.pool.get('ir.translation').read(cr, uid, tr_ids, ['value'])[0]['value']
48
52
def _get_order_state(self, cr, uid, ids, field_name, args, context=None):
79
83
Launches the correct view according to the user's choice
81
85
for followup in self.browse(cr, uid, ids, context=context):
83
for line in followup.order_id.order_line:
84
if self.pool.get('sale.order.line').search(cr, uid, [('original_line_id', '=', line.id)], context=context):
86
86
# if followup.choose_type == 'documents':
87
87
# view_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'sales_followup', 'sale_order_followup_document_view')[1]
90
view_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'sales_followup', 'sale_order_followup_split_progress_view')[1]
92
view_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'sales_followup', 'sale_order_followup_progress_view')[1]
89
view_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'sales_followup', 'sale_order_followup_progress_view')[1]
94
91
return {'type': 'ir.actions.act_window',
95
92
'res_model': 'sale.order.followup',
162
158
raise osv.except_osv(_('Error'), _('You should select one order to follow !'))
164
160
followup_id = False
166
162
for o in order_obj.browse(cr, uid, ids, context=context):
167
followup_id = self.create(cr, uid, {'order_id': o.id}, context=context)
163
followup_id = self.create(cr, uid, {'order_id': o.id})
169
165
for line in o.order_line:
170
split_line_ids = sol_obj.search(cr, uid, [('original_line_id', '=', line.id)], context=context)
174
lines = sol_obj.browse(cr, uid, split_line_ids, context=context)
179
purchase_ids = self.get_purchase_ids(cr, uid, l.id, context=context)
180
purchase_line_ids = self.get_purchase_line_ids(cr, uid, l.id, purchase_ids, context=context)
181
incoming_ids = self.get_incoming_ids(cr, uid, l.id, purchase_ids, context=context)
182
outgoing_ids = self.get_outgoing_ids(cr, uid, l.id, context=context)
183
displayed_out_ids = self.get_outgoing_ids(cr, uid, l.id, non_zero=True, context=context)
184
tender_ids = self.get_tender_ids(cr, uid, l.id, context=context)
185
# quotation_ids = self.get_quotation_ids(cr, uid, line.id, context=context)
166
purchase_ids = self.get_purchase_ids(cr, uid, line.id, context=context)
167
purchase_line_ids = self.get_purchase_line_ids(cr, uid, line.id, purchase_ids, context=context)
168
incoming_ids = self.get_incoming_ids(cr, uid, line.id, purchase_ids, context=context)
169
outgoing_ids = self.get_outgoing_ids(cr, uid, line.id, context=context)
170
displayed_out_ids = self.get_outgoing_ids(cr, uid, line.id, non_zero=True, context=context)
171
tender_ids = self.get_tender_ids(cr, uid, line.id, context=context)
172
# quotation_ids = self.get_quotation_ids(cr, uid, line.id, context=context)
187
line_obj.create(cr, uid, {'followup_id': followup_id,
189
'original_order_id': split_lines and l.order_id and l.order_id.id or False,
190
'first_line': first_line,
191
'tender_ids': [(6,0,tender_ids)],
192
# 'quotation_ids': [(6,0,quotation_ids)],
193
'purchase_ids': [(6,0,purchase_ids)],
194
'purchase_line_ids': [(6,0,purchase_line_ids)],
195
'incoming_ids': [(6,0,incoming_ids)],
196
'outgoing_ids': [(6,0,outgoing_ids)],
197
'displayed_out_ids': [(6,0,displayed_out_ids)]}, context=context)
201
view_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'sales_followup', 'sale_order_followup_split_progress_view')[1]
203
view_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'sales_followup', 'sale_order_followup_progress_view')[1]
174
line_obj.create(cr, uid, {'followup_id': followup_id,
176
'tender_ids': [(6,0,tender_ids)],
177
# 'quotation_ids': [(6,0,quotation_ids)],
178
'purchase_ids': [(6,0,purchase_ids)],
179
'purchase_line_ids': [(6,0,purchase_line_ids)],
180
'incoming_ids': [(6,0,incoming_ids)],
181
'outgoing_ids': [(6,0,outgoing_ids)],
182
'displayed_out_ids': [(6,0,displayed_out_ids)]})
184
view_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'sales_followup', 'sale_order_followup_progress_view')[1]
205
186
return {'type': 'ir.actions.act_window',
206
187
'res_model': 'sale.order.followup',
207
188
'res_id': followup_id,
208
189
'view_id': [view_id],
210
190
'view_type': 'form',
211
191
'view_mode': 'form',}
337
317
return tender_ids
339
def export_get_file_name(self, cr, uid, ids, prefix='FO_Follow_Up', context=None):
340
if isinstance(ids, (int, long)):
344
foup = self.browse(cr, uid, ids[0], context=context)
345
if not foup or not foup.order_id or not foup.order_id.name:
347
dt_now = datetime.datetime.now()
348
po_name = "%s_%s_%d_%02d_%02d" % (prefix,
349
foup.order_id.name.replace('/', '_'),
350
dt_now.year, dt_now.month, dt_now.day)
353
def export_xls(self, cr, uid, ids, context=None):
355
Print the report (Excel)
357
if isinstance(ids, (int, long)):
360
file_name = self.export_get_file_name(cr, uid, ids, context=context)
362
datas['target_filename'] = file_name
364
'type': 'ir.actions.report.xml',
365
'report_name': 'sales.follow.up.report_xls',
371
def export_pdf(self, cr, uid, ids, context=None):
373
Print the report (PDF)
375
if isinstance(ids, (int, long)):
378
file_name = self.export_get_file_name(cr, uid, ids, context=context)
380
datas['target_filename'] = file_name
382
'type': 'ir.actions.report.xml',
383
'report_name': 'sales.follow.up.report_pdf',
389
320
sale_order_followup()
392
322
class sale_order_line_followup(osv.osv_memory):
393
323
_name = 'sale.order.line.followup'
394
324
_description = 'Sales Order Lines Followup'
404
334
for line in self.browse(cr, uid, ids, context=context):
405
res[line.id] = {'sourced_ok': _('No'),
335
res[line.id] = {'sourced_ok': 'No',
406
336
# 'quotation_status': 'No quotation',
407
'tender_status': _('N/A'),
408
'purchase_status': _('N/A'),
409
'incoming_status': _('N/A'),
410
'outgoing_status': _('No deliveries'),
411
'product_available': _('Waiting'),
337
'tender_status': 'N/A',
338
'purchase_status': 'N/A',
339
'incoming_status': 'N/A',
340
'outgoing_status': 'No deliveries',
341
'product_available': 'Waiting',
412
342
'outgoing_nb': 0,
413
343
'available_qty': 0.00}
415
345
# Set the available qty in stock
416
# You may not have product with an Internal Request
417
if line.line_id.product_id:
418
res[line.id]['available_qty'] = self.pool.get('product.product').browse(cr, uid, line.line_id.product_id.id, context=context).qty_available
346
res[line.id]['available_qty'] = self.pool.get('product.product').browse(cr, uid, line.line_id.product_id.id, context=context).qty_available
420
348
# Define if the line is sourced or not according to the state on the SO line
421
349
if line.line_id.state == 'draft':
422
res[line.id]['sourced_ok'] = _('No')
350
res[line.id]['sourced_ok'] = 'No'
423
351
if line.line_id.state in ('confirmed', 'done'):
424
res[line.id]['sourced_ok'] = _('Closed')
352
res[line.id]['sourced_ok'] = 'Closed'
425
353
if line.line_id.state == 'cancel':
426
res[line.id]['sourced_ok'] = _('Cancelled')
354
res[line.id]['sourced_ok'] = 'Cancelled'
427
355
if line.line_id.state == 'exception':
428
res[line.id]['sourced_ok'] = _('Exception')
356
res[line.id]['sourced_ok'] = 'Exception'
430
358
####################################################
431
359
# Get information about the state of call for tender
432
360
####################################################
433
tender_status = {'n_a': _('N/A'),
434
'no_tender': _('No tender'),
435
'partial': _('Partial'),
436
'draft': _('Waiting'),
437
'comparison': _('In Progress'),
439
'cancel': _('Cancelled')}
361
tender_status = {'n_a': 'N/A',
362
'no_tender': 'No tender',
363
'partial': 'Partial',
365
'comparison': 'In Progress',
367
'cancel': 'Cancelled'}
441
if line.line_id.type == 'make_to_stock' or line.line_id.po_cft in ('po', 'dpo'):
442
res[line.id]['tender_status'] = tender_status.get('n_a', _('Error on state !'))
369
if line.line_id.type == 'make_to_stock' or line.line_id.po_cft == 'po':
370
res[line.id]['tender_status'] = tender_status.get('n_a', 'Error on state !')
443
371
elif line.line_id.po_cft == 'cft' and not line.tender_ids:
444
res[line.id]['tender_status'] = tender_status.get('no_tender', _('Error on state !'))
372
res[line.id]['tender_status'] = tender_status.get('no_tender', 'Error on state !')
446
374
# Check if all generated tenders are in the same state
447
375
tender_state = False
459
387
####################################################
460
388
# Get information about the state of purchase orders
461
389
####################################################
462
purchase_status = {'n_a': _('N/A'),
463
'no_order': _('No order'),
464
'partial': _('Partial'),
466
'confirmed': _('Validated'),
467
'wait': _('Validated'),
468
'confirmed_wait': _('Confirmed (waiting)'),
469
'approved': _('Confirmed'),
471
'cancel': _('Cancelled'),
472
'except_picking': _('Exception'),
473
'except_invoice': _('Exception'),}
390
purchase_status = {'n_a': 'N/A',
391
'no_order': 'No order',
392
'partial': 'Partial',
394
'confirmed': 'Confirmed',
396
'approved': 'Approved',
398
'cancel': 'Cancelled',
399
'except_picking': 'Exception',
400
'except_invoice': 'Exception',}
475
402
if line.line_id.type == 'make_to_stock':
476
res[line.id]['purchase_status'] = purchase_status.get('n_a', _('Error on state !'))
403
res[line.id]['purchase_status'] = purchase_status.get('n_a', 'Error on state !')
477
404
elif not line.purchase_ids:
478
res[line.id]['purchase_status'] = purchase_status.get('no_order', _('Error on state !'))
405
res[line.id]['purchase_status'] = purchase_status.get('no_order', 'Error on state !')
480
407
# Check if all generated PO are in the same state
481
408
purchase_state = False
493
420
###########################################################
494
421
# Get information about the state of all incoming shipments
495
422
###########################################################
496
incoming_status = {'n_a': _('N/A'),
497
'no_incoming': _('No shipment'),
498
'partial': _('Partial'),
499
'draft': _('Waiting'),
500
'confirmed': _('Waiting'),
501
'assigned': _('Available'),
503
'cancel': _('Cancelled')}
423
incoming_status = {'n_a': 'N/A',
424
'no_incoming': 'No shipment',
425
'partial': 'Partial',
427
'confirmed': 'Waiting',
428
'assigned': 'Available',
430
'cancel': 'Cancelled'}
505
432
if line.line_id.type == 'make_to_stock':
506
res[line.id]['incoming_status'] = incoming_status.get('n_a', _('Error on state !'))
433
res[line.id]['incoming_status'] = incoming_status.get('n_a', 'Error on state !')
507
434
elif not line.incoming_ids:
508
res[line.id]['incoming_status'] = incoming_status.get('no_incoming', _('Error on state !'))
435
res[line.id]['incoming_status'] = incoming_status.get('no_incoming', 'Error on state !')
510
437
shipment_state = False
511
438
for shipment in line.incoming_ids:
687
614
# If all products should be processed from the main picking ticket or if the main picking ticket is done
688
615
if total_line == line.line_id.product_uom_qty:
689
res[line.id]['product_available'] = out_status.get(out_step['general']['state'], _('Error on state !'))
690
res[line.id]['outgoing_status'] = out_status.get(out_step['general']['state'], _('Error on state !'))
616
res[line.id]['product_available'] = out_status.get(out_step['general']['state'], 'Error on state !')
617
res[line.id]['outgoing_status'] = out_status.get(out_step['general']['state'], 'Error on state !')
691
618
elif total_line < line.line_id.product_uom_qty and out_step['general']['state']:
692
res[line.id]['product_available'] = out_status.get('partial', _('Error on state !'))
693
res[line.id]['outgoing_status'] = out_status.get('partial', _('Error on state !'))
619
res[line.id]['product_available'] = out_status.get('partial', 'Error on state !')
620
res[line.id]['outgoing_status'] = out_status.get('partial', 'Error on state !')
694
621
elif out_step['customer']['state'] == 'done' and all_done:
695
res[line.id]['product_available'] = out_status.get('done', _('Error on state !'))
696
res[line.id]['outgoing_status'] = out_status.get('done', _('Error on state !'))
622
res[line.id]['product_available'] = out_status.get('done', 'Error on state !')
623
res[line.id]['outgoing_status'] = out_status.get('done', 'Error on state !')
698
625
# If not all products are sent to the supplier
699
626
if out_step['customer']['state'] and out_step['customer']['state'] == 'partial':
700
res[line.id]['outgoing_status'] = out_status.get('partial', _('Error on state !'))
701
res[line.id]['product_available'] = out_status.get('done', _('Error on state !'))
627
res[line.id]['outgoing_status'] = out_status.get('partial', 'Error on state !')
628
res[line.id]['product_available'] = out_status.get('done', 'Error on state !')
702
629
# If all products are waiting to send to customer
703
630
elif out_step['customer']['state'] and out_step['customer']['state'] == 'assigned':
704
res[line.id]['outgoing_status'] = out_status.get('shipped', _('Error on state !'))
705
res[line.id]['product_available'] = out_status.get('done', _('Error on state !'))
631
res[line.id]['outgoing_status'] = out_status.get('shipped', 'Error on state !')
632
res[line.id]['product_available'] = out_status.get('done', 'Error on state !')
707
634
# If all products are not in distribution
708
635
if out_step['distrib']['state'] and out_step['distrib']['state'] == 'partial':
709
res[line.id]['outgoing_status'] = out_status.get('partial', _('Error on state !'))
636
res[line.id]['outgoing_status'] = out_status.get('partial', 'Error on state !')
710
637
elif out_step['distrib']['state'] and out_step['distrib']['state'] == 'assigned':
711
res[line.id]['outgoing_status'] = out_status.get('packed', _('Error on state !'))
712
res[line.id]['product_available'] = out_status.get('done', _('Error on state !'))
638
res[line.id]['outgoing_status'] = out_status.get('packed', 'Error on state !')
639
res[line.id]['product_available'] = out_status.get('done', 'Error on state !')
714
641
# If all products are not in dispatch zone
715
642
if out_step['dispatch']['state'] == 'partial':
716
res[line.id]['outgoing_status'] = out_status.get('partial', _('Error on state !'))
643
res[line.id]['outgoing_status'] = out_status.get('partial', 'Error on state !')
718
645
# If all products are not picked
719
646
if out_step['picking']['state'] == 'partial' or out_step['packing']['state'] == 'partial':
720
647
res[line.id]['outgoing_status'] = out_status.get('partial', 'Error on state !')
721
res[line.id]['product_available'] = out_status.get(out_step['picking']['state'], _('Error on state !'))
648
res[line.id]['product_available'] = out_status.get(out_step['picking']['state'], 'Error on state !')
722
649
elif out_step['picking']['state'] == 'assigned':
723
res[line.id]['outgoing_status'] = out_status.get('assigned', _('Error on state !'))
724
res[line.id]['product_available'] = out_status.get('assigned', _('Error on state !'))
650
res[line.id]['outgoing_status'] = out_status.get('assigned', 'Error on state !')
651
res[line.id]['product_available'] = out_status.get('assigned', 'Error on state !')
725
652
elif out_step['picking']['state'] == 'done' and out_step['packing']['state'] == 'assigned':
726
res[line.id]['outgoing_status'] = out_status.get('picked', _('Error on state !'))
727
res[line.id]['product_available'] = out_status.get('done', _('Error on state !'))
653
res[line.id]['outgoing_status'] = out_status.get('picked', 'Error on state !')
654
res[line.id]['product_available'] = out_status.get('done', 'Error on state !')
729
656
if out_step['picking']['state'] == 'done':
730
res[line.id]['product_available'] = out_status.get('done', _('Error on state !'))
657
res[line.id]['product_available'] = out_status.get('done', 'Error on state !')
732
659
# Set the number of the outgoing deliveries
733
660
res[line.id]['outgoing_nb'] = '%s' %nb_out
742
669
'followup_id': fields.many2one('sale.order.followup', string='Sale Order Followup', required=True, on_delete='cascade'),
743
670
'line_id': fields.many2one('sale.order.line', string='Order line', required=True, readonly=True),
744
'original_order_id': fields.many2one('sale.order', string='Orig. line', readonly=True),
745
'first_line': fields.boolean(string='First line'),
746
671
'procure_method': fields.related('line_id', 'type', type='selection', selection=[('make_to_stock','From stock'), ('make_to_order','On order')], readonly=True, string='Proc. Method'),
747
'po_cft': fields.related('line_id', 'po_cft', type='selection', selection=[('po','PO'), ('dpo', 'DPO'), ('cft','CFT')], readonly=True, string='PO/CFT'),
672
'po_cft': fields.related('line_id', 'po_cft', type='selection', selection=[('po','PO'), ('cft','CFT')], readonly=True, string='PO/CFT'),
748
673
'line_number': fields.related('line_id', 'line_number', string='Order line', readonly=True, type='integer'),
749
'product_id': fields.related('line_id', 'product_id', string='Product Code', readondy=True,
674
'product_id': fields.related('line_id', 'product_id', string='Product reference', readondy=True,
750
675
type='many2one', relation='product.product'),
751
676
'qty_ordered': fields.related('line_id', 'product_uom_qty', string='Ordered qty', readonly=True),
752
677
'uom_id': fields.related('line_id', 'product_uom', type='many2one', relation='product.uom', string='UoM', readonly=True),
1011
935
_name = 'sale.order'
1012
936
_inherit = 'sale.order'
1014
def _get_dummy(self, cr, uid, ids, field_name, args, context=None):
1021
def _src_to_partner(self, cr, uid, obj, name, args, context=None):
1025
if arg[0] == 'to_partner_id' and arg[2] is not False:
1026
res.append(('partner_id', arg[1], arg[2]))
1031
'to_partner_id': fields.function(
1033
fnct_search=_src_to_partner,
1036
string='To partner',
1042
938
def name_search(self, cr, uid, name='', args=None, operator='ilike', context=None, limit=80):
1044
940
Search all SO by internal or customer reference
1048
944
if context.get('from_followup'):
1050
946
if name and len(name) > 1:
1051
args2 = [('client_order_ref', operator, name)]
1054
ids.extend(self.search(cr, uid, args2, context=context))
1055
res = self.name_get(cr, uid, ids, context=context)
947
ids.extend(self.search(cr, uid, [('client_order_ref', operator, name)], context=context))
949
return self.name_get(cr, uid, ids, context=context)
1057
res = super(sale_order, self).name_search(cr, uid, name, args, operator, context, limit)
951
return super(sale_order, self).name_search(cr, uid, name, args, operator, context, limit)
1060
953
def name_get(self, cr, uid, ids, context=None):