2011-03-02 18:56:06 +00:00
|
|
|
# -*- coding: utf-8 -*-
|
2011-03-10 15:53:45 +00:00
|
|
|
import glob, os
|
|
|
|
from xml.etree import ElementTree
|
2011-03-02 18:56:06 +00:00
|
|
|
|
2011-03-10 15:53:45 +00:00
|
|
|
import simplejson
|
2011-03-02 18:56:06 +00:00
|
|
|
|
|
|
|
import openerpweb
|
|
|
|
|
2011-03-03 14:55:52 +00:00
|
|
|
|
|
|
|
class Xml2Json:
|
|
|
|
# xml2json-direct
|
|
|
|
# Simple and straightforward XML-to-JSON converter in Python
|
|
|
|
# New BSD Licensed
|
|
|
|
#
|
|
|
|
# URL: http://code.google.com/p/xml2json-direct/
|
|
|
|
@staticmethod
|
|
|
|
def convert_to_json(s):
|
2011-03-10 15:53:45 +00:00
|
|
|
return simplejson.dumps(Xml2Json.convert_to_structure(s), sort_keys=True, indent=4)
|
2011-03-03 14:55:52 +00:00
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
def convert_to_structure(s):
|
|
|
|
root = ElementTree.fromstring(s)
|
|
|
|
return Xml2Json.convert_element(root)
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
def convert_element(el, skip_whitespaces=True):
|
|
|
|
res = {}
|
2011-03-21 08:13:31 +00:00
|
|
|
if el.tag[0] == "{":
|
|
|
|
ns, name = el.tag.rsplit("}", 1)
|
2011-03-03 14:55:52 +00:00
|
|
|
res["tag"] = name
|
|
|
|
res["namespace"] = ns[1:]
|
|
|
|
else:
|
|
|
|
res["tag"] = el.tag
|
|
|
|
res["attrs"] = {}
|
2011-03-21 08:13:31 +00:00
|
|
|
for k, v in el.items():
|
2011-03-03 14:55:52 +00:00
|
|
|
res["attrs"][k] = v
|
|
|
|
kids = []
|
|
|
|
if el.text and (not skip_whitespaces or el.text.strip() != ''):
|
|
|
|
kids.append(el.text)
|
|
|
|
for kid in el:
|
|
|
|
kids.append(Xml2Json.convert_element(kid))
|
|
|
|
if kid.tail and (not skip_whitespaces or kid.tail.strip() != ''):
|
2011-03-08 14:55:30 +00:00
|
|
|
kids.append(kid.tail)
|
2011-03-16 17:20:42 +00:00
|
|
|
res["children"] = kids
|
2011-03-03 14:55:52 +00:00
|
|
|
return res
|
|
|
|
|
2011-03-02 18:56:06 +00:00
|
|
|
#----------------------------------------------------------
|
|
|
|
# OpenERP Web base Controllers
|
|
|
|
#----------------------------------------------------------
|
|
|
|
|
2011-03-10 11:51:23 +00:00
|
|
|
class Session(openerpweb.Controller):
|
|
|
|
_cp_path = "/base/session"
|
|
|
|
|
2011-03-08 11:19:54 +00:00
|
|
|
def manifest_glob(self, modlist, key):
|
|
|
|
files = []
|
2011-03-11 13:26:22 +00:00
|
|
|
for i in modlist:
|
|
|
|
globlist = openerpweb.addons_manifest.get(i, {}).get(key, [])
|
2011-03-08 11:19:54 +00:00
|
|
|
for j in globlist:
|
2011-03-11 13:26:22 +00:00
|
|
|
for k in glob.glob(os.path.join(openerpweb.path_addons, i, j)):
|
|
|
|
files.append(k[len(openerpweb.path_addons):])
|
2011-03-08 11:19:54 +00:00
|
|
|
return files
|
|
|
|
|
|
|
|
def concat_files(self, file_list):
|
2011-03-02 18:56:06 +00:00
|
|
|
""" Concatenate file content
|
|
|
|
return (concat,timestamp)
|
|
|
|
concat: concatenation of file content
|
|
|
|
timestamp: max(os.path.getmtime of file_list)
|
|
|
|
"""
|
2011-03-07 09:26:32 +00:00
|
|
|
root = openerpweb.path_root
|
2011-03-02 18:56:06 +00:00
|
|
|
files_content = []
|
|
|
|
files_timestamp = 0
|
|
|
|
for i in file_list:
|
2011-03-21 08:13:31 +00:00
|
|
|
fname = os.path.join(root, i)
|
2011-03-02 18:56:06 +00:00
|
|
|
ftime = os.path.getmtime(fname)
|
|
|
|
if ftime > files_timestamp:
|
|
|
|
files_timestamp = ftime
|
|
|
|
files_content = open(fname).read()
|
|
|
|
files_concat = "".join(files_content)
|
|
|
|
return files_concat
|
|
|
|
|
2011-03-11 13:26:22 +00:00
|
|
|
@openerpweb.jsonrequest
|
|
|
|
def login(self, req, db, login, password):
|
2011-03-17 15:01:53 +00:00
|
|
|
req.session.login(db, login, password)
|
2011-03-17 17:14:03 +00:00
|
|
|
return {
|
2011-03-21 08:13:31 +00:00
|
|
|
"session_id": req.session_id,
|
2011-03-11 13:26:22 +00:00
|
|
|
"uid": req.session._uid,
|
|
|
|
}
|
|
|
|
|
|
|
|
@openerpweb.jsonrequest
|
|
|
|
def modules(self, req):
|
2011-03-17 14:53:21 +00:00
|
|
|
return {"modules": ["base", "base_hello", "base_calendar"]}
|
2011-03-11 13:26:22 +00:00
|
|
|
|
2011-03-10 11:51:23 +00:00
|
|
|
@openerpweb.jsonrequest
|
|
|
|
def csslist(self, req, mods='base,base_hello'):
|
|
|
|
return {'files': self.manifest_glob(mods.split(','), 'css')}
|
2011-03-08 11:19:54 +00:00
|
|
|
|
|
|
|
@openerpweb.jsonrequest
|
2011-03-10 11:51:23 +00:00
|
|
|
def jslist(self, req, mods='base,base_hello'):
|
|
|
|
return {'files': self.manifest_glob(mods.split(','), 'js')}
|
2011-03-08 11:19:54 +00:00
|
|
|
|
2011-03-10 11:51:23 +00:00
|
|
|
def css(self, req, mods='base,base_hello'):
|
2011-03-08 11:19:54 +00:00
|
|
|
files = self.manifest_glob(mods.split(','), 'css')
|
2011-03-08 14:57:54 +00:00
|
|
|
concat = self.concat_files(files)[0]
|
2011-03-02 18:56:06 +00:00
|
|
|
# TODO request set the Date of last modif and Etag
|
|
|
|
return concat
|
2011-03-21 08:13:31 +00:00
|
|
|
css.exposed = True
|
2011-03-02 18:56:06 +00:00
|
|
|
|
2011-03-10 11:51:23 +00:00
|
|
|
def js(self, req, mods='base,base_hello'):
|
2011-03-08 11:19:54 +00:00
|
|
|
files = self.manifest_glob(mods.split(','), 'js')
|
2011-03-08 14:57:54 +00:00
|
|
|
concat = self.concat_files(files)[0]
|
2011-03-02 18:56:06 +00:00
|
|
|
# TODO request set the Date of last modif and Etag
|
|
|
|
return concat
|
2011-03-21 08:13:31 +00:00
|
|
|
js.exposed = True
|
|
|
|
|
2011-03-02 18:56:06 +00:00
|
|
|
|
|
|
|
class Menu(openerpweb.Controller):
|
|
|
|
_cp_path = "/base/menu"
|
|
|
|
|
|
|
|
@openerpweb.jsonrequest
|
2011-03-21 08:13:31 +00:00
|
|
|
def load(self, req):
|
2011-03-21 10:47:35 +00:00
|
|
|
return {'data': self.do_load(req)}
|
|
|
|
|
|
|
|
def do_load(self, req):
|
|
|
|
""" Loads all menu items (all applications and their sub-menus).
|
|
|
|
|
|
|
|
:param req: A request object, with an OpenERP session attribute
|
|
|
|
:type req: < session -> OpenERPSession >
|
|
|
|
:return: the menu root
|
|
|
|
:rtype: dict('children': menu_nodes)
|
|
|
|
"""
|
2011-03-21 08:43:24 +00:00
|
|
|
Menus = req.session.model('ir.ui.menu')
|
2011-03-02 18:56:06 +00:00
|
|
|
# menus are loaded fully unlike a regular tree view, cause there are
|
|
|
|
# less than 512 items
|
2011-03-21 08:43:24 +00:00
|
|
|
menu_ids = Menus.search([])
|
|
|
|
menu_items = Menus.read(menu_ids, ['name', 'sequence', 'parent_id'])
|
2011-03-21 08:13:31 +00:00
|
|
|
menu_root = {'id': False, 'name': 'root', 'parent_id': [-1, '']}
|
2011-03-02 18:56:06 +00:00
|
|
|
menu_items.append(menu_root)
|
2011-03-21 08:43:24 +00:00
|
|
|
|
2011-03-02 18:56:06 +00:00
|
|
|
# make a tree using parent_id
|
2011-03-21 08:43:24 +00:00
|
|
|
menu_items_map = dict((menu_item["id"], menu_item) for menu_item in menu_items)
|
|
|
|
for menu_item in menu_items:
|
2011-03-21 15:40:34 +00:00
|
|
|
if menu_item['parent_id']:
|
|
|
|
parent = menu_item['parent_id'][0]
|
|
|
|
else:
|
|
|
|
parent = False
|
2011-03-21 08:43:24 +00:00
|
|
|
if parent in menu_items_map:
|
2011-03-21 10:47:35 +00:00
|
|
|
menu_items_map[parent].setdefault(
|
|
|
|
'children', []).append(menu_item)
|
2011-03-21 08:43:24 +00:00
|
|
|
|
2011-03-02 18:56:06 +00:00
|
|
|
# sort by sequence a tree using parent_id
|
2011-03-21 08:43:24 +00:00
|
|
|
for menu_item in menu_items:
|
2011-03-21 10:47:35 +00:00
|
|
|
menu_item.setdefault('children', []).sort(
|
2011-03-21 08:43:24 +00:00
|
|
|
key=lambda x:x["sequence"])
|
2011-03-14 09:38:25 +00:00
|
|
|
|
2011-03-21 10:47:35 +00:00
|
|
|
return menu_root
|
2011-03-02 18:56:06 +00:00
|
|
|
|
|
|
|
@openerpweb.jsonrequest
|
2011-03-21 08:13:31 +00:00
|
|
|
def action(self, req, menu_id):
|
2011-03-02 18:56:06 +00:00
|
|
|
m = req.session.model('ir.values')
|
|
|
|
r = m.get('action', 'tree_but_open', [('ir.ui.menu', menu_id)], False, {})
|
2011-03-21 08:13:31 +00:00
|
|
|
res = {"action": r}
|
2011-03-02 18:56:06 +00:00
|
|
|
return res
|
|
|
|
|
2011-03-21 08:13:31 +00:00
|
|
|
|
2011-03-02 18:56:06 +00:00
|
|
|
class DataSet(openerpweb.Controller):
|
|
|
|
_cp_path = "/base/dataset"
|
|
|
|
|
|
|
|
@openerpweb.jsonrequest
|
2011-03-21 08:13:31 +00:00
|
|
|
def fields(self, req, model):
|
2011-03-22 19:10:43 +00:00
|
|
|
return {'fields': req.session.model(model).fields_get()}
|
2011-03-02 18:56:06 +00:00
|
|
|
|
|
|
|
@openerpweb.jsonrequest
|
2011-03-23 08:34:41 +00:00
|
|
|
def find(self, request, model, fields=False, offset=0, limit=False,
|
|
|
|
domain=None, context=None, sort=None):
|
2011-03-23 09:08:01 +00:00
|
|
|
return self.do_find(request, model, fields, offset, limit,
|
|
|
|
domain, context, sort)
|
|
|
|
def do_find(self, request, model, fields=False, offset=0, limit=False,
|
|
|
|
domain=None, context=None, sort=None):
|
2011-03-23 12:08:06 +00:00
|
|
|
""" Performs a search() followed by a read() (if needed) using the
|
|
|
|
provided search criteria, only
|
|
|
|
"""
|
2011-03-23 08:34:41 +00:00
|
|
|
Model = request.session.model(model)
|
|
|
|
ids = Model.search(domain or [], offset or 0, limit or False,
|
|
|
|
sort or False, context or False)
|
|
|
|
if fields and fields == ['id']:
|
|
|
|
# shortcut read if we only want the ids
|
|
|
|
return map(lambda id: {'id': id}, ids)
|
|
|
|
return Model.read(ids, fields or False)
|
2011-03-02 18:56:06 +00:00
|
|
|
|
2011-03-23 12:08:06 +00:00
|
|
|
@openerpweb.jsonrequest
|
|
|
|
def get(self, request, model, ids):
|
|
|
|
self.do_get(request, model, ids)
|
|
|
|
|
|
|
|
def do_get(self, request, model, ids):
|
|
|
|
""" Fetches and returns the records of the model ``model`` whose ids
|
|
|
|
are in ``ids``.
|
|
|
|
|
|
|
|
The results are in the same order as the inputs, but elements may be
|
|
|
|
missing (if there is no record left for the id)
|
|
|
|
|
|
|
|
:param request: the JSON-RPC2 request object
|
|
|
|
:type request: openerpweb.JsonRequest
|
|
|
|
:param model: the model to read from
|
|
|
|
:type model: str
|
|
|
|
:param ids: a list of identifiers
|
|
|
|
:type ids: list
|
|
|
|
"""
|
|
|
|
Model = request.session.model(model)
|
|
|
|
records = Model.read(ids)
|
|
|
|
|
|
|
|
record_map = dict((record['id'], record) for record in records)
|
|
|
|
|
|
|
|
return [record_map[id] for id in ids if record_map.get(id)]
|
2011-03-21 08:13:31 +00:00
|
|
|
|
2011-03-17 14:06:38 +00:00
|
|
|
class DataRecord(openerpweb.Controller):
|
|
|
|
_cp_path = "/base/datarecord"
|
2011-03-21 08:13:31 +00:00
|
|
|
|
2011-03-17 14:06:38 +00:00
|
|
|
@openerpweb.jsonrequest
|
2011-03-21 08:13:31 +00:00
|
|
|
def load(self, req, model, id, fields):
|
2011-03-17 14:06:38 +00:00
|
|
|
m = req.session.model(model)
|
|
|
|
value = {}
|
|
|
|
r = m.read([id])
|
|
|
|
if r:
|
|
|
|
value = r[0]
|
|
|
|
return {'value': value}
|
|
|
|
|
2011-03-21 08:13:31 +00:00
|
|
|
|
2011-03-02 18:56:06 +00:00
|
|
|
class FormView(openerpweb.Controller):
|
|
|
|
_cp_path = "/base/formview"
|
2011-03-21 08:13:31 +00:00
|
|
|
|
2011-03-02 18:56:06 +00:00
|
|
|
@openerpweb.jsonrequest
|
2011-03-21 08:13:31 +00:00
|
|
|
def load(self, req, model, view_id):
|
2011-03-02 18:56:06 +00:00
|
|
|
m = req.session.model(model)
|
2011-03-21 08:13:31 +00:00
|
|
|
r = m.fields_view_get(view_id, 'form')
|
|
|
|
r["arch"] = Xml2Json.convert_to_structure(r["arch"])
|
|
|
|
return {'fields_view': r}
|
|
|
|
|
2011-03-02 18:56:06 +00:00
|
|
|
|
|
|
|
class ListView(openerpweb.Controller):
|
|
|
|
_cp_path = "/base/listview"
|
2011-03-21 08:13:31 +00:00
|
|
|
|
2011-03-02 18:56:06 +00:00
|
|
|
@openerpweb.jsonrequest
|
2011-03-21 08:13:31 +00:00
|
|
|
def load(self, req, model, view_id):
|
2011-03-02 18:56:06 +00:00
|
|
|
m = req.session.model(model)
|
2011-03-21 08:13:31 +00:00
|
|
|
r = m.fields_view_get(view_id, 'tree')
|
|
|
|
r["arch"] = Xml2Json.convert_to_structure(r["arch"])
|
|
|
|
return {'fields_view': r}
|
|
|
|
|
2011-03-02 18:56:06 +00:00
|
|
|
|
|
|
|
class SearchView(openerpweb.Controller):
|
|
|
|
_cp_path = "/base/searchview"
|
2011-03-21 08:13:31 +00:00
|
|
|
|
2011-03-02 18:56:06 +00:00
|
|
|
@openerpweb.jsonrequest
|
2011-03-21 08:13:31 +00:00
|
|
|
def load(self, req, model, view_id):
|
2011-03-02 18:56:06 +00:00
|
|
|
m = req.session.model(model)
|
2011-03-21 08:13:31 +00:00
|
|
|
r = m.fields_view_get(view_id, 'search')
|
|
|
|
r["arch"] = Xml2Json.convert_to_structure(r["arch"])
|
|
|
|
return {'fields_view': r}
|
|
|
|
|
2011-03-02 18:56:06 +00:00
|
|
|
|
|
|
|
class Action(openerpweb.Controller):
|
|
|
|
_cp_path = "/base/action"
|
|
|
|
|
|
|
|
@openerpweb.jsonrequest
|
2011-03-21 08:13:31 +00:00
|
|
|
def load(self, req, action_id):
|
2011-03-14 09:38:25 +00:00
|
|
|
return {}
|