summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--addons/base_import/models.py29
-rw-r--r--addons/base_import/static/src/js/import.js58
-rw-r--r--addons/base_import/static/src/xml/import.xml17
3 files changed, 89 insertions, 15 deletions
diff --git a/addons/base_import/models.py b/addons/base_import/models.py
index 560a28f9067..a464649758d 100644
--- a/addons/base_import/models.py
+++ b/addons/base_import/models.py
@@ -11,6 +11,8 @@ try:
except ImportError:
from StringIO import StringIO
+import psycopg2
+
from openerp.osv import orm, fields
from openerp.tools.translate import _
@@ -300,24 +302,39 @@ class ir_import(orm.TransientModel):
record, fields, options, context=context)
try:
+ _logger.info('importing %d rows...', len(data))
(code, record, message, _wat) = self.pool[record.res_model].import_data(
cr, uid, import_fields, data, context=context)
+ _logger.info('done')
+
except Exception, e:
+ _logger.exception("Import failed")
# TODO: remove when exceptions stop being an "expected"
- # behavior of import_data on some invalid input.
+ # behavior of import_data on some (most) invalid
+ # input.
code, record, message = -1, None, str(e)
- if dryrun:
- cr.execute('ROLLBACK TO SAVEPOINT import')
- else:
- cr.execute('RELEASE SAVEPOINT import')
+ # If transaction aborted, RELEASE SAVEPOINT is going to raise
+ # an InternalError (ROLLBACK should work, maybe). Ignore that.
+ # TODO: to handle multiple errors, create savepoint around
+ # write and release it in case of write error (after
+ # adding error to errors array) => can keep on trying to
+ # import stuff, and rollback at the end if there is any
+ # error in the results.
+ try:
+ if dryrun:
+ cr.execute('ROLLBACK TO SAVEPOINT import')
+ else:
+ cr.execute('RELEASE SAVEPOINT import')
+ except psycopg2.InternalError:
+ pass
if code != -1:
return []
# TODO: add key for error location?
# TODO: error not within normal preview, how to display? Re-preview
- # with higher count?
+ # with higher ``count``?
return [{
'type': 'error',
'message': message,
diff --git a/addons/base_import/static/src/js/import.js b/addons/base_import/static/src/js/import.js
index 559d74734e8..037a9662b02 100644
--- a/addons/base_import/static/src/js/import.js
+++ b/addons/base_import/static/src/js/import.js
@@ -1,5 +1,6 @@
openerp.base_import = function (instance) {
var QWeb = instance.web.qweb;
+ var _t = instance.web._t;
var _lt = instance.web._lt;
/**
@@ -41,7 +42,14 @@ openerp.base_import = function (instance) {
'change input.oe_import_file': 'file_update'
},
init: function (parent, dataset) {
- this._super(parent, {});
+ var self = this;
+ this._super(parent, {
+ buttons: [
+ {text: _t("Import File"), click: function () {
+ self.do_import();
+ }, 'class': 'oe_import_dialog_button'}
+ ]
+ });
this.res_model = parent.model;
// import object id
this.id = null;
@@ -57,6 +65,15 @@ openerp.base_import = function (instance) {
});
},
+ import_options: function () {
+ return {
+ // TODO: customizable gangnam style
+ quote: '"',
+ separator: ',',
+ headers: true,
+ };
+ },
+
//- File change section
file_update: function (e) {
if (!this.$('input.oe_import_file').val()) { return; }
@@ -69,22 +86,49 @@ openerp.base_import = function (instance) {
file_updated: function () {
// immediately trigger preview...
// TODO: test that write // succeeded?
- this.Import.call('parse_preview', [this.id, {
- quote: '"',
- separator: ',',
- headers: true,
- }]).then(this.proxy('preview'));
+ this.Import.call(
+ 'parse_preview', [this.id, this.import_options()])
+ .then(this.proxy('preview'));
},
preview: function (result) {
if (result.error) {
this.$element.addClass('oe_import_error');
this.$('.oe_import_error_report').html(
- QWeb.render('ImportView.error', result));
+ QWeb.render('ImportView.preview.error', result));
} else {
this.$element.addClass('oe_import_preview');
this.$('table').html(
QWeb.render('ImportView.preview', result));
}
},
+
+ //- import itself
+ do_import: function () {
+ var fields = this.$('.oe_import_fields input').map(function (index, el) {
+ return el.value || false;
+ }).get();
+ this.Import.call(
+ 'do', [this.id, fields, this.import_options()], {
+ // maybe could do a dryrun after successful
+ // preview or something (note: don't go to
+ // this.result if dryrun=true)
+ dryrun: false
+ })
+ .then(this.proxy('result'));
+ },
+ result: function (errors) {
+ if (!errors.length) {
+ if (this.getParent().reload_content) {
+ this.getParent().reload_content();
+ }
+ this.close();
+ return;
+ }
+ // import failed (or maybe just warnings, if we ever get
+ // warnings?)
+ this.$element.addClass('oe_import_error');
+ this.$('.oe_import_error_report').html(
+ QWeb.render('ImportView.error', {errors: errors}));
+ },
});
};
diff --git a/addons/base_import/static/src/xml/import.xml b/addons/base_import/static/src/xml/import.xml
index 7cf04c55292..483c9a4a3cb 100644
--- a/addons/base_import/static/src/xml/import.xml
+++ b/addons/base_import/static/src/xml/import.xml
@@ -7,9 +7,9 @@
<label for="csvfile">CSV File:</label>
<input type="file" id="csvfile" name="file" class="oe_import_file"/>
+ <div class="oe_import_error_report"></div>
<table class="oe_import_grid" width="100%">
</table>
- <div class="oe_import_error_report"></div>
</form>
</t>
<!-- TODO: column matcher? -->
@@ -18,14 +18,27 @@
<td t-foreach="headers" t-as="header" class="oe_import_grid-cell"
><t t-esc="header"/></td>
</tr>
+ <tr class="oe_import_fields">
+ <!-- Iterate on first row to ensure we have all columns -->
+ <td t-foreach="preview[0]" t-as="column">
+ <input placeholder="Don't Import"/>
+ </td>
+ </tr>
<tr t-foreach="preview" t-as="row" class="oe_import_grid-row">
<td t-foreach="row" t-as="cell" class="oe_import_grid-cell"
><t t-esc="cell"/></td>
</tr>
</t>
- <t t-name="ImportView.error">
+ <t t-name="ImportView.preview.error">
<p>Import preview failed due to: <t t-esc="error"/></p>
<p>Here is the start of the file we could not import:</p>
<pre><t t-esc="preview"/></pre>
</t>
+ <ul t-name="ImportView.error">
+ <li t-foreach="errors" t-as="error" t-attf-class="oe_import_report_#{error.type}">
+ <!-- can also have error.record, but may be *huge* if
+ e.g. has image fields -->
+ <t t-esc="error.message"/>
+ </li>
+ </ul>
</templates>