104
103
Import lines from file
107
if isinstance(ids, (int, long)):
109
110
product_obj = self.pool.get('product.product')
110
111
uom_obj = self.pool.get('product.uom')
111
112
obj_data = self.pool.get('ir.model.data')
112
113
currency_obj = self.pool.get('res.currency')
114
purchase_obj = self.pool.get('purchase.order')
115
purchase_line_obj = self.pool.get('purchase.order.line')
116
view_id = obj_data.get_object_reference(cr, uid, 'purchase', 'purchase_order_form')[1]
115
118
vals['order_line'] = []
116
msg_to_return = _("All lines successfully imported")
118
120
obj = self.browse(cr, uid, ids, context=context)[0]
119
121
if not obj.file_to_import:
120
122
raise osv.except_osv(_('Error'), _('Nothing to import.'))
122
124
fileobj = SpreadsheetXML(xmlstring=base64.decodestring(obj.file_to_import))
125
# check that the max number of lines is not excedeed
126
if check_nb_of_lines(fileobj=fileobj):
127
raise osv.except_osv(_('Warning !'), _("""You can\'t have more than %s lines in your file.""") % MAX_LINES_NB)
124
128
# iterator on rows
125
reader = fileobj.getRows()
129
rows = fileobj.getRows()
127
130
# ignore the first row
135
browse_purchase = purchase_obj.browse(cr, uid, ids, context=context)[0]
133
to_correct_ok = False
135
date_planned = obj.delivery_requested_date
136
functional_currency_id = False
139
nomen_manda_0 = obj_data.get_object_reference(cr, uid, 'msf_supply_doc_import', 'nomen_tbd0')[1]
140
nomen_manda_1 = obj_data.get_object_reference(cr, uid, 'msf_supply_doc_import', 'nomen_tbd1')[1]
141
nomen_manda_2 = obj_data.get_object_reference(cr, uid, 'msf_supply_doc_import', 'nomen_tbd2')[1]
142
nomen_manda_3 = obj_data.get_object_reference(cr, uid, 'msf_supply_doc_import', 'nomen_tbd3')[1]
147
raise osv.except_osv(_('Error'), _("""You should have exactly 8 columns in this order:
148
Product Code*, Product Description*, Quantity*, Product UoM*, Unit Price*, Delivery Requested Date*, Currency*, Comment"""))
150
product_code = row.cells[0].data
151
if not product_code :
154
error_list.append('No Product Code.')
155
comment = 'Product Code to be defined'
158
product_code = product_code.strip()
159
code_ids = product_obj.search(cr, uid, [('default_code', '=', product_code)])
163
comment = 'Code: %s'%product_code
165
default_code = code_ids[0]
167
error_list.append('The Product Code has to be a string.')
168
comment = 'Product Code to be defined'
172
p_id = row.cells[1].data
176
error_list.append('No Product Description')
177
comment = 'Product Description to be defined'
180
p_name = p_id.strip()
181
p_ids = product_obj.search(cr, uid, [('name', '=', p_name)])
185
comment = 'Description: %s' %p_name
186
error_list.append('The Product was not found in the list of the products.')
188
product_id = p_ids[0]
189
nomen_manda_0 = product_obj.browse(cr, uid, [product_id], context=context)[0].nomen_manda_0
190
nomen_manda_1 = product_obj.browse(cr, uid, [product_id], context=context)[0].nomen_manda_1
191
nomen_manda_2 = product_obj.browse(cr, uid, [product_id], context=context)[0].nomen_manda_2
192
nomen_manda_3 = product_obj.browse(cr, uid, [product_id], context=context)[0].nomen_manda_3
194
error_list.append('The Product Description has to be a string.')
195
comment = 'Product Description to be defined'
199
if not row.cells[2].data :
202
error_list.append('The Product Quantity was not set, we set it to 1 by default.')
204
if row.cells[4].type in ['int', 'float']:
205
product_qty = row.cells[2].data
207
error_list.append('The Product Quantity was not a number, we set it to 1 by default.')
211
p_uom = row.cells[3].data
213
uom_id = obj_data.get_object_reference(cr, uid, 'msf_supply_doc_import','uom_tbd')[1]
215
error_list.append('No product UoM was defined.')
218
uom_name = p_uom.strip()
219
uom_ids = uom_obj.search(cr, uid, [('name', '=', uom_name)], context=context)
221
uom_id = obj_data.get_object_reference(cr, uid, 'msf_supply_doc_import','uom_tbd')[1]
223
error_list.append('The UOM was not found.')
227
error_list.append('The UOM name has to be a string.')
228
uom_id = obj_data.get_object_reference(cr, uid, 'msf_supply_doc_import','uom_tbd')[1]
231
price_unit = row.cells[4].data
234
error_list.append('The Price Unit was not set, we set it to 1 by default.')
237
if row.cells[4].type in ['int', 'float']:
238
price_unit = row.cells[4].data
240
error_list.append('The Price Unit was not a number, we set it to 1 by default.')
244
if row.cells[5].data:
245
if row.cells[5].type == 'datetime':
246
date_planned = row.cells[5].data
248
error_list.append('The date format was not good so we took the date from the parent.')
251
error_list.append('The date was not specified or so we took the one from the parent.')
254
curr = row.cells[6].data
257
error_list.append('No currency was defined.')
260
curr_name = curr.strip()
261
currency_ids = currency_obj.search(cr, uid, [('name', '=', curr_name)])
263
functional_currency_id = curr
265
error_list.append('The currency was not found or the format of the currency was not good.')
267
error_list.append('The Currency name should be a string.')
270
proc_type = 'make_to_stock'
271
for product in product_obj.read(cr, uid, ids, ['type'], context=context):
272
if product['type'] == 'service_recep':
273
proc_type = 'make_to_order'
276
'to_correct_ok': to_correct_ok, # the lines with to_correct_ok=True will be red
278
'nomen_manda_0': nomen_manda_0,
279
'nomen_manda_1': nomen_manda_1,
280
'nomen_manda_2': nomen_manda_2,
281
'nomen_manda_3': nomen_manda_3,
140
'to_correct_ok': False,
141
'show_msg_ok': False,
143
'date_planned': obj.delivery_requested_date,
144
'functional_currency_id': browse_purchase.pricelist_id.currency_id.id,
145
'price_unit': 1, # as the price unit cannot be null, it will be computed in the method "compute_price_unit" after.
147
'nomen_manda_0': obj_data.get_object_reference(cr, uid, 'msf_supply_doc_import', 'nomen_tbd0')[1],
148
'nomen_manda_1': obj_data.get_object_reference(cr, uid, 'msf_supply_doc_import', 'nomen_tbd1')[1],
149
'nomen_manda_2': obj_data.get_object_reference(cr, uid, 'msf_supply_doc_import', 'nomen_tbd2')[1],
150
'nomen_manda_3': obj_data.get_object_reference(cr, uid, 'msf_supply_doc_import', 'nomen_tbd3')[1],
151
'proc_type': 'make_to_order',
152
'default_code': False,
282
153
'confirmed_delivery_date': False,
284
'default_code': default_code,
285
'product_id': product_id,
286
'product_uom': uom_id,
287
'product_qty': product_qty,
288
'price_unit': price_unit,
289
'date_planned': date_planned,
290
'functional_currency_id': functional_currency_id,
292
'text_error': '\n'.join(error_list),
295
vals['order_line'].append((0, 0, to_write))
159
raise osv.except_osv(_('Warning !'), _("""You should have exactly 8 columns in this order:
160
Product Code*, Product Description*, Quantity*, Product UoM*, Unit Price*, Delivery Requested Date*, Currency*, Comment. """))
162
if not check_empty_line(row=row, col_count=col_count):
165
# Cell 0: Product Code
167
p_value = product_value(cr, uid, obj_data=obj_data, product_obj=product_obj, row=row, to_write=to_write, context=context)
168
to_write.update({'default_code': p_value['default_code'], 'product_id': p_value['default_code'],
169
'comment': p_value['comment'], 'error_list': p_value['error_list'], 'type': p_value['proc_type']})
173
qty_value = quantity_value(product_obj=product_obj, row=row, to_write=to_write, context=context)
174
to_write.update({'product_qty': qty_value['product_qty'], 'error_list': qty_value['error_list'],
175
'warning_list': qty_value['warning_list']})
179
uom_value = compute_uom_value(cr, uid, obj_data=obj_data, uom_obj=uom_obj, row=row, to_write=to_write, context=context)
180
to_write.update({'product_uom': uom_value['uom_id'], 'error_list': uom_value['error_list']})
184
price_value = compute_price_value(row=row, to_write=to_write, price='Cost Price', context=context)
185
to_write.update({'price_unit': price_value['price_unit'], 'error_list': price_value['error_list'],
186
'warning_list': price_value['warning_list']})
188
# Cell 5: Delivery Request Date
190
date_value = compute_date_value(row=row, to_write=to_write, context=context)
191
to_write.update({'date_planned': date_value['date_planned'], 'error_list': date_value['error_list']})
195
curr_value = compute_currency_value(cr, uid, cell=6, browse_purchase=browse_purchase,
196
currency_obj=currency_obj, row=row, to_write=to_write, context=context)
197
to_write.update({'functional_currency_id': curr_value['functional_currency_id'], 'warning_list': curr_value['warning_list']})
201
c_value = comment_value(row=row, cell=7, to_write=to_write, context=context)
202
to_write.update({'comment': c_value['comment'], 'warning_list': c_value['warning_list']})
204
'to_correct_ok': [True for x in to_write['error_list']], # the lines with to_correct_ok=True will be red
205
'show_msg_ok': [True for x in to_write['warning_list']], # the lines with show_msg_ok=True won't change color, it is just info
207
'text_error': '\n'.join(to_write['error_list'] + to_write['warning_list']),
209
# we check consistency on the model of on_change functions to call for updating values
210
purchase_line_obj.check_line_consistency(cr, uid, ids, to_write=to_write, context=context)
212
vals['order_line'].append((0, 0, to_write))
215
print "The line num %s in the Excel file got element outside the defined 8 columns" % line_num
297
217
# write order line on PO
218
context['import_in_progress'] = True
298
219
self.write(cr, uid, ids, vals, context=context)
300
view_id = obj_data.get_object_reference(cr, uid, 'purchase','purchase_order_form')[1]
302
for line in obj.order_line:
303
if line.to_correct_ok:
304
msg_to_return = _("The import of lines had errors, please correct the red lines below")
306
return self.log(cr, uid, obj.id, msg_to_return, context={'view_id': view_id,})
220
msg_to_return = get_log_message(to_write=to_write, obj=obj)
222
self.log(cr, uid, obj.id, _(msg_to_return), context={'view_id': view_id})
308
225
def check_lines_to_fix(self, cr, uid, ids, context=None):
310
227
Check both the lines that need to be corrected and also that the supplier or the address is not 'To be defined'
344
261
_description = 'Purchase Order Line'
346
263
'to_correct_ok': fields.boolean('To correct'),
264
'show_msg_ok': fields.boolean('Info on importation of lines'),
347
265
'text_error': fields.text('Errors when trying to import file'),
268
def check_line_consistency(self, cr, uid, ids, *args, **kwargs):
270
After having taken the value in the to_write variable we are going to check them.
271
This function routes the value to check in dedicated methods (one for checking UoM, an other for Price Unit...).
273
context = kwargs['context']
276
if isinstance(ids, (int, long)):
278
obj_data = self.pool.get('ir.model.data')
279
to_write = kwargs['to_write']
280
order_id = to_write['order_id']
281
text_error = to_write['text_error']
282
po_obj = self.pool.get('purchase.order')
283
po = po_obj.browse(cr, uid, order_id, context=context)
284
# on_change functions to call for updating values
285
pricelist = po.pricelist_id.id or False
286
partner_id = po.partner_id.id or False
287
date_order = po.date_order or False
288
fiscal_position = po.fiscal_position or False
289
state = po.state or False
290
product = to_write['product_id']
291
qty = to_write['product_qty']
292
price_unit = to_write['price_unit']
293
uom = to_write['product_uom']
294
if product and qty and not price_unit:
295
res = self.product_id_on_change(cr, uid, ids, pricelist, product, qty, uom,
296
partner_id, date_order, fiscal_position, date_planned=False,
297
name=False, price_unit=price_unit, notes=False, state=state, old_price_unit=False,
298
nomen_manda_0=False, comment=False, context=context)
299
price_unit = res.get('value', {}).get('price_unit', False)
300
uom = res.get('value', {}).get('product_uom', False)
301
warning_msg = res.get('warning', {}).get('message', '')
302
text_error += '\n %s' % warning_msg
303
text_error += 'We use the price mechanism to compute the Price Unit.'
304
to_write.update({'price_unit': price_unit, 'product_uom': uom, 'text_error': text_error})
306
self.check_data_for_uom(cr, uid, ids, to_write=to_write, context=context)
308
uom = obj_data.get_object_reference(cr, uid, 'msf_supply_doc_import', 'uom_tbd')[1]
309
text_error += '\n It wasn\'t possible to update the UoM with the product\'s one because the former wasn\'t either defined.'
310
to_write.update({'product_uom': uom, 'text_error': text_error})
312
def check_data_for_uom(self, cr, uid, ids, *args, **kwargs):
313
context = kwargs['context']
316
if isinstance(ids, (int, long)):
318
obj_data = self.pool.get('ir.model.data')
319
# we take the values that we are going to write in PO line in "to_write"
320
to_write = kwargs['to_write']
321
text_error = to_write['text_error']
322
product_id = to_write['product_id']
323
uom_id = to_write['product_uom']
324
if uom_id and product_id:
325
product_obj = self.pool.get('product.product')
326
uom_obj = self.pool.get('product.uom')
327
product = product_obj.browse(cr, uid, product_id, context=context)
328
uom = uom_obj.browse(cr, uid, uom_id, context=context)
329
if product.uom_id.category_id.id != uom.category_id.id:
330
# this is inspired by onchange_uom in specific_rules>specific_rules.py
331
text_error += """\n You have to select a product UOM in the same category than the UOM of the product.
332
The category of the UoM of the product is '%s' whereas the category of the UoM you have chosen is '%s'.
333
""" % (product.uom_id.category_id.name, uom.category_id.name)
334
return to_write.update({'text_error': text_error,
335
'to_correct_ok': True})
336
elif not uom_id or uom_id == obj_data.get_object_reference(cr, uid, 'msf_supply_doc_import', 'uom_tbd')[1] and product_id:
337
# we take the default uom of the product
338
product_uom = product.uom_id.id
339
return to_write.update({'product_uom': product_uom})
340
elif not uom_id or uom_id == obj_data.get_object_reference(cr, uid, 'msf_supply_doc_import', 'uom_tbd')[1]:
341
# this is inspired by the on_change in purchase>purchase.py: product_uom_change
342
text_error += "\n The UoM was not defined so we set the price unit to 0.0."
343
return to_write.update({'text_error': text_error,
344
'to_correct_ok': True,
345
'price_unit': 0.0, })
350
347
def write(self, cr, uid, ids, vals, context=None):
351
348
if isinstance(ids, (int, long)):
353
uom_obj = self.pool.get('product.uom')
354
352
obj_data = self.pool.get('ir.model.data')
355
tbd_uom = obj_data.get_object_reference(cr, uid, 'msf_supply_doc_import','uom_tbd')[1]
353
tbd_uom = obj_data.get_object_reference(cr, uid, 'msf_supply_doc_import', 'uom_tbd')[1]
358
if vals.get('product_uom'):
359
if vals.get('product_uom') == tbd_uom:
360
message += 'You have to define a valid UOM, i.e. not "To be define".'
361
if vals.get('nomen_manda_0'):
362
if vals.get('nomen_manda_0') == obj_data.get_object_reference(cr, uid, 'msf_supply_doc_import', 'nomen_tbd0')[1]:
363
message += 'You have to define a valid Main Type (in tab "Nomenclature Selection"), i.e. not "To be define".'
364
if vals.get('nomen_manda_1'):
365
if vals.get('nomen_manda_1') == obj_data.get_object_reference(cr, uid, 'msf_supply_doc_import', 'nomen_tbd1')[1]:
366
message += 'You have to define a valid Group (in tab "Nomenclature Selection"), i.e. not "To be define".'
367
if vals.get('nomen_manda_2'):
368
if vals.get('nomen_manda_2') == obj_data.get_object_reference(cr, uid, 'msf_supply_doc_import', 'nomen_tbd2')[1]:
369
message += 'You have to define a valid Family (in tab "Nomenclature Selection"), i.e. not "To be define".'
370
# the 3rd level is not mandatory
372
raise osv.except_osv(_('Warning !'), _(message))
374
vals['to_correct_ok'] = False
375
vals['text_error'] = False
355
if not context.get('import_in_progress') and not context.get('button'):
356
if vals.get('product_uom'):
357
if vals.get('product_uom') == tbd_uom:
358
message += 'You have to define a valid UOM, i.e. not "To be define".'
359
if vals.get('nomen_manda_0'):
360
if vals.get('nomen_manda_0') == obj_data.get_object_reference(cr, uid, 'msf_supply_doc_import', 'nomen_tbd0')[1]:
361
message += 'You have to define a valid Main Type (in tab "Nomenclature Selection"), i.e. not "To be define".'
362
if vals.get('nomen_manda_1'):
363
if vals.get('nomen_manda_1') == obj_data.get_object_reference(cr, uid, 'msf_supply_doc_import', 'nomen_tbd1')[1]:
364
message += 'You have to define a valid Group (in tab "Nomenclature Selection"), i.e. not "To be define".'
365
if vals.get('nomen_manda_2'):
366
if vals.get('nomen_manda_2') == obj_data.get_object_reference(cr, uid, 'msf_supply_doc_import', 'nomen_tbd2')[1]:
367
message += 'You have to define a valid Family (in tab "Nomenclature Selection"), i.e. not "To be define".'
368
# the 3rd level is not mandatory
370
raise osv.except_osv(_('Warning !'), _(message))
372
vals['show_msg_ok'] = False
373
vals['to_correct_ok'] = False
374
vals['text_error'] = False
377
376
return super(purchase_order_line, self).write(cr, uid, ids, vals, context=context)
379
378
purchase_order_line()