26
26
from sale_override import SALE_ORDER_STATE_SELECTION
27
27
from msf_order_date.order_dates import compute_rts
30
class procurement_request_sourcing_document(osv.osv):
31
_name = 'procurement.request.sourcing.document'
32
_rec_name = 'order_id'
34
def _get_doc_name(self, cr, uid, ids, field_name, args, context=None):
36
Return for each record, the name of the sourcing document according to
37
the model of the sourcing document and its ID.
42
if isinstance(ids, (int, long)):
46
for doc in self.browse(cr, uid, ids, context=context):
47
res[doc.id] = self.pool.get(doc.sourcing_document_model).browse(
48
cr, uid, doc.sourcing_document_id, context=context).name
53
'order_id': fields.many2one(
55
string='Internal request',
58
'sourcing_document_id': fields.integer(
59
string='Sourcing document ID',
62
'sourcing_document_type': fields.selection(
64
('rfq', 'Request for Quotation'),
66
('po', 'Purchase order'),
67
('internal', 'Internal move'),
68
('out', 'Outgoing delivery'),
73
'sourcing_document_model': fields.selection(
75
('purchase.order', 'Purchase order'),
77
('stock.picking', 'Picking'),
82
'sourcing_document_name': fields.function(
85
string='Document name',
93
def go_to_document(self, cr, uid, ids, context=None):
95
Open the sourcing document in the new tab
97
data_obj = self.pool.get('ir.model.data')
102
if isinstance(ids, (int, long)):
105
brw = self.browse(cr, uid, ids[0], context=context)
106
doc = self.pool.get(brw.sourcing_document_model).browse(
107
cr, uid, brw.sourcing_document_id, context=context)
109
if brw.sourcing_document_type == 'rfq':
113
elif brw.sourcing_document_type == 'out':
114
pick_type = 'delivery'
115
if doc.subtype == 'picking':
116
pick_type = 'picking_ticket'
119
'pick_type': pick_type,
123
'type': 'ir.actions.act_window',
124
'res_model': brw.sourcing_document_model,
126
'view_mode': 'form,tree',
127
'res_id': brw.sourcing_document_id,
131
if brw.sourcing_document_type == 'out':
132
if doc.subtype == 'picking':
133
view_id = data_obj.get_object_reference(cr, uid,
134
'msf_outgoing', 'view_picking_ticket_form')[1]
135
elif doc.subtype == 'standard':
136
view_id = data_obj.get_object_reference(cr, uid,
137
'stock', 'view_picking_out_form')[1]
139
res['view_id'] = [view_id]
143
def chk_create(self, cr, uid, vals, context=None):
145
Check if a same record already exist. If not, create a new record.
150
chk_ids = self.search(cr, uid, [
151
('order_id', '=', vals.get('order_id')),
152
('sourcing_document_id', '=', vals.get('sourcing_document_id')),
153
('sourcing_document_model', '=', vals.get('sourcing_document_model')),
157
self.create(cr, uid, {
158
'order_id': vals.get('order_id'),
159
'sourcing_document_id': vals.get('sourcing_document_id'),
160
'sourcing_document_model': vals.get('sourcing_document_model'),
161
'sourcing_document_type': vals.get('sourcing_document_type'),
166
procurement_request_sourcing_document()
169
29
class procurement_request(osv.osv):
170
30
_name = 'sale.order'
171
31
_inherit = 'sale.order'
173
def _ir_amount_all(self, cr, uid, ids, field_name, arg, context=None):
174
cur_obj = self.pool.get('res.currency')
176
for ir in self.browse(cr, uid, ids, context=context):
179
if ir.procurement_request:
180
curr_browse = self.pool.get('res.users').browse(cr, uid, [uid], context)[0].company_id.currency_id
181
for line in ir.order_line:
182
val += line.price_subtotal
183
res[ir.id] = cur_obj.round(cr, uid, curr_browse.rounding, val)
186
33
def _amount_all(self, cr, uid, ids, field_name, arg, context=None):
188
35
Override the method to return 0.0 if the sale.order is a prcourement request
193
40
for order in self.browse(cr, uid, ids, context=context):
194
41
if order.procurement_request:
195
42
res[order.id] = {}
198
45
res[order.id]['amount_untaxed'] = 0.0
200
47
new_ids.append(order.id)
202
49
res.update(super(procurement_request, self)._amount_all(cr, uid, new_ids, field_name, arg, context=context))
206
def _amount_by_type(self, cr, uid, ids, field_name, arg, context=None):
208
Compute the amount of line by type of procurement
210
line_obj = self.pool.get('sale.order.line')
215
res[id] = {'purchase_amount': 0.00, 'stock_amount': 0.00, 'proc_amount': 0.00}
217
line_ids = line_obj.search(cr, uid, [('order_id', 'in', ids)], context=context)
219
for line_data in line_obj.read(cr, uid, line_ids, ['product_uom_qty', 'cost_price', 'order_id', 'type'], context=context):
220
order_id = line_data['order_id'][0]
221
line_amount = line_data['product_uom_qty'] * line_data['cost_price']
222
res[order_id]['proc_amount'] += line_amount
223
if line_data['type'] == 'make_to_stock':
224
res[order_id]['stock_amount'] += line_amount
226
res[order_id]['purchase_amount'] += line_amount
230
53
def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False, submenu=False):
250
69
result[line.order_id.id] = True
251
70
return result.keys()
255
'location_requestor_id': fields.many2one('stock.location', string='Location Requestor', ondelete="cascade",
256
domain=[('location_category', '!=', 'transition'), '|', ('usage', '=', 'internal'), '&', ('usage', '=', 'customer'), ('location_category', '=', 'consumption_unit')], help='You can only select an internal location'),
257
74
'requestor': fields.char(size=128, string='Requestor', states={'draft': [('readonly', False)]}, readonly=True),
258
75
'procurement_request': fields.boolean(string='Internal Request', readonly=True),
259
76
'warehouse_id': fields.many2one('stock.warehouse', string='Warehouse', states={'draft': [('readonly', False)]}, readonly=True),
260
'origin': fields.char(size=512, string='Origin', states={'draft': [('readonly', False)]}, readonly=True),
77
'origin': fields.char(size=64, string='Origin', states={'draft': [('readonly', False)]}, readonly=True),
261
78
'notes': fields.text(string='Notes'),
262
'order_ids': fields.one2many(
263
'procurement.request.sourcing.document',
265
string='Sourcing document',
268
'ir_total_amount': fields.function(_ir_amount_all, method=True, digits_compute=dp.get_precision('Sale Price'), string='Indicative Total Value'),
269
'amount_untaxed': fields.function(_amount_all, method=True, digits_compute=dp.get_precision('Sale Price'), string='Untaxed Amount',
79
'order_ids': fields.many2many('purchase.order', 'procurement_request_order_rel',
80
'request_id', 'order_id', string='Orders', readonly=True),
82
'amount_untaxed': fields.function(_amount_all, method=True, digits_compute= dp.get_precision('Sale Price'), string='Untaxed Amount',
271
84
'sale.order': (lambda self, cr, uid, ids, c=None: ids, ['order_line'], 10),
272
85
'sale.order.line': (_get_order, ['price_unit', 'tax_id', 'discount', 'product_uom_qty'], 10),
274
87
multi='sums', help="The amount without tax."),
275
'amount_tax': fields.function(_amount_all, method=True, digits_compute=dp.get_precision('Sale Price'), string='Taxes',
88
'amount_tax': fields.function(_amount_all, method=True, digits_compute= dp.get_precision('Sale Price'), string='Taxes',
277
90
'sale.order': (lambda self, cr, uid, ids, c=None: ids, ['order_line'], 10),
278
91
'sale.order.line': (_get_order, ['price_unit', 'tax_id', 'discount', 'product_uom_qty'], 10),
280
93
multi='sums', help="The tax amount."),
281
'amount_total': fields.function(_amount_all, method=True, digits_compute=dp.get_precision('Sale Price'), string='Total',
94
'amount_total': fields.function(_amount_all, method=True, digits_compute= dp.get_precision('Sale Price'), string='Total',
283
96
'sale.order': (lambda self, cr, uid, ids, c=None: ids, ['order_line'], 10),
284
97
'sale.order.line': (_get_order, ['price_unit', 'tax_id', 'discount', 'product_uom_qty'], 10),
286
99
multi='sums', help="The total amount."),
287
'purchase_amount': fields.function(_amount_by_type, method=True, digits_compute=dp.get_precision('Sale Price'), string='Purchase Total',
289
'sale.order': (lambda self, cr, uid, ids, c=None: ids, ['order_line'], 10),
290
'sale.order.line': (_get_order, ['price_unit', 'tax_id', 'discount', 'product_uom_qty', 'type'], 10),
292
multi='by_type', help="The amount of lines sourced on order"),
293
'stock_amount': fields.function(_amount_by_type, method=True, digits_compute=dp.get_precision('Sale Price'), string='Stock Total',
295
'sale.order': (lambda self, cr, uid, ids, c=None: ids, ['order_line'], 10),
296
'sale.order.line': (_get_order, ['price_unit', 'tax_id', 'discount', 'product_uom_qty', 'type'], 10),
298
multi='by_type', help="The amount of lines sourced from stock"),
299
'proc_amount': fields.function(_amount_by_type, method=True, digits_compute=dp.get_precision('Sale Price'), string='Stock Total',
301
'sale.order': (lambda self, cr, uid, ids, c=None: ids, ['order_line'], 10),
302
'sale.order.line': (_get_order, ['price_unit', 'tax_id', 'discount', 'product_uom_qty', 'type'], 10),
304
multi='by_type', help="The amount of lines sourced from stock"),
305
100
'state': fields.selection(SALE_ORDER_STATE_SELECTION, 'Order State', readonly=True, help="Gives the state of the quotation or sales order. \nThe exception state is automatically set when a cancel operation occurs in the invoice validation (Invoice Exception) or in the picking list process (Shipping Exception). \nThe 'Waiting Schedule' state is set when the invoice is confirmed but waiting for the scheduler to run on the date 'Ordered Date'.", select=True),
306
'name': fields.char('Order Reference', size=64, required=True, readonly=True, select=True),
307
'is_ir_from_po_cancel': fields.boolean('Is IR from a PO cancelled', invisible=True), # UFTP-82: flagging we are in an IR and its PO is cancelled
311
'name': lambda *a: False,
104
'name': lambda obj, cr, uid, context: not context.get('procurement_request', False) and obj.pool.get('ir.sequence').get(cr, uid, 'sale.order') or obj.pool.get('ir.sequence').get(cr, uid, 'procurement.request'),
312
105
'procurement_request': lambda obj, cr, uid, context: context.get('procurement_request', False),
313
106
'state': 'draft',
314
107
'warehouse_id': lambda obj, cr, uid, context: len(obj.pool.get('stock.warehouse').search(cr, uid, [])) and obj.pool.get('stock.warehouse').search(cr, uid, [])[0],
315
'is_ir_from_po_cancel': False, # UFTP-82
318
110
def create(self, cr, uid, vals, context=None):
446
236
self.write(cr, uid, ids, {'state': 'cancel'}, context=context)
447
237
self.pool.get('sale.order.line').write(cr, uid, line_ids, {'state': 'cancel'}, context=context)
450
self.infolog(cr, uid, "The IR id:%s has been canceled" % ir_id)
454
241
def validate_procurement(self, cr, uid, ids, context=None):
456
Validate the request (which is a the same object as a SO)
457
It is the action called on the activity of the workflow.
459
obj_data = self.pool.get('ir.model.data')
460
line_obj = self.pool.get('sale.order.line')
461
nomen_manda_0 = obj_data.get_object_reference(cr, uid, 'msf_doc_import', 'nomen_tbd0')[1]
462
nomen_manda_1 = obj_data.get_object_reference(cr, uid, 'msf_doc_import', 'nomen_tbd1')[1]
463
nomen_manda_2 = obj_data.get_object_reference(cr, uid, 'msf_doc_import', 'nomen_tbd2')[1]
464
nomen_manda_3 = obj_data.get_object_reference(cr, uid, 'msf_doc_import', 'nomen_tbd3')[1]
465
uom_tbd = obj_data.get_object_reference(cr, uid, 'msf_doc_import', 'uom_tbd')[1]
468
245
for req in self.browse(cr, uid, ids, context=context):
469
246
if len(req.order_line) <= 0:
470
247
raise osv.except_osv(_('Error'), _('You cannot validate an Internal request with no lines !'))
471
for line in req.order_line:
472
line_ids.append(line.id)
473
if line.nomen_manda_0.id == nomen_manda_0 \
474
or line.nomen_manda_1.id == nomen_manda_1 \
475
or line.nomen_manda_2.id == nomen_manda_2 \
476
or line.nomen_manda_3.id == nomen_manda_3 \
477
or line.product_uom.id == uom_tbd:
479
if line.product_uom_qty <= 0.00:
480
raise osv.except_osv(_('Error'), _('A line must a have a quantity larger than 0.00'))
482
raise osv.except_osv(_('Error'), _('Please check the lines : you cannot have "To Be confirmed" for Nomenclature Level". You have %s lines to correct !') % nb_lines)
483
self.log(cr, uid, req.id, _("The internal request '%s' has been validated (nb lines: %s).") % (req.name, len(req.order_line)), context=context)
484
line_obj.update_supplier_on_line(cr, uid, line_ids, context=context)
485
248
self.write(cr, uid, ids, {'state': 'validated'}, context=context)
489
252
def confirm_procurement(self, cr, uid, ids, context=None):
491
254
Confirmed the request
498
261
for request in self.browse(cr, uid, ids, context=context):
499
262
if len(request.order_line) <= 0:
500
263
raise osv.except_osv(_('Error'), _('You cannot confirm an Internal request with no lines !'))
501
for line in request.order_line:
503
if line.type == 'make_to_order' and not line.po_cft == 'cft':
504
if not line.supplier:
505
line_number = line.line_number
506
request_name = request.name
507
raise osv.except_osv(_('Error'), _('Please correct the line %s of the %s: the supplier is required for the procurement method "On Order" !') % (line_number, request_name))
508
# an Internal Request without product can only have Internal, Intersection or Intermission partners.
509
elif line.supplier and not line.product_id and line.order_id.procurement_request and line.supplier.partner_type not in ['internal', 'section', 'intermission']:
510
raise osv.except_osv(_('Warning'), _("""For an Internal Request with a procurement method 'On Order' and without product,
511
the supplier must be either in 'Internal', 'Inter-Section' or 'Intermission' type.
513
message = _("The internal request '%s' has been confirmed (nb lines: %s).") % (request.name, len(request.order_line))
264
message = _("The internal request '%s' has been confirmed.") %(request.name,)
514
265
proc_view = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'procurement_request', 'procurement_request_form_view')
515
266
context.update({'view_id': proc_view and proc_view[1] or False})
516
267
self.log(cr, uid, request.id, message, context=context)
518
269
self.action_ship_create(cr, uid, ids, context=context)
522
def test_state_done(self, cr, uid, ids, mode, *args):
523
if not self.test_state(cr, uid, ids, mode, *args):
526
for ir in self.browse(cr, uid, ids):
527
is_out = ir.location_requestor_id.usage == 'customer'
531
ir_lines = [x.id for x in ir.order_line]
532
out_move_ids = self.pool.get('stock.move').search(cr, uid, [
533
('picking_id.type', '=', 'out'),
534
('sale_line_id', 'in', ir_lines),
535
('state', 'not in', ['done', 'cancel']),
542
273
def procurement_done(self, cr, uid, ids, context=None):
544
275
Creates all procurement orders according to lines
546
277
self.write(cr, uid, ids, {'state': 'done'})
549
281
def pricelist_id_change(self, cr, uid, ids, pricelist_id):
551
283
Display a warning message on pricelist change
555
287
if pricelist_id and ids:
556
288
order = self.browse(cr, uid, ids[0])
557
289
if pricelist_id != order.pricelist_id.id and order.order_line:
558
290
res.update({'warning': {'title': 'Currency change',
559
291
'message': 'You have changed the currency of the order. \
560
292
Please note that all order lines in the old currency will be changed to the new currency without conversion !'}})
564
296
procurement_request()
566
298
class procurement_request_line(osv.osv):
567
299
_name = 'sale.order.line'
568
_inherit = 'sale.order.line'
300
_inherit= 'sale.order.line'
570
302
def _amount_line(self, cr, uid, ids, field_name, arg, context=None):
572
304
Override the method to return 0.0 if the line is a procurement request line
576
cur_obj = self.pool.get('res.currency')
577
curr_browse = self.pool.get('res.users').browse(cr, uid, [uid], context)[0].company_id.currency_id
578
308
for line in self.browse(cr, uid, ids):
579
309
if line.order_id.procurement_request:
580
subtotal = line.cost_price * line.product_uom_qty
581
res[line.id] = cur_obj.round(cr, uid, curr_browse.rounding, subtotal)
583
312
new_ids.append(line.id)
585
314
res.update(super(procurement_request_line, self)._amount_line(cr, uid, new_ids, field_name, arg, context=context))
589
318
def create(self, cr, uid, vals, context=None):
591
Adds the date_planned value.
592
Check if product or comment exist and set the the fields required accordingly.
320
Adds the date_planned value
594
322
if context is None:
596
if vals.get('product_id', False):
597
vals.update({'comment_ok': True})
598
if vals.get('comment', False):
599
vals.update({'product_ok': True})
601
325
if not 'date_planned' in vals and context.get('procurement_request'):
602
326
if 'date_planned' in context:
605
329
date_planned = self.pool.get('sale.order').browse(cr, uid, vals.get('order_id'), context=context).delivery_requested_date
606
330
vals.update({'date_planned': date_planned})
608
# Compute the rounding of the product qty
609
if vals.get('product_uom') and vals.get('product_uom_qty'):
610
vals['product_uom_qty'] = self.pool.get('product.uom')._compute_round_up_qty(cr, uid, vals.get('product_uom'), vals.get('product_uom_qty'), context=context)
612
332
return super(procurement_request_line, self).create(cr, uid, vals, context=context)
614
def write(self, cr, uid, ids, vals, context=None):
616
Compute the UoM qty according to UoM rounding value
620
if 'product_uom_qty' in vals or 'product_uom' in vals:
621
for req in self.read(cr, uid, ids, ['product_uom_qty', 'product_uom'], context=context):
622
# Compute the rounding of the product qty
623
uom_id = vals.get('product_uom', req['product_uom'][0])
624
uom_qty = vals.get('product_uom_qty', req['product_uom_qty'])
625
vals['product_uom_qty'] = self.pool.get('product.uom')._compute_round_up_qty(cr, uid, uom_id, uom_qty, context=context)
626
res = res and super(procurement_request_line, self).write(cr, uid, [req['id']], vals, context=context)
628
res = res and super(procurement_request_line, self).write(cr, uid, ids, vals, context=context)
632
334
def _get_fake_state(self, cr, uid, ids, field_name, args, context=None):
633
335
if isinstance(ids, (int, long)):
636
338
for pol in self.read(cr, uid, ids, ['state']):
637
339
ret[pol['id']] = pol['state']
640
def _get_product_id_ok(self, cr, uid, ids, field_name, args, context=None):
641
if isinstance(ids, (int, long)):
644
for pol in self.read(cr, uid, ids, ['product_id']):
645
if pol['product_id']:
646
res[pol['id']] = True
648
res[pol['id']] = False
652
'cost_price': fields.float(string='Cost price'),
653
343
'procurement_request': fields.boolean(string='Internal Request', readonly=True),
654
344
'latest': fields.char(size=64, string='Latest documents', readonly=True),
655
'price_subtotal': fields.function(_amount_line, method=True, string='Subtotal', digits_compute=dp.get_precision('Sale Price')),
656
'my_company_id': fields.many2one('res.company', 'Company', select=1),
345
'price_subtotal': fields.function(_amount_line, method=True, string='Subtotal', digits_compute= dp.get_precision('Sale Price')),
346
'my_company_id': fields.many2one('res.company','Company',select=1),
657
347
'supplier': fields.many2one('res.partner', 'Supplier', domain="[('id', '!=', my_company_id)]"),
658
348
# openerp bug: eval invisible in p.o use the po line state and not the po state !
659
349
'fake_state': fields.function(_get_fake_state, type='char', method=True, string='State', help='for internal use only'),
660
'product_id_ok': fields.function(_get_product_id_ok, type="boolean", method=True, string='Product defined?', help='for if true the button "configurator" is hidden'),
661
'product_ok': fields.boolean('Product selected'),
662
'comment_ok': fields.boolean('Comment written'),
665
352
def _get_planned_date(self, cr, uid, c=None):
674
361
'procurement_request': lambda self, cr, uid, c: c.get('procurement_request', False),
675
362
'date_planned': _get_planned_date,
676
363
'my_company_id': lambda obj, cr, uid, context: obj.pool.get('res.users').browse(cr, uid, uid, context=context).company_id.id,
681
def update_supplier_on_line(self, cr, uid, ids, context=None):
685
def requested_product_id_change(self, cr, uid, ids, product_id, comment=False, context=None):
366
def requested_product_id_change(self, cr, uid, ids, product_id, type, context=None):
687
Fills automatically the product_uom_id field and the name on the line when the
689
Add a domain on the product_uom when a product is selected.
368
Fills automatically the product_uom_id field on the line when the
691
371
if context is None:
693
373
product_obj = self.pool.get('product.product')
694
uom_obj = self.pool.get('product.uom')
698
376
if not product_id:
699
value = {'product_uom': False, 'supplier': False, 'name': '', 'type':'make_to_order', 'comment_ok': False, 'cost_price': False, 'price_subtotal': False, 'product_uom_qty': 0.00, 'product_uos_qty': 0.00}
700
domain = {'product_uom':[], 'supplier': [('partner_type', 'in', ['internal', 'section', 'intermission'])]}
702
product = product_obj.browse(cr, uid, product_id)
703
# Test the compatibility of the product with a consumption report
704
res, test = product_obj._on_change_restriction_error(cr, uid, product_id, field_name='product_id', values={'value': value}, vals={'constraints': 'consumption'}, context=context)
707
value = {'product_uom': product.uom_id.id, 'name': '[%s] %s' % (product.default_code, product.name),
708
'type': product.procure_method, 'comment_ok': True, 'cost_price': product.standard_price, }
709
if value['type'] != 'make_to_stock':
710
value.update({'supplier': product.seller_ids and product.seller_ids[0].name.id})
711
uom_val = uom_obj.read(cr, uid, [product.uom_id.id], ['category_id'])
712
domain = {'product_uom':[('category_id', '=', uom_val[0]['category_id'][0])]}
713
return {'value': value, 'domain': domain}
716
def requested_type_change(self, cr, uid, ids, product_id, type, context=None):
718
If there is a product, we check its type (procure_method) and update eventually the supplier.
724
product_obj = self.pool.get('product.product')
725
if product_id and type != 'make_to_stock':
726
product = product_obj.browse(cr, uid, product_id, context=context)
727
v.update({'supplier': product.seller_ids and product.seller_ids[0].name.id})
728
elif product_id and type == 'make_to_stock':
729
v.update({'supplier': False})
730
product = product_obj.browse(cr, uid, product_id, context=context)
731
if product.type in ('consu', 'service', 'service_recep'):
732
v.update({'type': 'make_to_order'})
733
m.update({'title': _('Warning'),
734
'message': _('You can\'t source a line \'from stock\' if line contains a non-stockable or service product.')})
735
return {'value': v, 'warning': m}
737
def comment_change(self, cr, uid, ids, comment, product_id, nomen_manda_0, context=None):
739
Fill the level of nomenclatures with tag "to be defined" if you have only comment
743
value = {'comment': comment}
745
obj_data = self.pool.get('ir.model.data')
746
tbd_0 = obj_data.get_object_reference(cr, uid, 'msf_doc_import', 'nomen_tbd0')[1]
747
tbd_1 = obj_data.get_object_reference(cr, uid, 'msf_doc_import', 'nomen_tbd1')[1]
748
tbd_2 = obj_data.get_object_reference(cr, uid, 'msf_doc_import', 'nomen_tbd2')[1]
750
if comment and not product_id:
751
value.update({'name': 'To be defined',
754
# it bugs with the To Be Defined => needs to be removed
755
# if not nomen_manda_0:
756
# value.update({'nomen_manda_0': tbd_0,
757
# 'nomen_manda_1': tbd_1,
758
# 'nomen_manda_2': tbd_2,})
759
domain = {'product_uom':[], 'supplier': [('partner_type', 'in', ['internal', 'section', 'intermission'])]}
761
value.update({'product_ok': True})
762
domain = {'product_uom':[], 'supplier': []}
763
return {'value': value, 'domain': domain}
377
v.update({'product_uom': False, 'supplier': False, 'name': ''})
379
product = product_obj.browse(cr, uid, product_id, context=context)
380
v.update({'product_uom': product.uom_id.id, 'name': '[%s] %s'%(product.default_code, product.name)})
381
if type != 'make_to_stock':
382
v.update({'supplier': product.seller_ids and product.seller_ids[0].name.id})
765
386
procurement_request_line()
767
388
class purchase_order(osv.osv):
768
389
_name = 'purchase.order'
769
390
_inherit = 'purchase.order'
771
392
def _hook_action_picking_create_modify_out_source_loc_check(self, cr, uid, ids, context=None, *args, **kwargs):
773
394
Please copy this to your module's method also.
774
395
This hook belongs to the action_picking_create method from purchase>purchase.py>purchase_order class
776
397
- allow to choose whether or not the source location of the corresponding outgoing stock move should
777
398
match the destination location of incoming stock move
781
402
proc_obj = self.pool.get('procurement.order')
782
403
move_obj = self.pool.get('stock.move')
783
404
sale_line_obj = self.pool.get('sale.order.line')
784
po_line_obj = self.pool.get('purchase.order.line')
785
# If the line comes from an ISR and it's not splitted line,
786
# change the move_dest_id of this line (and their children)
787
# to match with the procurement ordre move destination
788
if order_line.move_dest_id and not order_line.is_line_split: # UTP-972: Use the boolean for split line
405
if order_line.move_dest_id:
789
406
proc_ids = proc_obj.search(cr, uid, [('move_id', '=', order_line.move_dest_id.id)], context=context)
790
407
so_line_ids = sale_line_obj.search(cr, uid, [('procurement_id', 'in', proc_ids)], context=context)
791
po_line_ids = po_line_obj.search(cr, uid, [('move_dest_id', '=', order_line.move_dest_id.id)], context=context)
792
if so_line_ids and all(not line.order_id or (line.order_id.procurement_request and line.order_id.location_requestor_id.usage != 'customer') for line in sale_line_obj.browse(cr, uid, so_line_ids, context=context)):
408
if all(not line.order_id or line.order_id.procurement_request for line in sale_line_obj.browse(cr, uid, so_line_ids, context=context)):
793
409
for proc in proc_obj.browse(cr, uid, proc_ids, context=context):
795
move_obj.write(cr, uid, [proc.move_id.id], {'state': 'draft'}, context=context)
796
move_obj.unlink(cr, uid, [proc.move_id.id], context=context)
411
move_obj.write(cr, uid, [proc.move_id.id], {'state': 'draft'}, context=context)
412
move_obj.unlink(cr, uid, [proc.move_id.id], context=context)
797
413
proc_obj.write(cr, uid, [proc.id], {'move_id': move_id}, context=context)
798
# Update the move_dest_id of all children to avoid the system to deal with a deleted stock move
799
po_line_obj.write(cr, uid, po_line_ids, {'move_dest_id': move_id}, context=context)
801
415
return super(purchase_order, self)._hook_action_picking_create_modify_out_source_loc_check(cr, uid, ids, context, *args, **kwargs)
805
419
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: