Merge lp:~fabien-morin/unifield-server/fm-us-2619 into lp:unifield-server

Proposed by jftempo
Status: Merged
Merged at revision: 4783
Proposed branch: lp:~fabien-morin/unifield-server/fm-us-2619
Merge into: lp:unifield-server
Diff against target: 2941 lines (+2211/-110)
18 files modified
bin/addons/account_hq_entries/wizard/hq_entries_import.py (+9/-4)
bin/addons/base/ir/ir_actions.py (+1/-1)
bin/addons/import_data/import_data.py (+4/-1)
bin/addons/msf_budget/wizard/wizard_budget_import.py (+3/-0)
bin/addons/msf_doc_import/__init__.py (+1/-0)
bin/addons/msf_doc_import/__openerp__.py (+1/-0)
bin/addons/msf_doc_import/doc_import_report.xml (+11/-0)
bin/addons/msf_doc_import/msf_import_export.py (+853/-0)
bin/addons/msf_doc_import/msf_import_export_conf.py (+579/-0)
bin/addons/msf_doc_import/report/export_generic.mako (+137/-0)
bin/addons/msf_doc_import/report/import_generic_template.mako (+21/-0)
bin/addons/msf_doc_import/report/import_generic_template.py (+52/-0)
bin/addons/msf_doc_import/view/msf_import_export_view.xml (+99/-0)
bin/addons/msf_doc_import/wizard/abstract_wizard_import.py (+28/-3)
bin/addons/msf_profile/i18n/fr_MF.po (+395/-96)
bin/addons/product_nomenclature/product_nomenclature.py (+1/-1)
bin/addons/res_currency_tables/wizard/import_currencies.py (+4/-0)
bin/osv/orm.py (+12/-4)
To merge this branch: bzr merge lp:~fabien-morin/unifield-server/fm-us-2619
Reviewer Review Type Date Requested Status
UniField Reviewer Team Pending
Review via email: mp+322034@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Jeff Allen (jr.allen) :
Revision history for this message
Fabien MORIN (fabien-morin) wrote :

On Monday 10 April 2017 14:54:10 you wrote:
> > + def get_excel_size_from_string(self, string):
> > + """Compute the string to get the size of it in a excel
> > + understandable value
> > + :param string: the str chain to get the excel size
> > + :return: A int instance
> > + """
> > + # this complex calculation is used to translate the
> > + # character len to an excel understandable len
> > + size = round(7*len(string)*(3/4.)+15)
>
> Please explain the heuristic here.

fixed here : http://bazaar.launchpad.net/~fabien-morin/unifield-server/fm-us-2619/revision/4318

--
Fabien MORIN
TeMPO Consulting
20, avenue de la Paix
67000 Strasbourg
France

http://www.tempo-consulting.fr
Tel : +33 3 88 56 82 16
Fax : +33 9 70 63 35 46

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'bin/addons/account_hq_entries/wizard/hq_entries_import.py'
2--- bin/addons/account_hq_entries/wizard/hq_entries_import.py 2017-02-28 16:07:39 +0000
3+++ bin/addons/account_hq_entries/wizard/hq_entries_import.py 2017-09-27 13:17:20 +0000
4@@ -291,6 +291,9 @@
5 if not context:
6 context = {}
7
8+ if isinstance(ids, (int, long)):
9+ ids = [ids]
10+
11 # Verify that an HQ journal exists
12 journal_ids = self.pool.get('account.journal').search(cr, uid, [('type', '=', 'hq'),
13 ('is_current_instance', '=', True)])
14@@ -314,18 +317,20 @@
15 errors.append('Line %s, %s' % (line_index, _(msg)))
16
17 # Browse all given wizard
18- for wiz in self.browse(cr, uid, ids):
19- if not wiz.file:
20+ read_result = self.read(cr, uid, ids, ['file', 'filename'],
21+ context=context)
22+ for wiz in read_result:
23+ if not wiz['file']:
24 raise osv.except_osv(_('Error'), _('Nothing to import.'))
25 # Decode file string
26 fileobj = NamedTemporaryFile('w+')
27- fileobj.write(decodestring(wiz.file))
28+ fileobj.write(decodestring(wiz['file']))
29 # now we determine the file format
30 fileobj.seek(0)
31 # Read CSV file
32 try:
33 reader = csv.reader(fileobj, delimiter=',', quotechar='"')
34- filename = wiz.filename or ""
35+ filename = wiz['filename'] or ""
36 except:
37 fileobj.close()
38 raise osv.except_osv(_('Error'), _('Problem to read given file.'))
39
40=== modified file 'bin/addons/base/ir/ir_actions.py'
41--- bin/addons/base/ir/ir_actions.py 2017-05-18 12:16:12 +0000
42+++ bin/addons/base/ir/ir_actions.py 2017-09-27 13:17:20 +0000
43@@ -150,7 +150,7 @@
44 _name = 'ir.actions.act_window'
45 _table = 'ir_act_window'
46 _sequence = 'ir_actions_id_seq'
47- _order = 'name'
48+ _order = 'name, id'
49 _replace_exported_fields = {
50 'groups_txt': [
51 (['groups_id', 'Groups'], 10)
52
53=== modified file 'bin/addons/import_data/import_data.py'
54--- bin/addons/import_data/import_data.py 2016-05-24 08:44:23 +0000
55+++ bin/addons/import_data/import_data.py 2017-09-27 13:17:20 +0000
56@@ -46,7 +46,10 @@
57
58 if data.get('parent_id', False):
59 n_obj = self.pool.get('product.nomenclature')
60- parent_ids = n_obj.search(cr, uid, [('msfid', '=', data['parent_id'])], limit=1)
61+ if isinstance(data['parent_id'], (int, long)):
62+ parent_ids = [data['parent_id']]
63+ else:
64+ parent_ids = n_obj.search(cr, uid, [('msfid', '=', data['parent_id'])], limit=1)
65 if parent_ids:
66 parent_id = parent_ids[0]
67
68
69=== modified file 'bin/addons/msf_budget/wizard/wizard_budget_import.py'
70--- bin/addons/msf_budget/wizard/wizard_budget_import.py 2015-08-06 14:08:20 +0000
71+++ bin/addons/msf_budget/wizard/wizard_budget_import.py 2017-09-27 13:17:20 +0000
72@@ -216,6 +216,9 @@
73 if context is None:
74 context = {}
75
76+ if isinstance(ids, (int, long)):
77+ ids = [ids]
78+
79 # Prepare some values
80 budgets_2be_approved = {}
81 tool_obj = self.pool.get('msf.budget.tools')
82
83=== modified file 'bin/addons/msf_doc_import/__init__.py'
84--- bin/addons/msf_doc_import/__init__.py 2016-05-17 12:05:25 +0000
85+++ bin/addons/msf_doc_import/__init__.py 2017-09-27 13:17:20 +0000
86@@ -54,3 +54,4 @@
87 import product_list
88 import supplier_catalogue
89 import report
90+import msf_import_export
91
92=== modified file 'bin/addons/msf_doc_import/__openerp__.py'
93--- bin/addons/msf_doc_import/__openerp__.py 2017-05-22 16:04:34 +0000
94+++ bin/addons/msf_doc_import/__openerp__.py 2017-09-27 13:17:20 +0000
95@@ -51,6 +51,7 @@
96 'view/stock_picking_import_lines_view.xml',
97 'view/replenishment_rules_view.xml',
98 'view/supplier_catalogue_view.xml',
99+ 'view/msf_import_export_view.xml',
100 'wizard/wizard_import_po_line_view.xml',
101 'wizard/wizard_import_fo_line.xml',
102 'wizard/wizard_import_tender_line.xml',
103
104=== modified file 'bin/addons/msf_doc_import/doc_import_report.xml'
105--- bin/addons/msf_doc_import/doc_import_report.xml 2016-07-27 08:54:22 +0000
106+++ bin/addons/msf_doc_import/doc_import_report.xml 2017-09-27 13:17:20 +0000
107@@ -45,5 +45,16 @@
108 auto="False"
109 string="Import Generic template" />
110
111+ <report
112+ id="wizard_export_generic"
113+ model="msf.import.export"
114+ name="wizard.export.generic"
115+ file="msf_doc_import/report/export_generic.mako"
116+ report_type="webkit"
117+ header="False"
118+ menu="False"
119+ auto="False"
120+ string="Generic Export" />
121+
122 </data>
123 </openerp>
124
125=== added file 'bin/addons/msf_doc_import/msf_import_export.py'
126--- bin/addons/msf_doc_import/msf_import_export.py 1970-01-01 00:00:00 +0000
127+++ bin/addons/msf_doc_import/msf_import_export.py 2017-09-27 13:17:20 +0000
128@@ -0,0 +1,853 @@
129+# encoding: utf-8
130+##############################################################################
131+#
132+# OpenERP, Open Source Management Solution
133+# Copyright (C) 2017 MSF, TeMPO Consulting
134+#
135+# This program is free software: you can redistribute it and/or modify
136+# it under the terms of the GNU General Public License as published by
137+# the Free Software Foundation, either version 3 of the License, or
138+# (at your option) any later version.
139+#
140+# This program is distributed in the hope that it will be useful,
141+# but WITHOUT ANY WARRANTY; without even the implied warranty of
142+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
143+# GNU General Public License for more details.
144+#
145+# You should have received a copy of the GNU General Public License
146+# along with this program. If not, see <http://www.gnu.org/licenses/>.
147+#
148+##############################################################################
149+
150+import base64
151+import time
152+import threading
153+import logging
154+
155+import pooler
156+import tools
157+
158+from osv import fields
159+from osv import osv
160+from tools.translate import _
161+
162+from tempfile import TemporaryFile
163+from lxml import etree
164+from lxml.etree import XMLSyntaxError
165+
166+from msf_doc_import.wizard.abstract_wizard_import import ImportHeader
167+from msf_doc_import.msf_import_export_conf import MODEL_DICT
168+from msf_doc_import.msf_import_export_conf import MODEL_DATA_DICT
169+
170+MIN_COLUMN_SIZE = 40
171+MAX_COLUMN_SIZE = 400
172+
173+MODEL_HEADER_NOT_CHECKED = ['user.access.configurator', 'hr.employee', 'hq.entries', 'msf.budget']
174+
175+class msf_import_export(osv.osv_memory):
176+ _name = 'msf.import.export'
177+ _description = 'MSF Import Export'
178+ _inherit = 'abstract.wizard.import'
179+
180+ def _get_model_list(self, cr, uid, context=None):
181+ """The list of available model depend on the menu entry selected
182+ """
183+ if context is None:
184+ context = {}
185+ domain_type = None
186+ if 'domain_type' in context:
187+ domain_type = context['domain_type']
188+ result_list = [(key, _(value['name'])) for key, value in MODEL_DICT.items() if value['domain_type'] == domain_type]
189+ return [('', '')] + sorted(result_list, key=lambda a: a[0])
190+
191+ _columns = {
192+ 'display_file_import': fields.boolean('File Import'),
193+ 'display_file_export': fields.boolean('File Export'),
194+ 'model_list_selection': fields.selection(selection=_get_model_list, string='Object to Import/Export', required=True),
195+ 'import_file': fields.binary('File to import .xml'),
196+ 'hide_download_3_entries': fields.boolean('Hide export 3 entries button'),
197+ 'hide_download_all_entries': fields.boolean('Hide export all entries button'),
198+ 'display_import_buttons': fields.boolean('Display import buttons'),
199+ 'csv_button': fields.boolean('Import from CSV'),
200+ }
201+
202+ _default = {
203+ 'display_file_import': lambda *a: False,
204+ 'display_file_export': lambda *a: False,
205+ 'hide_download_3_entries': lambda *a: False,
206+ 'hide_download_all_entries': lambda *a: False,
207+ 'display_import_buttons': lambda *a: False,
208+ 'csv_button': lambda *a: False,
209+ }
210+
211+ def get_filename(self, cr, uid, model, selection, template_only=False, context=None):
212+ """Generate a filename for the import/export
213+ """
214+ model_obj = self.pool.get(model)
215+ file_name = _(MODEL_DICT[selection]['name'])
216+ file_name = file_name.replace(' ', '_')
217+ if template_only:
218+ file_name = _('%s_Import_Template') % file_name
219+ else:
220+ file_name = _('%s_Export_%s') % (file_name, time.strftime('%Y%m%d'))
221+ return file_name
222+
223+ def generic_download(self, cr, uid, ids, template_only=False,
224+ nb_lines=None, context=None):
225+ """Mutualise the code of all download buttons in one place
226+ """
227+ if context is None:
228+ context = {}
229+ if isinstance(ids, (int, long)):
230+ ids = [ids]
231+
232+ wiz = self.browse(cr, uid, ids[0])
233+ selection = wiz.model_list_selection
234+ model = MODEL_DICT[selection]['model']
235+ if selection not in MODEL_DATA_DICT:
236+ raise osv.except_osv(_('Error'),
237+ _('Selection \'%s\' not found. '
238+ 'Please contact the support team.') % (selection))
239+
240+ if 'header_list' not in MODEL_DATA_DICT[selection]:
241+ raise osv.except_osv(_('Error'),
242+ _('The header_list for report \'%s\' is not'
243+ ' defined. Please contact the support team.') % (selection))
244+ fields = MODEL_DATA_DICT[selection]['header_list']
245+ domain = MODEL_DICT[selection].get('domain', [])
246+ context['translate_selection_field'] = True
247+ data = {
248+ 'model': model,
249+ 'fields': fields,
250+ 'nb_lines': nb_lines,
251+ 'template_only': template_only,
252+ 'domain': domain,
253+ 'target_filename': self.get_filename(cr, uid, model, selection, template_only),
254+ }
255+ return {
256+ 'type': 'ir.actions.report.xml',
257+ 'report_name': 'wizard.export.generic',
258+ 'datas': data,
259+ 'context': context,
260+ }
261+
262+ def download_all_entries_file(self, cr, uid, ids, context=None):
263+ """Download a template filled with all datas of the modele
264+ """
265+ return self.generic_download(cr, uid, ids, context=context)
266+
267+ def download_3_entries_file(self, cr, uid, ids, context=None):
268+ """Download a template filled with the first 3 lines of data
269+ """
270+ return self.generic_download(cr, uid, ids, nb_lines=3, context=context)
271+
272+ def download_template_file(self, cr, uid, ids, context=None):
273+ """Download the template file (without any data)
274+ """
275+ return self.generic_download(cr, uid, ids, template_only=True,
276+ context=context)
277+
278+ def get_excel_size_from_string(self, string):
279+ """Compute the string to get the size of it in a excel
280+ understandable value
281+ :param string: the str chain to get the excel size
282+ :return: A int instance
283+ """
284+ # this calculation is used to translate the
285+ # character len to an excel understandable len
286+
287+ max_digit_width = 7 # For Calabri 11 which is the font used in our reports
288+ conversion_factor = 3/4. # to convert from pixel to points
289+ padding = 15
290+
291+ # this formule partially come from readings here:
292+ # http://stackoverflow.com/questions/4577546/calculating-height-width-and-ysplit-xsplit-for-open-xml-spreadsheets?answertab=votes#tab-top
293+ size = round(max_digit_width*len(string)*conversion_factor+padding)
294+
295+ # set a max and min len for the columns to avoid ridiculus column size
296+ size = min(size, MAX_COLUMN_SIZE)
297+ size = max(size, MIN_COLUMN_SIZE)
298+ return size
299+
300+ def get_child_field(self, cr, uid, field, model, fields_get_dict,
301+ context=None):
302+ if context is None:
303+ context = {}
304+ if '.' in field:
305+ model_obj = self.pool.get(model)
306+ if model not in fields_get_dict:
307+ fields_get_res = model_obj.fields_get(cr, uid, context=context)
308+ fields_get_dict[model] = fields_get_res
309+ else:
310+ fields_get_res = fields_get_dict[model]
311+
312+
313+ child_field = field.split('.')[0]
314+ rest = '.'.join(field.split('.')[1:])
315+ if child_field == 'id':
316+ return field, model
317+
318+ if child_field not in fields_get_res:
319+ raise osv.except_osv(_('Error'),
320+ _('field \'%s\' not found for model \'%s\'. Please contact the support team.')
321+ % (child_field, model))
322+
323+ #if child and child !='id' and fields_get_res[child_field].get('relation'):
324+ child_model = fields_get_res[child_field]['relation']
325+ if child_model not in fields_get_dict:
326+ model_obj = self.pool.get(child_model)
327+ fields_get_res = model_obj.fields_get(cr, uid, context=context)
328+ fields_get_dict[child_model] = fields_get_res
329+ return self.get_child_field(cr, uid, rest, child_model, fields_get_dict,
330+ context=context)
331+ else:
332+ return field, model
333+
334+ def _get_headers(self, cr, uid, model, selection=None, field_list=None, rows=None, context=None):
335+ """Generate a list of ImportHeader objects using the data that retived
336+ from the field name.
337+ :param model: Model of the object imported/exported
338+ :param selection: requried to get the list of fields to compose the header
339+ :param field_list: if known, the list of the fields to display in the
340+ header can be passed
341+ :param rows: Data rows to export. In case of export, the size of the
342+ columns matter and can be determinied according to the data string length
343+ :param context: Context of the call, this is particularly important to
344+ get the language for tranlsating the fields.
345+ :return: A list of ImportHeader
346+ """
347+ if context is None:
348+ context = {}
349+ headers = []
350+ if not field_list:
351+ field_list = MODEL_DATA_DICT[selection]['header_list']
352+ model_obj = self.pool.get(model)
353+
354+ fields_get_dict = {} # keep fields_get result in cache
355+ fields_get_dict[model] = model_obj.fields_get(cr, uid, context=context)
356+
357+ for field_index, field in enumerate(field_list):
358+ res = {'tech_name': field}
359+ if selection and field in MODEL_DATA_DICT[selection]['required_field_list']:
360+ res['required'] = True
361+ child_field, child_model = self.get_child_field(cr, uid, field, model,
362+ fields_get_dict, context=context)
363+ first_part = field.split('.')[0]
364+ if child_field == 'id':
365+ res['name'] = '%s / XMLID' % fields_get_dict[model][first_part]['string']
366+ elif first_part not in fields_get_dict[model]:
367+ raise osv.except_osv(_('Error'),
368+ _('field \'%s\' not found for model \'%s\'. Please contact the support team.')
369+ % (first_part, model))
370+ elif first_part != child_field:
371+ if child_field not in fields_get_dict[child_model]:
372+ raise osv.except_osv(_('Error'),
373+ _('field \'%s\' not found for model \'%s\'. Please contact the support team.')
374+ % (child_field, child_model))
375+ res['name'] = '%s / %s' % (fields_get_dict[model][first_part]['string'],
376+ fields_get_dict[child_model][child_field]['string'])
377+ else:
378+ res['name'] = fields_get_dict[model][first_part]['string']
379+
380+
381+ if child_field == 'id':
382+ field_type == 'String'
383+ else:
384+ field_type = fields_get_dict[child_model][child_field]['type']
385+ if field_type == 'boolean':
386+ res['ftype'] = 'Boolean'
387+ elif field_type == 'float':
388+ res['ftype'] = 'Float'
389+ elif field_type == 'integer':
390+ res['ftype'] = 'Number'
391+ else:
392+ res['ftype'] = 'String'
393+
394+ if not rows:
395+ # if no data passed, set the column size with the size of the header name
396+ res['size'] = self.get_excel_size_from_string(res['name'])
397+ else:
398+ # automatically set the width of the column by searching for the
399+ # biggest string in this column
400+ all_cells_chain = [tools.ustr(x[field_index]) for x in rows]
401+ res['size'] = MIN_COLUMN_SIZE
402+ if all_cells_chain:
403+ longest_chain = max(all_cells_chain, key=len)
404+ if longest_chain:
405+ res['size'] = self.get_excel_size_from_string(longest_chain)
406+ headers.append(ImportHeader(**res))
407+ return headers
408+
409+ def domain_type_change(self, cr, uid, ids, model_list_selection, context=None):
410+ """When the type of object to import/export change, change the buttons
411+ to display or not according to the new object model
412+ """
413+ if context is None:
414+ context = {}
415+ result = {'value': {}}
416+ result['value']['display_file_import'] = True
417+ result['value']['display_file_export'] = True
418+ if model_list_selection:
419+ if model_list_selection and model_list_selection in MODEL_DATA_DICT:
420+ hide_export = MODEL_DATA_DICT[model_list_selection].get('hide_export', False)
421+ result['value']['display_file_export'] = not hide_export
422+ hide_3 = MODEL_DATA_DICT[model_list_selection].get('hide_download_3_entries', False)
423+ result['value']['hide_download_3_entries'] = hide_3
424+ hide_all = MODEL_DATA_DICT[model_list_selection].get('hide_download_all_entries', False)
425+ result['value']['hide_download_all_entries'] = hide_all
426+ csv_button = MODEL_DATA_DICT[model_list_selection].get('csv_button', False)
427+ result['value']['csv_button'] = csv_button
428+ else:
429+ result['value']['hide_download_3_entries'] = False
430+ result['value']['hide_download_all_entries'] = False
431+ return result
432+
433+ def file_change(self, cr, uid, obj_id, import_file, context=None):
434+ """Display the import button only if a file as been selected
435+ """
436+ if context is None:
437+ context = {}
438+ result = {'value': {'display_import_buttons': False}}
439+ if import_file:
440+ result['value']['display_import_buttons'] = True
441+ return result
442+
443+ def check_xml_syntax(self, cr, uid, xml_string, context=None):
444+ """Try to parse the xml file and raise if there is an error
445+ """
446+ try:
447+ file_dom = etree.fromstring(xml_string)
448+ except XMLSyntaxError as e:
449+ raise osv.except_osv(_('Error'), _('File structure is incorrect, '
450+ 'please correct. You may generate a template with the File '
451+ 'export functionality.'))
452+
453+ def test_import(self, cr, uid, ids, context=None):
454+ """Warn if file structure is correct
455+ """
456+ if self.check_import(cr, uid, ids, context=context):
457+ raise osv.except_osv(_('Info'), _('File structure is correct.'))
458+
459+ def check_import(self, cr, uid, ids, context=None):
460+ """Verify that a file has been selected and all columns expected are
461+ present
462+ """
463+ obj = self.read(cr, uid, ids[0])
464+ if not obj['import_file']:
465+ raise osv.except_osv(_('Error'), _('Nothing to import.'))
466+ fileobj = TemporaryFile('w+')
467+ try:
468+ for wiz in self.browse(cr, uid, ids, context=context):
469+ selection = wiz.model_list_selection
470+ model = MODEL_DICT[selection]['model']
471+ if model in MODEL_HEADER_NOT_CHECKED:
472+ continue
473+ xml_string = base64.decodestring(obj['import_file'])
474+ self.check_xml_syntax(cr, uid, xml_string, context=context)
475+ rows, nb_rows = self.read_file(wiz, context=context)
476+ head = rows.next()
477+ self.check_missing_columns(cr, uid, wiz, head, context=context)
478+ finally:
479+ fileobj.close()
480+ return True
481+
482+ def excel_col(self, col):
483+ """Covert column number (1,2,...26,27,28...) to excel-style column label
484+ letters (A,B,..Z,AA,AB,...)."""
485+ quot, rem = divmod(col-1,26)
486+ return self.excel_col(quot) + chr(rem+ord('A')) if col!=0 else ''
487+
488+ def check_missing_columns(self, cr, uid, wizard_brw, head, context=None):
489+ """Check that the column names in the file match the expected property
490+ names, raise if any column is missing.
491+ """
492+ selection = wizard_brw.model_list_selection
493+ model = MODEL_DICT[selection]['model']
494+ model_obj = self.pool.get(model)
495+ header_columns = [head[i].data for i in range(0, len(head))]
496+ missing_columns = []
497+ field_list = MODEL_DATA_DICT[selection]['header_list']
498+
499+ fields_get_dict = {} # keep fields_get result in cache
500+ fields_get_dict[model] = model_obj.fields_get(cr, uid, context=context)
501+ fields_get_res = model_obj.fields_get(cr, uid,
502+ [x.split('.')[0] for x in field_list], context=context)
503+ if len(field_list) != len(header_columns):
504+ raise osv.except_osv(_('Info'), _('The number of column is not same ' \
505+ 'than expected (get %s, expected %s). Check your import file and ' \
506+ 'the Object to import/export.') % (len(header_columns), len(field_list)))
507+
508+ for field_index, field in enumerate(field_list):
509+ child_field, child_model = self.get_child_field(cr, uid, field, model,
510+ fields_get_dict, context=context)
511+ first_part = field.split('.')[0]
512+ if child_field == 'id':
513+ column_name = '%s / XMLID' % fields_get_dict[model][first_part]['string']
514+ elif first_part not in fields_get_dict[model]:
515+ raise osv.except_osv(_('Error'),
516+ _('field \'%s\' not found for model \'%s\'. Please contact the support team.')
517+ % (first_part, model))
518+ elif first_part != child_field:
519+ if child_field not in fields_get_dict[child_model]:
520+ raise osv.except_osv(_('Error'),
521+ _('field \'%s\' not found for model \'%s\'. Please contact the support team.')
522+ % (child_field, child_model))
523+ column_name = '%s / %s' % (fields_get_dict[model][first_part]['string'],
524+ fields_get_dict[child_model][child_field]['string'])
525+ else:
526+ column_name = fields_get_dict[model][first_part]['string']
527+
528+ if column_name.upper() != header_columns[field_index].upper():
529+ missing_columns.append(_('Column %s: get \'%s\' expected \'%s\'.')
530+ % (self.excel_col(field_index+1), header_columns[field_index], column_name))
531+ if missing_columns and model not in MODEL_HEADER_NOT_CHECKED:
532+ raise osv.except_osv(_('Info'), _('The following columns '
533+ 'are missing in the imported file:\n%s') % ',\n'.join(missing_columns))
534+
535+ def import_csv(self, cr, uid, ids, context=None):
536+ if context is None:
537+ context = {}
538+ if isinstance(ids, (int, long)):
539+ ids = [ids]
540+
541+ for wiz in self.browse(cr, uid, ids, context=context):
542+ selection = wiz.model_list_selection
543+ model = MODEL_DICT[selection]['model']
544+
545+ if model == 'hq.entries':
546+ hq_import = self.pool.get('hq.entries.import')
547+ vals = {'file': wiz.import_file}
548+ wizard_id = hq_import.create(cr, uid, vals, context=context)
549+ self.write(cr, uid, [wiz.id], {
550+ 'state': 'progress',
551+ 'start_date': time.strftime('%Y-%m-%d %H:%M:%S'),
552+ 'info_message': _('Import in progress in the specific wizard.'),
553+ }, context=context)
554+ res = hq_import.button_validate(cr, uid, wizard_id,
555+ context=context)
556+ elif model == 'msf.budget':
557+ budget_import = self.pool.get('wizard.budget.import')
558+ vals = {'import_file': wiz.import_file}
559+ wizard_id = budget_import.create(cr, uid, vals, context=context)
560+ res = budget_import.button_import(cr, uid, wizard_id,
561+ context=context)
562+
563+ else:
564+ raise osv.except_osv(_('Error'),
565+ _('The model \'%s\' is not made to be imported in CSV file.\n'
566+ 'Please contact the support team.') % (model))
567+ self.write(cr, uid, [wiz.id], {
568+ 'state': 'done',
569+ 'start_date': time.strftime('%Y-%m-%d %H:%M:%S'),
570+ 'info_message': _('Import has been done via the specific wizard. The latter had to give information on the import.'),
571+ }, context=context)
572+ return res
573+
574+ def import_xml(self, cr, uid, ids, context=None):
575+ """Create a thread to import the data after import checking
576+ """
577+ if context is None:
578+ context = {}
579+ if isinstance(ids, (int, long)):
580+ ids = [ids]
581+
582+ self.check_import(cr, uid, ids, context=context)
583+
584+ for wiz in self.browse(cr, uid, ids, context=context):
585+ rows, nb_rows = self.read_file(wiz, context=context)
586+ head = rows.next()
587+ selection = wiz.model_list_selection
588+ model = MODEL_DICT[selection]['model']
589+
590+ if model == 'user.access.configurator':
591+ # special case handling for this one
592+ model_obj = self.pool.get(model)
593+ wizard_id = model_obj.create(cr, uid, {}, context)
594+ model_obj.write(cr, uid, [wizard_id], {'file_to_import_uac':
595+ wiz.import_file}, context=context)
596+ return model_obj.do_process_uac(cr, uid, [wizard_id], context=context)
597+
598+ expected_headers = self._get_headers(cr, uid, model, selection=selection, context=context)
599+ if model not in MODEL_HEADER_NOT_CHECKED:
600+ self.check_headers(head, expected_headers, context=context)
601+
602+ self.write(cr, uid, [wiz.id], {
603+ 'total_lines_to_import': nb_rows,
604+ 'state': 'progress',
605+ 'start_date': time.strftime('%Y-%m-%d %H:%M:%S'),
606+ 'info_message': _('Import in progress, please leave this window open and press the button \'Update\' '
607+ 'to show the progression of the import. Otherwise, you can continue to use Unifield'),
608+ }, context=context)
609+ wiz.total_lines_to_import = nb_rows
610+
611+ thread = threading.Thread(
612+ target=self.bg_import,
613+ args=(cr.dbname, uid, wiz, expected_headers, rows, context),
614+ )
615+ thread.start()
616+ # for now we don't want background but foreground
617+ # in case background is needed, just set a value to wait time
618+ wait_time = None
619+ thread.join(wait_time)
620+ return True
621+
622+ def bg_import(self, dbname, uid, import_brw, headers, rows, context=None):
623+ """
624+ Run the import of lines in background
625+ :param dbname: Name of the database
626+ :param uid: ID of the res.users that calls this method
627+ :param import_brw: browse_record of a wizard.import.batch
628+ :param headers: List of expected headers
629+ :param rows: Iterator on file rows
630+ :param context: Context of the call
631+ :return: True
632+ """
633+ if context is None:
634+ context = {}
635+ cr = pooler.get_db(dbname).cursor()
636+ model = MODEL_DICT[import_brw.model_list_selection]['model']
637+ impobj = self.pool.get(model)
638+
639+ import_data_obj = self.pool.get('import_data')
640+ prod_nomenclature_obj = self.pool.get('product.nomenclature')
641+
642+ # Manage errors
643+ import_errors = {}
644+
645+ def save_error(errors, row_index):
646+ if not isinstance(errors, list):
647+ errors = [errors]
648+ import_errors.setdefault(row_index+2, [])
649+ import_errors[row_index+2].extend(errors)
650+
651+ # Manage warnings
652+ import_warnings = {}
653+
654+ def save_warnings(warnings):
655+ if not isinstance(warnings, list):
656+ warnings = [warnings]
657+ import_warnings.setdefault(row_index+2, [])
658+ import_warnings[row_index+2].extend(warnings)
659+
660+ start_time = time.time()
661+
662+ if model == 'product.product':
663+ # Create the cache
664+ if not hasattr(self, '_cache'):
665+ self._cache = {}
666+ self._cache.setdefault(dbname, {})
667+
668+ if not hasattr(prod_nomenclature_obj, '_cache'):
669+ prod_nomenclature_obj._cache = {}
670+ prod_nomenclature_obj._cache.setdefault(dbname, {})
671+
672+ # Clear the cache
673+ self._cache[dbname] = {'product.nomenclature': {'name': {}, 'complete_name': {}},
674+ 'product.uom': {'name': {}},
675+ 'product.asset.type': {'name': {}},
676+ 'product.international.status': {'name': {}},
677+ }
678+ # Product nomenclature
679+ cr.execute('SELECT name, id FROM product_nomenclature;')
680+ for nv in cr.dictfetchall():
681+ self._cache[dbname]['product.nomenclature']['name'].update({nv['name']: nv['id']})
682+ # Product category
683+ cr.execute('SELECT id, family_id FROM product_category;')
684+ for pc in cr.dictfetchall():
685+ prod_nomenclature_obj._cache[dbname].update({pc['family_id']: pc['id']})
686+ # Product nomenclature complete name
687+ cr.execute('''SELECT id, name FROM
688+(
689+(SELECT
690+ n0.id, n0.name AS name
691+FROM product_nomenclature n0
692+WHERE n0.level = 0)
693+UNION
694+(SELECT n1.id, n0.name ||' | '|| n1.name AS name
695+FROM product_nomenclature n1
696+ LEFT JOIN product_nomenclature n0 ON n1.parent_id = n0.id
697+WHERE n1.level = 1)
698+UNION
699+(SELECT n2.id, n0.name ||' | '|| n1.name ||' | '|| n2.name AS name
700+FROM product_nomenclature n1
701+ LEFT JOIN product_nomenclature n0 ON n1.parent_id = n0.id
702+ LEFT JOIN product_nomenclature n2 ON n2.parent_id = n1.id
703+WHERE n2.level = 2)
704+UNION
705+(SELECT n3.id, n0.name ||' | '|| n1.name ||' | '|| n2.name ||' | '|| n3.name AS name
706+FROM product_nomenclature n1
707+ LEFT JOIN product_nomenclature n0 ON n1.parent_id = n0.id
708+ LEFT JOIN product_nomenclature n2 ON n2.parent_id = n1.id
709+ LEFT JOIN product_nomenclature n3 ON n3.parent_id = n2.id
710+WHERE n3.level = 3)
711+) AS cn''')
712+ for cnv in cr.dictfetchall():
713+ self._cache[dbname]['product.nomenclature']['complete_name'].update({cnv['name']: cnv['id']})
714+ # Product UoM
715+ cr.execute('SELECT name, id FROM product_uom;')
716+ for uv in cr.dictfetchall():
717+ self._cache[dbname]['product.uom']['name'].update({uv['name']: uv['id']})
718+ # Asset type
719+ cr.execute('SELECT name, id FROM product_asset_type;')
720+ for av in cr.dictfetchall():
721+ self._cache[dbname]['product.asset.type']['name'].update({av['name']: av['id']})
722+ # International status
723+ cr.execute('SELECT name, id FROM product_international_status;')
724+ for iv in cr.dictfetchall():
725+ self._cache[dbname]['product.international.status']['name'].update({iv['name']: iv['id']})
726+
727+ fields_def = impobj.fields_get(cr, uid, context=context)
728+ i = 0
729+
730+ def _get_obj(header, value, fields_def):
731+ list_obj = header.split('.')
732+ relation = fields_def[list_obj[0]]['relation']
733+ if impobj._name == 'product.product' and value in self._cache.get(dbname, {}).get(relation, {}).get(list_obj[1], {}):
734+ return self._cache[dbname][relation][list_obj[1]][value]
735+ new_obj = self.pool.get(relation)
736+ if list_obj[1] == 'id':
737+ imd_obj = self.pool.get('ir.model.data')
738+
739+ if '.' in value:
740+ module, xml_id = value.rsplit('.', 1)
741+ else:
742+ module, xml_id = model, value
743+ record_id = imd_obj._get_id(cr, uid, module, xml_id)
744+ ir_model_data = imd_obj.read(cr, uid, [record_id], ['res_id'])
745+ if not ir_model_data:
746+ raise ValueError('No references to %s.%s' % (module, xml_id))
747+ newids = [ir_model_data[0]['res_id']]
748+ else:
749+ newids = new_obj.search(cr, uid, [(list_obj[1], '=', value)], limit=1)
750+ if not newids:
751+ # no obj
752+ raise osv.except_osv(_('Warning !'), _('%s \'%s\' does not exist') % (new_obj._description, value,))
753+
754+ if impobj._name == 'product.product':
755+ self._cache[dbname].setdefault(relation, {})
756+ self._cache[dbname][relation].setdefault(list_obj[1], {})
757+ self._cache[dbname][relation][list_obj[1]][value] = newids[0]
758+ return newids[0]
759+
760+ def process_data(field, value, fields_def):
761+ if value is None or field not in fields_def:
762+ return
763+ if '.' not in field:
764+ if fields_def[field]['type'] == 'selection':
765+ if impobj == 'product.product' and self._cache[dbname].get('product.product.%s.%s' % (field, value), False):
766+ value = self._cache[dbname]['product.product.%s.%s' % (field, value)]
767+ else:
768+ for key, val in fields_def[field]['selection']:
769+ if value.lower() in [tools.ustr(key).lower(), tools.ustr(val).lower()]:
770+ value = key
771+ if impobj == 'product.product':
772+ self._cache[dbname].setdefault('product.product.%s' % field, {})
773+ self._cache[dbname]['product.product.%s.%s' % (field, value)] = key
774+ break
775+ return value
776+
777+ else:
778+ if fields_def[field.split('.')[0]]['type'] in 'many2one':
779+ return _get_obj(field, value, fields_def)
780+
781+ raise osv.except_osv(_('Warning !'), _('%s does not exist')%(value,))
782+
783+ i = 1
784+ nb_error = 0
785+ nb_succes = 0
786+ nb_update_success = 0
787+ col_datas = {}
788+ nb_imported_lines = 0
789+ header_codes = [x[3] for x in headers]
790+ if import_data_obj.pre_hook.get(impobj._name):
791+ # for headers mod.
792+ col_datas = import_data_obj.pre_hook[impobj._name](impobj, cr, uid, header_codes, {}, col_datas)
793+
794+ for row_index, row in enumerate(rows):
795+ res, errors, line_data = self.check_error_and_format_row(import_brw.id, row, headers, context=context)
796+ if res < 0:
797+ save_error(errors, row_index)
798+ continue
799+
800+ if all(not x for x in line_data):
801+ save_warnings(
802+ _('Line seemed empty, so this line was ignored')
803+ )
804+ continue
805+
806+ newo2m = False
807+ delimiter = False
808+ o2mdatas = {}
809+ i += 1
810+ data = {}
811+ try:
812+ if model == 'hq.entries':
813+ hq_entries_obj = self.pool.get('hq.entries.import')
814+ hq_entries_obj.update_hq_entries(cr, uid, line_data, context=context)
815+ continue
816+
817+ n = 0
818+ line_ok = True
819+ if import_data_obj.pre_hook.get(impobj._name):
820+ import_data_obj.pre_hook[impobj._name](impobj, cr, uid, header_codes, line_data, col_datas)
821+
822+ for n, h in enumerate(header_codes):
823+ if isinstance(line_data[n], basestring):
824+ line_data[n] = line_data[n].rstrip()
825+
826+ # UFTP-327
827+ # if required reject cells with exceeded field length
828+ if 'import_data_field_max_size' in context:
829+ if h in context['import_data_field_max_size']:
830+ max_size = context['import_data_field_max_size'][h]
831+ if len(line_data[n]) > max_size:
832+ msg_tpl = "field '%s' value exceed field length of %d"
833+ msg = msg_tpl % (h , max_size, )
834+ logging.getLogger('import data').info(
835+ 'Error %s'% (msg, ))
836+ cr.rollback()
837+ error = "Line %s, row: %s, %s" % (i, n, msg, )
838+ save_error(error, row_index)
839+ nb_error += 1
840+ line_ok = False
841+ break
842+
843+ if newo2m and ('.' not in h or h.split('.')[0] != newo2m or h.split('.')[1] == delimiter):
844+ data.setdefault(newo2m, []).append((0, 0, o2mdatas.copy()))
845+ o2mdatas = {}
846+ delimiter = False
847+ newo2m = False
848+ if '.' not in h:
849+ # type datetime, date, bool, int, float
850+ value = process_data(h, line_data[n], fields_def)
851+ if value is not None:
852+ data[h] = value
853+ else:
854+ points = h.split('.')
855+ if row[n] and fields_def[points[0]]['type'] == 'one2many':
856+ newo2m = points[0]
857+ delimiter = points[1]
858+ new_fields_def = self.pool.get(fields_def[newo2m]['relation']).fields_get(cr, uid, context=context)
859+ o2mdatas[points[1]] = process_data('.'.join(points[1:]), line_data[n], new_fields_def)
860+ elif fields_def[points[0]]['type'] == 'many2one':
861+ if not line_data[n]:
862+ data[points[0]] = False
863+ elif line_data[n]:
864+ data[points[0]] = _get_obj(h, line_data[n], fields_def) or False
865+ elif fields_def[points[0]]['type'] == 'many2many' and line_data[n]:
866+ data.setdefault(points[0], []).append((4, _get_obj(h, line_data[n], fields_def)))
867+ if not line_ok:
868+ continue
869+ if newo2m and o2mdatas:
870+ data.setdefault(newo2m, []).append((0, 0, o2mdatas.copy()))
871+
872+ if import_data_obj.post_hook.get(impobj._name):
873+ import_data_obj.post_hook[impobj._name](impobj, cr, uid, data, line_data, header_codes)
874+
875+ # Search if an object already exist. If not, create it.
876+ ids_to_update = []
877+
878+ if impobj._name == 'product.product':
879+ # Allow to update the product, use xmlid_code or default_code
880+ if 'xmlid_code' in data:
881+ ids_to_update = impobj.search(cr, uid, [('xmlid_code',
882+ '=', data['xmlid_code'])], order='NO_ORDER')
883+ if 'default_code' in data:
884+ ids_to_update = impobj.search(cr, uid, [('default_code',
885+ '=', data['default_code'])], order='NO_ORDER')
886+ elif impobj._name == 'product.nomenclature':
887+ ids_to_update = impobj.search(cr, uid, [('msfid', '=',
888+ data['msfid'])], order='NO_ORDER')
889+ elif impobj._name == 'product.category':
890+ ids_to_update = impobj.search(cr, uid, [('msfid', '=',
891+ data['msfid'])], order='NO_ORDER')
892+
893+ if ids_to_update:
894+ #UF-2170: remove the standard price value from the list for update product case
895+ if 'standard_price' in data:
896+ del data['standard_price']
897+ impobj.write(cr, uid, ids_to_update, data)
898+ nb_update_success += 1
899+
900+ else:
901+ impobj.create(cr, uid, data, context={'from_import_menu': True})
902+ nb_succes += 1
903+ except osv.except_osv, e:
904+ logging.getLogger('import data').info('Error %s' % e.value)
905+ cr.rollback()
906+ save_error(e.value, row_index)
907+ nb_error += 1
908+ except Exception, e:
909+ cr.rollback()
910+ logging.getLogger('import data').info('Error %s' % e)
911+ save_error(e, row_index)
912+ nb_error += 1
913+ else:
914+ nb_imported_lines += 1
915+
916+ self.write(cr, uid, [import_brw.id], {'total_lines_imported': nb_imported_lines}, context=context)
917+
918+ warn_msg = ''
919+ for line_number in sorted(import_warnings.keys()):
920+ warnings = import_warnings[line_number]
921+ for warn in warnings:
922+ warn_msg += _('Line %s: %s') % (line, warn)
923+ if not warn_msg.endswith('\n'):
924+ warn_msg += '\n'
925+
926+ err_msg = ''
927+ for line_number in sorted(import_errors.keys()):
928+ errors = import_errors[line_number]
929+ for err in errors:
930+ err_msg += _('Line %s: %s') % (line_number, err)
931+ if not err_msg.endswith('\n'):
932+ err_msg += '\n'
933+
934+ if err_msg:
935+ cr.rollback()
936+
937+ info_msg = _('''Processing of file completed in %s second(s)!
938+- Total lines to import: %s
939+- Total lines %s: %s %s
940+- Total lines with errors: %s %s
941+%s
942+ ''') % (
943+ str(round(time.time() - start_time, 1)),
944+ import_brw.total_lines_to_import-1,
945+ err_msg and _('without errors') or _('imported'),
946+ nb_imported_lines,
947+ warn_msg and _('(%s line(s) with warning - see warning messages below)') % (
948+ len(import_warnings.keys()) or '',
949+ ),
950+ err_msg and len(import_errors.keys()) or 0,
951+ err_msg and _('(see error messages below)'),
952+ err_msg and _("no data will be imported until all the error messages are corrected") or '',
953+ )
954+
955+ self.write(cr, uid, [import_brw.id], {
956+ 'error_message': err_msg,
957+ 'show_error': err_msg and True or False,
958+ 'warning_message': warn_msg,
959+ 'show_warning': warn_msg and True or False,
960+ 'info_message': info_msg,
961+ 'state': 'done',
962+ 'end_date': time.strftime('%Y-%m-%d %H:%M:%S'),
963+ }, context=context)
964+
965+ if import_data_obj.post_load_hook.get(impobj._name):
966+ import_data_obj.post_load_hook[impobj._name](impobj, cr, uid)
967+
968+ if impobj == 'product.product':
969+ # Clear the cache
970+ self._cache[dbname] = {}
971+ prod_nomenclature_obj._cache[dbname] = {}
972+
973+
974+ cr.commit()
975+ cr.close()
976+
977+ return True
978+
979+msf_import_export()
980+
981+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
982
983=== added file 'bin/addons/msf_doc_import/msf_import_export_conf.py'
984--- bin/addons/msf_doc_import/msf_import_export_conf.py 1970-01-01 00:00:00 +0000
985+++ bin/addons/msf_doc_import/msf_import_export_conf.py 2017-09-27 13:17:20 +0000
986@@ -0,0 +1,579 @@
987+# encoding: utf-8
988+##############################################################################
989+#
990+# OpenERP, Open Source Management Solution
991+# Copyright (C) 2017 MSF, TeMPO Consulting
992+#
993+# This program is free software: you can redistribute it and/or modify
994+# it under the terms of the GNU General Public License as published by
995+# the Free Software Foundation, either version 3 of the License, or
996+# (at your option) any later version.
997+#
998+# This program is distributed in the hope that it will be useful,
999+# but WITHOUT ANY WARRANTY; without even the implied warranty of
1000+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1001+# GNU General Public License for more details.
1002+#
1003+# You should have received a copy of the GNU General Public License
1004+# along with this program. If not, see <http://www.gnu.org/licenses/>.
1005+#
1006+##############################################################################
1007+
1008+from tools.translate import _
1009+
1010+MODEL_DICT = {
1011+ # SUPPLY
1012+ 'products': {
1013+ 'name': 'Products',
1014+ 'domain_type': 'supply',
1015+ 'model': 'product.product',
1016+ },
1017+ 'product_nomenclature': {
1018+ 'name': 'Product Nomenclature',
1019+ 'domain_type': 'supply',
1020+ 'model': 'product.nomenclature',
1021+ },
1022+ 'product_category': {
1023+ 'name': 'Product Categories',
1024+ 'domain_type': 'supply',
1025+ 'model': 'product.category',
1026+ },
1027+ 'product_list': {
1028+ 'name': 'Products Lists',
1029+ 'domain_type': 'supply',
1030+ 'model': 'product.list',
1031+ },
1032+ 'product_list_line': {
1033+ 'name': 'Products Lists Lines',
1034+ 'domain_type': 'supply',
1035+ 'model': 'product.list.line',
1036+ },
1037+ 'suppliers': {
1038+ 'name': 'Suppliers',
1039+ 'domain_type': 'supply',
1040+ 'model': 'res.partner',
1041+ 'domain': [('supplier', '=', True)],
1042+ },
1043+ 'supplier_catalogues': {
1044+ 'name': 'Supplier Catalogues',
1045+ 'domain_type': 'supply',
1046+ 'model': 'supplier.catalogue',
1047+ },
1048+ 'supplier_catalogues_lines': {
1049+ 'name': 'Supplier Catalogue Lines',
1050+ 'domain_type': 'supply',
1051+ 'model': 'supplier.catalogue.line',
1052+ },
1053+
1054+
1055+ # FINANCE
1056+ 'gl_accounts': {
1057+ 'name': 'GL Accounts',
1058+ 'domain_type': 'finance',
1059+ 'model': 'account.account'
1060+ },
1061+ 'gl_journals': {
1062+ 'name': 'GL Journals',
1063+ 'domain_type': 'finance',
1064+ 'model': 'account.journal'
1065+ },
1066+ 'analytic_accounts': {
1067+ 'name': 'Analytic Accounts',
1068+ 'domain_type': 'finance',
1069+ 'model': 'account.analytic.account'
1070+ },
1071+ 'analytic_journals': {
1072+ 'name': 'Analytic Journals',
1073+ 'domain_type': 'finance',
1074+ 'model': 'account.analytic.journal'
1075+ },
1076+ 'employees': {
1077+ 'name': 'Employees',
1078+ 'domain_type': 'finance',
1079+ 'model': 'hr.employee'
1080+ },
1081+ 'hq_entries': {
1082+ 'name': 'HQ Entries',
1083+ 'domain_type': 'finance',
1084+ 'model': 'hq.entries'
1085+ },
1086+ 'currency_rate': {
1087+ 'name': 'Currencies Rates',
1088+ 'domain_type': 'finance',
1089+ 'model': 'res.currency.rate'
1090+ },
1091+ 'budget': {
1092+ 'name': 'Budget',
1093+ 'domain_type': 'finance',
1094+ 'model': 'msf.budget'
1095+ },
1096+
1097+
1098+ # NON FUNCTIONNAL
1099+ 'user_groups': {
1100+ 'name': 'User Groups',
1101+ 'domain_type': 'non_functionnal',
1102+ 'model': 'res.groups'
1103+ },
1104+ 'user_access': {
1105+ 'name': 'User Access',
1106+ 'domain_type': 'non_functionnal',
1107+ 'model': 'user.access.configurator'
1108+ },
1109+ 'record_rules': {
1110+ 'name': 'Record Rules',
1111+ 'domain_type': 'non_functionnal',
1112+ 'model': 'ir.rule'
1113+ },
1114+ 'access_control_list': {
1115+ 'name': 'Access Controls List',
1116+ 'domain_type': 'non_functionnal',
1117+ 'model': 'ir.model.access'
1118+ },
1119+ 'field_access_rules': {
1120+ 'name': 'Field Access Rules',
1121+ 'domain_type': 'non_functionnal',
1122+ 'model': 'msf_field_access_rights.field_access_rule'
1123+ },
1124+ 'field_access_rule_lines': {
1125+ 'name': 'Field Access Rule Lines',
1126+ 'domain_type': 'non_functionnal',
1127+ 'model': 'msf_field_access_rights.field_access_rule_line'
1128+ },
1129+ 'button_access_rules': {
1130+ 'name': 'Button Access Rules',
1131+ 'domain_type': 'non_functionnal',
1132+ 'model': 'msf_button_access_rights.button_access_rule'
1133+ },
1134+ 'window_actions': {
1135+ 'name': 'Window Actions',
1136+ 'domain_type': 'non_functionnal',
1137+ 'model': 'ir.actions.act_window'
1138+ },
1139+}
1140+
1141+MODEL_DATA_DICT = {
1142+ # SUPPLY
1143+ 'products': {
1144+ 'header_list': [
1145+ 'default_code',
1146+ 'name',
1147+ 'xmlid_code',
1148+ 'old_code',
1149+ 'type',
1150+ 'transport_ok',
1151+ 'subtype',
1152+ 'asset_type_id.name',
1153+ 'procure_method',
1154+ 'supply_method',
1155+ 'standard_price',
1156+ 'volume',
1157+ 'weight',
1158+ 'international_status.name',
1159+ 'state.name',
1160+ 'active',
1161+ 'perishable',
1162+ 'batch_management',
1163+ 'uom_id.name',
1164+ 'uom_po_id.name',
1165+ 'nomen_manda_0.name',
1166+ 'nomen_manda_1.name',
1167+ 'nomen_manda_2.name',
1168+ 'nomen_manda_3.name',
1169+ 'life_time',
1170+ 'use_time',
1171+ 'short_shelf_life',
1172+ 'alert_time',
1173+ 'heat_sensitive_item.code',
1174+ 'cold_chain',
1175+ 'sterilized',
1176+ 'single_use',
1177+ 'narcotic',
1178+ 'justification_code_id.code',
1179+ 'controlled_substance',
1180+ 'closed_article',
1181+ 'restricted_country',
1182+ 'country_restriction',
1183+ 'dangerous_goods',
1184+ 'un_code',
1185+ 'criticism',
1186+ 'abc_class',
1187+ 'product_catalog_path',
1188+ 'description',
1189+ 'description2',
1190+ 'description_sale',
1191+ 'description_purchase',
1192+ 'procure_delay',
1193+ 'property_account_income.code',
1194+ 'property_account_expense.code',
1195+ ],
1196+ 'required_field_list': [
1197+ 'name',
1198+ 'international_status.name',
1199+ 'nomen_manda_0.name',
1200+ 'nomen_manda_1.name',
1201+ 'nomen_manda_2.name',
1202+ 'nomen_manda_3.name',
1203+ ],
1204+ 'hide_download_all_entries': True,
1205+ },
1206+ 'product_nomenclature': {
1207+ 'header_list': [
1208+ 'level',
1209+ 'name',
1210+ 'type',
1211+ 'parent_id.msfid',
1212+ 'msfid',
1213+ ],
1214+ 'required_field_list': [
1215+ 'level',
1216+ 'name',
1217+ ],
1218+ 'hide_download_3_entries': True,
1219+ 'hide_download_all_entries': True,
1220+ },
1221+ 'product_category': {
1222+ 'header_list': [
1223+ 'type',
1224+ 'property_account_expense_categ',
1225+ 'property_account_income_categ',
1226+ 'name',
1227+ 'property_stock_journal',
1228+ 'donation_expense_account',
1229+ 'family_id',
1230+ 'msfid',
1231+ ],
1232+ 'required_field_list': [
1233+ 'name',
1234+ 'family_id',
1235+ 'msfid',
1236+ ],
1237+ },
1238+ 'product_list': {
1239+ 'header_list': [
1240+ 'name',
1241+ 'type',
1242+ 'creator',
1243+ 'ref',
1244+ ],
1245+ 'required_field_list': [
1246+ 'name',
1247+ 'type',
1248+ 'creator',
1249+ ],
1250+ },
1251+ 'product_list_line': {
1252+ 'header_list': [
1253+ 'list_id.name',
1254+ 'ref',
1255+ 'name',
1256+ 'comment',
1257+ ],
1258+ 'required_field_list': [
1259+ 'ref',
1260+ 'name',
1261+ ],
1262+ },
1263+ 'suppliers': {
1264+ 'header_list': [
1265+ 'address.type',
1266+ 'address.city',
1267+ 'address.name',
1268+ 'address.street',
1269+ 'address.zip',
1270+ 'address.country_id.name',
1271+ 'address.email',
1272+ 'property_account_payable.code',
1273+ 'property_account_receivable.code',
1274+ 'name',
1275+ 'lang',
1276+ 'partner_type',
1277+ 'customer',
1278+ 'supplier',
1279+ 'property_product_pricelist_purchase.currency_id',
1280+ 'property_product_pricelist.currency_id',
1281+ ],
1282+ 'required_field_list': [
1283+ 'property_account_payable.code',
1284+ 'property_account_receivable.code',
1285+ 'name',
1286+ ],
1287+ },
1288+ 'supplier_catalogues': {
1289+ 'header_list': [
1290+ 'name',
1291+ 'period_from',
1292+ 'period_to',
1293+ 'currency_id.name',
1294+ 'partner_id.name',
1295+ ],
1296+ 'required_field_list': [
1297+ 'name',
1298+ 'currency_id.name',
1299+ 'partner_id.name',
1300+ ],
1301+ },
1302+ 'supplier_catalogues_lines': {
1303+ 'header_list': [
1304+ 'catalogue_id.name',
1305+ 'product_id.code',
1306+ 'product_id.name',
1307+ 'line_uom_id.name',
1308+ 'min_qty',
1309+ 'unit_price',
1310+ 'rounding',
1311+ 'min_order_qty',
1312+ 'comment',
1313+ ],
1314+ 'required_field_list': [
1315+ 'catalogue_id.name',
1316+ 'product_id.code',
1317+ 'line_uom_id.name',
1318+ 'min_qty',
1319+ 'unit_price',
1320+ ],
1321+ },
1322+
1323+
1324+ # FINANCE
1325+ 'gl_accounts': {
1326+ 'header_list': [
1327+ 'user_type.name',
1328+ 'accrual_account',
1329+ 'activation_date',
1330+ 'code',
1331+ 'default_destination_id.id',
1332+ 'inactivation_date',
1333+ 'type',
1334+ 'name',
1335+ 'note',
1336+ 'type_for_register',
1337+ 'reconcile',
1338+ 'parent_id.code',
1339+ 'is_not_hq_correctible',
1340+ 'shrink_entries_for_hq',
1341+ 'currency_revaluation',
1342+ ],
1343+ 'required_field_list': [
1344+ 'user_type.name',
1345+ 'activation_date',
1346+ 'code',
1347+ 'type',
1348+ 'name',
1349+ 'type_for_register',
1350+ ],
1351+ },
1352+ 'gl_journals': {
1353+ 'header_list': [
1354+ 'code',
1355+ 'currency.name',
1356+ 'default_credit_account_id.code',
1357+ 'default_debit_account_id.code',
1358+ 'name',
1359+ 'type',
1360+ 'analytic_journal_id.name',
1361+ ],
1362+ 'required_field_list': [
1363+ 'code',
1364+ 'name',
1365+ 'type',
1366+ 'analytic_journal_id.name',
1367+ ],
1368+ },
1369+ 'analytic_accounts': {
1370+ 'header_list': [
1371+ 'name',
1372+ 'code',
1373+ 'category',
1374+ 'parent_id.code',
1375+ 'type',
1376+ 'date_start',
1377+ ],
1378+ 'required_field_list': [
1379+ 'name',
1380+ 'code',
1381+ 'category',
1382+ 'parent_id.code',
1383+ 'date_start',
1384+ ],
1385+ },
1386+ 'analytic_journals': {
1387+ 'header_list': [
1388+ 'active',
1389+ 'code',
1390+ 'name',
1391+ 'type',
1392+ ],
1393+ 'required_field_list': [
1394+ 'code',
1395+ 'name',
1396+ 'type',
1397+ ],
1398+ },
1399+ 'employees': {
1400+ 'header_list': [
1401+ 'name',
1402+ 'identification_id',
1403+ 'active',
1404+ ],
1405+ 'required_field_list': [
1406+ 'name',
1407+ 'identification_id',
1408+ ],
1409+ 'hide_export': True,
1410+ },
1411+ 'hq_entries': {
1412+ 'header_list': [
1413+ 'name',
1414+ 'ref',
1415+ 'document_date',
1416+ 'date',
1417+ 'account_id',
1418+ 'partner_txt',
1419+ 'amount',
1420+ 'currency_id.name',
1421+ 'destination_id',
1422+ 'cost_center_id',
1423+ 'analytic_id',
1424+ 'free_1_id',
1425+ 'free_2_id',
1426+ ],
1427+ 'required_field_list': [
1428+ 'name',
1429+ 'account_id',
1430+ 'currency_id.name',
1431+ 'destination_id',
1432+ 'analytic_id',
1433+ ],
1434+ 'csv_button': True,
1435+ 'hide_export': True,
1436+ },
1437+ 'currency_rate': {
1438+ 'header_list': [
1439+ 'name',
1440+ 'currency_id.name',
1441+ 'rate',
1442+ ],
1443+ 'required_field_list': [
1444+ 'name',
1445+ 'rate',
1446+ 'currency_id.name',
1447+ ],
1448+ },
1449+ 'budget': {
1450+ 'header_list': [],
1451+ 'required_field_list': [],
1452+ 'csv_button': True,
1453+ 'hide_export': True,
1454+ },
1455+
1456+
1457+ # NON FUNCTIONNAL
1458+ 'user_groups': {
1459+ 'header_list': [
1460+ 'name',
1461+ ],
1462+ 'required_field_list': [
1463+ 'name',
1464+ ],
1465+ },
1466+ 'user_access': {
1467+ 'header_list': [
1468+ ],
1469+ 'required_field_list': [
1470+ ],
1471+ 'hide_export': True,
1472+ },
1473+ 'record_rules': {
1474+ 'header_list': [
1475+ 'model_id.model',
1476+ 'name',
1477+ 'global',
1478+ 'domain_force',
1479+ 'perm_read',
1480+ 'perm_write',
1481+ 'perm_create',
1482+ 'perm_unlink',
1483+ ],
1484+ 'required_field_list': [
1485+ 'model_id.model',
1486+ 'name',
1487+ ],
1488+ },
1489+ 'access_control_list': {
1490+ 'header_list': [
1491+ 'name',
1492+ 'model_id.model',
1493+ 'group_id.name',
1494+ 'perm_read',
1495+ 'perm_write',
1496+ 'perm_create',
1497+ 'perm_unlink',
1498+ ],
1499+ 'required_field_list': [
1500+ 'name',
1501+ 'model_id.model',
1502+ ],
1503+ },
1504+ 'field_access_rules': {
1505+ 'header_list': [
1506+ 'name',
1507+ 'model_id.model',
1508+ 'instance_level',
1509+ 'domain_text',
1510+ 'status',
1511+ ],
1512+ 'required_field_list': [
1513+ 'name',
1514+ 'model_id.model',
1515+ 'instance_level',
1516+ ],
1517+ },
1518+ 'field_access_rule_lines': {
1519+ 'header_list': [
1520+ 'field_access_rule.name',
1521+ 'field_access_rule_model_id',
1522+ 'field.name',
1523+ 'field_name',
1524+ 'write_access',
1525+ 'value_not_synchronized_on_create',
1526+ 'value_not_synchronized_on_write',
1527+ ],
1528+ 'required_field_list': [
1529+ 'field_access_rule',
1530+ 'field',
1531+ ],
1532+ },
1533+ 'button_access_rules': {
1534+ 'header_list': [
1535+ 'model_id.model',
1536+ 'view_id.name',
1537+ 'label',
1538+ 'name',
1539+ 'group_names',
1540+ 'type',
1541+ ],
1542+ 'required_field_list': [
1543+ 'model_id.model',
1544+ 'view_id.name',
1545+ 'name',
1546+ ],
1547+ },
1548+ 'window_actions': {
1549+ 'header_list': [
1550+ 'name',
1551+ 'res_model',
1552+ 'view_type',
1553+ 'view_id.name',
1554+ 'domain',
1555+ 'groups_id',
1556+ ],
1557+ 'required_field_list': [
1558+ 'name',
1559+ 'res_model',
1560+ 'view_type',
1561+ ],
1562+ },
1563+}
1564+
1565+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
1566
1567=== added file 'bin/addons/msf_doc_import/report/export_generic.mako'
1568--- bin/addons/msf_doc_import/report/export_generic.mako 1970-01-01 00:00:00 +0000
1569+++ bin/addons/msf_doc_import/report/export_generic.mako 2017-09-27 13:17:20 +0000
1570@@ -0,0 +1,137 @@
1571+<?xml version="1.0"?>
1572+<?mso-application progid="Excel.Sheet"?>
1573+<Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet"
1574+ xmlns:o="urn:schemas-microsoft-com:office:office"
1575+ xmlns:x="urn:schemas-microsoft-com:office:excel"
1576+ xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"
1577+ xmlns:html="http://www.w3.org/TR/REC-html40">
1578+
1579+ <DocumentProperties xmlns="urn:schemas-microsoft-com:office:office">
1580+ <Author>MSFUser</Author>
1581+ <LastAuthor>MSFUser</LastAuthor>
1582+ <Created>2012-06-18T15:46:09Z</Created>
1583+ <Company>Medecins Sans Frontieres</Company>
1584+ <Version>11.9999</Version>
1585+ </DocumentProperties>
1586+
1587+ <ExcelWorkbook xmlns="urn:schemas-microsoft-com:office:excel">
1588+ <WindowHeight>13170</WindowHeight>
1589+ <WindowWidth>19020</WindowWidth>
1590+ <WindowTopX>120</WindowTopX>
1591+ <WindowTopY>60</WindowTopY>
1592+ <ProtectStructure>False</ProtectStructure>
1593+ <ProtectWindows>False</ProtectWindows>
1594+ </ExcelWorkbook>
1595+
1596+ <Styles>
1597+ <Style ss:ID="header">
1598+ <Alignment ss:Horizontal="Center" ss:Vertical="Center" ss:WrapText="1"/>
1599+ <Interior ss:Color="#ffcc99" ss:Pattern="Solid"/>
1600+ <Font ss:Bold="1" ss:Color="#000000" />
1601+ <Borders>
1602+ <Border ss:Position="Bottom" ss:LineStyle="Continuous" ss:Weight="1" />
1603+ <Border ss:Position="Left" ss:LineStyle="Continuous" ss:Weight="1" />
1604+ <Border ss:Position="Right" ss:LineStyle="Continuous" ss:Weight="1" />
1605+ <Border ss:Position="Top" ss:LineStyle="Continuous" ss:Weight="1" />
1606+ </Borders>
1607+ <Protection />
1608+ </Style>
1609+ <Style ss:ID="String">
1610+ <Alignment ss:Horizontal="Center" ss:Vertical="Center" ss:WrapText="1"/>
1611+ <Borders>
1612+ <Border ss:Position="Bottom" ss:LineStyle="Continuous" ss:Weight="1" />
1613+ <Border ss:Position="Left" ss:LineStyle="Continuous" ss:Weight="1" />
1614+ <Border ss:Position="Right" ss:LineStyle="Continuous" ss:Weight="1" />
1615+ <Border ss:Position="Top" ss:LineStyle="Continuous" ss:Weight="1" />
1616+ </Borders>
1617+ <Protection ss:Protected="0" />
1618+ </Style>
1619+ <Style ss:ID="Boolean">
1620+ <Alignment ss:Horizontal="Center" ss:Vertical="Center" ss:WrapText="1"/>
1621+ <Borders>
1622+ <Border ss:Position="Bottom" ss:LineStyle="Continuous" ss:Weight="1" />
1623+ <Border ss:Position="Left" ss:LineStyle="Continuous" ss:Weight="1" />
1624+ <Border ss:Position="Right" ss:LineStyle="Continuous" ss:Weight="1" />
1625+ <Border ss:Position="Top" ss:LineStyle="Continuous" ss:Weight="1" />
1626+ </Borders>
1627+ <Protection ss:Protected="0" />
1628+ </Style>
1629+ <Style ss:ID="Float">
1630+ <Alignment ss:Horizontal="Center" ss:Vertical="Center" ss:WrapText="1"/>
1631+ <Borders>
1632+ <Border ss:Position="Bottom" ss:LineStyle="Continuous" ss:Weight="1" />
1633+ <Border ss:Position="Left" ss:LineStyle="Continuous" ss:Weight="1" />
1634+ <Border ss:Position="Right" ss:LineStyle="Continuous" ss:Weight="1" />
1635+ <Border ss:Position="Top" ss:LineStyle="Continuous" ss:Weight="1" />
1636+ </Borders>
1637+ <NumberFormat ss:Format="Fixed" />
1638+ <Protection ss:Protected="0" />
1639+ </Style>
1640+ <Style ss:ID="Number">
1641+ <Alignment ss:Horizontal="Center" ss:Vertical="Center" ss:WrapText="1"/>
1642+ <Borders>
1643+ <Border ss:Position="Bottom" ss:LineStyle="Continuous" ss:Weight="1" />
1644+ <Border ss:Position="Left" ss:LineStyle="Continuous" ss:Weight="1" />
1645+ <Border ss:Position="Right" ss:LineStyle="Continuous" ss:Weight="1" />
1646+ <Border ss:Position="Top" ss:LineStyle="Continuous" ss:Weight="1" />
1647+ </Borders>
1648+ <NumberFormat ss:Format="Fixed" />
1649+ <Protection ss:Protected="0" />
1650+ </Style>
1651+ <Style ss:ID="DateTime">
1652+ <Alignment ss:Horizontal="Center" ss:Vertical="Center" ss:WrapText="1"/>
1653+ <Borders>
1654+ <Border ss:Position="Bottom" ss:LineStyle="Continuous" ss:Weight="1"/>
1655+ <Border ss:Position="Left" ss:LineStyle="Continuous" ss:Weight="1"/>
1656+ <Border ss:Position="Right" ss:LineStyle="Continuous" ss:Weight="1"/>
1657+ <Border ss:Position="Top" ss:LineStyle="Continuous" ss:Weight="1"/>
1658+ </Borders>
1659+ <NumberFormat ss:Format="Short Date" />
1660+ <Protection ss:Protected="0" />
1661+ </Style>
1662+ </Styles>
1663+
1664+ <ss:Worksheet ss:Name="${data.get('model_name', _('Sheet 1'))|x}" ss:Protected="0">
1665+
1666+ <Table x:FullColumns="1" x:FullRows="1">
1667+
1668+ <% rows = getRows(data['model'], data['fields'], data.get('nb_lines'), data.get('domain'), data.get('template_only', False), data['context']) %>
1669+ <% headers = getHeaders(data['model'], data['fields'], rows, data['context']) %>
1670+ % for col in headers:
1671+ <Column ss:AutoFitWidth="1" ss:Width="${col[2] or 70|x}" ss:StyleID="${col[1]|x}" />
1672+ % endfor
1673+
1674+ <Row>
1675+ % for col in headers:
1676+ <Cell ss:StyleID="header">
1677+ <Data ss:Type="String">${col[0]|x}</Data>
1678+ </Cell>
1679+ % endfor
1680+ </Row>
1681+
1682+ % if not data.get('template_only', False):
1683+ % for row in rows:
1684+ <Row>
1685+ % for index, cell in enumerate(row):
1686+ <Cell ss:StyleID="${headers[index][1]|x}">
1687+ % if headers[index][1] == 'String' and not cell:
1688+ <Data ss:Type="String"></Data>
1689+ % else:
1690+ <Data ss:Type="String">${cell|x}</Data>
1691+ % endif
1692+ </Cell>
1693+ % endfor
1694+ </Row>
1695+ % endfor
1696+ % endif
1697+ </Table>
1698+
1699+ <x:WorksheetOptions xmlns="urn:schemas-microsoft-com:office:excel">
1700+ <ProtectScenarios>False</ProtectScenarios>
1701+ <EnableSelection>UnlockedCells</EnableSelection>
1702+ <AllowInsertRows />
1703+ </x:WorksheetOptions>
1704+
1705+ </ss:Worksheet>
1706+
1707+</Workbook>
1708
1709=== modified file 'bin/addons/msf_doc_import/report/import_generic_template.mako'
1710--- bin/addons/msf_doc_import/report/import_generic_template.mako 2016-08-15 11:49:05 +0000
1711+++ bin/addons/msf_doc_import/report/import_generic_template.mako 2017-09-27 13:17:20 +0000
1712@@ -46,6 +46,27 @@
1713 </Borders>
1714 <Protection ss:Protected="0" />
1715 </Style>
1716+ <Style ss:ID="Boolean">
1717+ <Alignment ss:Horizontal="Center" ss:Vertical="Center" ss:WrapText="1"/>
1718+ <Borders>
1719+ <Border ss:Position="Bottom" ss:LineStyle="Continuous" ss:Weight="1" />
1720+ <Border ss:Position="Left" ss:LineStyle="Continuous" ss:Weight="1" />
1721+ <Border ss:Position="Right" ss:LineStyle="Continuous" ss:Weight="1" />
1722+ <Border ss:Position="Top" ss:LineStyle="Continuous" ss:Weight="1" />
1723+ </Borders>
1724+ <Protection ss:Protected="0" />
1725+ </Style>
1726+ <Style ss:ID="Float">
1727+ <Alignment ss:Horizontal="Center" ss:Vertical="Center" ss:WrapText="1"/>
1728+ <Borders>
1729+ <Border ss:Position="Bottom" ss:LineStyle="Continuous" ss:Weight="1" />
1730+ <Border ss:Position="Left" ss:LineStyle="Continuous" ss:Weight="1" />
1731+ <Border ss:Position="Right" ss:LineStyle="Continuous" ss:Weight="1" />
1732+ <Border ss:Position="Top" ss:LineStyle="Continuous" ss:Weight="1" />
1733+ </Borders>
1734+ <NumberFormat ss:Format="Fixed" />
1735+ <Protection ss:Protected="0" />
1736+ </Style>
1737 <Style ss:ID="Number">
1738 <Alignment ss:Horizontal="Center" ss:Vertical="Center" ss:WrapText="1"/>
1739 <Borders>
1740
1741=== modified file 'bin/addons/msf_doc_import/report/import_generic_template.py'
1742--- bin/addons/msf_doc_import/report/import_generic_template.py 2016-07-27 09:38:38 +0000
1743+++ bin/addons/msf_doc_import/report/import_generic_template.py 2017-09-27 13:17:20 +0000
1744@@ -19,12 +19,64 @@
1745 #
1746 ##############################################################################
1747
1748+from report import report_sxw
1749 from report_webkit.webkit_report import XlsWebKitParser
1750
1751+
1752 XlsWebKitParser(
1753 'report.wizard.import.generic.template',
1754 'abstract.wizard.import',
1755 'addons/msf_doc_import/report/import_generic_template.mako',
1756 )
1757
1758+
1759+class report_generic_export_parser(report_sxw.rml_parse):
1760+
1761+ def __init__(self, cr, uid, name, context=None):
1762+ super(report_generic_export_parser, self).__init__(cr, uid, name, context=context)
1763+ self.localcontext.update({
1764+ 'getHeaders': self.getHeaders,
1765+ 'getRows': self.getRows,
1766+ })
1767+ return
1768+
1769+ def getHeaders(self, model, field_list, rows, context=None):
1770+ '''
1771+ get the column names of the table. Set the type of the column and the
1772+ size of it.
1773+ '''
1774+ import_export_obj = self.pool.get('msf.import.export')
1775+ return import_export_obj._get_headers(self.cr, self.uid, model,
1776+ selection=None, field_list=field_list, rows=rows, context=context)
1777+
1778+ def getRows(self, model, fields, nb_lines=None, domain=None,
1779+ template_only=False, context=None):
1780+ """
1781+ Return list of lines from given generic export
1782+ """
1783+ if context is None:
1784+ context={}
1785+ if template_only:
1786+ return []
1787+ if not domain:
1788+ domain = []
1789+ rows = []
1790+ counter = 0
1791+ chunk_size = 100
1792+ model_obj = self.pool.get(model)
1793+ ids = model_obj.search(self.cr, self.uid, domain, limit=nb_lines)
1794+ fields = [x.replace('.', '/') for x in fields]
1795+ for i in range(0, len(ids), chunk_size):
1796+ ids_chunk = ids[i:i + chunk_size]
1797+ counter += len(ids_chunk)
1798+ context['translate_selection_field'] = True
1799+ rows.extend(model_obj.export_data(self.cr, self.uid, ids_chunk, fields, context=context)['datas'])
1800+ return rows
1801+
1802+XlsWebKitParser(
1803+ 'report.wizard.export.generic',
1804+ 'msf.import.export',
1805+ 'addons/msf_doc_import/report/export_generic.mako',
1806+ parser=report_generic_export_parser,
1807+)
1808 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
1809
1810=== added file 'bin/addons/msf_doc_import/view/msf_import_export_view.xml'
1811--- bin/addons/msf_doc_import/view/msf_import_export_view.xml 1970-01-01 00:00:00 +0000
1812+++ bin/addons/msf_doc_import/view/msf_import_export_view.xml 2017-09-27 13:17:20 +0000
1813@@ -0,0 +1,99 @@
1814+<?xml version="1.0" encoding="utf-8" ?>
1815+<openerp>
1816+<data>
1817+
1818+ <record id="msf_import_export_view" model="ir.ui.view">
1819+ <field name="name">msf.import.export.view</field>
1820+ <field name="model">msf.import.export</field>
1821+ <field name="type">form</field>
1822+ <field name="arch" type="xml">
1823+ <form string="Import / Export">
1824+ <group>
1825+ <field name="display_file_import" invisible="1" />
1826+ <field name="display_file_export" invisible="1" />
1827+ <field name="csv_button" invisible="1" />
1828+ <field name="state" invisible="1" />
1829+ <field name='model_list_selection' on_change="domain_type_change(model_list_selection)" />
1830+ </group>
1831+ <group col="4" colspan="4">
1832+ <field name="hide_download_3_entries" invisible="1" />
1833+ <field name="hide_download_all_entries" invisible="1" />
1834+ <group colspan="2" col="2" name="file_import" attrs="{'invisible':[('display_file_import', '=', False)]}">
1835+ <separator string="File Import" colspan="2"/>
1836+ <field name="display_import_buttons" invisible="1" />
1837+ <field name="import_file" colspan="4" on_change="file_change(import_file)"/>
1838+ <button name="test_import" string="Test file" type="object" icon="gtk-ok" colspan="4" attrs="{'invisible':[('display_import_buttons', '=', False)]}" />
1839+ <button name="import_xml" string="Run import" type="object" icon="gtk-execute" colspan="4" attrs="{'invisible': ['|', '|', ('display_import_buttons', '=', False), ('state', '!=', 'draft'), ('csv_button', '=', True)]}" />
1840+ <button name="import_csv" string="Run import" type="object" icon="gtk-execute" colspan="4" attrs="{'invisible': ['|', '|', ('display_import_buttons', '=', False), ('state', '!=', 'draft'), ('csv_button', '=', False)]}" />
1841+ <separator colspan="4" string="Information" />
1842+ <field name="info_message" colspan="4" nolabel="1" />
1843+ </group>
1844+ <group colspan="2" col="2" name="file_export">
1845+ <separator string="File Export" colspan="2"/>
1846+ <group attrs="{'invisible':[('display_file_export', '=', False)]}">
1847+ <button name="download_template_file" string="Export empty template" icon="gtk-save" help="Download template file" type="object" />
1848+ <button name="download_3_entries_file" string="Export first 3 entries" type="object" icon="gtk-save" colspan="4" attrs="{'invisible':[('hide_download_3_entries', '=', True)]}"/>
1849+ <button name="download_all_entries_file" string="Export all data" type="object" icon="gtk-save" colspan="4" attrs="{'invisible':[('hide_download_all_entries', '=', True)]}"/>
1850+ </group>
1851+ </group>
1852+ <group colspan="4" attrs="{'invisible': [('show_warning', '=', False)]}">
1853+ <separator colspan="4" string="Warning messages" />
1854+ <field name="warning_message" nolabel="1" colspan="4" widget="full_text"/>
1855+ </group>
1856+
1857+ <group colspan="4" attrs="{'invisible': [('show_error', '=', False)]}">
1858+ <separator colspan="4" string="Error messages" />
1859+ <field name="error_message" nolabel="1" colspan="4" widget="full_text"/>
1860+ </group>
1861+ </group>
1862+ </form>
1863+ </field>
1864+ </record>
1865+
1866+
1867+ <record id="msf_import_export_supply_action" model="ir.actions.act_window">
1868+ <field name="name">Supply</field>
1869+ <field name="res_model">msf.import.export</field>
1870+ <field name="view_type">form</field>
1871+ <field name="view_mode">form</field>
1872+ <field name="target">current</field>
1873+ <field name="context">{'domain_type': 'supply'}</field>
1874+ </record>
1875+
1876+ <record id="msf_import_export_finance_action" model="ir.actions.act_window">
1877+ <field name="name">Finance</field>
1878+ <field name="res_model">msf.import.export</field>
1879+ <field name="view_type">form</field>
1880+ <field name="view_mode">form</field>
1881+ <field name="target">current</field>
1882+ <field name="context">{'domain_type': 'finance'}</field>
1883+ </record>
1884+
1885+ <record id="msf_import_export_non_functional_action" model="ir.actions.act_window">
1886+ <field name="name">Non Functional</field>
1887+ <field name="res_model">msf.import.export</field>
1888+ <field name="view_type">form</field>
1889+ <field name="view_mode">form</field>
1890+ <field name="target">current</field>
1891+ <field name="context">{'domain_type': 'non_functionnal'}</field>
1892+ </record>
1893+
1894+ <menuitem id="msf_import_export_menu"
1895+ name="Import / Export"
1896+ parent="object_query.menu_preferences" />
1897+
1898+ <menuitem id="msf_import_export_supply_menu"
1899+ parent="msf_import_export_menu"
1900+ action="msf_import_export_supply_action" />
1901+
1902+ <menuitem id="msf_import_export_finance_menu"
1903+ parent="msf_import_export_menu"
1904+ action="msf_import_export_finance_action" />
1905+
1906+ <menuitem id="msf_import_export_non_functional_menu"
1907+ parent="msf_import_export_menu"
1908+ action="msf_import_export_non_functional_action" />
1909+
1910+
1911+</data>
1912+</openerp>
1913
1914=== modified file 'bin/addons/msf_doc_import/wizard/abstract_wizard_import.py'
1915--- bin/addons/msf_doc_import/wizard/abstract_wizard_import.py 2017-03-20 09:49:38 +0000
1916+++ bin/addons/msf_doc_import/wizard/abstract_wizard_import.py 2017-09-27 13:17:20 +0000
1917@@ -39,7 +39,7 @@
1918 """
1919 Class used to export Header template.
1920 """
1921- type_ok = ['String', 'Number', 'DateTime']
1922+ type_ok = ['String', 'Number', 'DateTime', 'Boolean', 'Float']
1923
1924 def __new__(cls, name, ftype='String', size=70, tech_name=None, required=False):
1925 """
1926@@ -71,12 +71,12 @@
1927 :return: A datetime instance or False
1928 """
1929 # US:2527: accept only one format, reject other
1930- date_format = [
1931+ accepted_date_format = [
1932 '%d/%m/%Y',
1933 ]
1934
1935 d = False
1936- for dformat in date_format:
1937+ for dformat in accepted_date_format:
1938 try:
1939 d = DateTime.strptime(date_value, dformat)
1940 d = d.strftime('%Y-%m-%d %H:%M:%S')
1941@@ -130,9 +130,24 @@
1942 return (0, value, None)
1943 else:
1944 try:
1945+ if isinstance(value, basestring):
1946+ value = value.rstrip().replace(',', '.')
1947 return (0, float(value), None)
1948 except Exception as e:
1949 return (-1, value, e)
1950+ elif header[1] == 'Boolean':
1951+ if isinstance(value, bool):
1952+ pass
1953+ elif value.upper() in ('T', 'TRUE', '1'):
1954+ value = True
1955+ else:
1956+ value = False
1957+ elif header[1] == 'Number':
1958+ if vtype =='int':
1959+ try:
1960+ return (0, int(value), None)
1961+ except Exception as e:
1962+ return (-1, value, e)
1963
1964 return (0, value, None)
1965
1966@@ -429,9 +444,19 @@
1967 len(line_content), len(headers)
1968 ))
1969
1970+ # if the last comlumn(s) is(are) empty, line_content do not contain
1971+ # this column: len(line_content) is equal to len(headers) - number of
1972+ # empty columns at the end
1973+ if len(line_content) < len(headers):
1974+ # add None instead of the missing column
1975+ line_content += [None for x in range((len(headers) - len(line_content)))]
1976+
1977 data = []
1978 errors = []
1979 for col_index, col_value in enumerate(line_content):
1980+ if col_value is None:
1981+ data.append(None)
1982+ continue
1983 # Check data values according to expected type
1984 chk_res = ImportHeader.check_value(headers[col_index], col_value.data, col_value.type, context=context)
1985 data.append(chk_res[1])
1986
1987=== modified file 'bin/addons/msf_profile/i18n/fr_MF.po'
1988--- bin/addons/msf_profile/i18n/fr_MF.po 2017-09-08 15:57:28 +0000
1989+++ bin/addons/msf_profile/i18n/fr_MF.po 2017-09-27 13:17:20 +0000
1990@@ -4544,13 +4544,14 @@
1991 msgid "Contact Titles"
1992 msgstr "Titre/Position Contact"
1993
1994-#. module: msf_button_access_rights
1995+#. modules: msf_button_access_rights, msf_doc_import
1996 #: model:ir.actions.act_window,name:msf_button_access_rights.button_access_rule_list
1997 #: model:ir.ui.menu,name:msf_button_access_rights.msf_button_access_rules
1998 #: view:ir.ui.view:0
1999 #: field:ir.ui.view,button_access_rules_ref:0
2000+#: code:addons/msf_doc_import/msf_import_export_conf.py:124
2001 msgid "Button Access Rules"
2002-msgstr "Button Access Rules"
2003+msgstr "Règles d'Accès de bouton"
2004
2005 #. module: stock
2006 #: code:addons/stock/stock.py:1091
2007@@ -7005,11 +7006,6 @@
2008 msgid "MSF Codification"
2009 msgstr "Codification MSF"
2010
2011-#. module: product_list
2012-#: view:product.list.line:0
2013-msgid "Products"
2014-msgstr "Products"
2015-
2016 #. module: base_setup
2017 #: view:base.setup.company:0
2018 msgid "Your company information will be used to personalize documents issued with OpenERP such as invoices, sales orders and much more."
2019@@ -13296,12 +13292,6 @@
2020 msgid "Destinations"
2021 msgstr "Destinations"
2022
2023-#. module: import_data
2024-#: selection:import_category,object:0
2025-#: selection:import_nomenclature,object:0
2026-msgid "Product Nomenclature"
2027-msgstr "Product Nomenclature"
2028-
2029 #. module: analytic_distribution
2030 #: code:addons/analytic_distribution/account_commitment.py:166
2031 #, python-format
2032@@ -15965,6 +15955,47 @@
2033 msgid "New Zealand"
2034 msgstr "Nouvelle-Zélande"
2035
2036+#. modules: msf_doc_import, msf_supply_doc_export
2037+#: code:addons/msf_doc_import/wizard/__init__.py:68
2038+#: code:addons/msf_doc_import/wizard/__init__.py:73
2039+#: code:addons/msf_doc_import/wizard/__init__.py:78
2040+#: code:addons/msf_doc_import/wizard/wizard_in_simulation_screen.py:65
2041+#: report:addons/msf_supply_doc_export/report/report_real_composition_kit_xls.mako:71
2042+#, python-format
2043+msgid "Expiry Date"
2044+msgstr "Date d'expiration"
2045+
2046+#. modules: account, msf_outgoing, register_accounting, account_override, purchase_compare_rfq, msf_doc_import, return_claim, analytic_distribution
2047+#: code:addons/account/report/account_general_ledger.py:550
2048+#: view:account.chart:0
2049+#: field:account.chart,currency_id:0
2050+#: view:account.analytic.chart:0
2051+#: field:account.analytic.chart,currency_id:0
2052+#: code:addons/msf_doc_import/wizard/wizard_in_simulation_screen.py:63
2053+#: code:addons/msf_doc_import/wizard/wizard_po_simulation_screen.py:70
2054+#: field:wizard.import.po.simulation.screen,in_currency:0
2055+#: field:wizard.import.po.simulation.screen.line,imp_currency:0
2056+#: field:wizard.import.po.simulation.screen.line,in_currency:0
2057+#: field:wizard.simu.import.po.line,currency_id:0
2058+#: field:wizard.simu.import.po.line,initial_currency:0
2059+#: field:create.picking.move.processor,currency:0
2060+#: field:internal.move.processor,currency:0
2061+#: field:outgoing.delivery.move.processor,currency:0
2062+#: field:ppl.move.processor,currency:0
2063+#: field:return.ppl.move.processor,currency:0
2064+#: field:stock.move.in.processor,currency:0
2065+#: field:stock.move.processor,currency:0
2066+#: field:validate.move.processor,currency:0
2067+#: field:wizard.compare.rfq,currency_id:0
2068+#: field:account.direct.invoice.wizard,currency_id:0
2069+#: field:wizard.account.invoice,fake_currency_id:0
2070+#: field:wizard.account.invoice,virtual_currency_id:0
2071+#: field:claim.product.line,price_currency_claim_product_line:0
2072+#: field:claim.product.line,price_unit_claim_product_line:0
2073+#, python-format
2074+msgid "Currency"
2075+msgstr "Devise"
2076+
2077 #. module: sale
2078 #: help:sale.order.line,delay:0
2079 msgid "Number of days between the order confirmation the shipping of the products to the customer"
2080@@ -17377,6 +17408,7 @@
2081
2082 #. module: msf_doc_import
2083 #: view:wizard.import.batch:0
2084+#: view:msf.import.export:0
2085 msgid "Warning messages"
2086 msgstr "Messages d'avertissement"
2087
2088@@ -20661,9 +20693,11 @@
2089 msgid "IN update OUT"
2090 msgstr "IN update OUT"
2091
2092-#. module: import_data
2093+#. modules: import_data, msf_doc_import
2094 #: code:addons/import_data/import_data.py:317
2095 #: code:addons/import_data/import_data.py:356
2096+#: code:addons/msf_doc_import/msf_import_export.py:499
2097+#: code:addons/msf_doc_import/msf_import_export.py:528
2098 #, python-format
2099 msgid "%s does not exist"
2100 msgstr "%s n'existe pas"
2101@@ -24759,11 +24793,12 @@
2102 msgid "This wizard will validate all journal entries of a particular journal and period. Once journal entries are validated, you can not update them anymore."
2103 msgstr "Cet assistant validera toutes les écritures comptables pour un journal particulier et une période. Une fois validées, les écritures comptables ne peuvent plus être modifiées."
2104
2105-#. module: msf_field_access_rights
2106+#. modules: msf_field_access_rights, msf_doc_import
2107 #: model:ir.actions.act_window,name:msf_field_access_rights.field_access_rules_list
2108 #: model:ir.ui.menu,name:msf_field_access_rights.msf_field_access_rules
2109+#: code:addons/msf_doc_import/msf_import_export_conf.py:114
2110 msgid "Field Access Rules"
2111-msgstr "Field Access Rules"
2112+msgstr "Règles d'Accès au Champs"
2113
2114 #. modules: account, msf_outgoing, finance, sync_client, register_accounting, account_override, sourcing, sync_so, res_currency_functional, analytic_distribution
2115 #: code:addons/account/report/account_general_ledger.py:252
2116@@ -25725,9 +25760,10 @@
2117 msgid "No Period found on Invoice!"
2118 msgstr "Pas de Période indiquée sur la Facture!"
2119
2120-#. module: supplier_catalogue
2121+#. modules: supplier_catalogue, msf_doc_import
2122 #: model:ir.actions.act_window,name:supplier_catalogue.action_supplier_catalogue_line_list
2123 #: view:supplier.catalogue.line:0
2124+#: code:addons/msf_doc_import/msf_import_export_conf.py:53
2125 msgid "Supplier catalogue lines"
2126 msgstr "Lignes Catalogue Fournisseur"
2127
2128@@ -25857,6 +25893,7 @@
2129
2130 #. module: msf_doc_import
2131 #: view:wizard.import.batch:0
2132+#: view:msf.import.export:0
2133 msgid "Run import"
2134 msgstr "Démarrer l'import"
2135
2136@@ -29743,7 +29780,13 @@
2137 msgid "Total amount this customer owes you."
2138 msgstr "Montant Total Dû par ce Client."
2139
2140-#. modules: tender_flow, msf_partner, account, product, base, useability_dashboard_and_menu
2141+#. modules: consumption_calculation, stock_override
2142+#: report:addons/consumption_calculation/report/report_monthly_consumption_xls.mako:70
2143+#: field:export.report.stock.move,name:0
2144+msgid "Generated on"
2145+msgstr "Generated on"
2146+
2147+#. modules: tender_flow, msf_partner, account, product, base, useability_dashboard_and_menu, msf_doc_import
2148 #: model:ir.ui.menu,name:account.menu_account_supplier
2149 #: model:ir.ui.menu,name:account.menu_finance_payables
2150 #: model:ir.actions.act_window,name:base.action_partner_supplier_form
2151@@ -29755,6 +29798,7 @@
2152 #: view:tender:0
2153 #: field:tender,supplier_ids:0
2154 #: model:ir.ui.menu,name:useability_dashboard_and_menu.menu_supplier
2155+#: code:addons/msf_doc_import/msf_import_export_conf.py:42
2156 msgid "Suppliers"
2157 msgstr "Fournisseurs"
2158
2159@@ -30275,11 +30319,6 @@
2160 msgid "Line %s. No info about given account: %s"
2161 msgstr "Line %s. No info about given account: %s"
2162
2163-#. module: account_hq_entries
2164-#: model:ir.module.module,shortdesc:account_hq_entries.module_meta_information
2165-msgid "HQ Entries"
2166-msgstr "HQ Entries"
2167-
2168 #. module: msf_budget
2169 #: view:wizard.budget.summary.export:0
2170 msgid "Budget Summary PDF Export"
2171@@ -30894,6 +30933,7 @@
2172
2173 #. module: msf_doc_import
2174 #: code:addons/msf_doc_import/wizard/wizard_import_batch.py:308
2175+#: code:addons/msf_doc_import/msf_import_export.py:688
2176 #, python-format
2177 msgid "(%s line(s) with warning - see warning messages below)"
2178 msgstr "(%s ligne(s) avec des avertissements - voir les avertissements ci-dessous)"
2179@@ -32587,6 +32627,7 @@
2180
2181 #. module: msf_doc_import
2182 #: code:addons/msf_doc_import/wizard/wizard_import_batch.py:313
2183+#: code:addons/msf_doc_import/msf_import_export.py:693
2184 #, python-format
2185 msgid "no data will be imported until all the error messages are corrected"
2186 msgstr "aucune donnée ne sera importée tant que toutes les erreurs ne seront pas corrigées"
2187@@ -35506,6 +35547,7 @@
2188
2189 #. module: msf_doc_import
2190 #: code:addons/msf_doc_import/wizard/wizard_import_batch.py:298
2191+#: code:addons/msf_doc_import/msf_import_export.py:678
2192 #, python-format
2193 msgid "Processing of file completed in %s second(s)!\n"
2194 "- Total lines to import: %s\n"
2195@@ -36767,8 +36809,11 @@
2196 msgid "Move state"
2197 msgstr "Statut de la transaction "
2198
2199-#. module: procurement_auto
2200+#. modules: procurement_auto, procurement, msf_doc_import
2201 #: field:stock.warehouse.automatic.supply.line,supply_id:0
2202+#: field:stock.warehouse.orderpoint.line,supply_id:0
2203+#: model:ir.actions.act_window,name:msf_doc_import.msf_import_export_supply_action
2204+#: model:ir.ui.menu,name:msf_doc_import.msf_import_export_supply_menu
2205 msgid "Supply"
2206 msgstr "Approvisionnement"
2207
2208@@ -40027,12 +40072,14 @@
2209 msgid "DP execute"
2210 msgstr "DP execute"
2211
2212-#. modules: msf_instance, sync_so, account_hq_entries
2213+#. modules: msf_instance, sync_so, account_hq_entries, account_hq_entries, msf_doc_import
2214 #: model:ir.actions.act_window,name:account_hq_entries.action_hq_entries_tree
2215 #: model:ir.model,name:account_hq_entries.model_hq_entries
2216 #: model:ir.ui.menu,name:account_hq_entries.menu_hq_entries
2217 #: view:res.company:0
2218 #: model:ir.model,name:sync_so.model_hq_entries
2219+#: model:ir.module.module,shortdesc:account_hq_entries.module_meta_information
2220+#: code:addons/msf_doc_import/msf_import_export_conf.py:81
2221 msgid "HQ Entries"
2222 msgstr "Ecritures HQ"
2223
2224@@ -42744,6 +42791,7 @@
2225
2226 #. module: msf_doc_import
2227 #: code:addons/msf_doc_import/wizard/wizard_import_batch.py:306
2228+#: code:addons/msf_doc_import/msf_import_export.py:686
2229 #, python-format
2230 msgid "imported"
2231 msgstr "importées"
2232@@ -42986,6 +43034,7 @@
2233
2234 #. module: msf_doc_import
2235 #: code:addons/msf_doc_import/wizard/wizard_import_batch.py:306
2236+#: code:addons/msf_doc_import/msf_import_export.py:686
2237 #, python-format
2238 msgid "without errors"
2239 msgstr "sans erreurs"
2240@@ -48145,7 +48194,8 @@
2241 msgid "Report can not be edited due to missing FX rates in specific currency table %s"
2242 msgstr "Report can not be edited due to missing FX rates in specific currency table %s"
2243
2244-#. module: base
2245+#. modules: base, msf_doc_import
2246+#: code:addons/msf_doc_import/msf_import_export_conf.py:86
2247 #: model:ir.actions.act_window,name:base.ir_access_act
2248 #: model:ir.ui.menu,name:base.menu_ir_access_act
2249 msgid "Access Controls List"
2250@@ -50484,7 +50534,7 @@
2251 msgid "Followup lines"
2252 msgstr "Suivi des Lignes"
2253
2254-#. modules: msf_budget, account, financing_contract, analytic_distribution
2255+#. modules: msf_budget, account, financing_contract, analytic_distribution, msf_doc_import
2256 #: view:account.analytic.account:0
2257 #: model:ir.ui.menu,name:account.account_analytic_def_account
2258 #: view:account.analytic.account:0
2259@@ -50492,6 +50542,7 @@
2260 #: model:ir.ui.menu,name:financing_contract.menu_action_account_analytic_account_form
2261 #: view:account.analytic.account:0
2262 #: model:ir.ui.menu,name:msf_budget.menu_action_account_analytic_account_budget_form
2263+#: code:addons/msf_doc_import/msf_import_export_conf.py:66
2264 msgid "Analytic Accounts"
2265 msgstr "Comptes Analytiques"
2266
2267@@ -50610,7 +50661,7 @@
2268 msgid "Read Access"
2269 msgstr "Accès Lecture"
2270
2271-#. modules: product_nomenclature, import_data, product_asset, kit
2272+#. modules: product_nomenclature, import_data, product_asset, kit, msf_doc_import
2273 #: selection:import_data,object:0
2274 #: selection:import_product,object:0
2275 #: selection:update_product,object:0
2276@@ -50618,6 +50669,9 @@
2277 #: field:product.asset,nomenclature_description:0
2278 #: model:ir.model,name:product_nomenclature.model_product_nomenclature
2279 #: view:product.nomenclature:0
2280+#: selection:import_category,object:0
2281+#: selection:import_nomenclature,object:0
2282+#: code:addons/msf_doc_import/msf_import_export_conf.py:32
2283 msgid "Product Nomenclature"
2284 msgstr "Nomenclature du Produit"
2285
2286@@ -51151,7 +51205,7 @@
2287 #: code:addons/msf_outgoing/wizard/validate_picking_processor.py:75
2288 #, python-format
2289 msgid "Line %s: %s"
2290-msgstr "Ligne %s: %s"
2291+msgstr "Ligne %s : %s"
2292
2293 #. module: account_override
2294 #: help:account.move.line,journal_type:0
2295@@ -52986,11 +53040,6 @@
2296 msgid "Included Fields"
2297 msgstr "Champs Inclus"
2298
2299-#. module: kit
2300-#: view:kit.mass.import:0
2301-msgid "Error messages"
2302-msgstr "Error messages"
2303-
2304 #. module: msf_partner
2305 #: view:res.partner:0
2306 msgid "Customer LT"
2307@@ -56414,13 +56463,14 @@
2308 msgid "Choose Fiscal Year"
2309 msgstr "Choisir l'Exercice Comptable "
2310
2311-#. module: msf_field_access_rights
2312+#. modules: msf_field_access_rights, msf_doc_import
2313 #: model:ir.actions.act_window,name:msf_field_access_rights.field_access_rule_line_list
2314 #: model:ir.ui.menu,name:msf_field_access_rights.field_access_rule_line_list_menu
2315 #: view:msf_field_access_rights.field_access_rule:0
2316 #: field:msf_field_access_rights.field_access_rule,field_access_rule_line_ids:0
2317+#: code:addons/msf_doc_import/msf_import_export_conf.py:119
2318 msgid "Field Access Rule Lines"
2319-msgstr "Field Access Rule Lines"
2320+msgstr "Lignes de Règle d'Accès au Champs"
2321
2322 #. module: analytic_distribution
2323 #: field:analytic.distribution.wizard,fp_line_ids:0
2324@@ -56584,11 +56634,12 @@
2325 msgid "Manually corrected"
2326 msgstr "Manually corrected"
2327
2328-#. modules: account, account_mcdb
2329+#. modules: account, account_mcdb, msf_doc_import
2330 #: view:account.analytic.journal:0
2331 #: model:ir.actions.act_window,name:account.action_account_analytic_journal_form
2332 #: model:ir.ui.menu,name:account.account_def_analytic_journal
2333 #: view:account.mcdb:0
2334+#: code:addons/msf_doc_import/msf_import_export_conf.py:71
2335 msgid "Analytic Journals"
2336 msgstr "Journaux analytiques"
2337
2338@@ -56652,8 +56703,10 @@
2339 msgid "In days"
2340 msgstr "En jours."
2341
2342-#. module: msf_doc_import
2343+#. modules: msf_doc_import, kit
2344+#: view:kit.mass.import:0
2345 #: view:wizard.import.batch:0
2346+#: view:msf.import.export:0
2347 msgid "Error messages"
2348 msgstr "Messages d'erreur"
2349
2350@@ -57560,9 +57613,10 @@
2351 msgid "Action to Trigger"
2352 msgstr "Action à Déclencher"
2353
2354-#. module: base
2355+#. modules: base, msf_doc_import
2356 #: model:ir.actions.act_window,name:base.ir_action_window
2357 #: model:ir.ui.menu,name:base.menu_ir_action_window
2358+#: code:addons/msf_doc_import/msf_import_export_conf.py:129
2359 msgid "Window Actions"
2360 msgstr "Fenêtre Actions"
2361
2362@@ -58838,11 +58892,6 @@
2363 msgid "Specific partner"
2364 msgstr "Partenaire spécifique"
2365
2366-#. module: procurement
2367-#: field:stock.warehouse.orderpoint.line,supply_id:0
2368-msgid "Supply"
2369-msgstr "Supply"
2370-
2371 #. module: sale_override
2372 #: view:sale.order.line:0
2373 msgid "This button shouldn't be use from form view. Please use the red cross on list view."
2374@@ -60862,6 +60911,7 @@
2375 #: selection:wizard.import.batch,state:0
2376 #: view:automated.import.job:0
2377 #: selection:automated.import.job,state:0
2378+#: selection:msf.import.export,state:0
2379 #, python-format
2380 msgid "In progress"
2381 msgstr "En cours"
2382@@ -61119,9 +61169,10 @@
2383 msgid "%y - Year without century [00,99]."
2384 msgstr "%y - Année sans le siècle (00 à 99)."
2385
2386-#. module: base
2387+#. modules: base, msf_doc_import
2388 #: model:ir.actions.act_window,name:base.action_rule
2389 #: model:ir.ui.menu,name:base.menu_action_rule
2390+#: code:addons/msf_doc_import/msf_import_export_conf.py:104
2391 msgid "Record Rules"
2392 msgstr "Règles d´Enregistrement"
2393
2394@@ -61450,6 +61501,7 @@
2395 #: code:addons/sale_override/sale.py:364
2396 #: code:addons/sale_override/sale.py:365
2397 #: code:addons/sale_override/sale.py:366
2398+#: selection:msf.import.export,state:0
2399 #, python-format
2400 msgid "Not started"
2401 msgstr "Non démarré"
2402@@ -61984,6 +62036,32 @@
2403 msgid "Nothing to import"
2404 msgstr "Rien à importer"
2405
2406+#. modules: msf_budget, msf_homere_interface, supplier_catalogue, consumption_calculation, account_hq_entries, msf_doc_import, analytic_distribution, msf_doc_import, register_accounting
2407+#: code:addons/account_hq_entries/wizard/hq_entries_import.py:319
2408+#: code:addons/analytic_distribution/wizard/import_commitment_wizard.py:72
2409+#: code:addons/consumption_calculation/wizard/wizard_import_fmc.py:87
2410+#: code:addons/consumption_calculation/wizard/wizard_import_rac.py:85
2411+#: code:addons/msf_budget/wizard/wizard_budget_import.py:240
2412+#: code:addons/msf_doc_import/composition_kit.py:86
2413+#: code:addons/msf_doc_import/composition_kit.py:181
2414+#: code:addons/msf_doc_import/initial_stock_inventory.py:92
2415+#: code:addons/msf_doc_import/initial_stock_inventory.py:600
2416+#: code:addons/msf_doc_import/stock_cost_reevaluation.py:51
2417+#: code:addons/msf_doc_import/tender.py:98
2418+#: code:addons/msf_doc_import/wizard/wizard_import_product_list.py:88
2419+#: code:addons/msf_doc_import/wizard/wizard_import_supplier_catalogue.py:164
2420+#: code:addons/msf_homere_interface/wizard/hr_payroll_employee_import.py:584
2421+#: code:addons/msf_homere_interface/wizard/hr_payroll_import.py:479
2422+#: code:addons/supplier_catalogue/supplier_catalogue.py:590
2423+#: code:addons/supplier_catalogue/wizard/catalogue_import_lines.py:45
2424+#: code:addons/msf_doc_import/account.py:196
2425+#: code:addons/msf_doc_import/wizard/stock_partial_picking.py:254
2426+#: code:addons/msf_doc_import/wizard/stock_partial_picking.py:785
2427+#: code:addons/register_accounting/wizard/wizard_register_import.py:255
2428+#, python-format
2429+msgid "Nothing to import."
2430+msgstr "Rien à importer"
2431+
2432 #. module: account_mcdb
2433 #: selection:account.mcdb,currency_choice:0
2434 msgid "Booking"
2435@@ -62406,6 +62484,7 @@
2436
2437 #. module: msf_doc_import
2438 #: code:addons/msf_doc_import/wizard/wizard_import_batch.py:106
2439+#: code:addons/msf_doc_import/msf_import_export.py:364
2440 #, python-format
2441 msgid "Import in progress, please leave this window open and press the button 'Update' to show the progression of the import. Otherwise, you can continue to use Unifield"
2442 msgstr "Traitement en cours, veuillez laisser cette fenêtre ouverte et cliquez sur le bouton 'Mettre à jour' pour voir la progression de l'import. Sinon, vous pouvez continuer d'utiliser Unifield"
2443@@ -67248,6 +67327,8 @@
2444 #: field:threshold.value,line_ids:0
2445 #: field:threshold.value,product_ids:0
2446 #: view:restrictive.country.setup:0
2447+#: view:product.list.line:0
2448+#: code:addons/msf_doc_import/msf_import_export_conf.py:27
2449 #, python-format
2450 msgid "Products"
2451 msgstr "Produits"
2452@@ -68849,6 +68930,8 @@
2453 #. module: msf_doc_import
2454 #: code:addons/msf_doc_import/wizard/wizard_import_batch.py:286
2455 #: code:addons/msf_doc_import/wizard/wizard_import_batch.py:292
2456+#: code:addons/msf_doc_import/msf_import_export.py:666
2457+#: code:addons/msf_doc_import/msf_import_export.py:672
2458 #, python-format
2459 msgid "Line %s: %s"
2460 msgstr "Ligne %s : %s"
2461@@ -79938,6 +80021,7 @@
2462 #: field:automated.import.job,state:0
2463 #: field:export.report.inconsistencies,state:0
2464 #: field:export.report.stopped.products,state:0
2465+#: field:msf.import.export,state:0
2466 #: field:wizard.import.invoice.line,state:0
2467 msgid "State"
2468 msgstr "État"
2469@@ -80596,6 +80680,7 @@
2470
2471 #. module: msf_doc_import
2472 #: code:addons/msf_doc_import/wizard/wizard_import_batch.py:170
2473+#: code:addons/msf_doc_import/msf_import_export.py:549
2474 #, python-format
2475 msgid "Line seemed empty, so this line was ignored"
2476 msgstr "La ligne semblait vide, donc cette ligne a été ignorée"
2477@@ -80655,7 +80740,7 @@
2478 msgid "Send a test email"
2479 msgstr "Send a test email"
2480
2481-#. modules: tender_flow, product_nomenclature, product_asset, account_override, purchase_allocation_report, register_accounting, product_expiry, procurement_cycle, return_claim, supplier_catalogue, import_data, stock_schedule, unifield_setup, stock_forecast, stock_batch_recall, order_types, msf_doc_import, purchase_followup, product, stock_override, service_purchasing, consumption_calculation, purchase_override, specific_rules, kit, sale_override, product_list, product_manufacturer, procurement_report, threshold_value, purchase, account, msf_outgoing, stock_move_tracking, product_attributes, procurement_auto, sale, transport_mgmt, procurement, sourcing, msf_audittrail, purchase_msf, stock, sync_so
2482+#. modules: tender_flow, product_nomenclature, product_asset, account_override, purchase_allocation_report, register_accounting, product_expiry, procurement_cycle, return_claim, supplier_catalogue, import_data, stock_schedule, unifield_setup, stock_forecast, stock_batch_recall, order_types, msf_doc_import, purchase_followup, product, stock_override, service_purchasing, consumption_calculation, purchase_override, specific_rules, kit, sale_override, product_list, product_manufacturer, procurement_report, threshold_value, purchase, account, msf_outgoing, stock_move_tracking, product_attributes, procurement_auto, sale, transport_mgmt, procurement, sourcing, msf_audittrail, purchase_msf, stock, sync_so, base
2483 #: field:account.analytic.line,product_id:0
2484 #: view:account.entries.report:0
2485 #: field:account.entries.report,product_id:0
2486@@ -80809,6 +80894,47 @@
2487 #: field:threshold.value.line,product_id:0
2488 #: model:ir.model,name:transport_mgmt.model_product_product
2489 #: model:ir.model,name:unifield_setup.model_product_product
2490+#: report:allocation.invoices.report:0
2491+#: selection:res.request,ref_doc1:0
2492+#: selection:res.request,ref_doc2:0
2493+#: field:product.history.consumption.product,product_id:0
2494+#: selection:import_category,object:0
2495+#: selection:import_nomenclature,object:0
2496+#: report:kit.report:0
2497+#: report:addons/msf_doc_import/report/in_simulation_screen_xls_report.mako:149
2498+#: report:addons/msf_doc_import/report/in_simulation_screen_xls_report.mako:158
2499+#: report:addons/msf_doc_import/report/po_simulation_screen_xls_report.mako:230
2500+#: report:addons/msf_doc_import/report/po_simulation_screen_xls_report.mako:241
2501+#: report:po.simulation.screen:0
2502+#: field:product.product.import.line.qty,product_id:0
2503+#: field:wizard.import.in.line.simulation.screen,imp_product_id:0
2504+#: field:wizard.import.in.line.simulation.screen,move_product_id:0
2505+#: field:wizard.import.po.simulation.screen.line,imp_product_id:0
2506+#: field:wizard.import.po.simulation.screen.line,in_product_id:0
2507+#: view:create.picking.move.processor:0
2508+#: field:create.picking.move.processor,product_id:0
2509+#: view:internal.move.processor:0
2510+#: field:internal.move.processor,product_id:0
2511+#: view:outgoing.delivery.move.processor:0
2512+#: field:outgoing.delivery.move.processor,product_id:0
2513+#: view:ppl.move.processor:0
2514+#: field:ppl.move.processor,product_id:0
2515+#: view:return.ppl.move.processor:0
2516+#: field:return.ppl.move.processor,product_id:0
2517+#: view:stock.move.in.processor:0
2518+#: field:stock.move.in.processor,product_id:0
2519+#: view:stock.move.processor:0
2520+#: field:stock.move.processor,product_id:0
2521+#: view:validate.move.processor:0
2522+#: field:validate.move.processor,product_id:0
2523+#: field:stock.warehouse.orderpoint.line,product_id:0
2524+#: view:product.where.used:0
2525+#: field:product.where.used,product_id:0
2526+#: field:standard.price.track.changes,product_id:0
2527+#: field:account.direct.invoice.wizard.line,product_id:0
2528+#: field:unconsistent.stock.report.line,product_id:0
2529+#: view:stock.card.wizard:0
2530+#: field:stock.card.wizard,product_id:0
2531 msgid "Product"
2532 msgstr "Produit"
2533
2534@@ -80902,7 +81028,7 @@
2535 msgid "Select a supplier"
2536 msgstr "Sélectionner un fournisseur"
2537
2538-#. modules: msf_budget, purchase, account, msf_outgoing, account_payment, purchase_override, specific_rules, sale, base, register_accounting, msf_doc_import, return_claim, stock, analytic_distribution, msf_homere_interface
2539+#. modules: msf_budget, purchase, account, msf_outgoing, account_payment, purchase_override, specific_rules, sale, base, register_accounting, msf_doc_import, return_claim, stock, analytic_distribution, delivery_mechanism, sales_followup, sync_client, tender_flow, sale_override, msf_tools, mission_stock, msf_homere_interface
2540 #: selection:account.invoice.report,state:0
2541 #: selection:account.journal.period,state:0
2542 #: selection:account.subscription,state:0
2543@@ -80947,6 +81073,30 @@
2544 #: selection:stock.inventory,state:0
2545 #: view:stock.move:0
2546 #: view:stock.picking:0
2547+#: code:addons/delivery_mechanism/delivery_mechanism.py:1295
2548+#: code:addons/delivery_mechanism/delivery_mechanism.py:1315
2549+#: code:addons/delivery_mechanism/delivery_mechanism.py:1343
2550+#: code:addons/delivery_mechanism/delivery_mechanism.py:1388
2551+#: code:addons/mission_stock/wizard/mission_stock_wizard.py:48
2552+#: code:addons/mission_stock/wizard/mission_stock_wizard.py:56
2553+#: code:addons/msf_outgoing/msf_outgoing.py:3197
2554+#: view:automated.import.job:0
2555+#: selection:automated.import.job,state:0
2556+#: code:addons/sale_override/sale.py:176
2557+#: code:addons/sale_override/sale.py:371
2558+#: code:addons/sale_override/sale.py:372
2559+#: code:addons/sale_override/sale.py:377
2560+#: code:addons/sale_override/sale.py:378
2561+#: code:addons/sale_override/sale.py:1483
2562+#: code:addons/sale_override/sale.py:2035
2563+#: code:addons/sale_override/sale.py:2244
2564+#: code:addons/sale_override/sale.py:2506
2565+#: code:addons/sale_override/sale.py:2578
2566+#: view:sale.order.sourcing.progress:0
2567+#: selection:sale.followup.multi.wizard,state:0
2568+#: selection:sync.monitor,state:0
2569+#: selection:tender.line,line_state:0
2570+#: selection:msf.import.export,state:0
2571 #: selection:wizard.import.invoice.line,state:0
2572 #: selection:hr.payroll.validation,state:0
2573 msgid "Done"
2574@@ -83695,6 +83845,7 @@
2575
2576 #. module: msf_doc_import
2577 #: code:addons/msf_doc_import/wizard/wizard_import_batch.py:312
2578+#: code:addons/msf_doc_import/msf_import_export.py:692
2579 #, python-format
2580 msgid "(see error messages below)"
2581 msgstr "(voir les erreurs ci-dessous)"
2582@@ -84421,7 +84572,7 @@
2583 #: code:addons/msf_doc_import/wizard/abstract_wizard_import.py:354
2584 #, python-format
2585 msgid "Import can be run only on draft wizard."
2586-msgstr "L'important ne peut être effectué que sur des assistants en état 'Non démarré'"
2587+msgstr "L'importation ne peut être effectuée que sur des assistants en état 'Non démarré'"
2588
2589 #. module: account_payment
2590 #: field:payment.line,currency:0
2591@@ -91108,6 +91259,7 @@
2592 #: field:local.transport.cost.report,func_currency_id:0
2593 #: field:local.transport.cost.report,transport_currency_id:0
2594 #: field:purchase.order,transport_currency_id:0
2595+#: code:addons/msf_doc_import/msf_import_export_conf.py:86
2596 #: report:allocation.invoices.report:0
2597 #: report:addons/msf_doc_import/report/po_simulation_screen_xls_report.mako:238
2598 #: report:addons/msf_doc_import/report/po_simulation_screen_xls_report.mako:245
2599@@ -92693,51 +92845,6 @@
2600 msgid "Patches marked as 'not-installed' must have an emission date"
2601 msgstr "Patches marked as 'not-installed' must have an emission date"
2602
2603-#. modules: register_accounting, msf_outgoing, product_attributes, import_data, stock_override, consumption_calculation, specific_rules, kit, account_override, procurement, base, msf_doc_import
2604-#: report:allocation.invoices.report:0
2605-#: selection:res.request,ref_doc1:0
2606-#: selection:res.request,ref_doc2:0
2607-#: field:product.history.consumption.product,product_id:0
2608-#: selection:import_category,object:0
2609-#: selection:import_nomenclature,object:0
2610-#: report:kit.report:0
2611-#: report:addons/msf_doc_import/report/in_simulation_screen_xls_report.mako:149
2612-#: report:addons/msf_doc_import/report/in_simulation_screen_xls_report.mako:158
2613-#: report:addons/msf_doc_import/report/po_simulation_screen_xls_report.mako:230
2614-#: report:addons/msf_doc_import/report/po_simulation_screen_xls_report.mako:241
2615-#: report:po.simulation.screen:0
2616-#: field:product.product.import.line.qty,product_id:0
2617-#: field:wizard.import.in.line.simulation.screen,imp_product_id:0
2618-#: field:wizard.import.in.line.simulation.screen,move_product_id:0
2619-#: field:wizard.import.po.simulation.screen.line,imp_product_id:0
2620-#: field:wizard.import.po.simulation.screen.line,in_product_id:0
2621-#: view:create.picking.move.processor:0
2622-#: field:create.picking.move.processor,product_id:0
2623-#: view:internal.move.processor:0
2624-#: field:internal.move.processor,product_id:0
2625-#: view:outgoing.delivery.move.processor:0
2626-#: field:outgoing.delivery.move.processor,product_id:0
2627-#: view:ppl.move.processor:0
2628-#: field:ppl.move.processor,product_id:0
2629-#: view:return.ppl.move.processor:0
2630-#: field:return.ppl.move.processor,product_id:0
2631-#: view:stock.move.in.processor:0
2632-#: field:stock.move.in.processor,product_id:0
2633-#: view:stock.move.processor:0
2634-#: field:stock.move.processor,product_id:0
2635-#: view:validate.move.processor:0
2636-#: field:validate.move.processor,product_id:0
2637-#: field:stock.warehouse.orderpoint.line,product_id:0
2638-#: view:product.where.used:0
2639-#: field:product.where.used,product_id:0
2640-#: field:standard.price.track.changes,product_id:0
2641-#: field:account.direct.invoice.wizard.line,product_id:0
2642-#: field:unconsistent.stock.report.line,product_id:0
2643-#: view:stock.card.wizard:0
2644-#: field:stock.card.wizard,product_id:0
2645-msgid "Product"
2646-msgstr "Product"
2647-
2648 #. module: report_webkit
2649 #: view:ir.header_webkit:0
2650 msgid "Content and styling"
2651@@ -92870,7 +92977,7 @@
2652 msgid "SQL Constraint"
2653 msgstr "Contrainte SQL"
2654
2655-#. modules: hr, base, msf_homere_interface
2656+#. modules: hr, base, msf_homere_interface, msf_doc_import
2657 #: model:ir.actions.act_window,name:base.action_partner_employee_form
2658 #: view:hr.employee:0
2659 #: field:hr.job,employee_ids:0
2660@@ -92880,6 +92987,7 @@
2661 #: model:ir.ui.menu,name:hr.menu_open_view_employee_list_my
2662 #: model:ir.ui.menu,name:hr.menu_view_employee_category_configuration_form
2663 #: view:hr.employee:0
2664+#: code:addons/msf_doc_import/msf_import_export_conf.py:76
2665 msgid "Employees"
2666 msgstr "Employé(e)s"
2667
2668@@ -95260,11 +95368,11 @@
2669 msgid "GRAND TOTAL"
2670 msgstr "GRAND TOTAL"
2671
2672-#. module: msf_field_access_rights
2673+#. module: msf_field_access_right
2674 #: model:ir.model,name:msf_field_access_rights.model_msf_field_access_rights_field_access_rule_line
2675 #: view:msf_field_access_rights.field_access_rule_line:0
2676 msgid "Field Access Rule Line"
2677-msgstr "Field Access Rule Line"
2678+msgstr "Ligne de Règle d'Accès au Champs"
2679
2680 #. module: account_mcdb
2681 #: view:account.mcdb:0
2682@@ -98029,6 +98137,166 @@
2683 msgid "Article must be used only in a properly designed programme, need a more detailed description."
2684 msgstr "L'article doit être uniquement utilisé dans un programme correctement construit, à besoin d'une description plus détaillée."
2685
2686+#. module: msf_doc_import
2687+#: model:ir.actions.report.xml,name:msf_doc_import.wizard_export_generic
2688+msgid "Generic Export"
2689+msgstr "Export Générique"
2690+
2691+#. module: msf_doc_import
2692+#: field:msf.import.export,model_list_selection:0
2693+msgid "Object to Import/Export"
2694+msgstr "Objet à Importer/Exporter"
2695+
2696+#. module: msf_doc_import
2697+#: field:msf.import.export,import_file:0
2698+msgid "File to import .xml"
2699+msgstr "Fichier à importer .xml"
2700+
2701+#. module: msf_doc_import
2702+#: code:addons/msf_doc_import/msf_import_export.py:93
2703+#, python-format
2704+msgid "%s_Import_Template"
2705+msgstr "%s_Modèle_d_import"
2706+
2707+#. module: msf_doc_import
2708+#: code:addons/msf_doc_import/msf_import_export.py:198
2709+#: code:addons/msf_doc_import/msf_import_export.py:322
2710+#, python-format
2711+msgid "field '%s' not found for model '%s'. Please contact the support team."
2712+msgstr "champ '%s' non trouvé pour le modèle '%s'. Veuillez contacter l'équipe support."
2713+
2714+#. module: msf_doc_import
2715+#: code:addons/msf_doc_import/msf_import_export.py:112
2716+#, python-format
2717+msgid "Selection '%s' not found. Please contact the support team."
2718+msgstr "Sélection '%s' non trouvée. Veuillez contacter l'équipe support."
2719+
2720+#. module: msf_doc_import
2721+#: code:addons/msf_doc_import/msf_import_export.py:117
2722+#, python-format
2723+msgid "The header_list for report '%s' is not defined. Please contact the support team."
2724+msgstr "La liste des entêtes pour le rapport '%s' n'est pas définie. Veuillez contacter l'équipe support."
2725+
2726+#. module: msf_doc_import
2727+#: code:addons/msf_doc_import/msf_import_export.py:264
2728+#, python-format
2729+msgid "File structure is incorrect, please correct. You may generate a template with the File export functionality."
2730+msgstr "La structure du fichier est incorrecte, veuillez corriger. Vous pouvez générer un modèle avec la fonctionnalité d'exportation de modèle."
2731+
2732+#. module: msf_doc_import
2733+#: code:addons/msf_doc_import/msf_import_export.py:272
2734+#, python-format
2735+msgid "File structure is correct."
2736+msgstr "La structure du fichier est correcte."
2737+
2738+#. module: msf_doc_import
2739+#: code:addons/msf_doc_import/msf_import_export.py:325
2740+#, python-format
2741+msgid "Column %s: get '%s' expected '%s'."
2742+msgstr "Colonne %s: reçu '%s' attendu '%s'."
2743+
2744+#. module: msf_doc_import
2745+#: code:addons/msf_doc_import/msf_import_export.py:328
2746+#, python-format
2747+msgid "The following columns are missing in the imported file:\n"
2748+"%s"
2749+msgstr "Les colonnes suivantes sont manquantes dans le fichier importé :\n"
2750+"%s"
2751+
2752+#. module: msf_doc_import
2753+#: code:addons/msf_doc_import/msf_import_export_conf.py:37
2754+#, python-format
2755+msgid "Product Categories"
2756+msgstr "Catégories Produit"
2757+
2758+#. module: msf_doc_import
2759+#: model:ir.actions.act_window,name:msf_doc_import.msf_import_export_non_functional_action
2760+#: model:ir.ui.menu,name:msf_doc_import.msf_import_export_non_functional_menu
2761+msgid "Non Functional"
2762+msgstr "Non Functionnel"
2763+
2764+#. module: msf_doc_import
2765+#: code:addons/msf_doc_import/msf_import_export_conf.py:48
2766+#, python-format
2767+msgid "Supplier Catalogues"
2768+msgstr "Catalogues Fournisseur"
2769+
2770+#. module: msf_doc_import
2771+#: view:msf.import.export:0
2772+#: field:msf.import.export,display_file_import:0
2773+msgid "File Import"
2774+msgstr "Import Fichier"
2775+
2776+#. module: msf_doc_import
2777+#: view:msf.import.export:0
2778+#: field:msf.import.export,display_file_export:0
2779+msgid "File Export"
2780+msgstr "Export Fichier"
2781+
2782+#. module: msf_doc_import
2783+#: view:msf.import.export:0
2784+msgid "Export empty template"
2785+msgstr "Exporter un modèle vide"
2786+
2787+#. module: msf_doc_import
2788+#: view:msf.import.export:0
2789+msgid "Export first 3 entries"
2790+msgstr "Exporter les 3 premières entrées"
2791+
2792+#. module: msf_doc_import
2793+#: view:msf.import.export:0
2794+msgid "Export all data"
2795+msgstr "Exporter toutes les données"
2796+
2797+#. module: msf_doc_import
2798+#: code:addons/msf_doc_import/msf_import_export_conf.py:56
2799+#, python-format
2800+msgid "GL Accounts"
2801+msgstr "Comptes"
2802+
2803+#. module: msf_doc_import
2804+#: code:addons/msf_doc_import/msf_import_export_conf.py:61
2805+#, python-format
2806+msgid "GL Journals"
2807+msgstr "Journaux"
2808+
2809+#. module: msf_doc_import
2810+#: view:msf.import.export:0
2811+msgid "Test file"
2812+msgstr "Tester le fichier"
2813+
2814+#. module: msf_doc_import
2815+#: view:msf.import.export:0
2816+#: view:wizard.import.batch:0
2817+msgid "Download template file"
2818+msgstr "Télécharger un fichier modèle"
2819+
2820+#. module: msf_homere_interface
2821+#: code:addons/msf_homere_interface/hr.py:137
2822+#, python-format
2823+msgid "Some employees have the same unique code: %s"
2824+msgstr "Certains employés ont le même code unique : %s"
2825+
2826+#. modules: msf_doc_import
2827+#: code:addons/msf_doc_import/msf_import_export_conf.py:86
2828+msgid "Currency"
2829+msgstr "Devise"
2830+
2831+#. modules: msf_doc_import
2832+#: code:addons/msf_doc_import/msf_import_export_conf.py:99
2833+msgid "User Access"
2834+msgstr "Accès utilisateur"
2835+
2836+#. modules: msf_doc_import
2837+#: code:addons/msf_doc_import/msf_import_export_conf.py:99
2838+msgid "User Groups"
2839+msgstr "Groupes utilisateur"
2840+
2841+#. modules: msf_doc_import
2842+#: code:addons/msf_doc_import/msf_import_export_conf.py:99
2843+msgid "Currencies Rates"
2844+msgstr "Taux des Devises"
2845+
2846 #. module: account
2847 #: code:addons/account/report/common_report_header.py:136
2848 #, python-format
2849@@ -98661,6 +98929,37 @@
2850 msgid "Warning, you have removed header value source location! The lines will be re-set to have 'Other Supplier' as the source location. Please check this is correct!"
2851 msgstr "Attention, vous avez supprimé la zone source d'en-tête! La zone source des lignes va être réinitialisée avec la valeur 'Autre Fournisseur'. Merci de vérifier leur cohérence!"
2852
2853+#. module: msf_doc_import
2854+#: field:msf.import.export,csv_button:0
2855+msgid "Import from CSV"
2856+msgstr "Importer depuis un fichier CSV"
2857+
2858+#. module: msf_doc_import
2859+#: field:msf.import.export,display_import_buttons:0
2860+msgid "Display import buttons"
2861+msgstr "Afficher les boutons d'import"
2862+
2863+#. module: msf_doc_import
2864+#: code:addons/msf_doc_import/msf_import_export.py:415
2865+#: code:addons/msf_doc_import/msf_import_export.py:429
2866+#, python-format
2867+msgid "Import in progress in the specific wizard."
2868+msgstr "Import en cours dans l'assistant spécifique."
2869+
2870+#. module: msf_doc_import
2871+#: code:addons/msf_doc_import/msf_import_export.py:434
2872+#, python-format
2873+msgid "The model '%s' is not made to be imported in CSV file.\n"
2874+"Please contact the support team."
2875+msgstr "Le model '%s' n'est pas fait pour être imorté en fichier CSV.\n"
2876+"Veuillez contacter léquipe support."
2877+
2878+#. module: msf_doc_import
2879+#: code:addons/msf_doc_import/msf_import_export.py:439
2880+#, python-format
2881+msgid "Import has been done via the specific wizard. The latter had to give information on the import."
2882+msgstr "L'import à été fait via l'assistant spécifique. Ce dernier à dû donnner les information concernant l'import."
2883+
2884 #. module: account_override
2885 #: code:addons/account_override/account.py:524
2886 #, python-format
2887
2888=== modified file 'bin/addons/product_nomenclature/product_nomenclature.py'
2889--- bin/addons/product_nomenclature/product_nomenclature.py 2017-05-29 14:06:25 +0000
2890+++ bin/addons/product_nomenclature/product_nomenclature.py 2017-09-27 13:17:20 +0000
2891@@ -821,7 +821,7 @@
2892 4. duplication from GUI: the default code XXX is saved, then modify in the write
2893 '''
2894 # The first 2 cases: dup of default_code/xmlid_code not allow
2895- if context.get('from_import_menu') or context.get('sync_update_execution', False):
2896+ if context.get('sync_update_execution', False):
2897 if not default_code or not vals.get('xmlid_code', False):
2898 raise Exception, "Problem creating product: Missing xmlid_code/default_code in the data"
2899 if not vals.get('xmlid_code'):
2900
2901=== modified file 'bin/addons/res_currency_tables/wizard/import_currencies.py'
2902--- bin/addons/res_currency_tables/wizard/import_currencies.py 2017-03-17 13:33:26 +0000
2903+++ bin/addons/res_currency_tables/wizard/import_currencies.py 2017-09-27 13:17:20 +0000
2904@@ -92,6 +92,10 @@
2905 # Some checks
2906 if context is None:
2907 context = {}
2908+
2909+ if isinstance(ids, (int, long)):
2910+ ids = [ids]
2911+
2912 # Prepare some values
2913 currency_obj = self.pool.get('res.currency')
2914 currency_rate_obj = self.pool.get('res.currency.rate')
2915
2916=== modified file 'bin/osv/orm.py'
2917--- bin/osv/orm.py 2017-08-18 14:26:52 +0000
2918+++ bin/osv/orm.py 2017-09-27 13:17:20 +0000
2919@@ -675,10 +675,18 @@
2920 elif f[i] in self._inherit_fields.keys():
2921 cols = selection_field(self._inherits)
2922 if cols and cols._type == 'selection' and not sync_context:
2923- sel_list = cols.selection
2924- if r and type(sel_list) == type([]):
2925- r = [x[1] for x in sel_list if r==x[0]]
2926- r = r and r[0] or False
2927+ # if requested, translate the fields.selection values
2928+ translated_selection = False
2929+ if context.get('translate_selection_field', False) and r and f:
2930+ fields_get_res = self.fields_get(cr, uid, f, context=context)
2931+ if f[0] in fields_get_res and 'selection' in fields_get_res[f[0]]:
2932+ r = dict(fields_get_res[f[0]]['selection'])[r]
2933+ translated_selection = True
2934+ if not translated_selection:
2935+ sel_list = cols.selection
2936+ if r and type(sel_list) == type([]):
2937+ r = [x[1] for x in sel_list if r==x[0]]
2938+ r = r and r[0] or False
2939 if not r:
2940 if f[i] in self._columns:
2941 r = check_type(self._columns[f[i]]._type)

Subscribers

People subscribed via source and target branches