[IMP]Implement show required field.
[odoo/odoo.git] / addons / base_export / controllers / main.py
1 from base.controllers.main import View
2 import openerpweb
3 import StringIO
4 import csv
5 import xml.dom.minidom
6
7 def node_attributes(node):
8     attrs = node.attributes
9
10     if not attrs:
11         return {}
12     # localName can be a unicode string, we're using attribute names as
13     # **kwargs keys and python-level kwargs don't take unicode keys kindly
14     # (they blow up) so we need to ensure all keys are ``str``
15     return dict([(str(attrs.item(i).localName), attrs.item(i).nodeValue)
16                  for i in range(attrs.length)])
17
18 def _fields_get_all(req, model, views, context=None):
19
20     if context is None:
21         context = {}
22
23     def parse(root, fields):
24         for node in root.childNodes:
25             if node.nodeName in ('form', 'notebook', 'page', 'group', 'tree', 'hpaned', 'vpaned'):
26                 parse(node, fields)
27             elif node.nodeName=='field':
28                 attrs = node_attributes(node)
29                 name = attrs['name']
30                 fields[name].update(attrs)
31         return fields
32
33     def get_view_fields(view):
34         return parse(
35             xml.dom.minidom.parseString(view['arch'].encode('utf-8')).documentElement,
36             view['fields'])
37
38     model_obj = req.session.model(model)
39     tree_view = model_obj.fields_view_get(views.get('tree', False), 'tree', context)
40     form_view = model_obj.fields_view_get(views.get('form', False), 'form', context)
41     fields = {}
42     fields.update(get_view_fields(tree_view))
43     fields.update(get_view_fields(form_view))
44     return fields
45
46
47 class Export(View):
48     _cp_path = "/base_export/export"
49
50     def fields_get(self, req, model):
51         Model = req.session.model(model)
52         fields = Model.fields_get(False, req.session.eval_context(req.context))
53         return fields
54
55     @openerpweb.jsonrequest
56     def get_fields(self, req, model, prefix='', name= '', field_parent=None, params={}):
57         import_compat = params.get("import_compat", False)
58         views_id = params.get("views_id", {})
59
60         fields = _fields_get_all(req, model, views=views_id, context=req.session.eval_context(req.context))
61         field_parent_type = params.get("parent_field_type",False)
62
63         if import_compat and field_parent_type and field_parent_type == "many2one":
64             fields = {}
65
66         fields.update({'id': {'string': 'ID'}, '.id': {'string': 'Database ID'}})
67         records = []
68         fields_order = fields.keys()
69         fields_order.sort(lambda x,y: -cmp(fields[x].get('string', ''), fields[y].get('string', '')))
70
71         for index, field in enumerate(fields_order):
72             value = fields[field]
73             record = {}
74             if import_compat and value.get('readonly', False):
75                 ok = False
76                 for sl in value.get('states', {}).values():
77                     for s in sl:
78                         ok = ok or (s==['readonly',False])
79                 if not ok: continue
80
81             id = prefix + (prefix and '/'or '') + field
82             nm = name + (name and '/' or '') + value['string']
83             record.update(id=id, string= nm, action='javascript: void(0)',
84                           target=None, icon=None, children=[], field_type=value.get('type',False), required=value.get('required', False))
85             records.append(record)
86
87             if len(nm.split('/')) < 3 and value.get('relation', False):
88                 if import_compat:
89                     ref = value.pop('relation')
90                     cfields = self.fields_get(req, ref)
91                     if (value['type'] == 'many2many'):
92                         record['children'] = []
93                         record['params'] = {'model': ref, 'prefix': id, 'name': nm}
94
95                     elif value['type'] == 'many2one':
96                         record['children'] = [id + '/id', id + '/.id']
97                         record['params'] = {'model': ref, 'prefix': id, 'name': nm}
98
99                     else:
100                         cfields_order = cfields.keys()
101                         cfields_order.sort(lambda x,y: -cmp(cfields[x].get('string', ''), cfields[y].get('string', '')))
102                         children = []
103                         for j, fld in enumerate(cfields_order):
104                             cid = id + '/' + fld
105                             cid = cid.replace(' ', '_')
106                             children.append(cid)
107                         record['children'] = children or []
108                         record['params'] = {'model': ref, 'prefix': id, 'name': nm}
109                 else:
110                     ref = value.pop('relation')
111                     cfields = self.fields_get(req, ref)
112                     cfields_order = cfields.keys()
113                     cfields_order.sort(lambda x,y: -cmp(cfields[x].get('string', ''), cfields[y].get('string', '')))
114                     children = []
115                     for j, fld in enumerate(cfields_order):
116                         cid = id + '/' + fld
117                         cid = cid.replace(' ', '_')
118                         children.append(cid)
119                     record['children'] = children or []
120                     record['params'] = {'model': ref, 'prefix': id, 'name': nm}
121
122         records.reverse()
123         return records
124
125     @openerpweb.jsonrequest
126     def save_export_lists(self, req, name, model, field_list):
127         result = {'resource':model, 'name':name, 'export_fields': []}
128         for field in field_list:
129             result['export_fields'].append((0, 0, {'name': field}))
130         return req.session.model("ir.exports").create(result, req.session.eval_context(req.context))
131
132     @openerpweb.jsonrequest
133     def exist_export_lists(self, req, model):
134         export_model = req.session.model("ir.exports")
135         return export_model.read(export_model.search([('resource', '=', model)]), ['name'])
136
137     @openerpweb.jsonrequest
138     def delete_export(self, req, export_id):
139         req.session.model("ir.exports").unlink(export_id, req.session.eval_context(req.context))
140         return True
141
142     @openerpweb.jsonrequest
143     def namelist(self,req,  model, export_id):
144
145         result = self.get_data(req, model, req.session.eval_context(req.context))
146         ir_export_obj = req.session.model("ir.exports")
147         ir_export_line_obj = req.session.model("ir.exports.line")
148
149         field = ir_export_obj.read(export_id)
150         fields = ir_export_line_obj.read(field['export_fields'])
151
152         name_list = {}
153         [name_list.update({field['name']: result.get(field['name'])}) for field in fields]
154         return name_list
155
156     def get_data(self, req, model, context=None):
157         ids = []
158         context = context or {}
159         fields_data = {}
160         proxy = req.session.model(model)
161         fields = self.fields_get(req, model)
162         if not ids:
163             f1 = proxy.fields_view_get(False, 'tree', context)['fields']
164             f2 = proxy.fields_view_get(False, 'form', context)['fields']
165
166             fields = dict(f1)
167             fields.update(f2)
168             fields.update({'id': {'string': 'ID'}, '.id': {'string': 'Database ID'}})
169
170         def rec(fields):
171             _fields = {'id': 'ID' , '.id': 'Database ID' }
172             def model_populate(fields, prefix_node='', prefix=None, prefix_value='', level=2):
173                 fields_order = fields.keys()
174                 fields_order.sort(lambda x,y: -cmp(fields[x].get('string', ''), fields[y].get('string', '')))
175
176                 for field in fields_order:
177                     fields_data[prefix_node+field] = fields[field]
178                     if prefix_node:
179                         fields_data[prefix_node + field]['string'] = '%s%s' % (prefix_value, fields_data[prefix_node + field]['string'])
180                     st_name = fields[field]['string'] or field
181                     _fields[prefix_node+field] = st_name
182                     if fields[field].get('relation', False) and level>0:
183                         fields2 = self.fields_get(req,  fields[field]['relation'])
184                         fields2.update({'id': {'string': 'ID'}, '.id': {'string': 'Database ID'}})
185                         model_populate(fields2, prefix_node+field+'/', None, st_name+'/', level-1)
186             model_populate(fields)
187             return _fields
188         return rec(fields)
189
190     def export_csv(self, req, fields, result):
191         fp = StringIO.StringIO()
192         writer = csv.writer(fp, quoting=csv.QUOTE_ALL)
193
194         writer.writerow(fields)
195
196         for data in result:
197             row = []
198             for d in data:
199                 if isinstance(d, basestring):
200                     d = d.replace('\n',' ').replace('\t',' ')
201                     try:
202                         d = d.encode('utf-8')
203                     except:
204                         pass
205                 if d is False: d = None
206                 row.append(d)
207             writer.writerow(row)
208
209         fp.seek(0)
210         data = fp.read()
211         fp.close()
212         return data
213
214     @openerpweb.jsonrequest
215     def export_data(self, req, model, fields, ids, domain, import_compat=False, context=None):
216         context = req.session.eval_context(req.context)
217         modle_obj = req.session.model(model)
218         ids = ids or modle_obj.search(domain, context=context)
219
220         field = fields.keys()
221         result = modle_obj.export_data(ids, field , context).get('datas',[])
222
223         if not import_compat:
224             field = [val.strip() for val in fields.values()]
225         return self.export_csv(req, field, result)