class Import(View):
_cp_path = "/base/import"
+ def fields_get(self, req, model):
+ Model = req.session.model(model)
+ fields = Model.fields_get(False, req.session.eval_context(req.context))
+ return fields
+
+ @openerpweb.httprequest
+ def detect_data(self, req, session_id, model, id, csvfile, csvsep, csvdel, csvcode, csvskip):
+ import StringIO
+ _fields = {}
+ _fields_invert = {}
+ error = None
+
+ fields = dict(req.session.model(model).fields_get(False, req.session.eval_context(req.context)))
+ fields.update({'id': {'string': 'ID'}, '.id': {'string': 'Database ID'}})
+
+ def model_populate(fields, prefix_node='', prefix=None, prefix_value='', level=2):
+ def str_comp(x,y):
+ if x<y: return 1
+ elif x>y: return -1
+ else: return 0
+
+ fields_order = fields.keys()
+ fields_order.sort(lambda x,y: str_comp(fields[x].get('string', ''), fields[y].get('string', '')))
+ for field in fields_order:
+ if (fields[field].get('type','') not in ('reference',))\
+ and (not fields[field].get('readonly')\
+ or not dict(fields[field].get('states', {}).get(
+ 'draft', [('readonly', True)])).get('readonly',True)):
+
+ st_name = prefix_value+fields[field]['string'] or field
+ _fields[prefix_node+field] = st_name
+ _fields_invert[st_name] = prefix_node+field
+
+ if fields[field].get('type','')=='one2many' and level>0:
+ fields2 = self.fields_get(req, fields[field]['relation'])
+ model_populate(fields2, prefix_node+field+'/', None, st_name+'/', level-1)
+
+ if fields[field].get('relation',False) and level>0:
+ model_populate({'/id': {'type': 'char', 'string': 'ID'}, '.id': {'type': 'char', 'string': 'Database ID'}},
+ prefix_node+field, None, st_name+'/', level-1)
+ fields.update({'id':{'string':'ID'},'.id':{'string':'Database ID'}})
+ model_populate(fields)
+
+ try:
+ data = csv.reader(csvfile.file, quotechar=str(csvdel), delimiter=str(csvsep))
+ except:
+ raise 'Error opening .CSV file', 'Input Error.'
+
+ records = []
+ fields = []
+ word=''
+ limit = 3
+
+ try:
+ for i, row in enumerate(data):
+ records.append(row)
+ if i == limit:
+ break
+ for line in records:
+ for word in line:
+ word = str(word.decode(csvcode))
+ if word in _fields:
+ fields.append((word, _fields[word]))
+ elif word in _fields_invert.keys():
+ fields.append((_fields_invert[word], word))
+ else:
+ error = {'message':("You cannot import the field '%s', because we cannot auto-detect it" % (word,))}
+ break
+ except:
+ error = {'message':('Error processing the first line of the file. Field "%s" is unknown') % (word,)}
+
+ if error:
+ csvfile.file.seek(0)
+ error=dict(error, preview=csvfile.file.read(200))
+ return simplejson.dumps({'error':error})
+
+ return simplejson.dumps({'records':records})
+
@openerpweb.httprequest
- def import_data(self, req, session_id, callback, model, id, csvfile, csvsep, csvdel, csvcode, csvskip, fields=[]):
+ def import_data(self, req, session_id, model, id, csvfile, csvsep, csvdel, csvcode, csvskip, fields=[]):
import StringIO
context = req.session.eval_context(req.context)
data = []
if not (csvdel and len(csvdel) == 1):
- return "The CSV delimiter must be a single character"
+ error={'message': "The CSV delimiter must be a single character"}
+ return simplejson.dumps({'error':error})
try:
for j, line in enumerate(csv.reader(input, quotechar=str(csvdel), delimiter=str(csvsep))):
fields = line
else:
data.append(line)
- except:
- return "CSV Error"
+ except csv.Error, e:
+ error={'message': str(e),'title': 'File Format Error'}
+ return simplejson.dumps({'error':error})
datas = []
ctx = context
# If the file contains nothing,
if not datas:
- return "The file is empty."
+ error = {'message': 'The file is empty !', 'title': 'Importation !'}
+ return simplejson.dumps({'error':error})
#Inverting the header into column names
try:
res = modle_obj.import_data(fields, datas, 'init', '', False, ctx)
- except:
- return "Error in Importing Data."
+ except Exception, e:
+ error = {'message':str(e), 'title':'XML-RPC error'}
+ return simplejson.dumps({'error':error})
if res[0]>=0:
- return "Successfully Imported %d objects." % (res[0],)
+ success={'message':'Imported %d objects' % (res[0],)}
+ return simplejson.dumps({'success':success})
d = ''
for key,val in res[1].items():
- d+= ('%s: %s' % (key,val))
+ d+= ('%s: %s' % (str(key),str(val)))
+ msg = 'Error trying to import this record:%s. ErrorMessage:%s %s' % (d,res[2],res[3])
+ error = {'message':str(msg), 'title':'ImportationError'}
- return "Error trying to import this record :%s. ErrorMessage:%s %s" % (d,res[2],res[3])
+ return simplejson.dumps({'error':error})
self.stop();
},
"Import File" : function() {
- $("#import_data").submit();
- //self.do_import();
+ //$("#import_data").submit();
+ self.do_import();
}
},
close: function(event, ui){ self.stop();}
});
+ this.$element.find('#csvfile').change(this.on_autodetect_data);
+ this.$element.find('fieldset legend').click(function () {
+ $(this).next().toggle();
+ });
+ },
+ do_import: function() {
+ var self = this;
+ if(!this.$element.find('#csvfile').val()) { return; }
+ this.$element.find('#import_data').attr({
+ 'action': '/base/import/import_data'
+ }).ajaxSubmit({
+ success: this.import_results
+ });
+ },
+ on_autodetect_data: function() {
+ var self = this;
+ if(this.$element.find("#res td")){
+ this.$element.find("#res td").remove();
+ this.$element.find("#imported_success").css('display','none');
+ }
+ if(!this.$element.find('#csvfile').val()) { return; }
+ this.$element.find('#import_data').attr({
+ 'action': '/base/import/detect_data'
+ }).ajaxSubmit({
+ success: this.import_results
+ });
+ },
+ import_results:function(res){
+ var self = this;
+ var results = $.parseJSON(res);
+
+ if (results['records']){
+ var result = results['records'];
+ if ($('#error').find('table')){
+ $("#error table").remove();
+ }
+ if ($('#records_data').find('tr')){
+ $("#records_data tr").remove();
+ }
+ for (i in result) {
+ if (i == 0){
+ $('#records_data').append('<tr class="grid-header"></tr>');
+ for (m in result[i]){
+ $('.grid-header').append('<th class="grid-cell">'+result[i][m]+'</th>');
+ }
+ }else{
+ $('#records_data tr:last').after('<tr id='+i+' class="grid-row"></tr>');
+ for (n in result[i]){
+ $("tr[id="+i+"]").append('<td class="grid-cell">'+result[i][n]+'</td>');
+ }
+ }
+ }
+ }else if(results['error']){
+ var result = results['error'];
+ if ($('#records_data').find('tr')){
+ $("#records_data tr").remove();
+ }
+ if ($('#error').find('table')){
+ $("#error table").remove();
+ }
+ $("#error").append('<table id="error_tbl"><tr style="white-space: pre-line;">The import failed due to:'+result['message']+'</tr></table>');
+ if (result['preview']){
+ $("#error_tbl tr:last").after('<tr>Here is a preview of the file we could not import:</tr>');
+ $("#error_tbl tr:last").after('<tr><pre>'+result['preview']+'</pre></tr>');
+ }
+ }else if(results['success']){
+ var result = results['success'];
+ $("#imported_success").css('display','block');
+ $("#res").append('<td>'+result['message']+'</td>')
+ }
+ },
+ stop: function() {
+ $(this.$dialog).remove();
+ this._super();
},
});
}
\ No newline at end of file
<a id="importview" href="javascript: void(0)" style="text-decoration: none;color: #3D3D3D;">Import</a>
</t>
<t t-name="ImportDataView">
-<form name="import_data" id="import_data" action="/base/import/import_data" method="post" enctype="multipart/form-data">
+<form name="import_data" id="import_data" action="" method="post" enctype="multipart/form-data">
<input type="hidden" name="session_id" t-att-value="session.session_id"/>
- <input type="hidden" name="callback" t-attf-value="#{element_id}_iframe"/>
<input type="hidden" name="model" t-att-value="dataset.model"/>
<input type="hidden" name="id" t-att-value="dataset.id"/>
<table cellspacing="5" border="0" width="100%">
<table width="100%">
<tr>
<td width="100%" valign="middle" colspan="4">
- <h2>1. Import a .CSV file</h2>
+ <h2 class="separator horizontal">1. Import a .CSV file</h2>
</td>
</tr>
<tr>
<table width="100%">
<tr>
<td width="100%" valign="middle">
- <h2>2. Check your file format</h2>
+ <h2 class="separator horizontal">2. Check your file format</h2>
</td>
</tr>
</table>
- <table id="records_data" width="100%" style="margin: 5px 0;">
+ <div id="error">
+ </div>
+ <table id="records_data" class="grid" width="100%" style="margin: 5px 0;">
</table>
<fieldset>
<legend style="cursor:pointer;">CSV Options</legend>
- <table style="display:block">
+ <table style="display:none">
<tr>
<td class="label"><label for="csv_separator">Separator:</label></td>
<td><input type="text" name="csvsep" id="csv_separator" value=","/></td>
</div>
</td>
</tr>
+ <tr>
+ <td width="100%">
+ <div id="imported_success" style="display:none;">
+ <table width="100%">
+ <tr>
+ <td width="100%" valign="middle" colspan="4">
+ <h2 class="separator horizontal">3. File imported</h2>
+ </td>
+ </tr>
+ <tr id="res">
+ </tr>
+ </table>
+ </div>
+ </td>
+ </tr>
</table>
</form>
</t>