diff --git a/addons/base/__openerp__.py b/addons/base/__openerp__.py index a983a4227ce..b4ff7052242 100644 --- a/addons/base/__openerp__.py +++ b/addons/base/__openerp__.py @@ -28,6 +28,7 @@ "static/src/js/list-editable.js", "static/src/js/search.js", "static/src/js/view_tree.js", + "static/src/js/import.js", ], 'css' : [ "static/lib/jquery.superfish/css/superfish.css", diff --git a/addons/base/controllers/main.py b/addons/base/controllers/main.py index 628a086e3d6..16b4613df5e 100644 --- a/addons/base/controllers/main.py +++ b/addons/base/controllers/main.py @@ -10,7 +10,7 @@ import openerpweb.ast import openerpweb.nonliterals import cherrypy - +import csv # Should move to openerpweb.Xml2Json class Xml2Json: # xml2json-direct @@ -119,8 +119,8 @@ class WebClient(openerpweb.Controller): %s @@ -222,7 +222,7 @@ class Session(openerpweb.Controller): context, domain = eval_context_and_domain(req.session, openerpweb.nonliterals.CompoundContext(*(contexts or [])), openerpweb.nonliterals.CompoundDomain(*(domains or []))) - + group_by_sequence = [] for candidate in (group_by_seq or []): ctx = req.session.eval_context(candidate, context) @@ -233,7 +233,7 @@ class Session(openerpweb.Controller): group_by_sequence.append(group_by) else: group_by_sequence.extend(group_by) - + return { 'context': context, 'domain': domain, @@ -246,7 +246,7 @@ class Session(openerpweb.Controller): This method store an action object in the session object and returns an integer identifying that action. The method get_session_action() can be used to get back the action. - + :param the_action: The action to save in the session. :type the_action: anything :return: A key identifying the saved action. @@ -269,7 +269,7 @@ class Session(openerpweb.Controller): """ Gets back a previously saved action. This method can return None if the action was saved since too much time (this case should be handled in a smart way). - + :param key: The key given by save_session_action() :type key: integer :return: The saved action or None. @@ -404,7 +404,7 @@ class Menu(openerpweb.Controller): menu_items = Menus.read(menu_ids, ['name', 'sequence', 'parent_id'], context) menu_root = {'id': False, 'name': 'root', 'parent_id': [-1, '']} menu_items.append(menu_root) - + # make a tree using parent_id menu_items_map = dict((menu_item["id"], menu_item) for menu_item in menu_items) for menu_item in menu_items: @@ -511,7 +511,7 @@ class DataSet(openerpweb.Controller): record_map = dict((record['id'], record) for record in records) return [record_map[id] for id in ids if record_map.get(id)] - + @openerpweb.jsonrequest def load(self, req, model, id, fields): m = req.session.model(model) @@ -674,7 +674,7 @@ class View(openerpweb.Controller): except ValueError: # not a literal return openerpweb.nonliterals.Domain(session, domain) - + def parse_context(self, context, session): """ Parses an arbitrary string containing a context, transforms it to either a literal context or a :class:`openerpweb.nonliterals.Context` @@ -764,7 +764,7 @@ class SearchView(View): if field.get('context'): field["context"] = self.parse_domain(field["context"], req.session) return {'fields': fields} - + @openerpweb.jsonrequest def get_filters(self, req, model): Model = req.session.model("ir.filters") @@ -773,7 +773,7 @@ class SearchView(View): filter["context"] = req.session.eval_context(self.parse_context(filter["context"], req.session)) filter["domain"] = req.session.eval_domain(self.parse_domain(filter["domain"], req.session)) return filters - + @openerpweb.jsonrequest def save_filter(self, req, model, name, context_to_save, domain): Model = req.session.model("ir.filters") @@ -903,4 +903,64 @@ class Action(openerpweb.Controller): return clean_action(req.session.model('ir.actions.server').run( [action_id], req.session.eval_context(req.context)), req.session) -# +class Import(View): + _cp_path = "/base/import" + + @openerpweb.httprequest + def import_data(self, req, session_id, callback, model, id, csvfile, csvsep, csvdel, csvcode, csvskip, fields=[]): + import StringIO + context = req.session.eval_context(req.context) + modle_obj = req.session.model(model) + + res = None + content = csvfile.file.read() + print "\n content++++++++++++++++++++++++++++",content + input=StringIO.StringIO(content) + limit = 0 + data = [] + + if not (csvdel and len(csvdel) == 1): + return "The CSV delimiter must be a single character" + + try: + for j, line in enumerate(csv.reader(input, quotechar=str(csvdel), delimiter=str(csvsep))): + # If the line contains no data, we should skip it. + if not line: + continue + if j == limit: + fields = line + else: + data.append(line) + except: + return "CSV Error" + + datas = [] + ctx = context + + if not isinstance(fields, list): + fields = [fields] + + for line in data: + try: + datas.append(map(lambda x:x.decode(csvcode).encode('utf-8'), line)) + except: + datas.append(map(lambda x:x.decode('latin').encode('utf-8'), line)) + + # If the file contains nothing, + if not datas: + return "The file is empty." + + #Inverting the header into column names + try: + res = modle_obj.import_data(fields, datas, 'init', '', False, ctx) + except: + return "Error in Importing Data." + + if res[0]>=0: + return "Successfully Imported %d objects." % (res[0],) + + d = '' + for key,val in res[1].items(): + d+= ('%s: %s' % (key,val)) + + return "Error trying to import this record :%s. ErrorMessage:%s %s" % (d,res[2],res[3]) diff --git a/addons/base/static/src/js/base.js b/addons/base/static/src/js/base.js index 28022f8b764..d5f23209723 100644 --- a/addons/base/static/src/js/base.js +++ b/addons/base/static/src/js/base.js @@ -87,6 +87,9 @@ openerp.base = function(instance) { if (openerp.base.view_tree) { openerp.base.view_tree(instance); } + if (openerp.base.import){ + openerp.base.import(instance); + } }; // vim:et fdc=0 fdl=0 foldnestmax=3 fdm=syntax: diff --git a/addons/base/static/src/js/import.js b/addons/base/static/src/js/import.js new file mode 100644 index 00000000000..5b6affe27c7 --- /dev/null +++ b/addons/base/static/src/js/import.js @@ -0,0 +1,35 @@ +openerp.base.import = function(openerp) { +openerp.base.Import = openerp.base.Dialog.extend({ + init: function(parent, dataset, views){ + this._super(parent); + this.dataset = dataset; + this.views = views; + this.views_id = {}; + for (var key in this.views) { + this.views_id[key] = this.views[key].view_id + } + }, + start: function() { + var self = this + self._super(false); + self.template = 'ImportDataView'; + self.dialog_title = "Import Data" + self.open({ + modal: true, + width: '70%', + height: 'auto', + position: 'top', + buttons : { + "Close" : function() { + self.stop(); + }, + "Import File" : function() { + $("#import_data").submit(); + //self.do_import(); + } + }, + close: function(event, ui){ self.close();} + }); + }, +}); +} \ No newline at end of file diff --git a/addons/base/static/src/js/views.js b/addons/base/static/src/js/views.js index b98b0bc637f..1d44fb3a0c0 100644 --- a/addons/base/static/src/js/views.js +++ b/addons/base/static/src/js/views.js @@ -212,11 +212,24 @@ openerp.base.ViewManager = openerp.base.Controller.extend({ } } } + if(this.flags && this.flags.sidebar) { + if(this.$element.find('#importview')){ + this.$element.find('#importview').remove() + } + if(this.active_view == 'list' || this.active_view == 'form') { + this.views[this.active_view].controller.$element.after(QWeb.render('ImportView')) + this.$element.find('#importview').click(function(ev) { + var import_view = new openerp.base.Import(self, self.dataset, self.views); + import_view.start(false); + ev.preventDefault(); + }); + } + } return view_promise; }, /** * Event launched when a controller has been inited. - * + * * @param {String} view_type type of view * @param {String} view the inited controller */ @@ -522,7 +535,7 @@ openerp.base.View = openerp.base.Controller.extend({ * Directly set a view to use instead of calling fields_view_get. This method must * be called before start(). When an embedded view is set, underlying implementations * of openerp.base.View must use the provided view instead of any other one. - * + * * @param embedded_view A view. */ set_embedded_view: function(embedded_view) { diff --git a/addons/base/static/src/xml/base.xml b/addons/base/static/src/xml/base.xml index 10d1539cde1..f7c2cf53054 100644 --- a/addons/base/static/src/xml/base.xml +++ b/addons/base/static/src/xml/base.xml @@ -103,7 +103,7 @@

We think that daily job activities can be more intuitive, efficient, automated, .. and even fun.

OpenERP's vision to be:

- + @@ -135,7 +135,7 @@
- +
@@ -333,7 +333,7 @@ t-att-data-index="row_index"> - + @@ -821,7 +821,7 @@ -
@@ -944,4 +944,87 @@ .unwrap();
+ + Import + + +
+ + + + + + + + + + + + + + + + + +
+ + + + + + + +
+

1. Import a .CSV file

+
+ Select a .CSV file to import. If you need a sample of file to import, + you should use the export tool with the "Import Compatible" option. +
+
+ + + + + +
+ +
+
+
+
+ + + + +
+

2. Check your file format

+
+ +
+
+ CSV Options + + + + + + + + + + + + + +
+ +
+
+
+
+
+