Merge lp:~camptocamp/openobject-addons/extra-6.0-syleam-document_csv-improvements into lp:~syleam/openobject-addons/extra-6.0-syleam

Proposed by Guewen Baconnier @ Camptocamp
Status: Merged
Merged at revision: 96
Proposed branch: lp:~camptocamp/openobject-addons/extra-6.0-syleam-document_csv-improvements
Merge into: lp:~syleam/openobject-addons/extra-6.0-syleam
Diff against target: 870 lines (+371/-281)
14 files modified
document_csv/__openerp__.py (+2/-1)
document_csv/document.py (+82/-1)
document_csv/document_view.xml (+2/-1)
document_csv/ir_attachment.py (+11/-6)
document_csv/menu_view.xml (+1/-1)
document_csv/wizard/export_yml.py (+72/-93)
document_csv/wizard/export_yml_view.xml (+36/-0)
document_csv/wizard/import_yml.py (+101/-128)
document_csv/wizard/import_yml_view.xml (+42/-0)
document_csv/wizard/launch.py (+13/-2)
document_csv/wizard/launch_view.xml (+3/-1)
document_csv/wizard/read_csv.py (+4/-0)
document_csv/wizard/read_csv_view.xml (+2/-1)
document_csv/wizard/wizard.xml (+0/-46)
To merge this branch: bzr merge lp:~camptocamp/openobject-addons/extra-6.0-syleam-document_csv-improvements
Reviewer Review Type Date Requested Status
Sylvain Garancher (community) Approve
openerp-syleam Pending
Review via email: mp+83785@code.launchpad.net

Description of the change

Hello,

Here is some improvements for your 6.0 branch on the document_csv module.
That's thoses I've done for 6.1 and backported for the 6.0 version.

 - Ported old wizard.interface wizards to osv_memory
 - Button to generate a structure with all fields of a model
 - Choose in which translation import a file
 - use /id and /.id as specified in the import_data documentation in orm.py
 - Fixed the menu and misplaced and a cast on a variable

Do you agree to merge that ?

Thanks
Guewen

To post a comment you must log in.
101. By Yannick Vaucher @ Camptocamp

[ADD] document_csv - field auto-completion option from csv in document import list

Revision history for this message
Yannick Vaucher @ Camptocamp (yvaucher-c2c) wrote :

Hello,

I just added an option in csv import wizard to auto fill fields of the document import lines.
It also adds all fields that are mandatory to the column list.

Regards,
Yannick

102. By Guewen Baconnier @ Camptocamp <email address hidden>

[FIX] allow to get references by db id or xmlid also for sub-lines (relation and relation field selected like bom_lines/product_uom/.id when importing a mrp.bom)

103. By Guewen Baconnier @ Camptocamp <email address hidden>

[IMP] review auto-completion

Revision history for this message
Guewen Baconnier @ Camptocamp (gbaconnier-c2c) wrote :

Hello,

I just commit 2 new revisions:
 - Now the selection DB ID / ID / Search is also applied on sub items searches like bom_lines/product_uom/.id
 - Some modifications on the Yannick's autocompletion

Do you agree to merge please ?

Thanks
Guewen

104. By Guewen Baconnier @ Camptocamp <email address hidden>

[FIX] help message

Revision history for this message
Sylvain Garancher (sylvain-garancher) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'document_csv/__openerp__.py'
2--- document_csv/__openerp__.py 2011-11-11 10:21:25 +0000
3+++ document_csv/__openerp__.py 2012-01-11 07:46:28 +0000
4@@ -44,9 +44,10 @@
5 'format_data.xml',
6 'directory_data.xml',
7 'content_type_data.xml',
8- 'wizard/wizard.xml',
9 'wizard/launch_view.xml',
10 'wizard/read_csv_view.xml',
11+ 'wizard/export_yml_view.xml',
12+ 'wizard/import_yml_view.xml',
13 'document_view.xml',
14 #'export_view.xml',
15 ],
16
17=== modified file 'document_csv/document.py'
18--- document_csv/document.py 2011-11-11 10:21:25 +0000
19+++ document_csv/document.py 2012-01-11 07:46:28 +0000
20@@ -3,6 +3,8 @@
21 #
22 # document_csv module for OpenERP
23 # Copyright (C) 2009-2011 SYLEAM (<http://www.syleam.fr>) Christophe CHAUVET
24+# Copyright (C) 2011 Camptocamp (http://www.camptocamp.com)
25+# Guewen Baconnier
26 #
27 # This file is a part of document_csv
28 #
29@@ -99,7 +101,7 @@
30 'ctx': fields.char('Context', size=256, help='this part complete the original context'),
31 'disable': fields.boolean('Disable', help='Check this, if you want to disable it'),
32 'err_mail': fields.boolean('Send log by mail', help='The log file was send to all users of the groupes'),
33- 'err_reject': fields.boolean('Reject all if error', help='Reject all lines if there is an error'),
34+ 'err_reject': fields.boolean('Reject all if error', help='Reject all lines if there is an error. You need to activate this flag if you import sub-items (like a BoM and its components) in the same file.'),
35 'csv_sep': fields.char('Separator', size=1, required=True),
36 'csv_esc': fields.char('Escape', size=1),
37 'lang_id': fields.many2one('res.lang', 'Language', help='Language use in this import, to convert correctly date and float'),
38@@ -158,6 +160,85 @@
39
40 return {'warning': False}
41
42+ def _prepare_structure_line(self, cr, uid, ids, field, context=None):
43+ """
44+ Prepare vals to write in document lines.
45+ @param field: browse instance of a field
46+ @return: dict of vals to write in the document for the field
47+ """
48+ import_line_obj = self.pool.get('document.import.list.line')
49+ line_vals = {
50+ 'name': field.name,
51+ 'field_id': field.id,
52+ }
53+ onchange_res = import_line_obj.onchange_model_field(cr, uid, [], field.id, context=context)
54+ line_vals.update(onchange_res['value'])
55+ return line_vals
56+
57+ def _get_model_fields(self, cr, uid, model_id, context=None):
58+ fields_obj = self.pool.get('ir.model.fields')
59+ ctx_import = context.copy()
60+ ctx_import.update({'import': True})
61+
62+ all_field_ids = fields_obj.search(cr, uid,
63+ [('model_id', '=', model_id),
64+ ('readonly', '=', False)],
65+ context=ctx_import, order='name asc')
66+ return all_field_ids
67+
68+ def complete_structure_from_model(self, cr, uid, ids, context=None):
69+ context = context or {}
70+ if not isinstance(ids, list):
71+ ids = [ids]
72+ fields_obj = self.pool.get('ir.model.fields')
73+ for import_list in self.browse(cr, uid, ids, context=context):
74+ existing_lines = import_list.line_ids
75+ struct_fields_ids = self._get_model_fields(cr, uid, import_list.model_id.id, context)
76+ struct_fields = fields_obj.browse(cr, uid, struct_fields_ids, context)
77+
78+ existing_line_names = [f.name for f in existing_lines]
79+
80+ lines = []
81+ # filter fields that match both list
82+ # then prepare those lines to be updated
83+ fields_to_replace = [(ef, sf) for ef in existing_lines for sf in struct_fields if ef.name[:].split('/')[0].split('.')[0] == sf.name]
84+ for field in fields_to_replace:
85+ line_vals = self._prepare_structure_line(cr, uid, ids, field[1], context=context)
86+ line_vals.update({'name': field[0].name}) # ensure that we keep the csv header name
87+ lines.append((1, field[0].id, line_vals))
88+
89+ # list fields that are mandatory but not listed in the csv file
90+ missing_fields = [sf for sf in struct_fields if sf.name not in existing_line_names and sf.required == 't']
91+ for field in missing_fields:
92+ line_vals = self._prepare_structure_line(cr, uid, ids, field, context=context)
93+ lines.append((0, 0, line_vals))
94+
95+ self.write(cr, uid, import_list.id,
96+ {'line_ids': lines},
97+ context=context)
98+ return True
99+
100+ def generate_structure_from_model(self, cr, uid, ids, context=None):
101+ fields_obj = self.pool.get('ir.model.fields')
102+ for import_list in self.browse(cr, uid, ids, context=context):
103+ existing_fields_ids = [il_field.id for il_field in [l.field_id for l in import_list.line_ids]]
104+ all_fields_ids = self._get_model_fields(cr, uid, import_list.model_id.id, context=context)
105+ # keep only non existing fields but keep the sort
106+ fields_to_add_ids = [f_id for f_id in all_fields_ids if f_id not in existing_fields_ids]
107+
108+ lines = []
109+ for field in fields_obj.browse(cr, uid, fields_to_add_ids, context=context):
110+ line_vals = self._prepare_structure_line(cr, uid, ids, field, context=context)
111+ if line_vals:
112+ lines.append((0, 0, line_vals))
113+
114+ self.write(cr, uid, import_list.id,
115+ {'line_ids': lines},
116+ context=context)
117+
118+ return True
119+
120+
121 import_list()
122
123
124
125=== modified file 'document_csv/document_view.xml'
126--- document_csv/document_view.xml 2011-11-11 10:21:25 +0000
127+++ document_csv/document_view.xml 2012-01-11 07:46:28 +0000
128@@ -123,7 +123,8 @@
129 <group colspan="2" col="2">
130 <separator string="Actions" colspan="2"/>
131 <button string="Read CSV Header" type="action" name="%(document_csv.action_wizard_read_csv_file_view)d" colspan="2"/>
132- <button string="Export structure" type="action" name="%(document_csv.document_csv_export_wizard)d" colspan="2"/>
133+ <button string="Generate structure from model" type="object" name="generate_structure_from_model" colspan="2"/>
134+ <button string="Export structure" type="action" name="%(document_csv.action_document_import_csv_export_yaml)d" colspan="2"/>
135 <separator string="Import file information" colspan="2"/>
136 <field name="csv_sep"/>
137 <field name="csv_esc"/>
138
139=== modified file 'document_csv/ir_attachment.py'
140--- document_csv/ir_attachment.py 2011-11-23 11:00:10 +0000
141+++ document_csv/ir_attachment.py 2012-01-11 07:46:28 +0000
142@@ -4,6 +4,8 @@
143 # document_csv module for OpenERP, Import structure in CSV
144 # Copyright (C) 2011 SYLEAM (<http://www.syleam.fr/>)
145 # Christophe CHAUVET <christophe.chauvet@syleam.fr>
146+# Copyright (C) 2011 Camptocamp (http://www.camptocamp.com)
147+# Guewen Baconnier
148 #
149 # This file is a part of document_csv
150 #
151@@ -88,7 +90,7 @@
152 args = {
153 'name': l.name,
154 'field': l.field_id.name,
155- 'rel_field': l .field_relation_id.name,
156+ 'rel_field': l.field_relation_id.name,
157 'type': l.field_id.ttype,
158 'relation': l.field_id.relation,
159 'key': l.refkey,
160@@ -113,7 +115,7 @@
161 header.append(u'id')
162 if rel_uniq_key:
163 for x in rel_uniq_key:
164- header.append('%s:id' % x)
165+ header.append('%s/id' % x)
166
167 for h in fld:
168 rej_header.append(h['name'])
169@@ -121,11 +123,14 @@
170 header.append(h['field'])
171 else:
172 if h['rel_field']:
173- header.append('%s/%s' % (h['field'], h['rel_field']))
174- elif h['ref'] in ('id', 'db_id'):
175- header.append('%s:%s' % (h['field'], h['ref']))
176+ base_field = '%s/%s' % (h['field'], h['rel_field'])
177 else:
178- header.append(h['field'])
179+ base_field = h['field']
180+ if h['ref'] == 'db_id':
181+ base_field = '%s/.id' % (base_field,)
182+ elif h['ref'] == 'id':
183+ base_field = '%s/id' % (base_field,)
184+ header.append(base_field)
185
186 _logger.debug('module document_csv: ' + log_compose('%s: %s' % ('Object', imp_data.model_id.model)))
187 _logger.debug('module document_csv: ' + log_compose('%s: %r' % ('Context', context)))
188
189=== modified file 'document_csv/menu_view.xml'
190--- document_csv/menu_view.xml 2011-11-11 10:21:25 +0000
191+++ document_csv/menu_view.xml 2012-01-11 07:46:28 +0000
192@@ -32,7 +32,7 @@
193 <menuitem id="menu_document_import_configuration"
194 sequence="30"
195 name="Exchange Datas"
196- parent="base.menu_lunch_survey_root"/>
197+ parent="base.menu_tools"/>
198
199 </data>
200 </openerp>
201
202=== modified file 'document_csv/wizard/export_yml.py'
203--- document_csv/wizard/export_yml.py 2011-11-11 10:21:25 +0000
204+++ document_csv/wizard/export_yml.py 2012-01-11 07:46:28 +0000
205@@ -3,6 +3,7 @@
206 #
207 # document_csv module for OpenERP
208 # Copyright (C) 2009-2011 SYLEAM (<http://www.syleam.fr>) Christophe CHAUVET
209+# Copyright (C) 2011 Camptocamp Guewen Baconnier
210 #
211 # This file is a part of document_csv
212 #
213@@ -21,103 +22,81 @@
214 #
215 ##############################################################################
216
217-import wizard
218-import pooler
219-from cStringIO import StringIO
220+from osv import osv, fields
221+try:
222+ from cStringIO import StringIO
223+except ImportError:
224+ from StringIO import StringIO
225 import base64
226 from tools.translate import _
227
228-init_form = """<?xml version="1.0" ?>
229-<form string="Export file structure">
230- <separator string="The export file is available, save it to a local drive" colspan="4"/>
231- <field name="name" invisible="1"/>
232- <field name="filename" colspan="4" width="350" fieldname="name" readonly="1"/>
233-</form>
234-"""
235-
236-init_fields = {
237- 'name': {'string': 'File name', 'type': 'char', 'size': 128},
238- 'filename': {'string': 'Select a filename, and save it', 'type': 'binary', 'required': True, 'filters': '*.yml'},
239-}
240-
241-
242-def _init(self, cr, uid, data, context):
243- if context is None:
244- context = {}
245-
246- try:
247- import yaml
248- except ImportError:
249- raise wizard.except_wizard(_('Error'), _('Python Yaml Module not found, see description module'))
250- pool = pooler.get_pool(cr.dbname)
251- doc_obj = pool.get('document.import.list')
252- doc = doc_obj.browse(cr, uid, data['id'], context=context)
253- yml_file = '%s.yml' % doc.name.lower().replace(' ', '_').replace('-', '')
254- content = {
255- 'version': '1.3',
256- 'name': doc.name,
257- 'object': doc.model_id.model,
258- 'context': doc.ctx,
259- 'separator': doc.csv_sep,
260- 'escape': doc.csv_esc,
261- 'encoding': doc.encoding,
262- 'key_field_name': doc.key_field_name,
263- 'reject_all': doc.err_reject,
264- 'log_filename': doc.log_filename,
265- 'reject_filename': doc.reject_filename,
266- 'backup_filename': doc.backup_filename,
267- 'lang': doc.lang_id.code or 'en_US',
268- 'notes': doc.notes or '',
269- 'send_mail': doc.err_mail,
270- 'mail_from': doc.mail_from,
271- 'mail_cc': doc.mail_cc,
272- 'mail_subject': doc.mail_subject,
273- 'mail_body': doc.mail_body,
274- 'mail_cc_err': doc.mail_cc_err,
275- 'mail_subject_err': doc.mail_subject_err,
276- 'mail_body_err': doc.mail_body_err,
277+class ExportYaml(osv.osv_memory):
278+
279+ _name = 'document.import.csv.export.yaml'
280+
281+ _columns = {
282+ 'name': fields.char('Filename', size=128),
283+ 'filename': fields.binary('Select a filename and save it', required=True, filters='*.yml'),
284 }
285- lines = []
286- for l in doc.line_ids:
287- line = {}
288- line['name'] = l.name
289- line['field'] = l.field_id.name
290- if l.field_id.ttype in ('many2one', 'one2many', 'many2many'):
291- line['model'] = l.model_relation_id.model and str(l.model_relation_id.model) or False
292- line['model_field'] = l.field_relation_id.name and str(l.field_relation_id.name) or False
293- line['relation'] = l.relation and str(l.relation) or False
294- line['refkey'] = l.refkey
295- lines.append(line)
296-
297- content['lines'] = lines
298- buf = StringIO()
299- buf.write(yaml.dump(content, encoding='utf-8', default_flow_style=False))
300- out = base64.encodestring(buf.getvalue())
301- buf.close()
302- return {'filename': out, 'name': yml_file}
303-
304-
305-class export_yaml(wizard.interface):
306-
307- states = {
308- 'init': {
309- 'actions': [_init],
310- 'result': {
311- 'type': 'form',
312- 'arch': init_form,
313- 'fields': init_fields,
314- 'state': [('end', 'Cancel', 'gtk-cancel'), ('valid', 'OK', 'gtk-ok', True)],
315- }
316- },
317- 'valid': {
318- 'actions': [],
319- 'result': {
320- 'type': 'state',
321- 'state': 'end'
322- }
323+
324+ def default_get(self, cr, uid, fields_list, context=None):
325+ if context is None: context = {}
326+ res = super(ExportYaml, self).default_get(cr, uid, fields_list, context=context)
327+
328+ try:
329+ import yaml
330+ except ImportError:
331+ raise osv.except_osv(_('Error'), _('Python Yaml Module not found, see description module'))
332+
333+ doc_id = context.get('active_id')
334+ doc_obj = self.pool.get('document.import.list')
335+ doc = doc_obj.browse(cr, uid, doc_id, context=context)
336+
337+ yml_file = '%s.yml' % doc.name.lower().replace(' ', '_').replace('-', '')
338+ content = {
339+ 'version': '1.3',
340+ 'name': doc.name,
341+ 'object': doc.model_id.model,
342+ 'context': doc.ctx,
343+ 'separator': doc.csv_sep,
344+ 'escape': doc.csv_esc,
345+ 'encoding': doc.encoding,
346+ 'key_field_name': doc.key_field_name,
347+ 'reject_all': doc.err_reject,
348+ 'log_filename': doc.log_filename,
349+ 'reject_filename': doc.reject_filename,
350+ 'backup_filename': doc.backup_filename,
351+ 'lang': doc.lang_id.code or 'en_US',
352+ 'notes': doc.notes or '',
353+ 'send_mail': doc.err_mail,
354+ 'mail_from': doc.mail_from,
355+ 'mail_cc': doc.mail_cc,
356+ 'mail_subject': doc.mail_subject,
357+ 'mail_body': doc.mail_body,
358+ 'mail_cc_err': doc.mail_cc_err,
359+ 'mail_subject_err': doc.mail_subject_err,
360+ 'mail_body_err': doc.mail_body_err,
361 }
362- }
363-
364-export_yaml('document_csv.export')
365+ lines = []
366+ for l in doc.line_ids:
367+ line = {}
368+ line['name'] = l.name
369+ line['field'] = l.field_id.name
370+ if l.field_id.ttype in ('many2one', 'one2many', 'many2many'):
371+ line['model'] = l.model_relation_id.model and str(l.model_relation_id.model) or False
372+ line['model_field'] = l.field_relation_id.name and str(l.field_relation_id.name) or False
373+ line['relation'] = l.relation and str(l.relation) or False
374+ line['refkey'] = l.refkey
375+ lines.append(line)
376+
377+ content['lines'] = lines
378+ buf = StringIO()
379+ buf.write(yaml.dump(content, encoding='utf-8', default_flow_style=False))
380+ out = base64.encodestring(buf.getvalue())
381+ buf.close()
382+ res.update({'filename': out, 'name': yml_file})
383+ return res
384+
385+ExportYaml()
386
387 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
388
389=== added file 'document_csv/wizard/export_yml_view.xml'
390--- document_csv/wizard/export_yml_view.xml 1970-01-01 00:00:00 +0000
391+++ document_csv/wizard/export_yml_view.xml 2012-01-11 07:46:28 +0000
392@@ -0,0 +1,36 @@
393+<?xml version="1.0" encoding="UTF-8"?>
394+<openerp>
395+ <data>
396+
397+ <record id="view_document_import_csv_export_yaml_form" model="ir.ui.view">
398+ <field name="name">document.import.csv.export.yaml.form</field>
399+ <field name="model">document.import.csv.export.yaml</field>
400+ <field name="type">form</field>
401+ <field name="priority" eval="8"/>
402+ <field name="arch" type="xml">
403+ <form string="Export file structure">
404+ <separator string="The export file is available, save it to a local drive" colspan="4"/>
405+ <field name="name" invisible="1"/>
406+ <field name="filename" colspan="4" width="350" fieldname="name" readonly="1"/>
407+ <separator string=""/>
408+ <group colspan="4" col="6">
409+ <label string ="" colspan="2"/>
410+ <button icon="gtk-cancel" special="cancel" string="Close"/>
411+ </group>
412+ </form>
413+ </field>
414+ </record>
415+
416+ <record model="ir.actions.act_window" id="action_document_import_csv_export_yaml">
417+ <field name="name">Export Yaml</field>
418+ <field name="type">ir.actions.act_window</field>
419+ <field name="res_model">document.import.csv.export.yaml</field>
420+ <field name="view_type">form</field>
421+ <field name="view_mode">form</field>
422+ <field name="domain">[]</field>
423+ <field name="context">{}</field>
424+ <field name="target">new</field>
425+ </record>
426+
427+ </data>
428+</openerp>
429
430=== modified file 'document_csv/wizard/import_yml.py'
431--- document_csv/wizard/import_yml.py 2011-11-11 10:21:25 +0000
432+++ document_csv/wizard/import_yml.py 2012-01-11 07:46:28 +0000
433@@ -21,140 +21,113 @@
434 #
435 ##############################################################################
436
437-import wizard
438-import pooler
439 import base64
440 import yaml
441+from osv import osv, fields
442 from tools.translate import _
443
444-init_form = """<?xml version="1.0" ?>
445-<form string="Import CSV structure">
446- <field name="name" colspan="4"/>
447- <separator string="Select file to import" colspan="4"/>
448- <field name="filename" colspan="4" width="350"/>
449-</form>
450-"""
451-
452-init_fields = {
453- 'filename': {'string': 'Select File', 'type': 'binary', 'required': True, 'filters': '*.yml'},
454- 'name': {'string': 'Name of the new import', 'type': 'char', 'size': 64, 'required': False},
455-}
456-
457-
458-def _import(self, cr, uid, data, context):
459- if context is None:
460- context = {}
461-
462- pool = pooler.get_pool(cr.dbname)
463- model_obj = pool.get('ir.model')
464- fld_obj = pool.get('ir.model.fields')
465- dat_obj = pool.get('ir.model.data')
466- dir_obj = pool.get('document.directory')
467- imp_obj = pool.get('document.import.list')
468- act_obj = pool.get('ir.actions.act_window')
469-
470- context['import'] = True
471-
472- content = base64.decodestring(data['form']['filename'])
473- st = yaml.load(content)
474-
475- # Search the model_id
476- mod_ids = model_obj.search(cr, uid, [('model', '=', st['object'])])
477- if not mod_ids:
478- raise wizard.except_wizard(_('Error'),
479- _('No model name %s found') % st['object'])
480- mod_id = mod_ids[0]
481- imp = {
482- 'name': data['form']['name'] or st['name'],
483- 'ctx': st['context'],
484- 'model_id': mod_id,
485- 'csv_sep': st.get('separator', ';'),
486- 'csv_esc': st.get('escape', '"'),
487- 'encoding': st.get('encoding', 'utf-8'),
488+class ImportYaml(osv.osv_memory):
489+ _name = 'document.import.csv.import.yaml'
490+
491+ _columns = {
492+ 'filename': fields.binary('Select file to import', required=True, filters='*.yml'),
493+ 'name': fields.char('Name of the new import', size=64),
494 }
495- if st.get('version', '0.0') >= '1.1':
496- imp['err_reject'] = st.get('reject_all', False)
497- imp['log_filename'] = st.get('log_filename', False)
498- imp['reject_filename'] = st.get('reject_filename', False)
499- imp['backup_filename'] = st.get('backup_filename', False)
500-
501- if st.get('version', '0.0') >= '1.2':
502- imp['notes'] = st.get('notes', False)
503- imp['lang'] = st.get('lang', 'en_US')
504- imp['err_mail'] = st.get('send_mail', False)
505- imp['mail_from'] = st.get('mail_from', False)
506- imp['mail_cc'] = st.get('mail_cc', False)
507- imp['mail_subject'] = st.get('mail_subject', False)
508- imp['mail_body'] = st.get('mail_body', False)
509- imp['mail_cc_err'] = st.get('mail_cc_err', False)
510- imp['mail_subject_err'] = st.get('mail_subject_err', False)
511- imp['mail_body_err'] = st.get('mail_body_err', False)
512-
513- if st.get('version', '0.0') >= '1.3':
514- imp['key_field_name'] = st.get('key_field_name', False)
515-
516- lines_ids = []
517- for i in st['lines']:
518- # The field id associate to the name
519- fld_ids = fld_obj.search(cr, uid, [('model_id', '=', mod_id), ('name', '=', i['field'])], context=context)
520- if not fld_ids:
521- raise wizard.except_wizard(_('Error'), _('No field %s found in the object') % i['field'])
522-
523- l = {
524- 'name': i['name'],
525- 'field_id': fld_ids[0],
526- 'relation': i.get('relation', False),
527- 'refkey': i.get('refkey', False),
528+
529+ def action_import(self, cr, uid, ids, context):
530+ if context is None:
531+ context = {}
532+
533+ context['import'] = True
534+
535+ model_obj = self.pool.get('ir.model')
536+ fld_obj = self.pool.get('ir.model.fields')
537+ dat_obj = self.pool.get('ir.model.data')
538+ imp_obj = self.pool.get('document.import.list')
539+ act_obj = self.pool.get('ir.actions.act_window')
540+
541+ form_id = ids
542+ if isinstance(form_id, list):
543+ form_id = form_id[0]
544+ form = self.read(cr, uid, form_id, context=context)
545+
546+ content = base64.decodestring(form['filename'])
547+ st = yaml.load(content)
548+
549+ # Search the model_id
550+ mod_ids = model_obj.search(cr, uid, [('model', '=', st['object'])])
551+ if not mod_ids:
552+ raise osv.except_osv(_('Error'),
553+ _('No model name %s found') % st['object'])
554+ mod_id = mod_ids[0]
555+ imp = {
556+ 'name': form['name'] or st['name'],
557+ 'ctx': st['context'],
558+ 'model_id': mod_id,
559+ 'csv_sep': st.get('separator', ';'),
560+ 'csv_esc': st.get('escape', '"'),
561+ 'encoding': st.get('encoding', 'utf-8'),
562 }
563- if i.get('model') and i.get('model') not in ('None', 'False'):
564- mod_ids = model_obj.search(cr, uid, [('model', '=', i['model'])])
565- if not mod_ids:
566- raise wizard.except_wizard(_('Error'),
567- _('No model name %s found') % i['model'])
568-
569- l['model_relation_id'] = mod_ids[0]
570- if i.get('model_field') and i.get('model_field') not in ('None', 'False'):
571- fld_ids = fld_obj.search(cr, uid, [('model_id', '=', mod_ids[0]), ('name', '=', i['model_field'])])
572+ if st.get('version', '0.0') >= '1.1':
573+ imp['err_reject'] = st.get('reject_all', False)
574+ imp['log_filename'] = st.get('log_filename', False)
575+ imp['reject_filename'] = st.get('reject_filename', False)
576+ imp['backup_filename'] = st.get('backup_filename', False)
577+
578+ if st.get('version', '0.0') >= '1.2':
579+ imp['notes'] = st.get('notes', False)
580+ imp['lang'] = st.get('lang', 'en_US')
581+ imp['err_mail'] = st.get('send_mail', False)
582+ imp['mail_from'] = st.get('mail_from', False)
583+ imp['mail_cc'] = st.get('mail_cc', False)
584+ imp['mail_subject'] = st.get('mail_subject', False)
585+ imp['mail_body'] = st.get('mail_body', False)
586+ imp['mail_cc_err'] = st.get('mail_cc_err', False)
587+ imp['mail_subject_err'] = st.get('mail_subject_err', False)
588+ imp['mail_body_err'] = st.get('mail_body_err', False)
589+
590+ if st.get('version', '0.0') >= '1.3':
591+ imp['key_field_name'] = st.get('key_field_name', False)
592+
593+ lines_ids = []
594+ for i in st['lines']:
595+ # The field id associate to the name
596+ fld_ids = fld_obj.search(cr, uid, [('model_id', '=', mod_id), ('name', '=', i['field'])], context=context)
597 if not fld_ids:
598- raise wizard.except_wizard(_('Error'), _('No field %s found in the object') % i['model_field'])
599- l['field_relation_id'] = fld_ids[0]
600-
601- lines_ids.append((0, 0, l))
602- imp['line_ids'] = lines_ids
603-
604- imp_id = imp_obj.create(cr, uid, imp, context=context)
605- if not imp_id:
606- raise wizard.except_wizard(_('Error'), _('Failed to create the list entry'))
607-
608- result = dat_obj._get_id(cr, uid, 'document_csv', 'action_document_import_list')
609- id = dat_obj.read(cr, uid, result, ['res_id'])['res_id']
610- result = act_obj.read(cr, uid, id)
611- result['domain'] = "[('id','in', [" + ','.join(map(str, [imp_id])) + "])]"
612- return result
613-
614-
615-class import_yaml(wizard.interface):
616-
617- states = {
618- 'init': {
619- 'actions': [],
620- 'result': {
621- 'type': 'form',
622- 'arch': init_form,
623- 'fields': init_fields,
624- 'state': [('end', 'Cancel', 'gtk-cancel'), ('valid', 'OK', 'gtk-ok', True)],
625- }
626- },
627- 'valid': {
628- 'actions': [],
629- 'result': {
630- 'type': 'action',
631- 'action': _import,
632- 'state': 'end'
633- }
634- }
635- }
636-
637-import_yaml('document_csv.import')
638+ raise osv.except_osv(_('Error'), _('No field %s found in the object') % i['field'])
639+
640+ l = {
641+ 'name': i['name'],
642+ 'field_id': fld_ids[0],
643+ 'relation': i.get('relation', False),
644+ 'refkey': i.get('refkey', False),
645+ }
646+ if i.get('model') and i.get('model') not in ('None', 'False'):
647+ mod_ids = model_obj.search(cr, uid, [('model', '=', i['model'])])
648+ if not mod_ids:
649+ raise osv.except_osv(_('Error'),
650+ _('No model name %s found') % i['model'])
651+
652+ l['model_relation_id'] = mod_ids[0]
653+ if i.get('model_field') and i.get('model_field') not in ('None', 'False'):
654+ fld_ids = fld_obj.search(cr, uid, [('model_id', '=', mod_ids[0]), ('name', '=', i['model_field'])])
655+ if not fld_ids:
656+ raise osv.except_osv(_('Error'), _('No field %s found in the object') % i['model_field'])
657+ l['field_relation_id'] = fld_ids[0]
658+
659+ lines_ids.append((0, 0, l))
660+ imp['line_ids'] = lines_ids
661+
662+ imp_id = imp_obj.create(cr, uid, imp, context=context)
663+ if not imp_id:
664+ raise osv.except_osv(_('Error'), _('Failed to create the list entry'))
665+
666+ result = dat_obj._get_id(cr, uid, 'document_csv', 'action_document_import_list')
667+ id = dat_obj.read(cr, uid, result, ['res_id'])['res_id']
668+ result = act_obj.read(cr, uid, id)
669+ result['domain'] = "[('id','in', [" + ','.join(map(str, [imp_id])) + "])]"
670+ return result
671+
672+ImportYaml()
673
674 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
675
676=== added file 'document_csv/wizard/import_yml_view.xml'
677--- document_csv/wizard/import_yml_view.xml 1970-01-01 00:00:00 +0000
678+++ document_csv/wizard/import_yml_view.xml 2012-01-11 07:46:28 +0000
679@@ -0,0 +1,42 @@
680+<?xml version="1.0" encoding="UTF-8"?>
681+<openerp>
682+ <data>
683+
684+ <record id="view_document_import_csv_import_yaml_form" model="ir.ui.view">
685+ <field name="name">document.import.csv.import.yaml.form</field>
686+ <field name="model">document.import.csv.import.yaml</field>
687+ <field name="type">form</field>
688+ <field name="priority" eval="8"/>
689+ <field name="arch" type="xml">
690+ <form string="Import file structure">
691+ <field name="name" colspan="4"/>
692+ <field name="filename" colspan="4" width="350"/>
693+ <separator string=""/>
694+ <group colspan="4" col="6">
695+ <label string ="" colspan="2"/>
696+ <button icon="gtk-cancel" special="cancel" string="Close"/>
697+ <button icon="terp-gtk-go-back-rtl" string="Import Yaml structure" name="action_import" type="object" default_focus="1"/>
698+ </group>
699+ </form>
700+ </field>
701+ </record>
702+
703+ <record model="ir.actions.act_window" id="action_document_import_csv_import_yaml">
704+ <field name="name">Import Yaml</field>
705+ <field name="type">ir.actions.act_window</field>
706+ <field name="res_model">document.import.csv.import.yaml</field>
707+ <field name="view_type">form</field>
708+ <field name="view_mode">form</field>
709+ <field name="domain">[]</field>
710+ <field name="context">{}</field>
711+ <field name="target">new</field>
712+ </record>
713+
714+ <menuitem id="menu_document_csv_import"
715+ sequence="20"
716+ name="Import Structure"
717+ action="action_document_import_csv_import_yaml"
718+ parent="menu_document_import_configuration"/>
719+
720+ </data>
721+</openerp>
722
723=== modified file 'document_csv/wizard/launch.py'
724--- document_csv/wizard/launch.py 2011-11-11 10:21:25 +0000
725+++ document_csv/wizard/launch.py 2012-01-11 07:46:28 +0000
726@@ -4,6 +4,8 @@
727 # document_csv module for OpenERP, Import structure in CSV
728 # Copyright (C) 2011 SYLEAM (<http://www.syleam.fr/>)
729 # Christophe CHAUVET <christophe.chauvet@syleam.fr>
730+# Copyright (C) 2011 Camptocamp (http://www.camptocamp.com)
731+# Guewen Baconnier
732 #
733 # This file is a part of document_csv
734 #
735@@ -41,6 +43,7 @@
736 _columns = {
737 'import_list': fields.selection(_import_list, 'List', help='List of available import structure', required=True),
738 'import_file': fields.binary('Filename', required=True),
739+ 'lang_id': fields.many2one('res.lang', 'Language', help='Translation to update.'),
740 'email_result': fields.char('Email', size=256, help='Email to send notification when import is finished'),
741 }
742
743@@ -52,15 +55,23 @@
744 context = {}
745
746 res = super(LaunchImport, self).default_get(cr, uid, fields_list, context=context)
747- res['email_result'] = self.pool.get('res.users').browse(cr, uid, uid, context=context).user_email or ''
748+ user = self.pool.get('res.users').browse(cr, uid, uid, context=context)
749+ res['email_result'] = user.user_email or ''
750+ if context.get('lang'):
751+ res['lang_id'] = self.pool.get('res.lang').search(cr, uid, [('code', '=', context['lang'])], context=context)
752 return res
753
754 def launch_import(self, cr, uid, ids, context=None):
755 """
756 Save file, and execute importation
757 """
758+ if context is None:
759+ context = {}
760 cur = self.browse(cr, uid, ids[0], context=context)
761- self.pool.get('ir.attachment').import_csv(cr, uid, cur.import_list, cur.import_file, cur.email_result, context=context)
762+ ctx = context.copy()
763+ if cur.lang_id:
764+ ctx.update({'lang': cur.lang_id.code})
765+ self.pool.get('ir.attachment').import_csv(cr, uid, int(cur.import_list), cur.import_file, cur.email_result, context=ctx)
766 return {'type': 'ir.actions.act_window_close'}
767
768 LaunchImport()
769
770=== modified file 'document_csv/wizard/launch_view.xml'
771--- document_csv/wizard/launch_view.xml 2011-11-11 10:21:25 +0000
772+++ document_csv/wizard/launch_view.xml 2012-01-11 07:46:28 +0000
773@@ -35,7 +35,9 @@
774 <field name="import_list" nolabel="1" />
775 <separator string="Select file to import" colspan="4"/>
776 <field name="import_file" nolabel="1" />
777- <separator string="Email to send notificaiton when import is finished" colspan="4"/>
778+ <separator string="Translation to update from this file" colspan="4"/>
779+ <field name="lang_id" widget="selection" nolabel="1"/>
780+ <separator string="Email to send notification when import is finished" colspan="4"/>
781 <field name="email_result" nolabel="1" />
782 <separator string="" colspan="4" />
783 <group colspan="4" col="6">
784
785=== modified file 'document_csv/wizard/read_csv.py'
786--- document_csv/wizard/read_csv.py 2011-11-11 10:21:25 +0000
787+++ document_csv/wizard/read_csv.py 2012-01-11 07:46:28 +0000
788@@ -40,6 +40,7 @@
789
790 _columns = {
791 'import_file': fields.binary('Filename', required=True),
792+ 'auto_completion': fields.boolean('Automatic Completion', help="Auto-complete the fields and relations based on the header names if the header names are the same as the OpenERP field names."),
793 }
794
795 def read_header(self, cr, uid, ids, context=None):
796@@ -73,6 +74,9 @@
797 finally:
798 fpcsv.close()
799
800+ if cur.auto_completion:
801+ implist_obj.complete_structure_from_model(cr, uid, implist.id, context=context)
802+
803 return {'type': 'ir.actions.act_window_close'}
804
805 ReadCsv()
806
807=== modified file 'document_csv/wizard/read_csv_view.xml'
808--- document_csv/wizard/read_csv_view.xml 2011-11-11 10:21:25 +0000
809+++ document_csv/wizard/read_csv_view.xml 2012-01-11 07:46:28 +0000
810@@ -32,7 +32,8 @@
811 <field name="arch" type="xml">
812 <form string="Import Form">
813 <separator string="Select file to analyse" colspan="4"/>
814- <field name="import_file" nolabel="1" />
815+ <field name="import_file" nolabel="1" colspan="4"/>
816+ <field name="auto_completion" />
817 <separator string="" colspan="4" />
818 <group colspan="4" col="6">
819 <label string ="" colspan="2"/>
820
821=== removed file 'document_csv/wizard/wizard.xml'
822--- document_csv/wizard/wizard.xml 2011-11-11 10:21:25 +0000
823+++ document_csv/wizard/wizard.xml 1970-01-01 00:00:00 +0000
824@@ -1,46 +0,0 @@
825-<?xml version="1.0" encoding="UTF-8"?>
826-<openerp>
827- <data>
828- ##############################################################################
829- #
830- # document_csv module for OpenERP
831- # Copyright (C) 2009-2011 SYLEAM ([http://www.syleam.fr]) Christophe CHAUVET
832- #
833- # This file is a part of document_csv
834- #
835- # document_csv is free software: you can redistribute it and/or modify
836- # it under the terms of the GNU General Public License as published by
837- # the Free Software Foundation, either version 3 of the License, or
838- # (at your option) any later version.
839- #
840- # document_csv is distributed in the hope that it will be useful,
841- # but WITHOUT ANY WARRANTY; without even the implied warranty of
842- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
843- # GNU General Public License for more details.
844- #
845- # You should have received a copy of the GNU General Public License
846- # along with this program. If not, see [http://www.gnu.org/licenses/].
847- #
848- ##############################################################################
849-
850- <wizard id="document_csv_export_wizard"
851- name="document_csv.export"
852- model="document.import.list"
853- menu="False"
854- string="Export structure"/>
855-
856- <wizard id='document_csv_import_wizard'
857- name="document_csv.import"
858- model="document.import.list"
859- string="Import structure"
860- menu="False"/>
861-
862- <menuitem id="menu_document_csv_import"
863- sequence="20"
864- name="Import Structure"
865- action="document_csv_import_wizard"
866- parent="menu_document_import_configuration"
867- type="wizard"/>
868-
869- </data>
870-</openerp>

Subscribers

People subscribed via source and target branches

to all changes: