Merge lp:~extra-addons-commiter/openobject-extension/oerp6.1-cleanning into lp:openobject-extension/oerp6.1-stable

Proposed by Sébastien BEAU - http://www.akretion.com
Status: Merged
Merged at revision: 378
Proposed branch: lp:~extra-addons-commiter/openobject-extension/oerp6.1-cleanning
Merge into: lp:openobject-extension/oerp6.1-stable
Diff against target: 4199 lines (+2030/-416)
40 files modified
base_external_cron/__openerp__.py (+2/-2)
base_external_cron/external_cron.py (+82/-16)
base_external_cron/external_cron_view.xml (+25/-15)
base_external_file_protocole/__openerp__.py (+4/-1)
base_external_file_protocole/external_referential_view.xml (+24/-0)
base_external_file_protocole/external_referentials.py (+18/-16)
base_external_file_protocole/file_buffer.py (+55/-16)
base_external_file_protocole/file_buffer_data.xml (+14/-1)
base_external_file_protocole/file_buffer_view.xml (+27/-9)
base_external_file_protocole/settings/external.referential.type.csv (+4/-0)
base_external_file_protocole/settings/external.referential.version.csv (+4/-0)
base_external_referentials/__openerp__.py (+3/-2)
base_external_referentials/decorator.py (+8/-8)
base_external_referentials/external_osv.py (+182/-129)
base_external_referentials/external_referentials.py (+90/-38)
base_external_referentials/external_referentials_menu.xml (+1/-2)
base_external_referentials/external_referentials_view.xml (+14/-17)
base_external_referentials/group_fields.py (+8/-7)
base_external_referentials/i18n/fr.po (+1070/-0)
base_external_referentials/ir_model.py (+20/-7)
base_external_referentials/message_error.py (+4/-2)
base_external_referentials/report.py (+52/-21)
base_external_referentials/report_mail_template.xml (+26/-0)
base_external_referentials/report_view.xml (+1/-0)
base_file_protocole/__openerp__.py (+2/-2)
base_file_protocole/base_file_protocole.py (+63/-12)
base_onchange_player/__init__.py (+2/-4)
base_onchange_player/__openerp__.py (+7/-6)
base_onchange_player/onchange_osv.py (+24/-21)
base_pop_up/__openerp__.py (+2/-2)
base_pop_up/pop_up_file.py (+3/-3)
base_scheduler_creator/schedulder_creator.py (+6/-7)
file_exchange/__openerp__.py (+1/-0)
file_exchange/file_exchange.py (+37/-33)
file_exchange/file_exchange_osv.py (+12/-13)
file_exchange/settings/external.referential.type.csv (+3/-0)
framework_helpers/__init__.py (+22/-0)
framework_helpers/__openerp__.py (+37/-0)
framework_helpers/context_managers.py (+66/-0)
report_synchronizer/report_osv.py (+5/-4)
To merge this branch: bzr merge lp:~extra-addons-commiter/openobject-extension/oerp6.1-cleanning
Reviewer Review Type Date Requested Status
Guewen Baconnier @ Camptocamp no test, review Needs Fixing
Review via email: mp+135018@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Guewen Baconnier @ Camptocamp (gbaconnier-c2c) wrote :

Hi,

Line 3278 +#: code:addons/base_external_referentials/external_osv.py:962
There is a problem in the gettext call because a big chunk of the python module appears in the translation file.

Otherwise did not see major issues

review: Needs Fixing (no test, review)
Revision history for this message
Sébastien BEAU - http://www.akretion.com (sebastien.beau) wrote :

Yes I see it, it's fixed now

Revision history for this message
Alexandre Fayolle - camptocamp (alexandre-fayolle-c2c) wrote :

Nitpicking: a frequency is expressed in Hertz (1/time). A period or rate is expressed in Time. (no need to change in the column name, as it would be cumbersome to migrate, but maybe in the help and displayed strings)

You should add a comment next to EXT_CRON_MINIMUM_FREQUENCY = 10 telling what the unit for this constant is.

line 95: are you sure you want to use <= to trigger the error ? having to specify at least 11 sounds a bit strange.

line 96: s/must be upper/must be greater than/

line 113: no space before ':' in English

line 114: no space before '!' in English (happens in other places too, esp. line 3773 and following in "Error !")

line 198 and following: remove space before ':'

line 415: you should probably add something like : if context is None: context = {} before using context.update(). I don't think the framework guarantees that a dict context argument is provided.

line 635: s/Not parent/No parent/

378. By Sébastien BEAU - http://www.akretion.com

[MERGE] merge from cleanning branch : please do not forget to start an update on the module updated.
base_external_referential :
    REFACTOR
        - redesign the view and for commun fields between various e-commerce the visibility can be set withthe variable REF_VISIBLE_FIELD
        ex : REF_VISIBLE_FIELDS['Magento'] = ['location', 'apiusername', 'apipass']

    FIX
        - fix copy method on mapping
        - fix export resource when ids an empty tuple or an empty list
        - increase the size of the field action on the report line to avoid error
        - FIX Call the onchange correctly using args and kwargs

    ADD
        - add the type url in the mapping
        - improve reporting system, avoid the creation of unlimited error message on some object
        - add the posibility to send an email when an error occure

file_exchange / base_file_protocol:
    ADD
        - add support of xls

base_external_file_protocole
    REFACTOR
        - improve file.buffer (need for amazon)

report_syncronizer
    REFACTOR
        - refactor the export of file (needed for exporting OpenERP PDf into magento)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'base_external_cron/__openerp__.py'
2--- base_external_cron/__openerp__.py 2012-07-24 15:54:02 +0000
3+++ base_external_cron/__openerp__.py 2012-12-03 16:33:32 +0000
4@@ -29,9 +29,9 @@
5 'description': """empty""",
6 'author': 'Akretion',
7 'website': 'http://www.akretion.com/',
8- 'depends': ['base_external_referentials'],
9+ 'depends': ['base_external_referentials'],
10 'init_xml': [],
11- 'update_xml': [
12+ 'update_xml': [
13 'external_cron_view.xml',
14 ],
15 'demo_xml': [],
16
17=== modified file 'base_external_cron/external_cron.py'
18--- base_external_cron/external_cron.py 2012-08-24 00:40:58 +0000
19+++ base_external_cron/external_cron.py 2012-12-03 16:33:32 +0000
20@@ -19,34 +19,100 @@
21 # #
22 ###############################################################################
23
24-from osv import osv, fields
25-import netsvc
26-from base_external_referentials.external_osv import ExternalSession
27-import sys
28-from ebaypyt import EbayWebService
29-
30-class external_cron(osv.osv):
31+from openerp.osv.orm import Model, except_orm
32+from openerp.osv import fields
33+from tools.translate import _
34+
35+#TODO refactor the constraint on ext_cron, this should be not harcoded
36+EXT_CRON_MINIMUM_FREQUENCY = 10 #in minute
37+
38+#TODO rename the fields, do not mix frequency with period :S
39+
40+class external_cron(Model):
41
42 _name = "external.cron"
43 _description = "external.cron"
44
45+ def _export_management_one_row(self, cr, uid, cron_id, field, arg, context=None):
46+ """ set exported et readonly value"""
47+ res = {}
48+ domain = [('model','=','external.cron'),('res_id','=',cron_id)]
49+ my_search = self.pool.get('ir.model.data').search(cr, uid, domain, context=context)
50+ if len(my_search) > 0:
51+ res[cron_id] = {'exported': True, 'readonly': False}
52+ else:
53+ res[cron_id] = {'exported': False, 'readonly': False}
54+ return res
55+
56+ def _export_management(self, cr, uid, ids, field, arg, context=None):
57+ res={}
58+ for cron_id in ids:
59+ res.update(self._export_management_one_row(cr, uid, cron_id, field, arg, context=context))
60+ return res
61+
62 _columns = {
63 'name': fields.char('Name', size=50, required=True),
64- 'active': fields.boolean('Active', help="The active field allows to hide the item in tree view without deleting it."),
65+ 'active': fields.boolean('Active',
66+ help="The active field allows to hide the item in tree view without deleting it."),
67 'period': fields.selection((('month','Month'), ('week','Week'), ('day','Day'),
68- ('minute','Minute')), 'Periodicity', help="Base unit periodicity used by cron"),
69- 'frequency': fields.integer('Frequency', help="Interval cron in minutes. Set periodicity on 'minute'"),
70- 'repeat': fields.datetime('Repeat',
71- help="Recurrency selection with datetime widget : if 'periodicity' is 'day' only hour indicate the external data; if is 'week' "),
72- 'report_type': fields.selection([('sale','Sale'), ('product','Product')],'Report', help="Report type name to cron"),
73- 'referential_id':fields.many2one('external.referential', 'Referential', help="External referential"),
74+ ('minute','Minute')), 'Periodicity', required=True,
75+ help="Base unit periodicity used by cron"),
76+ 'frequency': fields.integer('Frequency (min.)',
77+ help="Interval cron in minutes if periodicity is in 'minutes'"),
78+ 'repeat': fields.datetime('Repeat', help="Recurrency selection with datetime widget : \
79+ if 'periodicity' is 'day' only hour indicate the external data; if is 'week'"),
80+ 'report_type': fields.selection([('sale','Sale'), ('product','Product')],'Report',
81+ required=True, help="Report type name to cron"),
82+ 'referential_id':fields.many2one('external.referential', 'Referential', required=True,
83+ help="External referential"),
84+ 'exported': fields.function(_export_management, multi='export', method=True, string='Exported', type='boolean',
85+ help="True if cron has been exported to external application with success and subsequently has an external referential in 'ir.model.data'"),
86+ 'readonly': fields.function(_export_management, multi='export', type='boolean', method=True, string='Read only', help='define form read only behavior'),
87 }
88
89 _defaults = {
90- 'active': 1
91+ 'active': 1,
92+ 'name': 'external cron',
93 }
94
95+#TODO refactor the constraint (only used by the prototype, ebayerpconnect)
96+ def _check_field_frequency(self, cr, uid, ids, context=None):
97+ for cron in self.browse(cr, uid, ids):
98+ if cron.frequency <= EXT_CRON_MINIMUM_FREQUENCY and cron.period == 'minute':
99+ raise except_orm(_('Invalid field value :'), _("'Frequency' field must be greater than %s minutes" %EXT_CRON_MINIMUM_FREQUENCY))
100+ return True
101+
102+ def _count_duplicate_report(self, cr, uid, vals, context=None):
103+ domain = []
104+ for key, val in vals.items():
105+ domain.append((key, '=', val))
106+ domain.append(('active', '=', 'True'))
107+ return len(self.search(cr, uid, domain, context=context))
108+
109+ def _check_field_active(self, cr, uid, ids, context=None):
110+ """ """
111+ for cron in self.browse(cr, uid, ids, context=context):
112+ vals = {'report_type': cron.report_type, 'referential_id': cron.referential_id.id}
113+ if cron.active == True:
114+ report_count = self._count_duplicate_report(cr, uid, vals, context=context)
115+ if report_count > 1:
116+ raise except_orm(_('Too many reports of the same type for this referential:'),
117+ _("There are %s 'Reports' of '%s' type with 'active' value checked. \nOnly 1 is authorized!" % (report_count, cron.report_type)))
118+ return True
119+
120+ def copy(self, cr, uid, id, default=None, context=None):
121+ row = self.browse(cr, uid, id, context=context)
122+ if default is None:
123+ default = {}
124+ default_custom={'exported': False, 'active': False, 'name': row.name+' copy'}
125+ default.update(default_custom)
126+ return super(external_cron, self).copy(cr, uid, id, default, context=context)
127+
128+ _constraints = [
129+ (_check_field_frequency, "Error message in raise", ['frequency']),
130+ (_check_field_active, "Only one active cron per job", ['active']),
131+ ]
132+
133 def unlink(self, cr, uid, ids, context=None):
134 self.ext_unlink(cr, uid, ids, context=context)
135 return super(external_cron, self).unlink(cr, uid, ids, context=context)
136-
137
138=== modified file 'base_external_cron/external_cron_view.xml'
139--- base_external_cron/external_cron_view.xml 2012-08-24 00:40:58 +0000
140+++ base_external_cron/external_cron_view.xml 2012-12-03 16:33:32 +0000
141@@ -8,8 +8,7 @@
142 <openerp>
143 <data>
144
145- <!-- VIEWS FOR THE OBJECT : external.cron -->
146- <!-- form -->
147+ <!-- FORM -->
148 <record id="external_cron_view_form" model="ir.ui.view">
149 <field name="name">base_external_cron.external.cron.view_form</field>
150 <field name="model">external.cron</field>
151@@ -17,21 +16,22 @@
152 <field name="type">form</field>
153 <field name="arch" type="xml">
154 <form string="external.cron">
155- <field name="name" />
156- <field name="active" />
157- <field name="period" />
158- <field name="frequency" />
159-<!--
160- <field name="repeat" readonly="1" />
161--->
162- <field name="repeat" />
163- <field name="report_type" />
164- <field name="referential_id" />
165+ <group name="common">
166+ <field name="name" />
167+ <field name="active" attrs="{'readonly':[('readonly','=',True)]}"/>
168+ <field name="period" attrs="{'readonly':[('readonly','=',True)]}"/>
169+ <field name="report_type" attrs="{'readonly':[('readonly','=',True)]}"/>
170+ <field name="repeat" attrs="{'invisible':[('frequency','!=',0),('period','=','minute')], 'required': [('period','!=', 'minute')]}"/>
171+ <field name="frequency" attrs="{'invisible':[('period','!=','minute')],'readonly':[('readonly','=',True)]}"/>
172+ <field name="referential_id" attrs="{'readonly':[('readonly','=',True)]}"/>
173+ <field name="exported" />
174+ <field name="readonly" invisible="1" />
175+ </group>
176 </form>
177 </field>
178 </record>
179
180- <!-- tree -->
181+ <!-- TREE -->
182 <record id="external_cron_view_tree" model="ir.ui.view">
183 <field name="name">base_external_cron.external.cron.view_tree</field>
184 <field name="model">external.cron</field>
185@@ -43,18 +43,28 @@
186 <field name="active" />
187 <field name="period" />
188 <field name="report_type" />
189- <field name="frequency" />
190- <field name="repeat" />
191+ <field name="frequency" attrs="{'invisible':[('period','!=','minute')]}"/>
192 <field name="referential_id" />
193+ <field name="exported" string="exp."/>
194 </tree>
195 </field>
196 </record>
197
198 <!-- Action used by menu -->
199 <record id="action_external_cron" model="ir.actions.act_window">
200+ <field name="help">
201+'Repeat' field behavior: only visible if 'Periodicity' is in 'Month/Day/Week' -------
202+'Repeat' format is 'mm/dd/YYYY HH:MM:SS': example: 12/24/2013 12:05:32 (Tuesday) -------
203+If 'Periodicity' is 'Month': next cron will be each 24th day of the month at 12:05:32 -------
204+If 'Periodicity' is 'Month' and you set 29, 30 or 31 instead of 24th day next execution always will be the last day of the month-------
205+If 'Periodicity' is 'Week': next cron will be each Tuesday at 12:05:32 -------
206+If 'Periodicity' is 'Day': next cron will be each day at 12:05:32 ----------------
207+If 'Periodicity' is 'Minute': next cron will be each X minutes (depends on 'frequency' field value)------
208+ </field>
209 <field name="name">External Cron</field>
210 <field name="res_model">external.cron</field>
211 <field name="view_type">form</field>
212+ <field name="context">{'active_test': False}</field>
213 <field name="view_mode">tree,form</field>
214 </record>
215
216
217=== modified file 'base_external_file_protocole/__openerp__.py'
218--- base_external_file_protocole/__openerp__.py 2012-08-22 22:42:00 +0000
219+++ base_external_file_protocole/__openerp__.py 2012-12-03 16:33:32 +0000
220@@ -36,8 +36,11 @@
221 'init_xml': [],
222 'update_xml': [
223 'file_buffer_view.xml',
224+ 'file_buffer_data.xml',
225+ 'external_referential_view.xml',
226 'settings/external.referential.category.csv',
227- 'file_buffer_data.xml',
228+ 'settings/external.referential.type.csv',
229+ 'settings/external.referential.version.csv',
230 ],
231 'demo_xml': [],
232 'installable': True,
233
234=== added file 'base_external_file_protocole/external_referential_view.xml'
235--- base_external_file_protocole/external_referential_view.xml 1970-01-01 00:00:00 +0000
236+++ base_external_file_protocole/external_referential_view.xml 2012-12-03 16:33:32 +0000
237@@ -0,0 +1,24 @@
238+<?xml version="1.0" encoding="utf-8"?>
239+<!--
240+ base_sale_report_synchronizer for OpenERP
241+ Copyright (C) 2012 Akretion Sébastien BEAU <sebastien.beau@akretion.com>
242+ The licence is in the file __openerp__.py
243+-->
244+
245+<openerp>
246+ <data>
247+ <record id="external_referential_form_view" model="ir.ui.view">
248+ <field name="name">base_external_file_protocole.external_referential_form_view</field>
249+ <field name="model">external.referential</field>
250+ <field name="inherit_id" ref="base_external_referentials.external_referential_form_view" />
251+ <field name="type">form</field>
252+ <field name="arch" type="xml">
253+ <field name="location" position="after">
254+ <field name="port" attrs="{'invisible': [['type_name', 'not in', ['SFTP', 'FTP']]],
255+ 'required': [['type_name', 'in', ['SFTP', 'FTP']]]}"/>
256+ <field name="home_folder" attrs="{'invisible': [['type_name', 'not in', ['SFTP', 'FTP', 'File System']]]}"/>
257+ </field>
258+ </field>
259+ </record>
260+ </data>
261+</openerp>
262
263=== modified file 'base_external_file_protocole/external_referentials.py'
264--- base_external_file_protocole/external_referentials.py 2012-08-10 08:07:58 +0000
265+++ base_external_file_protocole/external_referentials.py 2012-12-03 16:33:32 +0000
266@@ -1,4 +1,4 @@
267- # -*- encoding: utf-8 -*-
268+ # -*- encoding: utf-8 -*-
269 ###############################################################################
270 # #
271 # file_exchange for OpenERP #
272@@ -19,12 +19,21 @@
273 # #
274 ###############################################################################
275
276-from osv import osv, fields
277-import netsvc
278+from openerp.osv.orm import Model
279+from openerp.osv import fields
280+from openerp.osv.osv import except_osv
281 from base_file_protocole.base_file_protocole import FileConnection
282 from tools.translate import _
283-
284-class external_referential(osv.osv):
285+from base_external_referentials.external_referentials import REF_VISIBLE_FIELDS
286+
287+REF_VISIBLE_FIELDS.update({
288+ 'SFTP': ['location', 'apiusername', 'apipass'],
289+ 'FTP': ['location', 'apiusername', 'apipass'],
290+})
291+
292+
293+
294+class external_referential(Model):
295 _inherit = "external.referential"
296
297 def external_connection(self, cr, uid, id, debug=False, logger=False, context=None):
298@@ -32,32 +41,25 @@
299 id=id[0]
300 referential = self.browse(cr, uid, id, context=context)
301 try:
302- return FileConnection(referential.protocole, referential.location, referential.apiusername,\
303+ return FileConnection(referential.type_id.code, referential.location, referential.apiusername,\
304 referential.apipass, port=referential. port, allow_dir_creation = True, \
305 home_folder=referential.home_folder)
306 except Exception, e:
307- raise osv.except_osv(_("Base File Protocole Connection Error"), _("Could not connect to server\nCheck url & user & password.\n %s"%e))
308+ raise except_osv(_("Base File Protocole Connection Error"),
309+ _("Could not connect to server\nCheck url & user & password.\n %s") % e)
310
311 _columns={
312- 'protocole': fields.selection([('ftp','ftp'), ('filestore', 'Filestore'), ('sftp', 'sftp')], 'Protocole'),
313 'port': fields.integer('Port'),
314 'home_folder': fields.char('Home Folder', size=64),
315 }
316
317- def get_file_to_import(cr, uid, referential_id, mapping_id, context=None):
318- '''
319- return les file_buffer qui sont a l’état waiting pour le referential et le mapping_id choisi
320- '''
321-
322 def _prepare_external_referential_fieldnames(self, cr, uid, context=None):
323 res = super(external_referential, self)._prepare_external_referential_fieldnames(cr, uid, context=context)
324 res.append('protocole')
325 return res
326
327 def _prepare_external_referential_vals(self, cr, uid, referential, context=None):
328- res = super(external_referential, self)._prepare_external_referential_vals(cr, uid, mapping, context=context)
329+ res = super(external_referential, self)._prepare_external_referential_vals(cr, uid, referential, context=context)
330 res['protocole'] = referential.protocole
331 return res
332
333-external_referential()
334-
335
336=== modified file 'base_external_file_protocole/file_buffer.py'
337--- base_external_file_protocole/file_buffer.py 2012-08-22 22:48:00 +0000
338+++ base_external_file_protocole/file_buffer.py 2012-12-03 16:33:32 +0000
339@@ -19,38 +19,41 @@
340 # #
341 ###############################################################################
342
343-
344-from osv import osv, fields
345+from openerp.osv.orm import Model
346+from openerp.osv import fields
347 import base64
348 from base_external_referentials.external_osv import ExternalSession
349
350-class file_buffer(osv.osv):
351+class file_buffer(Model):
352
353 _name = "file.buffer"
354 _description = "File Buffer"
355
356-
357 _columns = {
358 'name': fields.char('Name', size=64),
359- 'file_id': fields.char('Ext. file', size=64),
360- 'state': fields.selection((('waiting','Waiting'), ('running','Running'), ('done','Done')), 'State'),
361+ 'file_id': fields.char('Exch. file', size=64, help="Exchange id file"),
362+ 'state': fields.selection((('waiting','Waiting'), ('running','Running'), ('done','Done'),
363+ ('fail','Fail')), 'State'),
364 'active': fields.boolean('Active'),
365- 'mapping_id': fields.many2one('external.mapping', 'Mapping',
366- help=""),
367- 'job_ended': fields.datetime('Job ended'),
368- 'referential_id': fields.related('mapping_id', 'referential_id', type='many2one', relation='external.referential', string='Ext. referential', store=True),
369+ 'mapping_id': fields.many2one('external.mapping', 'Mapping'),
370+ 'job_ended': fields.datetime('Job ended', help="GMT date given by external application"),
371+ 'referential_id': fields.related('shop_id', 'referential_id', type='many2one',
372+ relation='external.referential', string='Ext. referential', store=True),
373 #This field add a dependency on sale (maybe move it into an other module if it's problematic)
374 'shop_id': fields.many2one('sale.shop', 'Shop'),
375+ 'direction': fields.selection([('input', 'Input'),('output', 'Output')], 'Direction',
376+ help='flow direction of the file'),
377+ 'response': fields.text('Response', help='External application response'),
378 }
379
380- _order = 'name desc'
381+ _order = 'job_ended desc'
382
383 _defaults = {
384 'active': 1,
385 'state': 'waiting',
386 }
387
388- def get_file(self, cr, uid, file_id, context=None):
389+ def get_file(self, cr, uid, file_buffer_id, context=None):
390 """
391 Fonction that return the content of the attachment
392 :param int file_id : id of the file buffer
393@@ -58,13 +61,44 @@
394 :return: the content attachment
395 """
396 attach_obj = self.pool.get('ir.attachment')
397- attachment_id = attach_obj.search(cr, uid, [('res_model','=','file.buffer'), ('res_id','=', file_id)])
398+ attachment_id = attach_obj.search(cr, uid, [('res_model','=','file.buffer'),
399+ ('res_id','=', file_buffer_id)])
400 if not attachment_id:
401 return False
402 else:
403 attachment = attach_obj.browse(cr, uid, attachment_id[0], context=context)
404 return base64.decodestring(attachment.datas)
405
406+ def create_file_buffer_attachment(self, cr, uid, file_buffer_id, datas, file_name,
407+ context=None, extension='csv', prefix_file_name='report'):
408+ """
409+ Create file attachment to file.buffer object
410+ :param int file_buffer_id:
411+ :param str datas: file content
412+ :param str file_id: file name component
413+ :param str extension: file extension
414+ :param str prefix_file_name:
415+ :rtype: boolean
416+ :return: True
417+ """
418+ if context is None: context = {}
419+ context.update({'default_res_id': file_buffer_id, 'default_res_model': 'file.buffer'})
420+ datas_encoded = base64.encodestring(datas)
421+ attach_name = prefix_file_name + '_' + file_name + '.' + extension
422+ params_attachment = {'name': attach_name, 'datas': datas_encoded,
423+ 'datas_fname': attach_name}
424+ attachment_id = self.pool.get('ir.attachment').create(cr, uid, params_attachment, context)
425+
426+ return True
427+
428+ def check_state_file_buffer_scheduler(self, cr, uid, domain=None, context=None):
429+ if not domain: domain = []
430+ domain.append(('state', '=', 'running'))
431+ ids = self.search(cr, uid, domain, context=context)
432+ if ids:
433+ return self.check_state(cr, uid, ids, context=context)
434+ return True
435+
436 def run_file_buffer_scheduler(self, cr, uid, domain=None, context=None):
437 if not domain: domain = []
438 domain.append(('state', '=', 'waiting'))
439@@ -80,10 +114,11 @@
440 if context is None: context = {}
441 for filebuffer in self.browse(cr, uid, ids, context=context):
442 external_session = ExternalSession(filebuffer.referential_id, filebuffer)
443- self._run(cr, uid, external_session, filebuffer, context=context)
444- filebuffer.done()
445+ self._run(cr, uid, external_session, filebuffer, context=context)
446+ if filebuffer.direction == 'input':
447+ filebuffer.done()
448 return True
449-
450+
451 def _run(self, cr, uid, external_session, filebuffer, context=None):
452 filebuffer._set_state('running', context=context)
453
454@@ -93,3 +128,7 @@
455 def _set_state(self, cr, uid, ids, state, context=None):
456 for id in ids:
457 self.write(cr, uid, id, {'state': state}, context=context)
458+
459+ def check_state(self, cr, uid, ids, context=None):
460+ """ Inherit this function in your module """
461+ return True
462
463=== modified file 'base_external_file_protocole/file_buffer_data.xml'
464--- base_external_file_protocole/file_buffer_data.xml 2012-08-22 22:42:00 +0000
465+++ base_external_file_protocole/file_buffer_data.xml 2012-12-03 16:33:32 +0000
466@@ -3,7 +3,7 @@
467 <data noupdate="1">
468
469 <record forcecreate="True" id="ir_cron_run_file_buffer_scheduler_action" model="ir.cron">
470- <field name="name">Proccess File Buffer</field>
471+ <field name="name">File Buffer: process</field>
472 <field eval="False" name="active"/>
473 <field name="user_id" ref="base.user_root"/>
474 <field name="interval_number">10</field>
475@@ -15,5 +15,18 @@
476 <field eval="'()'" name="args"/>
477 </record>
478
479+ <record forcecreate="True" id="ir_cron_check_state_file_buffer_scheduler_action" model="ir.cron">
480+ <field name="name">File Buffer: check state (output buffer)</field>
481+ <field eval="False" name="active"/>
482+ <field name="user_id" ref="base.user_root"/>
483+ <field name="interval_number">10</field>
484+ <field name="interval_type">minutes</field>
485+ <field name="numbercall">-1</field>
486+ <field eval="False" name="doall"/>
487+ <field eval="'file.buffer'" name="model"/>
488+ <field eval="'check_state_file_buffer_scheduler'" name="function"/>
489+ <field eval="'()'" name="args"/>
490+ </record>
491+
492 </data>
493 </openerp>
494
495=== modified file 'base_external_file_protocole/file_buffer_view.xml'
496--- base_external_file_protocole/file_buffer_view.xml 2012-08-22 22:36:44 +0000
497+++ base_external_file_protocole/file_buffer_view.xml 2012-12-03 16:33:32 +0000
498@@ -6,21 +6,30 @@
499
500 <openerp>
501 <data>
502-
503+<!-- SEARCH -->
504 <record id="file_buffer_view_search" model="ir.ui.view">
505 <field name="name">file.buffer.search</field>
506 <field name="model">file.buffer</field>
507 <field name="type">search</field>
508 <field name="arch" type="xml">
509- <search string="Search Sales Order">
510- <filter icon="terp-document-new" name="wait" string="Waiting" domain="[('state','=','waiting')]"/>
511- <filter icon="terp-check" string="Done" domain="[('state','=','done')]"/>
512+ <search string="Search Files Buffer">
513+ <group>
514+ <filter icon="kanban-pause" name="wait" string="Waiting" domain="[('state','=','waiting')]"/>
515+ <filter icon="gtk-apply" string="Done" domain="[('state','=','done')]"/>
516+ <filter icon="gtk-execute" string="Running" domain="[('state','=','running')]"/>
517+ <filter icon="terp-gtk-stop" string="Fail" domain="[('state','=','fail')]"/>
518+ </group>
519+ <group>
520+ <filter icon="gtk-go-down" string="In" domain="[('direction','=','input')]"/>
521+ <filter icon="gtk-go-up" string="Out" domain="[('direction','=','output')]"/>
522+ <field name="name" />
523+ <field name="file_id" string="Exchange file"/>
524+ </group>
525 </search>
526 </field>
527 </record>
528
529-
530-<!-- VIEW FOR THE OBJECT : file_buffer -->
531+<!-- FORM -->
532 <record id="file_buffer_view_form" model="ir.ui.view">
533 <field name="name">file_buffer.file_buffer.view_form</field>
534 <field name="model">file.buffer</field>
535@@ -29,18 +38,26 @@
536 <field name="arch" type="xml">
537 <form string="file_buffer">
538 <field name="name" />
539- <field name="state" />
540+ <field name="state" readonly="1"/>
541 <field name="mapping_id" />
542 <field name="file_id" />
543- <field name="referential_id"/>
544+ <field name="referential_id" readonly="1"/>
545 <field name="shop_id"/>
546 <field name="job_ended" />
547 <field name="active"/>
548- <button name="run" string="Run" colspan="2" type="object" />
549+ <field name="direction" readonly="1" />
550+ <newline />
551+ <button name="run" string="Run" colspan="2" type="object" attrs="{'invisible':[('state','in', ('running','done'))]}"/>
552+ <newline />
553+ <button name="check_state" string="Check state" colspan="2" type="object" attrs="{'invisible':[('state','!=', 'running')]}"/>
554+ <newline />
555+ <separator string="External application response (for output direction)" colspan="4"/>
556+ <field name="response" nolabel="1" readonly="1" colspan="4" />
557 </form>
558 </field>
559 </record>
560
561+<!-- TREE -->
562 <record id="file_buffer_view_tree" model="ir.ui.view">
563 <field name="name">file_buffer.file_buffer.view_tree</field>
564 <field name="model">file.buffer</field>
565@@ -54,6 +71,7 @@
566 <field name="mapping_id" />
567 <field name="file_id" />
568 <field name="job_ended" />
569+ <field name="direction" string="direct." />
570 <field name="referential_id" string="ex ref"/>
571 <button name="run" string="Run" icon="gtk-go-forward" type="object"/>
572 </tree>
573
574=== added file 'base_external_file_protocole/settings/external.referential.type.csv'
575--- base_external_file_protocole/settings/external.referential.type.csv 1970-01-01 00:00:00 +0000
576+++ base_external_file_protocole/settings/external.referential.type.csv 2012-12-03 16:33:32 +0000
577@@ -0,0 +1,4 @@
578+id,name,categ_id:id,code
579+t-sftp,SFTP,file-protocole,sftp
580+t-ftp,FTP,file-protocole,ftp
581+t-filesystem,File System,file-protocole,filesystem
582
583=== added file 'base_external_file_protocole/settings/external.referential.version.csv'
584--- base_external_file_protocole/settings/external.referential.version.csv 1970-01-01 00:00:00 +0000
585+++ base_external_file_protocole/settings/external.referential.version.csv 2012-12-03 16:33:32 +0000
586@@ -0,0 +1,4 @@
587+type_id:id,id,name,code
588+t-sftp,v-stfp,.,.
589+t-ftp,v-ftp,.,.
590+t-filesystem,v-filesystem,.,.
591
592=== modified file 'base_external_referentials/__openerp__.py'
593--- base_external_referentials/__openerp__.py 2012-03-30 13:07:11 +0000
594+++ base_external_referentials/__openerp__.py 2012-12-03 16:33:32 +0000
595@@ -1,7 +1,7 @@
596 # -*- encoding: utf-8 -*-
597 ##############################################################################
598 #
599-# OpenERP, Open Source Management Solution
600+# OpenERP, Open Source Management Solution
601 # Copyright (C) 2009 Akretion (<http://www.akretion.com>). All Rights Reserved
602 # authors: Raphaël Valyi, Sharoon Thomas
603 #
604@@ -48,7 +48,7 @@
605 """,
606 'author': 'Raphaël Valyi (Akretion.com), Sharoon Thomas (Openlabs.co.in)',
607 'website': 'http://www.akretion.com, http://openlabs.co.in/',
608- 'depends': ['base','base_pop_up'],
609+ 'depends': ['base','base_pop_up', 'base_file_protocole', 'email_template'],
610 'init_xml': [],
611 'update_xml': [
612 'external_referentials_view.xml',
613@@ -57,6 +57,7 @@
614 'security/ir.model.access.csv',
615 'group_fields_view.xml',
616 'security/base_external_referentials_security.xml',
617+ 'report_mail_template.xml',
618 ],
619 'demo_xml': [],
620 'installable': True,
621
622=== modified file 'base_external_referentials/decorator.py'
623--- base_external_referentials/decorator.py 2012-08-21 07:39:24 +0000
624+++ base_external_referentials/decorator.py 2012-12-03 16:33:32 +0000
625@@ -19,7 +19,7 @@
626 # #
627 ###############################################################################
628
629-from osv import osv
630+from openerp.osv.osv import except_osv
631 import pooler
632 from tools.translate import _
633 from message_error import MappingError
634@@ -61,7 +61,7 @@
635 original_func = class_func.__dict__.get("_original_func_before_wrap")
636 if original_func is func:
637 use_next_class = True
638- raise osv.except_osv(_("Not Implemented"), _("Not parent method found"))
639+ raise except_osv(_("Not Implemented"), _("No parent method found"))
640 wrapped._original_func_before_wrap = func
641 return wrapped
642 return decorator
643@@ -75,7 +75,7 @@
644 @functools.wraps(func)
645 def wrapper(self, cr, uid, external_session, *args, **kwargs):
646 #if not self._columns.get('referential_id'):
647- # raise osv.except_osv(_("Not Implemented"), _("The field referential_id doesn't exist on the object %s. Reporting system can not be used" %(self._name,)))
648+ # raise except_osv(_("Not Implemented"), _("The field referential_id doesn't exist on the object %s. Reporting system can not be used" %(self._name,)))
649
650 report_obj = self.pool.get('external.report')
651 context = kwargs.get('context')
652@@ -109,7 +109,7 @@
653 external_session.logger.debug(_("There is no key report_id in the context, error will be not catch"))
654 return func(self, cr, uid, external_session, resource, *args, **kwargs)
655 if context.get('report_line_based_on'):
656- if context is None['report_line_based_on'] == self._name:
657+ if not context['report_line_based_on'] == self._name:
658 return func(self, cr, uid, external_session, resource, *args, **kwargs)
659 report_line_obj = self.pool.get('external.report.line')
660 report_line_id = report_line_obj.start_log(
661@@ -138,7 +138,7 @@
662 import_cr.rollback()
663 error_message = 'Error with xmlrpc protocole. Error details : error %s : %s'%(e.faultCode, e.faultString)
664 report_line_obj.log_fail(cr, uid, external_session, report_line_id, error_message, context=context)
665- except osv.except_osv as e:
666+ except except_osv as e:
667 if config['debug_mode']: raise
668 import_cr.rollback()
669 error_message = '%s : %s'%(e.name, e.value)
670@@ -157,10 +157,10 @@
671 return response
672 return wrapper
673
674-#This decorator is for now a prototype it will be improve latter, maybe the best will to have to kind of decorator (import and export)
675+#This decorator is for now a prototype it will be improve latter, maybe the best will to have two kind of decorator (import and export)
676 def catch_action(func):
677 """ This decorator open and close a new cursor and if an error occure it will generate a error line in the reporting system
678- The function must start with "self, cr, uid, object"
679+ The function must start with "self, cr, uid, object_id"
680 And the object must have a field call "referential_id" related to the object "external.referential"
681 """
682 @functools.wraps(func)
683@@ -190,7 +190,7 @@
684 import_cr.rollback()
685 error_message = 'Error with xmlrpc protocole. Error details : error %s : %s'%(e.faultCode, e.faultString)
686 report_line_obj.log_fail(cr, uid, None, report_line_id, error_message, context=context)
687- except osv.except_osv as e:
688+ except except_osv as e:
689 if config['debug_mode']: raise
690 import_cr.rollback()
691 error_message = '%s : %s'%(e.name, e.value)
692
693=== modified file 'base_external_referentials/external_osv.py'
694--- base_external_referentials/external_osv.py 2012-08-23 17:04:44 +0000
695+++ base_external_referentials/external_osv.py 2012-12-03 16:33:32 +0000
696@@ -21,14 +21,14 @@
697 #
698 ##############################################################################
699
700-from osv import fields, osv
701+from openerp.osv.orm import Model
702+from openerp.osv.osv import except_osv
703 import base64
704+import urllib
705 import time
706 import netsvc
707 from datetime import datetime
708 import logging
709-import pooler
710-from collections import defaultdict
711 from lxml import objectify
712 from openerp.tools.config import config
713
714@@ -45,16 +45,16 @@
715 def extend(class_to_extend):
716 """
717 Decorator to use to extend a existing class with a new method
718- Example :
719- @extend(osv.osv)
720+ Example :
721+ @extend(Model)
722 def new_method(self, *args, **kwargs):
723 print 'I am in the new_method', self._name
724 return True
725- Will add the method new_method to the class osv.osv
726+ Will add the method new_method to the class Model
727 """
728 def decorator(func):
729 if hasattr(class_to_extend, func.func_name):
730- raise osv.except_osv(_("Developper Error"),
731+ raise except_osv(_("Developper Error"),
732 _("You can extend the class %s with the method %s.",
733 "Indeed this method already exist use the decorator 'replace' instead"))
734 setattr(class_to_extend, func.func_name, func)
735@@ -64,33 +64,33 @@
736 def override(class_to_extend, prefix):
737 """
738 Decorator for overiding an existing method in a class
739-
740+
741 Example of use:
742-
743- @override(osv.osv, 'magento_')
744+
745+ @override(Model, 'magento_')
746 def write(self, *args, **kwargs):
747 print 'I am in the write overwrited 1', self._name
748- return osv.osv.magento_write(self, *args, **kwargs)
749+ return Model.magento_write(self, *args, **kwargs)
750
751- @override(osv.osv, 'amazon_')
752+ @override(Model, 'amazon_')
753 def write(self, *args, **kwargs):
754 print 'I am in the write overwrited 2', self._name
755- return osv.osv.amazon_write(self, *args, **kwargs)
756+ return Model.amazon_write(self, *args, **kwargs)
757
758- @override(osv.osv, 'ebay_')
759+ @override(Model, 'ebay_')
760 def write(self, *args, **kwargs):
761 print 'I am in the write overwrited 3', self._name
762- return osv.osv.ebay_write(self, *args, **kwargs)
763+ return Model.ebay_write(self, *args, **kwargs)
764
765 """
766 def decorator(func):
767 if not hasattr(class_to_extend, func.func_name):
768- raise osv.except_osv(_("Developper Error"),
769+ raise except_osv(_("Developper Error"),
770 _("You can replace the method %s of the class %s. "
771 "Indeed this method doesn't exist")%(func.func_name, class_to_extend))
772 original_function_name = prefix + func.func_name
773 if hasattr(class_to_extend, original_function_name):
774- raise osv.except_osv(_("Developper Error"),
775+ raise except_osv(_("Developper Error"),
776 _("The method %s already exist. "
777 "Please change the prefix name")%original_function_name)
778 setattr(class_to_extend, original_function_name, getattr(class_to_extend, func.func_name))
779@@ -102,7 +102,7 @@
780 class ExternalSession(object):
781 def __init__(self, referential, sync_from_object=None):
782 """External Session in an object to store the information about a connection with an
783- extenal system, like Magento, Prestashop, Ebay, ftp....
784+ external system, like Magento, Prestashop, Ebay, ftp....
785 This class have for fields
786 - referential_id : a many2one related to the referential used for this connection
787 - sync_from_object : a many2one related to the object that launch the synchronization
788@@ -130,7 +130,7 @@
789 """Resource class in a container for using other class like objectify as a dictionnary
790 The implemented dict fonctionality are "get", "__getitem__", "keys"
791 The original object is store in the data field
792-
793+
794 Example :
795 resource = Resource(objectify_resource)
796 my_keys = resource.keys()
797@@ -168,7 +168,7 @@
798 #
799 ########################################################################################################################
800
801-@extend(osv.osv)
802+@extend(Model)
803 def read_w_order(self, cr, uid, ids, fields_to_read=None, context=None, load='_classic_read'):
804 """Read records with given ids with the given fields and return it respecting the order of the ids
805 This is very usefull for synchronizing data in a special order with an external system
806@@ -185,7 +185,7 @@
807 resultat += [x for x in res if x['id'] == id]
808 return resultat
809
810-@extend(osv.osv)
811+@extend(Model)
812 def browse_w_order(self, cr, uid, ids, context=None, list_class=None, fields_process={}):
813 """Fetch records as objects and return it respecting the order of the ids
814 This is very usefull for synchronizing data in a special order with an external system
815@@ -201,7 +201,7 @@
816 resultat += [x for x in res if x.id == id]
817 return resultat
818
819-@extend(osv.osv)
820+@extend(Model)
821 def prefixed_id(self, id):
822 """Return the prefixed_id for an id given
823 :param str or int id: external id
824@@ -212,10 +212,10 @@
825 #is to avoid unique ir_model_data#name per module constraint violation.
826 return self._name.replace('.', '_') + '/' + str(id)
827
828-@extend(osv.osv)
829+@extend(Model)
830 def id_from_prefixed_id(self, prefixed_id):
831 """Return the external id extracted from an prefixed_id
832-
833+
834 :param str prefixed_id: prefixed_id to process
835 :rtype int/str
836 :return the id extracted
837@@ -226,7 +226,7 @@
838 else:
839 return res
840
841-@extend(osv.osv)
842+@extend(Model)
843 def get_all_extid_from_referential(self, cr, uid, referential_id, context=None):
844 """Returns the external ids of the ressource which have an ext_id in the referential
845 :param int referential_id : id of the external referential
846@@ -243,21 +243,21 @@
847 return []
848 return [int(oeid_to_extid[oe_id]) for oe_id in self.exists(cr, uid, oeid_to_extid.keys(), context=context)]
849
850-@extend(osv.osv)
851+@extend(Model)
852 def get_all_oeid_from_referential(self, cr, uid, referential_id, context=None):
853 """Returns the openerp ids of the ressource which have an ext_id in the referential
854 :param int referential_id : id of the external referential
855 :rtype: list
856 :return: the list of all of the openerp ids which have an ext_id in the referential specified
857 """
858-
859+
860 ir_model_data_obj = self.pool.get('ir.model.data')
861 model_data_ids = ir_model_data_obj.search(cr, uid, [('model', '=', self._name), ('referential_id', '=', referential_id)])
862 #because OpenERP might keep ir_model_data (is it a bug?) for deleted records, we check if record exists:
863 claimed_oe_ids = [x['res_id'] for x in ir_model_data_obj.read(cr, uid, model_data_ids, ['res_id'], context=context)]
864 return claimed_oe_ids and self.exists(cr, uid, claimed_oe_ids, context=context) or []
865
866-@extend(osv.osv)
867+@extend(Model)
868 def get_or_create_extid(self, cr, uid, external_session, openerp_id, context=None):
869 """Returns the external id of a resource by its OpenERP id.
870 If not external id have been found, the resource will be automatically exported
871@@ -272,14 +272,12 @@
872 else:
873 return self._export_one_resource(cr, uid, external_session, openerp_id, context=context)
874
875-@extend(osv.osv)
876+@extend(Model)
877 def get_extid(self, cr, uid, openerp_id, referential_id, context=None):
878 """Returns the external id of a resource by its OpenERP id.
879- Return False If not external id have been found
880 :param int openerp_id : openerp id of the resource
881- :param int referential_id : referential id
882- :return: the external id of the resource or False if not exist
883- :rtype: int
884+ :param int referential_id : referential id
885+ :rtype: int
886 """
887 if isinstance(openerp_id, list):
888 openerp_id = openerp_id[0]
889@@ -291,17 +289,17 @@
890 return False
891
892 #TODO Deprecated remove for V7 version
893-@extend(osv.osv)
894+@extend(Model)
895 def oeid_to_existing_extid(self, cr, uid, referential_id, openerp_id, context=None):
896 """Returns the external id of a resource by its OpenERP id.
897 Returns False if the resource id does not exists."""
898 return self.get_extid(cr, uid, openerp_id, referential_id, context=context)
899
900-osv.osv.oeid_to_extid = osv.osv.get_or_create_extid
901+Model.oeid_to_extid = Model.get_or_create_extid
902 ############## END OF DEPRECATED
903
904
905-@extend(osv.osv)
906+@extend(Model)
907 def _get_expected_oeid(self, cr, uid, external_id, referential_id, context=None):
908 """Returns the id of the entry in ir.model.data and the expected id of the resource in the current model
909 Warning the expected_oe_id may not exists in the model, that's the res_id registered in ir.model.data
910@@ -322,13 +320,13 @@
911 expected_oe_id = model_data_obj.read(cr, uid, model_data_id, ['res_id'])['res_id']
912 return model_data_id, expected_oe_id
913
914-@extend(osv.osv)
915+@extend(Model)
916 def get_oeid(self, cr, uid, external_id, referential_id, context=None):
917 """Returns the OpenERP id of a resource by its external id.
918 Returns False if the resource does not exist.
919-
920+
921 :param int/str external_id : external id of the resource
922- :param int referential_id : referential id
923+ :param int referential_id : referential id
924 :return: the openerp id of the resource or False if not exist
925 :rtype: int
926 """
927@@ -342,11 +340,11 @@
928 return expected_oe_id
929 return False
930
931-@extend(osv.osv)
932+@extend(Model)
933 def get_or_create_oeid(self, cr, uid, external_session, external_id, context=None):
934 """Returns the OpenERP ID of a resource by its external id.
935 Creates the resource from the external connection if the resource does not exist.
936-
937+
938 :param ExternalSession external_session : External_session that contain all params of connection
939 :param int/str external_id : external id of the resource
940 :return: the openerp id of the resource
941@@ -360,14 +358,14 @@
942 return False
943
944 #TODO Deprecated remove for V7 version
945-@extend(osv.osv)
946+@extend(Model)
947 def extid_to_existing_oeid(self, cr, uid, referential_id, external_id, context=None):
948 """Returns the OpenERP id of a resource by its external id.
949 Returns False if the resource does not exist."""
950 res = self.get_oeid(cr, uid, external_id, referential_id, context=context)
951 return res
952
953-osv.osv.extid_to_oeid = osv.osv.get_or_create_oeid
954+Model.extid_to_oeid = Model.get_or_create_oeid
955 ############## END OF DEPRECATED
956
957
958@@ -388,7 +386,7 @@
959 ########################################################################################################################
960
961
962-@extend(osv.osv)
963+@extend(Model)
964 def _get_filter(self, cr, uid, external_session, step, previous_filter=None, context=None):
965 """Abstract function that return the filter
966 Can be overwriten in your module
967@@ -401,7 +399,7 @@
968 """
969 return None
970
971-@extend(osv.osv)
972+@extend(Model)
973 def _get_external_resource_ids(self, cr, uid, external_session, resource_filter=None, mapping=None, context=None):
974 """Abstract function that return the external resource ids
975 Can be overwriten in your module
976@@ -412,9 +410,9 @@
977 :rtype: list
978 :return: a list of external_id
979 """
980- raise osv.except_osv(_("Not Implemented"), _("The method _get_external_resource_ids is not implemented in abstract base module!"))
981+ raise except_osv(_("Not Implemented"), _("The method _get_external_resource_ids is not implemented in abstract base module!"))
982
983-@extend(osv.osv)
984+@extend(Model)
985 def _get_default_import_values(self, cr, uid, external_session, mapping_id=None, defaults=None, context=None):
986 """Abstract function that return the default value for on object
987 Can be overwriten in your module
988@@ -426,7 +424,7 @@
989 """
990 return defaults
991
992-@extend(osv.osv)
993+@extend(Model)
994 def _get_import_step(self, cr, uid, external_session, context=None):
995 """Abstract function that return the step for importing data
996 Can be overwriten in your module
997@@ -437,7 +435,7 @@
998 """
999 return 100
1000
1001-@extend(osv.osv)
1002+@extend(Model)
1003 def _get_external_resources(self, cr, uid, external_session, external_id=None, resource_filter=None, mapping=None, fields=None, context=None):
1004 """Abstract function that return the external resource
1005 Can be overwriten in your module
1006@@ -456,7 +454,7 @@
1007
1008 return getattr(external_session.connection, mapping[mapping_id]['external_get_method'])(mapping[mapping_id]['external_resource_name'], resource_filter)
1009
1010-@extend(osv.osv)
1011+@extend(Model)
1012 def _get_mapping_id(self, cr, uid, referential_id, context=None):
1013 """Function that return the mapping id for the corresponding object
1014
1015@@ -464,11 +462,14 @@
1016 :rtype integer
1017 :return the id of the mapping
1018 """
1019- mapping_id = self.pool.get('external.mapping').search(cr, uid, [('model', '=', self._name), ('referential_id', '=', referential_id)], context=context)
1020+ mapping_id = self.pool.get('external.mapping').search(cr, uid, [('model', '=', self._name),
1021+ ('referential_id', '=', referential_id)],
1022+ context=context)
1023 return mapping_id and mapping_id[0] or False
1024
1025-@extend(osv.osv)
1026-def _init_mapping(self, cr, uid, referential_id, convertion_type='from_external_to_openerp', mapping_line_filter_ids=None, mapping=None, mapping_id=None, context=None):
1027+@extend(Model)
1028+def _init_mapping(self, cr, uid, referential_id, convertion_type='from_external_to_openerp',
1029+ mapping_line_filter_ids=None, mapping=None, mapping_id=None, context=None):
1030 """Function to initialise mapping
1031 :param int referential_id: the referential id
1032 :param str convertion_type: the type of convertion 'from_external_to_openerp' or 'from_openerp_to_external'
1033@@ -483,11 +484,16 @@
1034 if not mapping_id:
1035 mapping_id = self._get_mapping_id(cr, uid, referential_id, context=context)
1036 if not mapping.get(mapping_id):
1037- mapping[mapping_id] = self._get_mapping(cr, uid, referential_id, convertion_type=convertion_type, mapping_line_filter_ids=mapping_line_filter_ids, mapping_id=mapping_id, context=context)
1038+ mapping[mapping_id] = self._get_mapping(cr, uid, referential_id,
1039+ convertion_type=convertion_type,
1040+ mapping_line_filter_ids=mapping_line_filter_ids,
1041+ mapping_id=mapping_id,
1042+ context=context)
1043 return mapping, mapping_id
1044
1045-@extend(osv.osv)
1046-def _get_mapping(self, cr, uid, referential_id, convertion_type='from_external_to_openerp', mapping_line_filter_ids=None, mapping_id=None, context=None):
1047+@extend(Model)
1048+def _get_mapping(self, cr, uid, referential_id, convertion_type='from_external_to_openerp',
1049+ mapping_line_filter_ids=None, mapping_id=None, context=None):
1050 """Function that return the mapping line for the corresponding object
1051
1052 :param int referential_id: the referential id
1053@@ -500,7 +506,8 @@
1054 if not mapping_id:
1055 mapping_id = self._get_mapping_id(cr, uid, referential_id, context=context)
1056 if not mapping_id:
1057- raise osv.except_osv(_('External Import Error'), _("The object %s doesn't have an external mapping" %self._name))
1058+ raise except_osv(_('External Import Error'),
1059+ _("The object %s doesn't have an external mapping" % self._name))
1060 else:
1061 #If a mapping exists for current model, search for mapping lines
1062
1063@@ -508,7 +515,9 @@
1064 mapping_line_filter = [('mapping_id', '=', mapping_id),
1065 ('type', 'in', ['in_out', mapping_type])]
1066 if mapping_line_filter_ids:
1067- mapping_line_filter += ['|', ('id', 'in', mapping_line_filter_ids), ('evaluation_type', '=', 'sub-mapping')]
1068+ mapping_line_filter += ['|',
1069+ ('id', 'in', mapping_line_filter_ids),
1070+ ('evaluation_type', '=', 'sub-mapping')]
1071 mapping_line_ids = self.pool.get('external.mapping.line').search(cr, uid, mapping_line_filter, context=context)
1072 if mapping_line_ids:
1073 mapping_lines = self.pool.get('external.mapping.line').read(cr, uid, mapping_line_ids, [], context=context)
1074@@ -521,7 +530,7 @@
1075 res['mapping_lines'] = mapping_lines
1076 return res
1077
1078-@extend(osv.osv)
1079+@extend(Model)
1080 def import_resources(self, cr, uid, ids, resource_name, method="search_then_read", context=None):
1081 """Abstract function to import resources from a shop / a referential...
1082
1083@@ -542,7 +551,8 @@
1084 context['%s_id'%browse_record._name.replace('.', '_')] = browse_record.id
1085 external_session = ExternalSession(browse_record.referential_id, browse_record)
1086 else:
1087- raise osv.except_osv(_("Not Implemented"), _("The field referential_id doesn't exist on the object %s. Reporting system can not be used" %(browse_record._name,)))
1088+ raise except_osv(_("Not Implemented"),
1089+ _("The field referential_id doesn't exist on the object %s. Reporting system can not be used") % (browse_record._name,))
1090 defaults = self.pool.get(resource_name)._get_default_import_values(cr, uid, external_session, context=context)
1091 res = self.pool.get(resource_name)._import_resources(cr, uid, external_session, defaults, method=method, context=context)
1092 for key in result:
1093@@ -550,7 +560,7 @@
1094 return result
1095
1096
1097-@extend(osv.osv)
1098+@extend(Model)
1099 def _import_resources(self, cr, uid, external_session, defaults=None, method="search_then_read", context=None):
1100 """Abstract function to import resources form a specific object (like shop, referential...)
1101
1102@@ -592,11 +602,12 @@
1103 for ext_id in ext_ids:
1104 #TODO import only the field needed to improve speed import ;)
1105 resources = self._get_external_resources(cr, uid, external_session, ext_id, mapping=mapping, fields=None, context=context)
1106- if not isinstance(resources, list):
1107- resources = [resources]
1108- res = self._record_external_resources(cr, uid, external_session, resources, defaults=defaults, mapping=mapping, mapping_id=mapping_id, context=context)
1109- for key in result:
1110- result[key].append(res.get(key, []))
1111+ if resources:
1112+ if not isinstance(resources, list):
1113+ resources = [resources]
1114+ res = self._record_external_resources(cr, uid, external_session, resources, defaults=defaults, mapping=mapping, mapping_id=mapping_id, context=context)
1115+ for key in result:
1116+ result[key].append(res.get(key, []))
1117 elif method == 'search_read':
1118 while True:
1119 resource_filter = self._get_filter(cr, uid, external_session, step, previous_filter=resource_filter, context=context)
1120@@ -614,14 +625,15 @@
1121 resource_filter = self._get_filter(cr, uid, external_session, step, previous_filter=resource_filter, context=context)
1122 #TODO import only the field needed to improve speed import ;)
1123 resources = self._get_external_resources(cr, uid, external_session, resource_filter=resource_filter, mapping=mapping, fields=None, context=context)
1124- if not isinstance(resources, list):
1125- resources = [resources]
1126- res = self._record_external_resources(cr, uid, external_session, resources, defaults=defaults, mapping=mapping, mapping_id=mapping_id, context=context)
1127- for key in result:
1128- result[key].append(res.get(key, []))
1129+ if resources:
1130+ if not isinstance(resources, list):
1131+ resources = [resources]
1132+ res = self._record_external_resources(cr, uid, external_session, resources, defaults=defaults, mapping=mapping, mapping_id=mapping_id, context=context)
1133+ for key in result:
1134+ result[key].append(res.get(key, []))
1135 return result
1136
1137-@extend(osv.osv)
1138+@extend(Model)
1139 def _import_one_resource(self, cr, uid, external_session, external_id, context=None):
1140 """Abstract function to import one resource
1141
1142@@ -639,7 +651,7 @@
1143 id = res.get('write_id') or res.get('create_id')
1144 return id
1145
1146-@extend(osv.osv)
1147+@extend(Model)
1148 def _record_external_resources(self, cr, uid, external_session, resources, defaults=None, mapping=None, mapping_id=None, context=None):
1149 """Abstract function to record external resources (this will convert the data and create/update the object in openerp)
1150
1151@@ -651,6 +663,7 @@
1152 :rtype: dict
1153 :return: dictionary with the key "create_ids" and "write_ids" which containt the id created/written
1154 """
1155+ if context is None: context = {}
1156 result = {'write_ids': [], 'create_ids': []}
1157 mapping, mapping_id = self._init_mapping(cr, uid, external_session.referential_id.id, mapping=mapping, mapping_id=mapping_id, context=context)
1158 if mapping[mapping_id]['key_for_external_id']:
1159@@ -667,7 +680,7 @@
1160 if res.get('write_id'): result['write_ids'].append(res['write_id'])
1161 return result
1162
1163-@extend(osv.osv)
1164+@extend(Model)
1165 def _record_one_external_resource(self, cr, uid, external_session, resource, defaults=None, mapping=None, mapping_id=None, context=None):
1166 """Used in _record_external_resources
1167 The resource will converted into OpenERP data by using the function _transform_external_resources
1168@@ -742,10 +755,10 @@
1169 return {'write_id' : existing_rec_id}
1170 return {}
1171
1172-@extend(osv.osv)
1173+@extend(Model)
1174 def oe_update(self, cr, uid, external_session, existing_rec_id, vals, resource, defaults, context=None):
1175 """Update an existing resource in OpenERP
1176-
1177+
1178 :param ExternalSession external_session : External_session that contain all params of connection
1179 :param int existing_rec_id: openerp id to update
1180 :param dict vals: vals to write
1181@@ -758,10 +771,10 @@
1182 context['referential_id'] = external_session.referential_id.id #did it's needed somewhere?
1183 return self.write(cr, uid, existing_rec_id, vals, context)
1184
1185-@extend(osv.osv)
1186+@extend(Model)
1187 def oe_create(self, cr, uid, external_session, vals, resource, defaults, context=None):
1188 """Create an new resource in OpenERP
1189-
1190+
1191 :param ExternalSession external_session : External_session that contain all params of connection
1192 :param dict vals: vals to create
1193 :param dict resource: resource to convert into OpenERP data
1194@@ -788,7 +801,7 @@
1195 #
1196 ########################################################################################################################
1197
1198-@extend(osv.osv)
1199+@extend(Model)
1200 def _get_export_step(self, cr, uid, external_session, context=None):
1201 """Abstract function that return the step for importing data
1202 Can be overwriten in your module
1203@@ -799,7 +812,7 @@
1204 """
1205 return 10
1206
1207-@extend(osv.osv)
1208+@extend(Model)
1209 def _get_default_export_values(self, cr, uid, external_session, mapping_id=None, defaults=None, context=None):
1210 """Abstract function that return the default value for on object
1211 Can be overwriten in your module
1212@@ -812,7 +825,7 @@
1213 """
1214 return defaults
1215
1216-@extend(osv.osv)
1217+@extend(Model)
1218 def _get_last_exported_date(self, cr, uid, external_session, context=None):
1219 """Abstract function that return the last export date for on object
1220 Can be overwriten in your module
1221@@ -823,7 +836,7 @@
1222 """
1223 return False
1224
1225-@extend(osv.osv)
1226+@extend(Model)
1227 def _set_last_exported_date(self, cr, uid, external_session, date, context=None):
1228 """Abstract function that update the last exported date
1229 Can be overwriten in your module
1230@@ -836,7 +849,7 @@
1231 return True
1232
1233 #For now it's just support 1 level of inherit TODO make it recursive
1234-@extend(osv.osv)
1235+@extend(Model)
1236 def _get_query_and_params_for_ids_and_date(self, cr, uid, external_session, ids=None, last_exported_date=None, context=None):
1237 """Function that build the sql query for getting the ids and the udpate date of each record
1238
1239@@ -899,7 +912,7 @@
1240 query += " order by update_date asc;"
1241 return query, params
1242
1243-@extend(osv.osv)
1244+@extend(Model)
1245 def get_ids_and_update_date(self, cr, uid, external_session, ids=None, last_exported_date=None, context=None):
1246 """This function will return the list of ids and the update date of each record_dicts
1247
1248@@ -909,6 +922,8 @@
1249 :rtype: tuple
1250 :return: an tuple of ids and ids_2_dates (dict with key => 'id' and val => 'last_update_date')
1251 """
1252+ if ids in [[], ()]:
1253+ return [], {}
1254 query, params = self._get_query_and_params_for_ids_and_date(cr, uid, external_session, ids=ids, last_exported_date=last_exported_date, context=context)
1255 cr.execute(query, params)
1256 read = cr.dictfetchall()
1257@@ -921,13 +936,13 @@
1258
1259
1260 #Deprecated
1261-@extend(osv.osv)
1262+@extend(Model)
1263 def init_context_before_exporting_resource(self, cr, uid, external_session, object_id, resource_name, context=None):
1264 if self._name != 'external.referential' and 'referential_id' in self._columns.keys():
1265 context['%s_id'%self._name.replace('.', '_')] = object_id
1266 return context
1267
1268-@extend(osv.osv)
1269+@extend(Model)
1270 def export_resources(self, cr, uid, ids, resource_name, context=None):
1271 """
1272 Abstract function to export resources from a shop / a referential...
1273@@ -944,7 +959,7 @@
1274 if hasattr(browse_record, 'referential_id'):
1275 external_session = ExternalSession(browse_record.referential_id, browse_record)
1276 else:
1277- raise osv.except_osv(_("Not Implemented"), _("The field referential_id doesn't exist on the object %s." %(browse_record._name,)))
1278+ raise except_osv(_("Not Implemented"), _("The field referential_id doesn't exist on the object %s." %(browse_record._name,)))
1279 context = self.init_context_before_exporting_resource(cr, uid, external_session, browse_record.id, resource_name, context=context)
1280 self.pool.get(resource_name)._export_resources(cr, uid, external_session, context=context)
1281 return True
1282@@ -952,7 +967,7 @@
1283
1284 #TODO refactor update date,maybe it will be better to have an update date per resource
1285 #TODO deal correctly with multi resource
1286-@extend(osv.osv)
1287+@extend(Model)
1288 def send_to_external(self, cr, uid, external_session, resources, mapping, mapping_id, update_date=None, context=None):
1289 """Generic method that send the resource to an external referential
1290
1291@@ -982,7 +997,7 @@
1292 self._set_last_exported_date(cr, uid, external_session, update_date, context=context)
1293 return ext_id
1294
1295-@extend(osv.osv)
1296+@extend(Model)
1297 def ext_create(self, cr, uid, external_session, resources, mapping=None, mapping_id=None, context=None):
1298 res = {}
1299 mapping, mapping_id = self._init_mapping(cr, uid, external_session.referential_id.id, mapping=mapping, mapping_id=mapping_id, context=context)
1300@@ -991,12 +1006,12 @@
1301 res[resource_id] = getattr(external_session.connection, mapping[mapping_id]['external_create_method'])(mapping[mapping_id]['external_resource_name'], resource[resource.keys()[0]])
1302 return res
1303
1304-@extend(osv.osv)
1305+@extend(Model)
1306 def ext_update(self, cr, uid, external_session, resources, mapping=None, mapping_id=None, context=None):
1307 """Not Implemented here"""
1308 return False
1309
1310-@extend(osv.osv)
1311+@extend(Model)
1312 def ext_unlink(self, cr, uid, ids, context=None):
1313 ir_model_obj = self.pool.get('ir.model.data')
1314 for object_id in ids:
1315@@ -1011,24 +1026,24 @@
1316 ir_model.unlink()
1317 return True
1318
1319-@extend(osv.osv)
1320+@extend(Model)
1321 def get_lang_to_export(self, cr, uid, external_session, context=None):
1322 """Get the list of lang to export
1323-
1324+
1325 :param ExternalSession external_session : External_session that contain all params of connection
1326 :rtype: list
1327 return: the list of lang to export
1328 """
1329-
1330+
1331 if context is None:
1332 return []
1333 else:
1334 return context.get('lang_to_export') or [context.get('lang')]
1335
1336-@extend(osv.osv)
1337+@extend(Model)
1338 def _export_resources(self, cr, uid, external_session, method="onebyone", context=None):
1339 """Export resource
1340-
1341+
1342 :param ExternalSession external_session : External_session that contain all params of connection
1343 :param str method: method to export data (for now only onebyone)
1344 :rtype: boolean
1345@@ -1065,12 +1080,12 @@
1346 external_session.logger.info("Start to transform and send the ressource %s : %s"%(self._name, resource_id))
1347 self._transform_and_send_one_resource(cr, uid, external_session, resources[resource_id], resource_id, ids_2_date.get(resource_id), mapping, mapping_id, defaults=defaults, context=context)
1348 else:
1349- raise osv.except_osv(_('Developper Error'), _('only method export onebyone is implemented in base_external_referentials'))
1350+ raise except_osv(_('Developper Error'), _('only method export onebyone is implemented in base_external_referentials'))
1351 #now = datetime.now().strftime(DEFAULT_SERVER_DATETIME_FORMAT)
1352 #self._set_last_exported_date(cr, uid, external_session, now, context=context)
1353 return True
1354
1355-@extend(osv.osv)
1356+@extend(Model)
1357 def _transform_and_send_one_resource(self, cr, uid, external_session, resource, resource_id,
1358 update_date, mapping, mapping_id, defaults=None, context=None):
1359 """Transform and send one resource
1360@@ -1093,7 +1108,7 @@
1361 defaults=defaults, context=context)
1362 return self.send_to_external(cr, uid, external_session, {resource_id : resource}, mapping, mapping_id, update_date, context=context)
1363
1364-@extend(osv.osv)
1365+@extend(Model)
1366 def _export_one_resource(self, cr, uid, external_session, resource_id, context=None):
1367 """Export one resource
1368 Export an OpenERP resource into an external system
1369@@ -1115,7 +1130,7 @@
1370
1371 #TODO finish docstring
1372
1373-@extend(osv.osv)
1374+@extend(Model)
1375 def get_translatable_fields(self, cr, uid, fields, context=None):
1376 #TODO make fields parameter optionnal
1377 def is_translatable(field):
1378@@ -1132,7 +1147,7 @@
1379 untranslatable_fields.append(field)
1380 return translatable_fields, untranslatable_fields
1381
1382-@extend(osv.osv)
1383+@extend(Model)
1384 def multi_lang_read(self, cr, uid, external_session, ids, fields_to_read, langs, resources=None, use_multi_lang = True, context=None):
1385 if not resources:
1386 resources = {}
1387@@ -1150,7 +1165,7 @@
1388 if not first and lang_support == 'fields_with_main_lang' or lang_support == 'fields_with_no_lang':
1389 fields = translatable_fields
1390 ctx['lang'] = lang
1391-
1392+
1393 if fields:
1394 for resource in self.read(cr, uid, ids, fields, context=ctx):
1395 if not resources.get(resource['id']): resources[resource['id']] = {}
1396@@ -1158,12 +1173,12 @@
1397 first = False
1398 return resources
1399
1400-@extend(osv.osv)
1401+@extend(Model)
1402 def full_read(self, cr, uid, external_session, ids, langs, resources, mapping=None, mapping_id=None, context=None):
1403 fields_to_read = self.get_field_to_export(cr, uid, ids, mapping, mapping_id, context=context)
1404 return self.multi_lang_read(cr, uid, external_session, ids, fields_to_read, langs, resources=resources, context=context)
1405
1406-@extend(osv.osv)
1407+@extend(Model)
1408 def smart_read(self, cr, uid, external_session, ids, langs, resources, group_ids, inherits_group_ids, last_exported_date=None,
1409 mapping=None, mapping_id=None, context=None):
1410 if last_exported_date:
1411@@ -1188,11 +1203,11 @@
1412 resources = self.multi_lang_read(cr, uid, external_session, resource_ids, fields_to_read, langs, resources=resources, context=context)
1413 return resources
1414
1415-@extend(osv.osv)
1416+@extend(Model)
1417 def get_field_to_export(self, cr, uid, ids, mapping, mapping_id, context=None):
1418 return list(set(self._columns.keys() + self._inherit_fields.keys()))
1419
1420-@extend(osv.osv)
1421+@extend(Model)
1422 def _get_oe_resources(self, cr, uid, external_session, ids, langs, smart_export=None,
1423 last_exported_date=None, mapping=None, mapping_id=None, context=None):
1424 resources = None
1425@@ -1204,7 +1219,7 @@
1426 return resources
1427
1428
1429-@extend(osv.osv)
1430+@extend(Model)
1431 def _get_oeid_from_extid_or_alternative_keys(self, cr, uid, vals, external_id, referential_id, alternative_keys, context=None):
1432 """
1433 Used in ext_import in order to search the OpenERP resource to update when importing an external resource.
1434@@ -1242,7 +1257,7 @@
1435 expected_res_id = expected_res_id and expected_res_id[0] or False
1436 return existing_ir_model_data_id, expected_res_id
1437
1438-@extend(osv.osv)
1439+@extend(Model)
1440 def _prepare_external_id_vals(self, cr, uid, res_id, ext_id, referential_id, context=None):
1441 """ Create an external reference for a resource id in the ir.model.data table"""
1442 ir_model_data_vals = {
1443@@ -1255,9 +1270,16 @@
1444 }
1445 return ir_model_data_vals
1446
1447-@extend(osv.osv)
1448+@extend(Model)
1449 def create_external_id_vals(self, cr, uid, existing_rec_id, external_id, referential_id, context=None):
1450- """Add the external id in the table ir_model_data"""
1451+ """
1452+ Add the external id in the table ir_model_data
1453+ :param id existing_rec_id: erp id object
1454+ :param id external_id: external application id
1455+ :param id referential_id: external id
1456+ :rtype: int
1457+ :return:
1458+ """
1459 ir_model_data_vals = \
1460 self._prepare_external_id_vals(cr, uid, existing_rec_id,
1461 external_id, referential_id,
1462@@ -1280,7 +1302,7 @@
1463 #
1464 ########################################################################################################################
1465
1466-@extend(osv.osv)
1467+@extend(Model)
1468 def _transform_resources(self, cr, uid, external_session, convertion_type, resources, mapping=None, mapping_id=None,
1469 mapping_line_filter_ids=None, parent_data=None, defaults=None, context=None):
1470 """
1471@@ -1294,7 +1316,12 @@
1472 """
1473 result= []
1474 if resources:
1475- mapping, mapping_id = self._init_mapping(cr, uid, external_session.referential_id.id, convertion_type=convertion_type, mapping_line_filter_ids=mapping_line_filter_ids, mapping=mapping, mapping_id=mapping_id, context=context)
1476+ mapping, mapping_id = self._init_mapping(cr, uid, external_session.referential_id.id,
1477+ convertion_type=convertion_type,
1478+ mapping_line_filter_ids=mapping_line_filter_ids,
1479+ mapping=mapping,
1480+ mapping_id=mapping_id,
1481+ context=context)
1482 if mapping[mapping_id].get("mapping_lines"):
1483 for resource in resources:
1484 result.append(self._transform_one_resource(cr, uid, external_session, convertion_type, resource,
1485@@ -1302,7 +1329,7 @@
1486 previous_result=result, defaults=defaults, context=context))
1487 return result
1488
1489-@extend(osv.osv)
1490+@extend(Model)
1491 def _transform_one_resource(self, cr, uid, external_session, convertion_type, resource, mapping=None, mapping_id=None,
1492 mapping_line_filter_ids=None, parent_data=None, previous_result=None, defaults=None, context=None):
1493 """
1494@@ -1327,7 +1354,12 @@
1495 defaults = {}
1496
1497 referential_id = external_session.referential_id.id
1498- mapping, mapping_id = self._init_mapping(cr, uid, referential_id, convertion_type=convertion_type, mapping_line_filter_ids=mapping_line_filter_ids, mapping=mapping, mapping_id=mapping_id, context=context)
1499+ mapping, mapping_id = self._init_mapping(cr, uid, referential_id,
1500+ convertion_type=convertion_type,
1501+ mapping_line_filter_ids=mapping_line_filter_ids,
1502+ mapping=mapping,
1503+ mapping_id=mapping_id,
1504+ context=context)
1505
1506 mapping_lines = mapping[mapping_id].get("mapping_lines")
1507 key_for_external_id = mapping[mapping_id].get("key_for_external_id")
1508@@ -1350,7 +1382,11 @@
1509 sub_mapping_list.append(mapping_line)
1510 else:
1511 if mapping_line['evaluation_type'] == 'direct':
1512- vals[to_field] = self._transform_field(cr, uid, external_session, convertion_type, field_value, mapping_line, context=context)
1513+ vals[to_field] = self._transform_field(cr, uid, external_session,
1514+ convertion_type,
1515+ field_value,
1516+ mapping_line,
1517+ context=context)
1518 else:
1519 #Build the space for expr
1520 #Seb : removing ifield can be great ?
1521@@ -1364,7 +1400,8 @@
1522 'referential_id': external_session.referential_id.id,
1523 'defaults': defaults,
1524 'context': context,
1525- 'ifield': self._transform_field(cr, uid, external_session, convertion_type, field_value, mapping_line, context=context),
1526+ 'ifield': self._transform_field(cr, uid, external_session, convertion_type,
1527+ field_value, mapping_line, context=context),
1528 'conn': context.get('conn_obj', False),
1529 'base64': base64,
1530 'vals': vals,
1531@@ -1400,18 +1437,25 @@
1532 ext_id = ext_id.isdigit() and int(ext_id) or ext_id
1533 vals.update({'external_id': ext_id})
1534 if self._name in context.get('do_not_update', []):
1535- # if the update of the object is not wanted, we skipped the sub_mapping update also. In the function _transform_one_resource, the creation will also be skipped.
1536+ # if the update of the object is not wanted, we skipped the
1537+ # sub_mapping update also. In the function
1538+ # _transform_one_resource, the creation will also be skipped.
1539 alternative_keys = mapping[mapping_id]['alternative_keys']
1540 existing_ir_model_data_id, existing_rec_id = self._get_oeid_from_extid_or_alternative_keys\
1541 (cr, uid, vals, ext_id, referential_id, alternative_keys, context=context)
1542 if existing_rec_id:
1543 return {}
1544 vals = self._merge_with_default_values(cr, uid, external_session, resource, vals, sub_mapping_list, defaults=defaults, context=context)
1545- vals = self._transform_sub_mapping(cr, uid, external_session, convertion_type, resource, vals, sub_mapping_list, mapping, mapping_id, mapping_line_filter_ids=mapping_line_filter_ids, defaults=defaults, context=context)
1546+ vals = self._transform_sub_mapping(cr, uid, external_session,
1547+ convertion_type, resource, vals, sub_mapping_list,
1548+ mapping, mapping_id,
1549+ mapping_line_filter_ids=mapping_line_filter_ids,
1550+ defaults=defaults,
1551+ context=context)
1552
1553 return vals
1554
1555-@extend(osv.osv)
1556+@extend(Model)
1557 def _transform_field(self, cr, uid, external_session, convertion_type, field_value, mapping_line, context=None):
1558 field = False
1559 external_type = mapping_line['external_type']
1560@@ -1420,7 +1464,8 @@
1561 if not (field_value is False or field_value is None):
1562 if internal_type == 'many2one' and mapping_line['evaluation_type']=='direct':
1563 if external_type not in ['int', 'unicode']:
1564- raise osv.except_osv(_('User Error'), _('Wrong external type for mapping %s. One2Many object must have for external type string or integer')%(mapping_line['name'],))
1565+ raise except_osv(_('User Error'),
1566+ _('Wrong external type for mapping %s. One2Many object must have for external type string or integer') % (mapping_line['name'],))
1567 if self._columns.get(internal_field):
1568 related_obj_name = self._columns[internal_field]._obj
1569 else:
1570@@ -1468,6 +1513,14 @@
1571 if not hasattr(casted_field, '__iter__'):
1572 casted_field = (casted_field,)
1573 field = list(casted_field)
1574+ elif external_type == 'url' and internal_type == "binary":
1575+ (filename, header) = urllib.urlretrieve(field_value)
1576+ try:
1577+ f = open(filename , 'rb')
1578+ data = f.read()
1579+ finally:
1580+ f.close()
1581+ return base64.encodestring(data)
1582 else:
1583 if external_type == 'float' and isinstance(field_value, (str, unicode)):
1584 field_value = field_value.replace(',','.')
1585@@ -1513,10 +1566,12 @@
1586
1587 return field
1588
1589-@extend(osv.osv)
1590+@extend(Model)
1591 def _merge_with_default_values(self, cr, uid, external_session, ressource, vals, sub_mapping_list, defaults=None, context=None):
1592 """
1593- Used in _transform_one_external_resource in order to merge the defaults values, some params are useless here but need in base_sale_multichannels to play the on_change
1594+ Used in _transform_one_external_resource in order to merge the
1595+ defaults values, some params are useless here but need in
1596+ base_sale_multichannels to play the on_change
1597
1598 @param sub_mapping_list: list of sub-mapping to apply
1599 @param external_data: list of data to convert into OpenERP data
1600@@ -1531,8 +1586,9 @@
1601 vals[key] = defaults[key]
1602 return vals
1603
1604-@extend(osv.osv)
1605-def _transform_sub_mapping(self, cr, uid, external_session, convertion_type, resource, vals, sub_mapping_list, mapping, mapping_id, mapping_line_filter_ids=None, defaults=None, context=None):
1606+@extend(Model)
1607+def _transform_sub_mapping(self, cr, uid, external_session, convertion_type, resource, vals, sub_mapping_list,
1608+ mapping, mapping_id, mapping_line_filter_ids=None, defaults=None, context=None):
1609 """
1610 Used in _transform_one_external_resource in order to call the sub mapping
1611
1612@@ -1639,7 +1695,8 @@
1613 transform_args[4] = sub_resource
1614 vals[to_field] = sub_mapping_obj._transform_one_resource(*transform_args, **transform_kwargs)
1615 else:
1616- raise osv.except_osv(_('User Error'), _('Error with mapping : %s. Sub mapping can be only apply on one2many, many2one or many2many fields')%(sub_mapping['name'],))
1617+ raise except_osv(_('User Error'),
1618+ _('Error with mapping : %s. Sub mapping can be only apply on one2many, many2one or many2many fields') % (sub_mapping['name'],))
1619 return vals
1620
1621
1622@@ -1648,7 +1705,3 @@
1623 # END GENERIC TRANSFORM FEATURES
1624 #
1625 ########################################################################################################################
1626-
1627-
1628-
1629-
1630
1631=== modified file 'base_external_referentials/external_referentials.py'
1632--- base_external_referentials/external_referentials.py 2012-08-10 08:06:40 +0000
1633+++ base_external_referentials/external_referentials.py 2012-12-03 16:33:32 +0000
1634@@ -20,15 +20,25 @@
1635 #
1636 ##############################################################################
1637
1638-from osv import fields, osv
1639-from sets import Set
1640-from tools.translate import _
1641+from openerp.osv.orm import Model
1642+from openerp.osv import fields
1643 from tempfile import TemporaryFile
1644 from base_file_protocole.base_file_protocole import FileCsvWriter
1645-import time
1646-
1647-
1648-class external_referential_category(osv.osv):
1649+from lxml import etree
1650+from openerp.osv import orm
1651+
1652+
1653+REF_FIELDS = ['location', 'apiusername', 'apipass']
1654+#In your custom module you can specify which field will be visible
1655+#example for making visible the fields location, apiusername and apipass
1656+#for the referential type Magento :
1657+#from base_external_referentials.external_referentials import REF_VISIBLE_FIELDS
1658+#REF_VISIBLE_FIELDS['Magento'] = ['location', 'apiusername', 'apipass']
1659+
1660+REF_VISIBLE_FIELDS = {}
1661+
1662+
1663+class external_referential_category(Model):
1664 _name = 'external.referential.category'
1665 _description = 'External Referential Category (Ex: e-commerce, crm, warehouse)'
1666
1667@@ -46,9 +56,7 @@
1668 categ_id = referential_categ.name.replace('.','_').replace(' ','_')
1669 return categ_id
1670
1671-external_referential_category()
1672-
1673-class external_referential_type(osv.osv):
1674+class external_referential_type(Model):
1675 _name = 'external.referential.type'
1676 _description = 'External Referential Type (Ex.Magento,Spree)'
1677
1678@@ -68,9 +76,8 @@
1679 type_id = referential_type.code.replace('.','_').replace(' ','_')
1680 return type_id
1681
1682-external_referential_type()
1683
1684-class external_referential_version(osv.osv):
1685+class external_referential_version(Model):
1686 _name = 'external.referential.version'
1687 _description = 'External Referential Version (Ex: v1.5.0.0 +, v1.3.2.4 +)'
1688 _rec_name = 'full_name'
1689@@ -97,9 +104,8 @@
1690 'code': fields.char('code', size=64, required=True),
1691 }
1692
1693-external_referential_version()
1694
1695-class external_mapping_template(osv.osv):
1696+class external_mapping_template(Model):
1697 _name = "external.mapping.template"
1698 _description = "The source mapping records"
1699 _rec_name = 'model'
1700@@ -119,9 +125,8 @@
1701 'external_resource_name':fields.char('External Resource Name', size=64),
1702 'extra_name': fields.char('Extra Name', size=100),
1703 }
1704-external_mapping_template()
1705
1706-class external_mappinglines_template(osv.osv):
1707+class external_mappinglines_template(Model):
1708 _name = 'external.mappinglines.template'
1709 _description = 'The source mapping line records'
1710 _rec_name = 'name'
1711@@ -144,7 +149,7 @@
1712 'external_field': fields.char('External Field', size=128),
1713 'type': fields.selection([('in_out', 'External <-> OpenERP'), ('in', 'External -> OpenERP'), ('out', 'External <- OpenERP')], 'Type'),
1714 'evaluation_type': fields.selection([('function', 'Function'), ('sub-mapping','Sub Mapping Line'), ('direct', 'Direct Mapping')], 'Evalution Type', required=True),
1715- 'external_type': fields.selection([('datetime', 'Datetime'), ('unicode', 'String'), ('bool', 'Boolean'), ('int', 'Integer'), ('float', 'Float'), ('list', 'List'), ('dict', 'Dictionnary')], 'External Type', required=True),
1716+ 'external_type': fields.selection([('url', 'URL'), ('datetime', 'Datetime'), ('unicode', 'String'), ('bool', 'Boolean'), ('int', 'Integer'), ('float', 'Float'), ('list', 'List'), ('dict', 'Dictionnary')], 'External Type', required=True),
1717 'datetime_format': fields.char('Datetime Format', size=32),
1718 'in_function': fields.text('Import in OpenERP Mapping Python Function'),
1719 'out_function': fields.text('Export from OpenERP Mapping Python Function'),
1720@@ -160,10 +165,9 @@
1721 'function_name': fields.char('Function Name', size=128),
1722 }
1723
1724-external_mappinglines_template()
1725
1726-class external_referential(osv.osv):
1727- """External referential can have the option _lang_support. It can be equal to :
1728+class external_referential(Model):
1729+ """External referential can have the option _lang_support. It can be equal to :
1730 - fields_with_main_lang : the fields to create will be organized all in the main lang and only the translatable fields in the others.example : {'main_lang': {trad_field : value, untrad_field: value, trad_field : value, untrad_field : value ...}, 'other_lang': {trad_field: value, trad_field: value}, ...}
1731 - fields_with_no_lang : all the fields untranslatable are grouped and the translatable fields are grouped in each lang. example : {'no_lang' : {untrad_field: value, untrad_field: value, untrad_field: value}, 'lang_one' : {trad_field: value, trad_field: value}, 'lang_two' : {trad_field: value, trad_field: value} ...}
1732 - all_fields : all the fields are in all languagues. example = {'lang_one' : {all_fields}, 'lang_two': {all_fields}...}"""
1733@@ -175,6 +179,11 @@
1734 #Only user that can write crypted field can read it
1735 _crypted_field = ['apiusername', 'apipass', 'location']
1736
1737+
1738+ def onchange_version_id(self, cr, uid, ids, version_id, context=None):
1739+ version = self.pool.get('external.referential.version').browse(cr, uid, version_id, context=context)
1740+ return {'value': {'type_name': version.type_id.name}}
1741+
1742 def read(self,cr, uid, ids, fields=None, context=None, load='_classic_read'):
1743 canwrite = self.check_write(cr, uid, raise_exception=False)
1744 res = super(external_referential, self).read(cr, uid, ids, fields=fields, context=context, load=load)
1745@@ -185,6 +194,39 @@
1746 val[crypted_field]='********'
1747 return res
1748
1749+
1750+ def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False, submenu=False):
1751+ """
1752+ Override the original field view get in order to insert dynamically the various fields need
1753+ for the configuration of the referential
1754+ """
1755+ # use lxml to compose the arch XML
1756+ result = super(external_referential, self).fields_view_get(cr, uid,
1757+ view_id=view_id,
1758+ view_type=view_type,
1759+ context=context,
1760+ toolbar=toolbar,
1761+ submenu=submenu,
1762+ )
1763+ if view_type == 'form':
1764+ eview = etree.fromstring(result['arch'])
1765+ toupdate_fields = []
1766+ for field_name in REF_FIELDS:
1767+ field = eview.xpath("//field[@name='%s']"%field_name)
1768+ if field:
1769+ field = field[0]
1770+ referentials = []
1771+ for ref_type, visible_fields in REF_VISIBLE_FIELDS.items():
1772+ if field_name in visible_fields:
1773+ referentials.append(ref_type)
1774+ field.set('attrs', """{
1775+ 'invisible': [('type_name', 'not in', %s)],
1776+ 'required': [('type_name', 'in', %s)]
1777+ }"""%(referentials, referentials))
1778+ orm.setup_modifiers(field, field=result['fields'][field_name], context=context)
1779+ result['arch'] = etree.tostring(eview, pretty_print=True)
1780+ return result
1781+
1782 def external_connection(self, cr, uid, referential, debug=False, context=None):
1783 """Should be overridden to provide valid external referential connection"""
1784 return False
1785@@ -271,10 +313,12 @@
1786 _columns = {
1787 'name': fields.char('Name', size=32, required=True),
1788 'type_id': fields.related('version_id', 'type_id', type='many2one', relation='external.referential.type', string='External Type'),
1789+ 'type_name': fields.related('type_id', 'name', type='char', string='External Type Name',
1790+ store=True),
1791 'categ_id': fields.related('type_id', 'categ_id', type='many2one', relation='external.referential.category', string='External Category'),
1792 'categ_name': fields.related('categ_id', 'name', type='char', string='External Category Name'),
1793 'version_id': fields.many2one('external.referential.version', 'Referential Version', required=True),
1794- 'location': fields.char('Location', size=200, required=True),
1795+ 'location': fields.char('Location', size=200),
1796 'apiusername': fields.char('User Name', size=64),
1797 'apipass': fields.char('Password', size=64),
1798 'mapping_ids': fields.one2many('external.mapping', 'referential_id', 'Mappings'),
1799@@ -487,9 +531,8 @@
1800 referential_id = referential.name.replace('.','_').replace(' ','_')
1801 return referential_id
1802
1803-external_referential()
1804
1805-class external_mapping_line(osv.osv):
1806+class external_mapping_line(Model):
1807 _name = 'external.mapping.line'
1808 _description = 'Field Mapping'
1809 _rec_name = 'name'
1810@@ -509,10 +552,8 @@
1811 'name': fields.function(_name_get_fnc, type="char", string='Name', size=256),
1812 }
1813
1814-external_mapping_line()
1815-
1816-
1817-class external_mapping(osv.osv):
1818+
1819+class external_mapping(Model):
1820 _name = 'external.mapping'
1821 _description = 'External Mapping'
1822 _rec_name = 'model'
1823@@ -621,15 +662,20 @@
1824 ('ref_template_uniq', 'unique (referential_id, template_id)', 'A referential can not have various mapping imported from the same template')
1825 ]
1826
1827-external_mapping()
1828-
1829-
1830-class external_mapping_line(osv.osv):
1831+ def copy(self, cr, uid, id, default=None, context=None):
1832+ if default is None:
1833+ default = {}
1834+
1835+ default['template_id'] = False
1836+
1837+ return super(external_mapping, self).copy(cr, uid, id, default=default, context=context)
1838+
1839+class external_mapping_line(Model): # FIXME : tidy up this remnant of old OERP version
1840 _inherit = 'external.mapping.line'
1841
1842 _columns = {
1843 'template_id': fields.many2one('external.mappinglines.template', 'External Mapping Lines Template'),
1844- 'referential_id': fields.related('mapping_id', 'referential_id', type='many2one', relation='external.referential', string='Referential'),
1845+ 'referential_id': fields.related('mapping_id', 'referential_id', type='many2one', relation='external.referential', string='Referential', store=True),
1846 'field_id': fields.many2one('ir.model.fields', 'OpenERP Field', ondelete='cascade'),
1847 'internal_field': fields.related('field_id', 'name', type='char', relation='ir.model.field', string='Field name',readonly=True),
1848 'external_field': fields.char('External Field', size=128, help=("When importing flat csv file from file exchange,"
1849@@ -637,7 +683,7 @@
1850 'mapping_id': fields.many2one('external.mapping', 'External Mapping', ondelete='cascade'),
1851 'related_model_id': fields.related('mapping_id', 'model_id', type='many2one', relation='ir.model', string='Related Model'),
1852 'type': fields.selection([('in_out', 'External <-> OpenERP'), ('in', 'External -> OpenERP'), ('out', 'External <- OpenERP')], 'Type'),
1853- 'external_type': fields.selection([('datetime', 'Datetime'), ('unicode', 'String'), ('bool', 'Boolean'), ('int', 'Integer'), ('float', 'Float'), ('list', 'List'), ('dict', 'Dictionnary')], 'External Type', required=True),
1854+ 'external_type': fields.selection([('url', 'URL'),('datetime', 'Datetime'), ('unicode', 'String'), ('bool', 'Boolean'), ('int', 'Integer'), ('float', 'Float'), ('list', 'List'), ('dict', 'Dictionnary')], 'External Type', required=True),
1855 'datetime_format': fields.char('Datetime Format', size=32),
1856 'evaluation_type': fields.selection([('function', 'Function'), ('sub-mapping','Sub Mapping Line'), ('direct', 'Direct Mapping')], 'Evalution Type', required=True),
1857 'in_function': fields.text('Import in OpenERP Mapping Python Function'),
1858@@ -689,9 +735,16 @@
1859 line_id = (version_code + '_' + mapping_name + '_' + line_name).replace('.','_')
1860 return line_id
1861
1862-external_mapping_line()
1863-
1864-class ir_model_data(osv.osv):
1865+ def copy(self, cr, uid, id, default=None, context=None):
1866+ if default is None:
1867+ default = {}
1868+
1869+ default['template_id'] = False
1870+
1871+ return super(external_mapping_line, self).copy(cr, uid, id, default=default, context=context)
1872+
1873+
1874+class ir_model_data(Model):
1875 _inherit = "ir.model.data"
1876
1877 def init(self, cr):
1878@@ -728,7 +781,6 @@
1879 }
1880
1881 _sql_constraints = [
1882- ('external_reference_uniq_per_object', 'unique(model, res_id, referential_id)', 'You cannot have on record with multiple external id for a sae referential'),
1883+ ('external_reference_uniq_per_object', 'unique(model, res_id, referential_id)', 'You cannot have on record with multiple external id for a same referential'),
1884 ]
1885
1886-ir_model_data()
1887
1888=== modified file 'base_external_referentials/external_referentials_menu.xml'
1889--- base_external_referentials/external_referentials_menu.xml 2012-07-20 15:13:11 +0000
1890+++ base_external_referentials/external_referentials_menu.xml 2012-12-03 16:33:32 +0000
1891@@ -16,8 +16,7 @@
1892 <field name="search_view_id" ref="external_referential_search_view"/>
1893 </record>
1894
1895- <menuitem id="menu_external_referential" name="External Referentials" parent="ir_ui_menu_external_referentials" />
1896- <menuitem id="menu_all_external_referential" name="All Referentials" parent="menu_external_referential" action="act_window_external_referential" />
1897+ <menuitem id="menu_external_referential" name="External Referentials" parent="ir_ui_menu_external_referentials" action="act_window_external_referential"/>
1898 <!-- External Referentials Types -->
1899
1900 <record id="ir_actions_act_window_external_type" model="ir.actions.act_window">
1901
1902=== modified file 'base_external_referentials/external_referentials_view.xml'
1903--- base_external_referentials/external_referentials_view.xml 2012-06-27 14:27:22 +0000
1904+++ base_external_referentials/external_referentials_view.xml 2012-12-03 16:33:32 +0000
1905@@ -25,30 +25,27 @@
1906 <field name="type">form</field>
1907 <field name="arch" type="xml">
1908 <form>
1909- <group col="4" colspan="4">
1910+ <group col="6" colspan="4" name='name'>
1911+ <separator string="Configuration" colspan="6"/>
1912 <field name="name" attrs="{'readonly':[('create_date','!=',False)]}"/>
1913+ <field name="version_id" on_change="onchange_version_id(version_id)"/>
1914+ <field name="debug"/>
1915+ <field name="location"/>
1916+ <field name="apiusername"/>
1917+ <field name="apipass"/>
1918 <field name="create_date" invisible="True"/>
1919- <notebook colspan="4">
1920- <page string="General">
1921- <field name="version_id"/>
1922- <field name="location"/>
1923- <field name="categ_name" invisible="True"/>
1924- </page>
1925- <page string="Authentication">
1926- <field name="apiusername" />
1927- <field name="apipass" />
1928- <!-- TODO improve view -->
1929- <field name="debug" />
1930- </page>
1931- </notebook>
1932+ <field name="categ_name" invisible="True"/>
1933+ <field name="type_name" invisible="True" readonly="1"/>
1934 </group>
1935 <group col="4" colspan="4">
1936 <separator string="Core Components" colspan="4" />
1937 <notebook colspan="4">
1938 <page string="Referential Actions">
1939- <separator string="Compulsory" colspan="4" />
1940- <button name="refresh_mapping" string="1 - Reload Referential Mapping Templates" colspan="2" type="object" />
1941- <button name="import_referentials" string="2 - Synchronize Referential Settings" colspan="2" type="object" attrs="{'readonly':[('mapping_ids','=',[])]}"/>
1942+ <group name="compulsory" col="4" colspan="4">
1943+ <separator string="Compulsory" colspan="4" />
1944+ <button name="refresh_mapping" string="1 - Reload Referential Mapping Templates" colspan="2" type="object" />
1945+ <button name="import_referentials" string="2 - Synchronize Referential Settings" colspan="2" type="object" attrs="{'readonly':[('mapping_ids','=',[])]}"/>
1946+ </group>
1947 </page>
1948 <page string="CSV file generation" groups="base_external_referentials.group_export_mapping" >
1949 <button name="build_external_ref_categ" string="1- Export category" colspan="1" type="object" />
1950
1951=== modified file 'base_external_referentials/group_fields.py'
1952--- base_external_referentials/group_fields.py 2012-06-27 14:27:22 +0000
1953+++ base_external_referentials/group_fields.py 2012-12-03 16:33:32 +0000
1954@@ -19,11 +19,12 @@
1955 # #
1956 ###############################################################################
1957
1958-
1959-from osv import osv, fields
1960-
1961-
1962-class group_fields(osv.osv):
1963+from openerp.osv.orm import Model
1964+from openerp.osv import fields
1965+from openerp.osv.osv import except_osv
1966+from openerp.tools.translate import _
1967+
1968+class group_fields(Model):
1969 _name = 'group.fields'
1970 _description = 'trigger last write date by group of field'
1971
1972@@ -64,10 +65,10 @@
1973
1974 def write(self, cr, uid, ids, vals, context=None):
1975 if vals.get('column_name'):
1976- raise osv.except_osv(_("User Error"), _("Changing Column name is not supported yet"))
1977+ raise except_osv(_("User Error"), _("Changing Column name is not supported yet"))
1978 return super(group_fields, self).write(cr, uid, ids, vals, context=context)
1979
1980-class ir_model_fields(osv.osv):
1981+class ir_model_fields(Model):
1982 _inherit = "ir.model.fields"
1983
1984 _columns = {
1985
1986=== added file 'base_external_referentials/i18n/fr.po'
1987--- base_external_referentials/i18n/fr.po 1970-01-01 00:00:00 +0000
1988+++ base_external_referentials/i18n/fr.po 2012-12-03 16:33:32 +0000
1989@@ -0,0 +1,1070 @@
1990+# Translation of OpenERP Server.
1991+# This file contains the translation of the following modules:
1992+# * base_external_referentials
1993+#
1994+msgid ""
1995+msgstr ""
1996+"Project-Id-Version: OpenERP Server 6.1\n"
1997+"Report-Msgid-Bugs-To: \n"
1998+"POT-Creation-Date: 2012-10-24 13:11+0000\n"
1999+"PO-Revision-Date: 2012-10-24 13:11+0000\n"
2000+"Last-Translator: <Benoît Guillot>\n"
2001+"Language-Team: \n"
2002+"MIME-Version: 1.0\n"
2003+"Content-Type: text/plain; charset=UTF-8\n"
2004+"Content-Transfer-Encoding: \n"
2005+"Plural-Forms: \n"
2006+
2007+#. module: base_external_referentials
2008+#: field:external.referential.type,code:0
2009+#: field:external.referential.version,code:0
2010+msgid "code"
2011+msgstr "code"
2012+
2013+#. module: base_external_referentials
2014+#: view:external.mapping.line:0
2015+msgid "Mapping line"
2016+msgstr "Ligne de mapping"
2017+
2018+#. module: base_external_referentials
2019+#: field:external.mapping.line,selected:0
2020+msgid "Selected"
2021+msgstr "Sélectionné"
2022+
2023+#. module: base_external_referentials
2024+#: help:external.mapping.line,external_field:0
2025+msgid "When importing flat csv file from file exchange,you can leave this field empty, because this field doesn't exist in your csv file'"
2026+msgstr "Lors de l'import d'un fichier csv plat depuis file_exchange, vous pouvez laisser ce champ vide parce qu'il n'existe pas dans votre fichier csv."
2027+
2028+#. module: base_external_referentials
2029+#: model:ir.model,name:base_external_referentials.model_external_referential_type
2030+msgid "External Referential Type (Ex.Magento,Spree)"
2031+msgstr "Type de référentiel externe (Ex.Magento,Spree)"
2032+
2033+#. module: base_external_referentials
2034+#: view:group.fields:0
2035+#: model:ir.actions.act_window,name:base_external_referentials.group_field_action_open_form
2036+msgid "Group fields"
2037+msgstr "Champs groupés"
2038+
2039+#. module: base_external_referentials
2040+#: view:external.referential:0
2041+msgid "CSV file generation"
2042+msgstr "Génération de fichiers CSV"
2043+
2044+#. module: base_external_referentials
2045+#: view:external.report.line:0
2046+msgid "Action On Model"
2047+msgstr "Action sur le modèle"
2048+
2049+#. module: base_external_referentials
2050+#: code:addons/base_external_referentials/external_osv.py:413
2051+#, python-format
2052+msgid "The method _get_external_resource_ids is not implemented in abstract base module!"
2053+msgstr "La méthode _get_external_resource_ids n'est pas implémentée dans le module d'abstraction!"
2054+
2055+#. module: base_external_referentials
2056+#: code:addons/base_external_referentials/external_osv.py:1468
2057+#, python-format
2058+msgid "Wrong external type for mapping %s. One2Many object must have for external type string or integer"
2059+msgstr "Mauvais type externe pour le mapping %s. Les objects One2Many doivent avoir pour type externe string ou integer"
2060+
2061+#. module: base_external_referentials
2062+#: field:external.report.line,args:0
2063+msgid "Args"
2064+msgstr "Args"
2065+
2066+#. module: base_external_referentials
2067+#: sql_constraint:ir.model.data:0
2068+msgid "You cannot have multiple records with the same external ID in the same module!"
2069+msgstr "Vous ne pouvez pas avoir plusieurs enregistrements avec le même ID externe dans le même module!"
2070+
2071+#. module: base_external_referentials
2072+#: field:external.mapping.line,related_model_id:0
2073+msgid "Related Model"
2074+msgstr "Modèle lié"
2075+
2076+#. module: base_external_referentials
2077+#: model:ir.actions.act_window,name:base_external_referentials.ext_sale_order
2078+msgid "External Order"
2079+msgstr "Commande externe"
2080+
2081+#. module: base_external_referentials
2082+#: code:addons/base_external_referentials/external_osv.py:94
2083+#, python-format
2084+msgid "The method %s already exist. Please change the prefix name"
2085+msgstr "La méthode %s existe déjà. Veuillez changer le nom préfixé"
2086+
2087+#. module: base_external_referentials
2088+#: field:external.mapping,model:0
2089+#: field:external.mapping.template,model:0
2090+msgid "Model Name"
2091+msgstr "Nom du modèle"
2092+
2093+#. module: base_external_referentials
2094+#: field:external.report,history_ids:0
2095+msgid "History"
2096+msgstr "Historique"
2097+
2098+#. module: base_external_referentials
2099+#: view:external.referential:0
2100+msgid "Compulsory"
2101+msgstr "Obligatoire"
2102+
2103+#. module: base_external_referentials
2104+#: view:external.report:0
2105+msgid "Retry All Failed"
2106+msgstr "Réessayer tous les échecs"
2107+
2108+#. module: base_external_referentials
2109+#: code:addons/base_external_referentials/external_osv.py:1467
2110+#: code:addons/base_external_referentials/external_osv.py:1698
2111+#: code:addons/base_external_referentials/group_fields.py:68
2112+#, python-format
2113+msgid "User Error"
2114+msgstr "Erreur utilisateur"
2115+
2116+#. module: base_external_referentials
2117+#: model:ir.model,name:base_external_referentials.model_external_mapping_template
2118+msgid "The source mapping records"
2119+msgstr "Enregistrement du mapping source"
2120+
2121+#. module: base_external_referentials
2122+#: view:external.referential.type:0
2123+msgid "External Referential Types"
2124+msgstr "Types de référentiel externe"
2125+
2126+#. module: base_external_referentials
2127+#: model:ir.actions.act_window,name:base_external_referentials.ir_actions_act_window_external_mapping_line
2128+#: model:ir.ui.menu,name:base_external_referentials.ir_ui_menu_external_mapping_lines
2129+msgid "External Mapping Lines"
2130+msgstr "Lignes de mapping externes"
2131+
2132+#. module: base_external_referentials
2133+#: field:external.referential,categ_id:0
2134+#: model:ir.actions.act_window,name:base_external_referentials.ext_product_category
2135+msgid "External Category"
2136+msgstr "Catégorie externe"
2137+
2138+#. module: base_external_referentials
2139+#: model:ir.model,name:base_external_referentials.model_ir_model
2140+msgid "Models"
2141+msgstr "Modèles"
2142+
2143+#. module: base_external_referentials
2144+#: view:external.report.history:0
2145+#: view:external.report.line:0
2146+msgid "Report"
2147+msgstr "Rapport"
2148+
2149+#. module: base_external_referentials
2150+#: model:ir.model,name:base_external_referentials.model_external_referential_category
2151+msgid "External Referential Category (Ex: e-commerce, crm, warehouse)"
2152+msgstr "Catégorie du référentiel externe (Ex: e-commerce, crm, entrepôt)"
2153+
2154+#. module: base_external_referentials
2155+#: view:external.mapping.line:0
2156+msgid "Other Information"
2157+msgstr "Autre information"
2158+
2159+#. module: base_external_referentials
2160+#: field:external.referential,debug:0
2161+msgid "Debug"
2162+msgstr "Debug"
2163+
2164+#. module: base_external_referentials
2165+#: view:external.report.history:0
2166+#: view:external.report.line:0
2167+msgid "Failures"
2168+msgstr "Echecs"
2169+
2170+#. module: base_external_referentials
2171+#: model:ir.model,name:base_external_referentials.model_external_mappinglines_template
2172+msgid "The source mapping line records"
2173+msgstr "Enregistrement de la ligne de mapping source"
2174+
2175+#. module: base_external_referentials
2176+#: view:external.referential:0
2177+msgid "2- Export type"
2178+msgstr "2- Export du type de référentiel"
2179+
2180+#. module: base_external_referentials
2181+#: field:external.mapping,external_done_method:0
2182+#: field:external.mapping.template,external_done_method:0
2183+msgid "Done Method"
2184+msgstr "Méthode de finalisation"
2185+
2186+#. module: base_external_referentials
2187+#: model:ir.model,name:base_external_referentials.model_external_mapping_line
2188+msgid "Field Mapping"
2189+msgstr "Mapping du champ"
2190+
2191+#. module: base_external_referentials
2192+#: field:external.referential.version,name:0
2193+msgid "name"
2194+msgstr "Nom"
2195+
2196+#. module: base_external_referentials
2197+#: constraint:external.referential:0
2198+msgid "The name cannot contain a dot!"
2199+msgstr "Le nom ne doit pas contenir de point!"
2200+
2201+#. module: base_external_referentials
2202+#: model:ir.actions.act_window,name:base_external_referentials.ir_actions_act_window_external_type
2203+#: model:ir.ui.menu,name:base_external_referentials.ir_ui_menu_external_types
2204+msgid "External Referentials Types"
2205+msgstr "Types de référentiels externes"
2206+
2207+#. module: base_external_referentials
2208+#: field:external.mapping,related_model_ids:0
2209+msgid "Related Inherited Models"
2210+msgstr "Modèles liés hérités"
2211+
2212+#. module: base_external_referentials
2213+#: view:external.report:0
2214+msgid "External Referential Reports"
2215+msgstr "Rapports des référentiels externes"
2216+
2217+#. module: base_external_referentials
2218+#: field:external.mapping,external_create_method:0
2219+#: field:external.mapping.template,external_create_method:0
2220+msgid "Create Method"
2221+msgstr "Méthode de création"
2222+
2223+#. module: base_external_referentials
2224+#: selection:external.mapping.line,external_type:0
2225+#: selection:external.mappinglines.template,external_type:0
2226+msgid "Datetime"
2227+msgstr "Datetime"
2228+
2229+#. module: base_external_referentials
2230+#: field:ir.model.data,referential_id:0
2231+msgid "Ext. Referential"
2232+msgstr "Référentiel externe"
2233+
2234+#. module: base_external_referentials
2235+#: help:external.mapping.line,selected:0
2236+msgid "to select for mapping"
2237+msgstr "A selectionner pour mapper"
2238+
2239+#. module: base_external_referentials
2240+#: field:external.referential,version_id:0
2241+msgid "Referential Version"
2242+msgstr "Version du référentiel"
2243+
2244+#. module: base_external_referentials
2245+#: view:external.report.line:0
2246+msgid "Retry"
2247+msgstr "Réessayer"
2248+
2249+#. module: base_external_referentials
2250+#: field:external.report.history,end_date:0
2251+msgid "End Date"
2252+msgstr "Date de fin"
2253+
2254+#. module: base_external_referentials
2255+#: selection:external.report.line,state:0
2256+msgid "Failed"
2257+msgstr "Echecs"
2258+
2259+#. module: base_external_referentials
2260+#: view:external.mapping:0
2261+#: field:external.mapping.line,referential_id:0
2262+msgid "Referential"
2263+msgstr "Référentiel"
2264+
2265+#. module: base_external_referentials
2266+#: view:external.referential:0
2267+msgid "Referential Actions"
2268+msgstr "Actions du référentiel"
2269+
2270+#. module: base_external_referentials
2271+#: field:external.referential,location:0
2272+msgid "Location"
2273+msgstr "Emplacement"
2274+
2275+#. module: base_external_referentials
2276+#: selection:external.mapping.line,evaluation_type:0
2277+#: selection:external.mappinglines.template,evaluation_type:0
2278+msgid "Sub Mapping Line"
2279+msgstr "Ligne de sous-mapping"
2280+
2281+#. module: base_external_referentials
2282+#: field:external.report,failed_line_ids:0
2283+msgid "Failed Report Lines"
2284+msgstr "Lignes de rapport en échecs"
2285+
2286+#. module: base_external_referentials
2287+#: selection:external.mapping.line,external_type:0
2288+#: selection:external.mappinglines.template,external_type:0
2289+msgid "Dictionnary"
2290+msgstr "Dictionnary"
2291+
2292+#. module: base_external_referentials
2293+#: field:external.mapping,key_for_external_id:0
2294+#: field:external.mapping.template,key_for_external_id:0
2295+msgid "External field used as key"
2296+msgstr "Champ externe utilisé comme clé"
2297+
2298+#. module: base_external_referentials
2299+#: field:external.mapping.line,type:0
2300+#: field:external.mappinglines.template,type:0
2301+#: field:external.referential.version,type_id:0
2302+msgid "Type"
2303+msgstr "Type"
2304+
2305+#. module: base_external_referentials
2306+#: field:external.mapping.line,field_id:0
2307+#: field:external.mappinglines.template,field_id:0
2308+msgid "OpenERP Field"
2309+msgstr "Champ d'OpenERP"
2310+
2311+#. module: base_external_referentials
2312+#: field:external.mapping.line,name:0
2313+#: field:external.mappinglines.template,name:0
2314+#: field:external.referential,name:0
2315+#: field:external.referential.category,name:0
2316+#: field:external.referential.type,name:0
2317+#: field:external.report,name:0
2318+#: field:group.fields,name:0
2319+msgid "Name"
2320+msgstr "Nom"
2321+
2322+#. module: base_external_referentials
2323+#: selection:external.mapping.line,type:0
2324+#: selection:external.mappinglines.template,type:0
2325+msgid "External -> OpenERP"
2326+msgstr "Externe -> OpenERP"
2327+
2328+#. module: base_external_referentials
2329+#: selection:external.mapping.line,external_type:0
2330+#: selection:external.mappinglines.template,external_type:0
2331+msgid "String"
2332+msgstr "String"
2333+
2334+#. module: base_external_referentials
2335+#: field:external.referential,create_date:0
2336+msgid "Creation Date"
2337+msgstr "Date de création"
2338+
2339+#. module: base_external_referentials
2340+#: view:external.report.line:0
2341+#: field:external.report.line,error_message:0
2342+msgid "Error Message"
2343+msgstr "Message d'erreur"
2344+
2345+#. module: base_external_referentials
2346+#: field:external.mapping,external_get_method:0
2347+#: field:external.mapping.template,external_get_method:0
2348+msgid "Get Method"
2349+msgstr "Méthode d'optention"
2350+
2351+#. module: base_external_referentials
2352+#: code:addons/base_external_referentials/group_fields.py:68
2353+#, python-format
2354+msgid "Changing Column name is not supported yet"
2355+msgstr "Le changement de nom de colonne n'est pas supporté pour l'instant"
2356+
2357+#. module: base_external_referentials
2358+#: field:external.mapping,extra_name:0
2359+#: field:external.mapping.template,extra_name:0
2360+msgid "Extra Name"
2361+msgstr "Nom supplémentaire"
2362+
2363+#. module: base_external_referentials
2364+#: view:external.mapping.line:0
2365+msgid "Internal fields"
2366+msgstr "Field interne"
2367+
2368+#. module: base_external_referentials
2369+#: view:external.referential:0
2370+msgid "Configuration"
2371+msgstr "Configuration"
2372+
2373+#. module: base_external_referentials
2374+#: model:ir.ui.menu,name:base_external_referentials.ir_ui_menu_group_fields
2375+msgid "Group Fields"
2376+msgstr "Groupe de champs"
2377+
2378+#. module: base_external_referentials
2379+#: field:external.mapping,mapping_ids:0
2380+msgid "Mappings Lines"
2381+msgstr "Lignes de mapping"
2382+
2383+#. module: base_external_referentials
2384+#: field:ir.model.fields,group_fields_id:0
2385+msgid "Trigger Group"
2386+msgstr "Trigger Group"
2387+
2388+#. module: base_external_referentials
2389+#: field:external.mapping,template_id:0
2390+msgid "External Mapping Template"
2391+msgstr "Template de mapping"
2392+
2393+#. module: base_external_referentials
2394+#: field:external.referential.type,version_ids:0
2395+msgid "Versions"
2396+msgstr "Versions"
2397+
2398+#. module: base_external_referentials
2399+#: view:external.report:0
2400+#: model:ir.actions.act_window,name:base_external_referentials.ir_actions_act_window_external_report
2401+msgid "External Reports"
2402+msgstr "Rapports externes"
2403+
2404+#. module: base_external_referentials
2405+#: code:addons/base_external_referentials/external_osv.py:1432
2406+#, python-format
2407+msgid "Invalid format for the variable result."
2408+msgstr "Le format de la variable result est incorrect."
2409+
2410+#. module: base_external_referentials
2411+#: field:external.report.line,traceback:0
2412+msgid "Traceback"
2413+msgstr "Traceback"
2414+
2415+#. module: base_external_referentials
2416+#: selection:external.mapping.line,type:0
2417+#: selection:external.mappinglines.template,type:0
2418+msgid "External <- OpenERP"
2419+msgstr "Externe <- OpenERP"
2420+
2421+#. module: base_external_referentials
2422+#: field:external.mapping,referential_id:0
2423+#: view:external.referential:0
2424+#: view:external.referential.type:0
2425+#: view:external.report:0
2426+#: field:external.report,referential_id:0
2427+#: model:ir.model,name:base_external_referentials.model_external_referential
2428+msgid "External Referential"
2429+msgstr "Référentiel externe"
2430+
2431+#. module: base_external_referentials
2432+#: field:external.mapping.line,child_mapping_id:0
2433+#: field:external.mappinglines.template,child_mapping_id:0
2434+msgid "Child Mapping"
2435+msgstr "Mapping enfant"
2436+
2437+#. module: base_external_referentials
2438+#: field:external.mapping.line,sequence:0
2439+#: field:external.mappinglines.template,sequence:0
2440+msgid "Sequence"
2441+msgstr "Séquence"
2442+
2443+#. module: base_external_referentials
2444+#: code:addons/base_external_referentials/decorator.py:64
2445+#: code:addons/base_external_referentials/decorator.py:78
2446+#: code:addons/base_external_referentials/external_osv.py:413
2447+#: code:addons/base_external_referentials/external_osv.py:962
2448+#, python-format
2449+msgid "Not Implemented"
2450+msgstr "Non implémenté"
2451+
2452+#. module: base_external_referentials
2453+#: view:external.report.line:0
2454+#: field:external.report.line,resource:0
2455+#: field:external.report.line,resource_text:0
2456+msgid "External Data"
2457+msgstr "Données externe"
2458+
2459+#. module: base_external_referentials
2460+#: view:external.mapping.line:0
2461+#: field:external.referential.version,full_name:0
2462+msgid "Full Name"
2463+msgstr "Nom entier"
2464+
2465+#. module: base_external_referentials
2466+#: field:external.referential,categ_name:0
2467+msgid "External Category Name"
2468+msgstr "Nom de la catégorie du référentiel"
2469+
2470+#. module: base_external_referentials
2471+#: view:external.mapping.line:0
2472+#: field:external.mapping.line,in_function:0
2473+#: field:external.mappinglines.template,in_function:0
2474+msgid "Import in OpenERP Mapping Python Function"
2475+msgstr "Import in OpenERP Mapping Python Function"
2476+
2477+#. module: base_external_referentials
2478+#: selection:external.mapping.line,evaluation_type:0
2479+#: selection:external.mappinglines.template,evaluation_type:0
2480+msgid "Direct Mapping"
2481+msgstr "Direct Mapping"
2482+
2483+#. module: base_external_referentials
2484+#: view:external.referential:0
2485+msgid "Core Components"
2486+msgstr "Composants du coeur"
2487+
2488+#. module: base_external_referentials
2489+#: sql_constraint:external.mapping.line:0
2490+msgid "A referential can not have various mapping line imported from the same template mapping line"
2491+msgstr "Un référentiel ne peut pas avoir de différentes lignes de mapping importées depuis le même template de ligne de mapping"
2492+
2493+#. module: base_external_referentials
2494+#: view:external.referential:0
2495+msgid "6- Export mapping lines"
2496+msgstr "6- Export des lignes de mapping"
2497+
2498+#. module: base_external_referentials
2499+#: view:external.mapping:0
2500+#: view:external.mapping.line:0
2501+#: view:external.referential:0
2502+#: view:external.referential.type:0
2503+#: view:external.report:0
2504+#: view:external.report.history:0
2505+#: view:external.report.line:0
2506+#: view:group.fields:0
2507+msgid "Group by..."
2508+msgstr "Regrouper par..."
2509+
2510+#. module: base_external_referentials
2511+#: field:external.mapping,external_resource_name:0
2512+#: field:external.mapping.template,external_resource_name:0
2513+msgid "External Resource Name"
2514+msgstr "Nom de la resource externe"
2515+
2516+#. module: base_external_referentials
2517+#: sql_constraint:external.mapping:0
2518+msgid "A referential can not have various mapping imported from the same template"
2519+msgstr "Un référentiel ne peut pas avoir de différents mapping importés depuis le même template"
2520+
2521+#. module: base_external_referentials
2522+#: field:external.report.history,start_date:0
2523+msgid "Start Date"
2524+msgstr "Date de départ"
2525+
2526+#. module: base_external_referentials
2527+#: code:addons/base_external_referentials/external_osv.py:1083
2528+#, python-format
2529+msgid "only method export onebyone is implemented in base_external_referentials"
2530+msgstr "Seule la méthode d'export un par un est implémenté dans base_external_referentials"
2531+
2532+#. module: base_external_referentials
2533+#: model:ir.actions.act_window,name:base_external_referentials.act_window_external_referential
2534+#: model:ir.ui.menu,name:base_external_referentials.ir_ui_menu_external_referentials
2535+#: model:ir.ui.menu,name:base_external_referentials.menu_external_referential
2536+msgid "External Referentials"
2537+msgstr "Référentiels externes"
2538+
2539+#. module: base_external_referentials
2540+#: code:addons/base_external_referentials/external_osv.py:1699
2541+#, python-format
2542+msgid "Error with mapping : %s. Sub mapping can be only apply on one2many, many2one or many2many fields"
2543+msgstr "Erreur avec le mapping : %s. Un sous-mapping ne peut être appliqué seulement sur des champs : one2many, many2one ou many2many"
2544+
2545+#. module: base_external_referentials
2546+#: selection:external.mapping.line,type:0
2547+#: selection:external.mappinglines.template,type:0
2548+msgid "External <-> OpenERP"
2549+msgstr "Externe <-> OpenERP"
2550+
2551+#. module: base_external_referentials
2552+#: view:external.referential:0
2553+#: field:external.referential.type,categ_id:0
2554+msgid "Category"
2555+msgstr "Catégorie"
2556+
2557+#. module: base_external_referentials
2558+#: field:external.referential,mapping_ids:0
2559+msgid "Mappings"
2560+msgstr "Mappings"
2561+
2562+#. module: base_external_referentials
2563+#: selection:external.mapping.line,external_type:0
2564+#: selection:external.mappinglines.template,external_type:0
2565+msgid "URL"
2566+msgstr "URL"
2567+
2568+#. module: base_external_referentials
2569+#: view:external.mapping:0
2570+#: view:external.referential:0
2571+msgid "Object Mappings"
2572+msgstr "Object du mapping"
2573+
2574+#. module: base_external_referentials
2575+#: model:ir.model,name:base_external_referentials.model_ir_model_data
2576+msgid "ir.model.data"
2577+msgstr "ir.model.data"
2578+
2579+#. module: base_external_referentials
2580+#: field:external.mapping,external_search_method:0
2581+#: field:external.mapping.template,external_search_method:0
2582+msgid "Search Method"
2583+msgstr "Méthode de recherche"
2584+
2585+#. module: base_external_referentials
2586+#: model:ir.actions.act_window,name:base_external_referentials.ext_res_partner
2587+msgid "External Partner"
2588+msgstr "Partenaire externe"
2589+
2590+#. module: base_external_referentials
2591+#: view:external.report.history:0
2592+#: view:external.report.line:0
2593+#: model:ir.actions.act_window,name:base_external_referentials.ir_actions_act_window_external_report_history
2594+#: model:ir.model,name:base_external_referentials.model_external_report_history
2595+#: model:ir.ui.menu,name:base_external_referentials.ir_ui_menu_external_report_history
2596+msgid "External Report History"
2597+msgstr "Historique des rapports externes"
2598+
2599+#. module: base_external_referentials
2600+#: field:external.mapping.line,datetime_format:0
2601+#: field:external.mappinglines.template,datetime_format:0
2602+msgid "Datetime Format"
2603+msgstr "Datetime Format"
2604+
2605+#. module: base_external_referentials
2606+#: model:ir.actions.act_window,name:base_external_referentials.ext_product_product
2607+msgid "External Product"
2608+msgstr "Produit externe"
2609+
2610+#. module: base_external_referentials
2611+#: field:external.report.line,state:0
2612+msgid "Status"
2613+msgstr "Status"
2614+
2615+#. module: base_external_referentials
2616+#: sql_constraint:ir.model:0
2617+msgid "Each model must be unique!"
2618+msgstr "Chaque modèle doit être unique!"
2619+
2620+#. module: base_external_referentials
2621+#: field:external.mapping.template,version_id:0
2622+#: field:external.mappinglines.template,version_id:0
2623+msgid "External Referential Version"
2624+msgstr "Version du référentiel externe"
2625+
2626+#. module: base_external_referentials
2627+#: sql_constraint:external.referential:0
2628+msgid "Referential names must be unique !"
2629+msgstr "Les noms des référentiels doivent être unique !"
2630+
2631+#. module: base_external_referentials
2632+#: field:external.mapping,external_list_method:0
2633+#: field:external.mapping.template,external_list_method:0
2634+msgid "List Method"
2635+msgstr "Méthode de listage"
2636+
2637+#. module: base_external_referentials
2638+#: code:addons/base_external_referentials/external_osv.py:57
2639+#: code:addons/base_external_referentials/external_osv.py:88
2640+#: code:addons/base_external_referentials/external_osv.py:93
2641+#: code:addons/base_external_referentials/external_osv.py:1083
2642+#, python-format
2643+msgid "Developper Error"
2644+msgstr "Erreur développeur"
2645+
2646+#. module: base_external_referentials
2647+#: view:external.referential:0
2648+msgid "1 - Reload Referential Mapping Templates"
2649+msgstr "1 - Rechercher les templates de mapping externe"
2650+
2651+#. module: base_external_referentials
2652+#: field:external.referential,apiusername:0
2653+msgid "User Name"
2654+msgstr "Nom d'utilisateur"
2655+
2656+#. module: base_external_referentials
2657+#: help:external.mapping,related_model_ids:0
2658+msgid "potentially inherited through '_inherits' model, used for mapping field selection"
2659+msgstr "potentielement héritable grâce au modèle '_inherits', utilisé pour la séléction des champs de mapping"
2660+
2661+#. module: base_external_referentials
2662+#: view:external.referential:0
2663+msgid "1- Export category"
2664+msgstr "1- Export de la catégorie"
2665+
2666+#. module: base_external_referentials
2667+#: model:res.groups,name:base_external_referentials.group_export_mapping
2668+msgid "Export Mapping Manager"
2669+msgstr "Responsable des mappings d'export"
2670+
2671+#. module: base_external_referentials
2672+#: view:external.report.history:0
2673+#: view:external.report.line:0
2674+#: field:external.report.line,date:0
2675+msgid "Date"
2676+msgstr "Date"
2677+
2678+#. module: base_external_referentials
2679+#: selection:external.mapping.line,external_type:0
2680+#: selection:external.mappinglines.template,external_type:0
2681+msgid "Integer"
2682+msgstr "Integer"
2683+
2684+#. module: base_external_referentials
2685+#: field:external.report,sync_from_object_id:0
2686+msgid "Sync From Object ID"
2687+msgstr "Synchro depuis l'ID d'objet"
2688+
2689+#. module: base_external_referentials
2690+#: code:addons/base_external_referentials/external_osv.py:555
2691+#, python-format
2692+msgid "The field referential_id doesn't exist on the object %s. Reporting system can not be used"
2693+msgstr "Le champ référential_id n'existe pas sur l'object %s. Le système de rapports d'erreurs ne peut pas être utilisé"
2694+
2695+#. module: base_external_referentials
2696+#: field:external.referential,type_name:0
2697+msgid "External Type Name"
2698+msgstr "Nom du type de référentiel externe"
2699+
2700+#. module: base_external_referentials
2701+#: field:external.report.history,user_id:0
2702+msgid "User"
2703+msgstr "Utilisateur"
2704+
2705+#. module: base_external_referentials
2706+#: field:external.mapping.line,external_field:0
2707+#: field:external.mappinglines.template,external_field:0
2708+msgid "External Field"
2709+msgstr "Champ externe"
2710+
2711+#. module: base_external_referentials
2712+#: view:external.report.history:0
2713+#: view:external.report.line:0
2714+#: selection:external.report.line,state:0
2715+msgid "Success"
2716+msgstr "Succès"
2717+
2718+#. module: base_external_referentials
2719+#: field:external.report,email_tmpl_id:0
2720+msgid "Email Template"
2721+msgstr "Email Template"
2722+
2723+#. module: base_external_referentials
2724+#: code:addons/base_external_referentials/external_osv.py:58
2725+#, python-format
2726+msgid "You can extend the class %s with the method %s.\",\n"
2727+" \"Indeed this method already exist use the decorator 'replace' instead"
2728+msgstr "Vous pouvez étendre la classe %s avec la méthode %s.\",\n"
2729+" \"En effet, cette méthode éxiste déjà. Veuillez utiliser le décorateur 'replace' à la place"
2730+
2731+#. module: base_external_referentials
2732+#: code:addons/base_external_referentials/external_osv.py:509
2733+#, python-format
2734+msgid "External Import Error"
2735+msgstr "Erreur d'import externe"
2736+
2737+#. module: base_external_referentials
2738+#: field:external.mapping.line,alternative_key:0
2739+#: field:external.mappinglines.template,alternative_key:0
2740+msgid "Alternative Key"
2741+msgstr "Alternative Key"
2742+
2743+#. module: base_external_referentials
2744+#: field:external.report,action:0
2745+#: view:external.report.line:0
2746+#: field:external.report.line,action:0
2747+msgid "Action"
2748+msgstr "Action"
2749+
2750+#. module: base_external_referentials
2751+#: field:external.report,line_ids:0
2752+msgid "Report Lines"
2753+msgstr "Lignes de rapports"
2754+
2755+#. module: base_external_referentials
2756+#: view:external.report:0
2757+msgid "Delete All Failed"
2758+msgstr "Supprimer tous les échecs"
2759+
2760+#. module: base_external_referentials
2761+#: view:external.referential:0
2762+msgid "3- Export version"
2763+msgstr "3- Export de la version du référentiel"
2764+
2765+#. module: base_external_referentials
2766+#: view:external.mapping.line:0
2767+#: field:external.mapping.line,out_function:0
2768+#: field:external.mappinglines.template,out_function:0
2769+msgid "Export from OpenERP Mapping Python Function"
2770+msgstr "Export from OpenERP Mapping Python Function"
2771+
2772+#. module: base_external_referentials
2773+#: view:external.mapping:0
2774+#: view:external.mapping.line:0
2775+#: field:external.mapping.line,mapping_id:0
2776+#: field:external.mappinglines.template,mapping_id:0
2777+#: model:ir.model,name:base_external_referentials.model_external_mapping
2778+msgid "External Mapping"
2779+msgstr "Mapping externe"
2780+
2781+#. module: base_external_referentials
2782+#: view:external.referential:0
2783+msgid "2 - Synchronize Referential Settings"
2784+msgstr "2 - Synchroniser les paramètres du référentiel"
2785+
2786+#. module: base_external_referentials
2787+#: field:external.mapping,external_delete_method:0
2788+#: field:external.mapping.template,external_delete_method:0
2789+msgid "Delete Method"
2790+msgstr "Méthode de suppression"
2791+
2792+#. module: base_external_referentials
2793+#: field:external.report.history,report_id:0
2794+#: field:external.report.line,report_id:0
2795+#: model:ir.model,name:base_external_referentials.model_external_report
2796+#: model:ir.ui.menu,name:base_external_referentials.ir_ui_menu_external_report
2797+msgid "External Report"
2798+msgstr "Rapports externes"
2799+
2800+#. module: base_external_referentials
2801+#: model:ir.model,name:base_external_referentials.model_external_referential_version
2802+msgid "External Referential Version (Ex: v1.5.0.0 +, v1.3.2.4 +)"
2803+msgstr "Version du référentiel externe (Ex: v1.5.0.0 +, v1.3.2.4 +)"
2804+
2805+#. module: base_external_referentials
2806+#: selection:external.mapping.line,external_type:0
2807+#: selection:external.mappinglines.template,external_type:0
2808+msgid "Float"
2809+msgstr "Float"
2810+
2811+#. module: base_external_referentials
2812+#: field:external.report,action_on:0
2813+#: field:external.report.line,action_on:0
2814+msgid "Action On"
2815+msgstr "Action sur"
2816+
2817+#. module: base_external_referentials
2818+#: view:external.report.line:0
2819+#: field:external.report.line,kwargs_text:0
2820+msgid "Kwargs Data"
2821+msgstr "Kwargs Data"
2822+
2823+#. module: base_external_referentials
2824+#: view:external.report.line:0
2825+#: field:external.report.line,args_text:0
2826+msgid "Args Data"
2827+msgstr "Args Data"
2828+
2829+#. module: base_external_referentials
2830+#: model:ir.actions.act_window,name:base_external_referentials.ext_sale_shop
2831+msgid "External Shop"
2832+msgstr "Boutique externe"
2833+
2834+#. module: base_external_referentials
2835+#: model:ir.model,name:base_external_referentials.model_group_fields
2836+msgid "trigger last write date by group of field"
2837+msgstr "trigger last write date by group of field"
2838+
2839+#. module: base_external_referentials
2840+#: field:external.report.line,kwargs:0
2841+msgid "Kwargs"
2842+msgstr "Kwargs"
2843+
2844+#. module: base_external_referentials
2845+#: help:external.mapping,extra_name:0
2846+msgid "In case you need to make many mappings on the same object"
2847+msgstr "En cas de besoin de créer plusieurs mappings pour le même objet"
2848+
2849+#. module: base_external_referentials
2850+#: selection:external.mapping.line,evaluation_type:0
2851+#: selection:external.mappinglines.template,evaluation_type:0
2852+msgid "Function"
2853+msgstr "Fonction"
2854+
2855+#. module: base_external_referentials
2856+#: field:external.report.line,res_id:0
2857+msgid "Resource Id"
2858+msgstr "Resource Id"
2859+
2860+#. module: base_external_referentials
2861+#: code:addons/base_external_referentials/decorator.py:64
2862+#, python-format
2863+msgid "Not parent method found"
2864+msgstr "Aucune méthode parent n'a été trouvée"
2865+
2866+#. module: base_external_referentials
2867+#: help:external.referential,create_date:0
2868+msgid "Date on which external referential is created."
2869+msgstr "Date de création du référentiel externe."
2870+
2871+#. module: base_external_referentials
2872+#: field:external.mapping.line,internal_field:0
2873+msgid "Field name"
2874+msgstr "Nom du champ"
2875+
2876+#. module: base_external_referentials
2877+#: view:external.mapping:0
2878+#: view:external.referential:0
2879+msgid "Add all object fields"
2880+msgstr "Ajouter tous les champs de l'objet"
2881+
2882+#. module: base_external_referentials
2883+#: field:external.mapping.line,internal_type:0
2884+msgid "Internal Type"
2885+msgstr "Type interne"
2886+
2887+#. module: base_external_referentials
2888+#: help:external.mapping.line,alternative_key:0
2889+#: help:external.mappinglines.template,alternative_key:0
2890+msgid "Only one field can be selected as alternative key,if no external id was found for the record the alternative keywill be used to identify the resource"
2891+msgstr "Seulement un champ peut être séléctionner en tant qu'alternative key, Si aucune id externe n'est trouvée pour l'enregistrement, l'alternative key sera utilisée pour identifier la resource"
2892+
2893+#. module: base_external_referentials
2894+#: field:external.referential,apipass:0
2895+msgid "Password"
2896+msgstr "Mot de passe"
2897+
2898+#. module: base_external_referentials
2899+#: view:external.mapping:0
2900+#: view:external.referential:0
2901+msgid "Export mapping file"
2902+msgstr "Export des fichers de mapping"
2903+
2904+#. module: base_external_referentials
2905+#: field:external.referential.category,type_ids:0
2906+msgid "Types"
2907+msgstr "Types"
2908+
2909+#. module: base_external_referentials
2910+#: field:external.report,sync_from_object_model:0
2911+msgid "Sync From Object"
2912+msgstr "Synchro depuis l'objet"
2913+
2914+#. module: base_external_referentials
2915+#: model:ir.actions.act_window,name:base_external_referentials.ext_res_partner_address
2916+msgid "External Address"
2917+msgstr "Adresse externe"
2918+
2919+#. module: base_external_referentials
2920+#: code:addons/base_external_referentials/external_osv.py:89
2921+#, python-format
2922+msgid "You can replace the method %s of the class %s. Indeed this method doesn't exist"
2923+msgstr "vous pouvez remplacer la méthode %s de la classe %s. En effet, cette méthode n'existe pas"
2924+
2925+#. module: base_external_referentials
2926+#: field:external.mapping.line,function_name:0
2927+#: field:external.mappinglines.template,function_name:0
2928+msgid "Function Name"
2929+msgstr "Function Name"
2930+
2931+#. module: base_external_referentials
2932+#: field:external.report.history,count_success:0
2933+msgid "Count Success"
2934+msgstr "Somme des succès"
2935+
2936+#. module: base_external_referentials
2937+#: model:ir.actions.act_window,name:base_external_referentials.ir_actions_act_window_external_mapping
2938+#: model:ir.ui.menu,name:base_external_referentials.ir_ui_menu_external_mappings
2939+msgid "External Mappings"
2940+msgstr "Mappings externes"
2941+
2942+#. module: base_external_referentials
2943+#: field:external.report.history,count_failed:0
2944+msgid "Count Failed"
2945+msgstr "Somme des échecs"
2946+
2947+#. module: base_external_referentials
2948+#: field:group.fields,field_ids:0
2949+#: model:ir.model,name:base_external_referentials.model_ir_model_fields
2950+msgid "Fields"
2951+msgstr "Champs"
2952+
2953+#. module: base_external_referentials
2954+#: selection:external.mapping.line,external_type:0
2955+#: selection:external.mappinglines.template,external_type:0
2956+msgid "List"
2957+msgstr "List"
2958+
2959+#. module: base_external_referentials
2960+#: field:external.mapping.line,external_type:0
2961+#: field:external.mappinglines.template,external_type:0
2962+#: field:external.referential,type_id:0
2963+msgid "External Type"
2964+msgstr "Type externe"
2965+
2966+#. module: base_external_referentials
2967+#: help:external.mapping.line,child_mapping_id:0
2968+#: help:external.mappinglines.template,child_mapping_id:0
2969+msgid "This give you the possibility to import data with a structure of Parent/childFor example when you import a sale order, the sale order is the parent of the sale order lineIn this case you have to select the child mapping in order to convert the data"
2970+msgstr "Ceci vous donne la possibilité d'importer des données avec une structure de parents/enfants. Par exemple, lors de l'import d'une commande de vente, la commande est le parent des lignes de commandes de vente. Dans ce cas, veuillez sélectionner le mapping enfant afin de convertir les données."
2971+
2972+#. module: base_external_referentials
2973+#: view:group.fields:0
2974+#: field:group.fields,model_id:0
2975+msgid "Model"
2976+msgstr "Modèle"
2977+
2978+#. module: base_external_referentials
2979+#: field:external.mapping,external_update_method:0
2980+#: field:external.mapping.template,external_update_method:0
2981+msgid "Update Method"
2982+msgstr "Méthode de mise à jour"
2983+
2984+#. module: base_external_referentials
2985+#: view:external.report.line:0
2986+msgid "External Report Line"
2987+msgstr "Ligne de rapport externe"
2988+
2989+#. module: base_external_referentials
2990+#: field:external.mapping,model_id:0
2991+#: field:external.mapping.template,model_id:0
2992+msgid "OpenERP Model"
2993+msgstr "Modèle OpenERP"
2994+
2995+#. module: base_external_referentials
2996+#: sql_constraint:ir.model.data:0
2997+msgid "You cannot have on record with multiple external id for a same referential"
2998+msgstr "Vous ne pouvez pas avoir un enregistrement avec plusieurs id externe pour un même référentiel"
2999+
3000+#. module: base_external_referentials
3001+#: field:external.report.line,exception_type:0
3002+msgid "Exception Type"
3003+msgstr "Type d'exception"
3004+
3005+#. module: base_external_referentials
3006+#: field:external.report.line,external_id:0
3007+msgid "External ID"
3008+msgstr "ID externe"
3009+
3010+#. module: base_external_referentials
3011+#: view:external.referential:0
3012+msgid "5- Export mapping template"
3013+msgstr "5- Export des template de mapping"
3014+
3015+#. module: base_external_referentials
3016+#: field:external.mapping.line,template_id:0
3017+msgid "External Mapping Lines Template"
3018+msgstr "Template de lignes de mapping externe"
3019+
3020+#. module: base_external_referentials
3021+#: help:external.referential,debug:0
3022+msgid "If debug mode is active all request between the external referential and OpenERP will be in the log"
3023+msgstr "Si le mode debug est activé, toutes les requètes entre le référentiel externe et OpenERP apparaitront dans les logs"
3024+
3025+#. module: base_external_referentials
3026+#: selection:external.mapping.line,external_type:0
3027+#: selection:external.mappinglines.template,external_type:0
3028+msgid "Boolean"
3029+msgstr "Boolean"
3030+
3031+#. module: base_external_referentials
3032+#: field:group.fields,column_name:0
3033+msgid "Column Name"
3034+msgstr "Nom de la colonne"
3035+
3036+#. module: base_external_referentials
3037+#: field:external.mapping.line,evaluation_type:0
3038+#: field:external.mappinglines.template,evaluation_type:0
3039+msgid "Evalution Type"
3040+msgstr "Type pour l'évaluation"
3041+
3042+#. module: base_external_referentials
3043+#: view:external.referential:0
3044+msgid "4- Export referential"
3045+msgstr "4- Export du référentiel"
3046+
3047+#. module: base_external_referentials
3048+#: view:external.mapping.line:0
3049+msgid "External fields"
3050+msgstr "Champs externes"
3051+
3052+#. module: base_external_referentials
3053+#: view:external.report.line:0
3054+#: model:ir.actions.act_window,name:base_external_referentials.ir_actions_act_window_external_report_line
3055+#: model:ir.model,name:base_external_referentials.model_external_report_line
3056+#: model:ir.ui.menu,name:base_external_referentials.ir_ui_menu_external_report_line
3057+msgid "External Report Lines"
3058+msgstr "Lignes des rapports externes"
3059+
3060
3061=== modified file 'base_external_referentials/ir_model.py'
3062--- base_external_referentials/ir_model.py 2012-03-14 13:44:15 +0000
3063+++ base_external_referentials/ir_model.py 2012-12-03 16:33:32 +0000
3064@@ -19,17 +19,30 @@
3065 # #
3066 ###############################################################################
3067
3068-from osv import osv
3069-
3070-
3071-class ir_model(osv.osv):
3072+from openerp.osv.orm import Model
3073+
3074+
3075+class ir_model(Model):
3076 _inherit='ir.model'
3077
3078 def create_external_link(self, cr, uid, model_id, context=None):
3079 model = self.pool.get('ir.model').browse(cr, uid, model_id, context=context)
3080- vals = {'domain': "[('res_id', '=', active_id), ('model', '=', '%s')]" %(model.model,), 'name': 'External %s'%(model.name), 'res_model': 'ir.model.data', 'src_model': model.model, 'view_type': 'form'}
3081+ vals = {'domain': "[('res_id', '=', active_id), ('model', '=', '%s')]" %(model.model,),
3082+ 'name': 'External %s'%(model.name),
3083+ 'res_model': 'ir.model.data',
3084+ 'src_model': model.model,
3085+ 'view_type': 'form',
3086+ }
3087 xml_id = "ext_" + model.model.replace(".", "_")
3088- ir_model_data_id = self.pool.get('ir.model.data')._update(cr, uid, 'ir.actions.act_window', "base_external_referentials", vals, xml_id, False, 'update')
3089+ ir_model_data_id = self.pool.get('ir.model.data')._update(cr, uid,
3090+ 'ir.actions.act_window',
3091+ "base_external_referentials",
3092+ vals, xml_id, False, 'update')
3093 value = 'ir.actions.act_window,'+str(ir_model_data_id)
3094- return self.pool.get('ir.model.data').ir_set(cr, uid, 'action', 'client_action_relate', xml_id, [model.model], value, replace=True, isobject=True, xml_id=xml_id)
3095+ return self.pool.get('ir.model.data').ir_set(cr, uid, 'action',
3096+ 'client_action_relate',
3097+ xml_id, [model.model],
3098+ value, replace=True,
3099+ isobject=True,
3100+ xml_id=xml_id)
3101
3102
3103=== modified file 'base_external_referentials/message_error.py'
3104--- base_external_referentials/message_error.py 2012-02-06 14:48:49 +0000
3105+++ base_external_referentials/message_error.py 2012-12-03 16:33:32 +0000
3106@@ -26,12 +26,14 @@
3107 self.mapping_name = mapping_name
3108 self.mapping_object = mapping_object
3109 def __str__(self):
3110- return repr('the mapping line : %s for the object %s have an error : %s'%(self.mapping_name, self.mapping_object, self.value))
3111+ return 'the mapping line: %s for the object %s has this error: %s' % (self.mapping_name,
3112+ self.mapping_object,
3113+ self.value)
3114
3115
3116 class ExtConnError(Exception):
3117 def __init__(self, value):
3118 self.value = value
3119 def __str__(self):
3120- return repr(self.value)
3121+ return str(self.value)
3122
3123
3124=== modified file 'base_external_referentials/report.py'
3125--- base_external_referentials/report.py 2012-08-21 07:39:24 +0000
3126+++ base_external_referentials/report.py 2012-12-03 16:33:32 +0000
3127@@ -18,19 +18,23 @@
3128 #
3129 ##############################################################################
3130 import time
3131-import pooler
3132 import logging
3133 import sys
3134 import traceback
3135-from osv import osv, fields
3136-from tools.translate import _
3137-from tools.safe_eval import safe_eval
3138+from openerp.osv.orm import Model
3139+from openerp.osv import fields
3140 from tools import DEFAULT_SERVER_DATETIME_FORMAT
3141 import simplejson
3142 from base_external_referentials.external_osv import ExternalSession
3143 from base_external_referentials.decorator import commit_now
3144
3145-class external_report(osv.osv):
3146+MODEL_WITH_UNIQUE_REPORT_LINE = [
3147+ 'product.product',
3148+ 'product.category',
3149+ ]
3150+
3151+
3152+class external_report(Model):
3153 _name = 'external.report'
3154 _description = 'External Report'
3155 _order = 'name desc'
3156@@ -49,7 +53,7 @@
3157
3158 _columns = {
3159 'name': fields.function(_get_full_name, store=True, type='char', size=256, string='Name'),
3160- 'action': fields.char('Action', size=32, required=True, readonly=True),
3161+ 'action': fields.char('Action', size=256, required=True, readonly=True),
3162 'action_on': fields.many2one('ir.model', 'Action On',required=True, readonly=True),
3163 'sync_from_object_model': fields.many2one('ir.model', 'Sync From Object',
3164 required=True, readonly=True),
3165@@ -60,6 +64,7 @@
3166 'failed_line_ids': fields.one2many('external.report.line', 'report_id',
3167 'Failed Report Lines', domain=[('state', '!=', 'success')]),
3168 'history_ids': fields.one2many('external.report.history','report_id', 'History'),
3169+ 'email_tmpl_id': fields.many2one('email.template', 'Email Template', help="Email template used to send an email every time a failed report line is created"),
3170 }
3171
3172 def _get_report(self, cr, uid, action, action_on, sync_from_object, context=None):
3173@@ -104,7 +109,7 @@
3174 'action_on': action_on_model_id,
3175 'sync_from_object_model': model_id,
3176 'sync_from_object_id': sync_from_object.id,
3177- 'referential_id': sync_from_object._name == 'external.referential' and sync_from_object.id or sync_from_object.referential_id.id,
3178+ 'referential_id': sync_from_object.id if sync_from_object._name == 'external.referential' else sync_from_object.referential_id.id,
3179 }
3180
3181 @commit_now
3182@@ -161,10 +166,8 @@
3183 self.pool.get('external.report.line').unlink(cr, uid, failed_line_ids, context=context)
3184 return True
3185
3186-external_report()
3187-
3188-
3189-class external_report_history(osv.osv):
3190+
3191+class external_report_history(Model):
3192 _name = 'external.report.history'
3193 _description = 'External Report History'
3194 _rec_name = 'report_id'
3195@@ -203,10 +206,8 @@
3196 self.write(cr, uid, history_id, vals, context=context)
3197 return True
3198
3199-external_report_history()
3200-
3201-
3202-class external_report_lines(osv.osv):
3203+
3204+class external_report_lines(Model):
3205 _name = 'external.report.line'
3206 _description = 'External Report Lines'
3207 _rec_name = 'res_id'
3208@@ -238,7 +239,7 @@
3209 'state': fields.selection((('success', 'Success'),
3210 ('fail', 'Failed')),
3211 'Status', required=True, readonly=True),
3212- 'action': fields.char('Action', size=32, required=True, readonly=True),
3213+ 'action': fields.char('Action', size=256, required=True, readonly=True),
3214 'action_on': fields.many2one('ir.model', 'Action On',required=True, readonly=True),
3215 'res_id': fields.integer('Resource Id', readonly=True),
3216 'date': fields.datetime('Date', required=True, readonly=True),
3217@@ -258,6 +259,18 @@
3218 "date": lambda *a: time.strftime(DEFAULT_SERVER_DATETIME_FORMAT)
3219 }
3220
3221+ def get_existing_line_id(self, cr, uid, action_on, action, res_id=None, external_id=None, context=None):
3222+ if context.get('retry_report_line_id'):
3223+ return context['retry_report_line_id']
3224+ elif action_on in MODEL_WITH_UNIQUE_REPORT_LINE:
3225+ existing_line_id = self.search(cr, uid, [
3226+ ('action_on', '=', action_on),
3227+ ('action', '=', action),
3228+ ('res_id', '=', res_id),
3229+ ('external_id', '=', external_id),
3230+ ], context=context)
3231+ return existing_line_id and existing_line_id[0] or False
3232+ return False
3233
3234 #TODO
3235 #1 - Did it usefull to log sucessfull entry?
3236@@ -267,7 +280,8 @@
3237 def start_log(self, cr, uid, action_on, action, res_id=None,
3238 external_id=None, resource=None, args=None, kwargs=None):
3239 context = kwargs.get('context') or {}
3240- existing_line_id = context.get('retry_report_line_id', False)
3241+ existing_line_id = self.get_existing_line_id(cr, uid,action_on, action,
3242+ res_id=res_id, external_id=external_id, context=context)
3243 report_id = context.get('report_id')
3244
3245 if existing_line_id:
3246@@ -296,11 +310,17 @@
3247 })
3248 return existing_line_id
3249
3250- @commit_now
3251 def log_fail(self, cr, uid, external_session, report_line_id, error_message, context=None):
3252+ self._log_fail(cr, uid, external_session, report_line_id, error_message, context=context)
3253+ if not context.get('no_mail'):
3254+ self._send_mail(cr, uid, report_line_id, context=context)
3255+ return True
3256+
3257+ @commit_now
3258+ def _log_fail(self, cr, uid, external_session, report_line_id, error_message, context=None):
3259 exc_type, exc_value, exc_traceback = sys.exc_info()
3260-
3261- external_session and external_session.logger.exception(error_message)
3262+ if external_session:
3263+ external_session.logger.exception(error_message)
3264 self.write(cr, uid, report_line_id, {
3265 'error_message': error_message,
3266 'exception_type': exc_type,
3267@@ -314,6 +334,14 @@
3268 return True
3269
3270 @commit_now
3271+ def _send_mail(self, cr, uid, report_line_id, context=None):
3272+ line = self.browse(cr, uid, report_line_id, context=context)
3273+ if line.report_id.email_tmpl_id:
3274+ self.pool.get('email.template').send_mail(cr, uid, line.report_id.email_tmpl_id.id,\
3275+ report_line_id, force_send=True, context=context)
3276+ return True
3277+
3278+ @commit_now
3279 def log_success(self, cr, uid, external_session, report_line_id, context=None):
3280 self.write(cr, uid, report_line_id, {'state': 'success'}, context=context)
3281 if external_session and external_session.tmp.get('history_id'):
3282@@ -337,6 +365,8 @@
3283 if not kwargs.get('context', False):
3284 kwargs['context']={}
3285
3286+ #don't send email when retry
3287+ kwargs['context']['no_mail'] = True
3288 # keep the id of the line to update it with the result
3289 kwargs['context']['retry_report_line_id'] = log.id
3290
3291@@ -344,6 +374,8 @@
3292 else:
3293 if not kwargs.get('context', False):
3294 kwargs['context']={}
3295+ #don't send email when retry
3296+ kwargs['context']['no_mail'] = True
3297 kwargs['context']['retry_report_line_id'] = log.id
3298 method(cr, uid, *args, **kwargs)
3299 return True
3300@@ -361,4 +393,3 @@
3301
3302 return res
3303
3304-external_report_lines()
3305
3306=== added file 'base_external_referentials/report_mail_template.xml'
3307--- base_external_referentials/report_mail_template.xml 1970-01-01 00:00:00 +0000
3308+++ base_external_referentials/report_mail_template.xml 2012-12-03 16:33:32 +0000
3309@@ -0,0 +1,26 @@
3310+<?xml version="1.0" encoding="utf-8"?>
3311+<!--
3312+ crm_claim_categ_as_name for OpenERP
3313+ Copyright (C) 2012 Akretion Benoît GUILLOT <benoit.guillot@akretion.com>
3314+ The licence is in the file __openerp__.py
3315+-->
3316+<openerp>
3317+ <data noupdate="1">
3318+
3319+ <!--Email template -->
3320+ <record id="email_template_report" model="email.template">
3321+ <field name="name">Reporting error</field>
3322+ <field name="email_from">${object.company_id.email or ''}</field>
3323+ <field name="subject">${object.company_id.name} Error with ${object.report_id.name or '' })</field>
3324+ <field name="email_to">${object.company_id.email or ''}</field>
3325+ <field name="model_id" ref="base_external_referentials.model_external_report_line"/>
3326+ <field name="auto_delete" eval="True"/>
3327+ <field name="lang">${object.company_id.partner_id.lang}</field>
3328+ <field name="body_html"><![CDATA[]]></field>
3329+ <field name="body_text"><![CDATA[
3330+An error occurred during the import of the ${object.report_id.action_on}
3331+
3332+The message is : ${object.error_message}]]></field>
3333+ </record>
3334+ </data>
3335+</openerp>
3336
3337=== modified file 'base_external_referentials/report_view.xml'
3338--- base_external_referentials/report_view.xml 2012-08-19 21:30:31 +0000
3339+++ base_external_referentials/report_view.xml 2012-12-03 16:33:32 +0000
3340@@ -16,6 +16,7 @@
3341 <field name="sync_from_object_model"/>
3342 <field name="sync_from_object_id"/>
3343 <field name="referential_id"/>
3344+ <field name="email_tmpl_id"/>
3345 <newline/>
3346 <field name="failed_line_ids" nolabel="1" colspan="4"/>
3347 <button name="retry_failed_lines" string="Retry All Failed" icon="gtk-go-forward" type="object" colspan="2"/>
3348
3349=== modified file 'base_file_protocole/__openerp__.py'
3350--- base_file_protocole/__openerp__.py 2012-02-20 03:02:09 +0000
3351+++ base_file_protocole/__openerp__.py 2012-12-03 16:33:32 +0000
3352@@ -27,9 +27,9 @@
3353 'description': """empty""",
3354 'author': 'Akretion',
3355 'website': 'http://www.akretion.com/',
3356- 'depends': ['base'],
3357+ 'depends': ['base'],
3358 'init_xml': [],
3359- 'update_xml': [
3360+ 'update_xml': [
3361 ],
3362 'demo_xml': [],
3363 'installable': True,
3364
3365=== modified file 'base_file_protocole/base_file_protocole.py'
3366--- base_file_protocole/base_file_protocole.py 2012-08-21 05:41:58 +0000
3367+++ base_file_protocole/base_file_protocole.py 2012-12-03 16:33:32 +0000
3368@@ -19,17 +19,20 @@
3369 # #
3370 ###############################################################################
3371
3372-from osv import osv, fields
3373-import netsvc
3374 from tempfile import TemporaryFile
3375-from ftplib import FTP
3376-import sys
3377+import ftplib
3378 import os
3379-import shutil
3380 import csv
3381 import paramiko
3382 import errno
3383 import functools
3384+import logging
3385+
3386+_logger = logging.getLogger(__name__)
3387+try:
3388+ import xlrd
3389+except ImportError:
3390+ _logger.warning('You must install xlrd, if you need to read xls file')
3391
3392 def open_and_close_connection(func):
3393 """
3394@@ -50,7 +53,8 @@
3395 return wrapper
3396
3397 # Extend paramiko lib with the method mkdirs
3398-def mkdirs(self, path, mode=511):
3399+def stfp_mkdirs(self, path, mode=511):
3400+ current_dir = self.getcwd()
3401 try:
3402 self.stat(path)
3403 except IOError, e:
3404@@ -63,7 +67,26 @@
3405 self.mkdir(path, mode)
3406 else:
3407 raise
3408-paramiko.SFTPClient.mkdirs = mkdirs
3409+ self.stat(current_dir)
3410+paramiko.SFTPClient.mkdirs = stfp_mkdirs
3411+
3412+# Extend ftplib with the method mkdirs
3413+def ftp_mkdirs(self, path):
3414+ current_dir = self.pwd()
3415+ try:
3416+ self.cwd(path)
3417+ except ftplib.error_perm, e:
3418+ if "550" in str(e):
3419+ try:
3420+ self.mkd(path)
3421+ except ftplib.error_perm, e:
3422+ if "550" in str(e):
3423+ self.mkdirs(os.path.dirname(path))
3424+ self.mkd(path)
3425+ else:
3426+ raise
3427+ self.cwd(current_dir)
3428+ftplib.FTP.mkdirs = ftp_mkdirs
3429
3430
3431 class FileConnection(object):
3432@@ -75,15 +98,16 @@
3433 self.protocole = protocole
3434 self.allow_dir_creation = allow_dir_creation
3435 self.location = location
3436- self.home_folder = home_folder
3437+ self.home_folder = home_folder or '/'
3438 self.port = port
3439 self.user = user
3440 self.pwd = pwd
3441+ self.connection = None
3442
3443
3444 def connect(self):
3445 if self.is_('ftp'):
3446- self.connection = FTP(self.location)
3447+ self.connection = ftplib.FTP(self.location)
3448 self.connection.login(self.user, self.pwd)
3449 elif self.is_('sftp'):
3450 transport = paramiko.Transport((self.location, self.port or 22))
3451@@ -91,12 +115,15 @@
3452 self.connection = paramiko.SFTPClient.from_transport(transport)
3453
3454 def close(self):
3455- if self.is_('ftp') or self.is_('sftp'):
3456+ if self.is_('ftp') or self.is_('sftp') and self.connection is not None:
3457 self.connection.close()
3458
3459 @open_and_close_connection
3460 def send(self, filepath, filename, output_file, create_patch=None):
3461 if self.is_('ftp'):
3462+ filepath = os.path.join(self.home_folder, filepath)
3463+ if self.allow_dir_creation:
3464+ self.connection.mkdirs(filepath)
3465 self.connection.cwd(filepath)
3466 self.connection.storbinary('STOR ' + filename, output_file)
3467 output_file.close()
3468@@ -157,7 +184,7 @@
3469 which is encoded in the given encoding.
3470 """
3471
3472- def __init__(self, f, encoding="utf-8", **kwds):
3473+ def __init__(self, f, encoding="utf-8", **kwds):
3474 self.encoding = encoding
3475 self.reader = csv.DictReader(f, **kwds)
3476
3477@@ -177,7 +204,7 @@
3478
3479 def reorganize(self, field_structure=None, merge_keys=None, ref_field=None):
3480 """
3481- Function to reorganize the resource from the csv. It uses the mapping (field_structure)
3482+ Function to reorganize the resource from the csv. It uses the mapping (field_structure)
3483 to deal with the different architecture of an object (sale order with sale order line ...)
3484 the ref_field is used to merge the different lines (sale order with several sale order lines)
3485 """
3486@@ -236,3 +263,27 @@
3487 def writerows(self, rows):
3488 for row in rows:
3489 self.writerow(row)
3490+
3491+
3492+class FileXlsReader(object):
3493+
3494+ def __init__(self, file_contents):
3495+ self.file_contents = file_contents
3496+
3497+ def read(self):
3498+ wb = xlrd.open_workbook(file_contents=self.file_contents)
3499+ sheet_name = wb.sheet_names()[0]
3500+ sh = wb.sheet_by_name(sheet_name)
3501+ header = sh.row_values(0)
3502+ result = []
3503+ for rownum in range(1, sh.nrows):
3504+ row = {}
3505+ index = 0
3506+ for val in sh.row_values(rownum):
3507+ row[header[index]] = val
3508+ index += 1
3509+ result.append(row)
3510+ return result
3511+
3512+
3513+
3514
3515=== modified file 'base_onchange_player/__init__.py'
3516--- base_onchange_player/__init__.py 2011-12-21 10:11:00 +0000
3517+++ base_onchange_player/__init__.py 2012-12-03 16:33:32 +0000
3518@@ -2,7 +2,8 @@
3519 #################################################################################
3520 # #
3521 # base_onchange_player for OpenERP #
3522-# Copyright (C) 2011 Akretion Sébastien BEAU <sebastien.beau@akretion.com> #
3523+# Copyright (C) 2011 Akretion http://www.akretion.com/ #
3524+# @author Sébastien BEAU <sebastien.beau@akretion.com> #
3525 # #
3526 # This program is free software: you can redistribute it and/or modify #
3527 # it under the terms of the GNU Affero General Public License as #
3528@@ -22,6 +23,3 @@
3529
3530 import onchange_osv
3531
3532-
3533-
3534-
3535
3536=== modified file 'base_onchange_player/__openerp__.py'
3537--- base_onchange_player/__openerp__.py 2011-12-21 10:11:00 +0000
3538+++ base_onchange_player/__openerp__.py 2012-12-03 16:33:32 +0000
3539@@ -2,7 +2,8 @@
3540 #################################################################################
3541 # #
3542 # base_onchange_player for OpenERP #
3543-# Copyright (C) 2011 Akretion Sébastien BEAU <sebastien.beau@akretion.com> #
3544+# Copyright (C) 2011 Akretion http://www.akretion.com/ #
3545+# @author Sébastien BEAU <sebastien.beau@akretion.com> #
3546 # #
3547 # This program is free software: you can redistribute it and/or modify #
3548 # it under the terms of the GNU Affero General Public License as #
3549@@ -25,15 +26,15 @@
3550 'version': '0.1',
3551 'category': 'ORM Extention',
3552 'license': 'AGPL-3',
3553- 'description': """This module give the possibility to call onchange method easily in your code, it's just an Abstract Module that add some abstraction when you need to call onchange method.
3554- A sample of call is done in the module base_sale_multichannels
3555+ 'description': """This module gives the possibility to call onchange methods easily in your code. This module just adds some abstraction when you need to call onchange methods.
3556+
3557+To get an example of how you should use this code, look at the module base_sale_multichannels.
3558 """,
3559 'author': 'Akretion',
3560 'website': 'http://www.akretion.com/',
3561- 'depends': ['base'],
3562+ 'depends': ['base'],
3563 'init_xml': [],
3564- 'update_xml': [
3565- ],
3566+ 'update_xml': [],
3567 'demo_xml': [],
3568 'installable': True,
3569 'active': False,
3570
3571=== modified file 'base_onchange_player/onchange_osv.py'
3572--- base_onchange_player/onchange_osv.py 2012-08-21 06:04:49 +0000
3573+++ base_onchange_player/onchange_osv.py 2012-12-03 16:33:32 +0000
3574@@ -2,7 +2,8 @@
3575 ################################################################################
3576 # #
3577 # base_onchange_player for OpenERP #
3578-# Copyright (C) 2011 Akretion Sébastien BEAU <sebastien.beau@akretion.com> #
3579+# Copyright (C) 2011 Akretion http://www.akretion.com/ #
3580+# @author Sébastien BEAU <sebastien.beau@akretion.com> #
3581 # #
3582 # This program is free software: you can redistribute it and/or modify #
3583 # it under the terms of the GNU Affero General Public License as #
3584@@ -19,45 +20,47 @@
3585 # #
3586 ################################################################################
3587
3588-from osv import osv
3589-import netsvc
3590+from openerp.osv.orm import Model
3591+from openerp.osv.osv import except_osv
3592 from tools.translate import _
3593 from openerp.tools.config import config
3594
3595 def call_onchange(self, cr, uid, onchange_name, vals, defaults=None, **kwargs):
3596 """
3597- Used in base_sale_multichannel in order to call onchange method on sale_order_line and sale_order
3598- In order to call onchange you must have to create a function "_get_kwargs_my_onchange_name"
3599- that will return the kwargs for your onchange
3600+ Used in base_sale_multichannel in order to call onchange method on sale_order_line and sale_order.
3601+ In order to call onchange, you must have to create a function "_get_kwargs_my_onchange_name"
3602+ that will return the kwargs for your onchange.
3603
3604- @param onchange_name: string that contain the onchange method to call
3605- @param vals: dictionnary of value that have been filled for the object
3606+ @param onchange_name: string that contains the onchange method to call
3607+ @param vals: dictionnary of values that has been filled for the object
3608 @param defaults: dictionnary of defaults values for the object
3609- @return: dictionary of line updated with the value returned by the onchange
3610+ @return: dictionary of lines updated with the values returned by the onchange
3611 """
3612- if not defaults:
3613- defaults={}
3614+ if defaults is None:
3615+ defaults = {}
3616 vals_with_default = defaults.copy()
3617 vals_with_default.update(vals)
3618 try :
3619- kwargs2 = eval("self._get_kwargs_%s"%onchange_name)(cr, uid, vals_with_default, **kwargs)
3620+ args2, kwargs2 = getattr(self, "_get_params_%s" % onchange_name)(cr, uid, vals_with_default, **kwargs)
3621 except Exception, e:
3622 if config['debug_mode']: raise
3623- raise osv.except_osv(_('On Change Player'), _("Error when trying to get the kwargs for the onchange %s on \
3624- the object %s. Error message : %s" %(onchange_name, self._name, e)))
3625+ raise except_osv(_('On Change Player'),
3626+ _("Error when trying to get the params for the onchange %s on "
3627+ "the object %s. Error message : %s") % (onchange_name, self._name, e))
3628 try :
3629- res = eval("self.%s"%onchange_name)(cr, uid, **kwargs2)
3630+ res = getattr(self, onchange_name)(cr, uid, *args2, **kwargs2)
3631 for key in res['value']:
3632 if not key in vals:
3633- # If the value is false and the field is not a boolean we don't pass it as it useless
3634- # If it's a problem for you please contact me sebastien.beau@akretion.com,
3635- # because pass empty value will provoque some conflict with magentoerpconnect. Thanks
3636+ # If the value is false and the field is not a boolean, we don't pass it as it is useless
3637+ # If it's a problem for you, please contact me sebastien.beau@akretion.com,
3638+ # because passing empty value will trigger a conflict with magentoerpconnect. Thanks.
3639 if res['value'][key] or self._columns[key]._type == 'bool':
3640 vals[key] = res['value'][key]
3641 except Exception, e:
3642 if config['debug_mode']: raise
3643- raise osv.except_osv(_('On Change Player'), _("Error when trying to playing the onchange %s on the object %s. \
3644- Error message : %s" %(onchange_name, self._name, e)))
3645+ raise except_osv(_('On Change Player'),
3646+ _("Error when trying to play the onchange %s on the object %s. "
3647+ "Error message : %s") % (onchange_name, self._name, e))
3648 return vals
3649
3650-osv.osv.call_onchange = call_onchange
3651+Model.call_onchange = call_onchange
3652
3653=== modified file 'base_pop_up/__openerp__.py'
3654--- base_pop_up/__openerp__.py 2012-05-19 10:43:23 +0000
3655+++ base_pop_up/__openerp__.py 2012-12-03 16:33:32 +0000
3656@@ -28,9 +28,9 @@
3657 'description': """empty""",
3658 'author': 'Akretion',
3659 'website': 'http://www.akretion.com/',
3660- 'depends': ['base'],
3661+ 'depends': ['base'],
3662 'init_xml': [],
3663- 'update_xml': [
3664+ 'update_xml': [
3665 'pop_up_file_view.xml',
3666 ],
3667 'demo_xml': [],
3668
3669=== modified file 'base_pop_up/pop_up_file.py'
3670--- base_pop_up/pop_up_file.py 2012-05-19 10:43:23 +0000
3671+++ base_pop_up/pop_up_file.py 2012-12-03 16:33:32 +0000
3672@@ -20,12 +20,12 @@
3673 # #
3674 #################################################################################
3675
3676-from osv import osv, fields
3677-import netsvc
3678+from openerp.osv.orm import TransientModel
3679+from osv import fields
3680 import base64
3681 from tempfile import TemporaryFile
3682
3683-class pop_up_file(osv.osv_memory):
3684+class pop_up_file(TransientModel):
3685 _name = "pop.up.file"
3686 _description = "Output File"
3687
3688
3689=== modified file 'base_scheduler_creator/schedulder_creator.py'
3690--- base_scheduler_creator/schedulder_creator.py 2012-05-19 16:31:30 +0000
3691+++ base_scheduler_creator/schedulder_creator.py 2012-12-03 16:33:32 +0000
3692@@ -19,18 +19,19 @@
3693 #
3694 #########################################################################
3695
3696-from osv import fields,osv
3697+from openerp.osv.orm import TransientModel
3698+from openerp.osv.osv import except_osv
3699 from tools.translate import _
3700
3701-class scheduler_creator_wizard(osv.osv_memory):
3702+class scheduler_creator_wizard(TransientModel):
3703 _name = 'scheduler.creator.wizard'
3704 _description = 'scheduler creator wizard'
3705-
3706+
3707 def action_create(self, cr, uid, id, context):
3708 for id in context['active_ids']:
3709 if context.get('object_link', False) and self.pool.get(context['object_link']).read(cr, uid, id, ['scheduler'], context)['scheduler']:
3710- raise osv.except_osv(_('USER ERROR'), _('A scheduler already exists !'))
3711-
3712+ raise except_osv(_('USER ERROR'), _('A scheduler already exists !'))
3713+
3714 vals = {'name':self.pool.get(context['object_link']).read(cr, uid, id, ['name'], context)['name'],
3715 'active':False,
3716 'user_id':uid,
3717@@ -46,5 +47,3 @@
3718 if context.get('object_link', False):
3719 self.pool.get(context['object_link']).write(cr, uid, id, {'scheduler' : cron_id}, context)
3720 return {'type': 'ir.actions.act_window_close'}
3721-
3722-scheduler_creator_wizard()
3723
3724=== modified file 'file_exchange/__openerp__.py'
3725--- file_exchange/__openerp__.py 2012-07-06 08:43:37 +0000
3726+++ file_exchange/__openerp__.py 2012-12-03 16:33:32 +0000
3727@@ -36,6 +36,7 @@
3728 'file_exchange_view.xml',
3729 'file_exchange_menu.xml',
3730 'settings/external.referential.category.csv',
3731+ 'settings/external.referential.type.csv',
3732 'security/file_exchange_security.xml',
3733 'security/file_exchange_security.xml',
3734 'security/ir.model.access.csv',
3735
3736=== modified file 'file_exchange/file_exchange.py'
3737--- file_exchange/file_exchange.py 2012-08-21 07:39:24 +0000
3738+++ file_exchange/file_exchange.py 2012-12-03 16:33:32 +0000
3739@@ -19,15 +19,17 @@
3740 # along with this program. If not, see <http://www.gnu.org/licenses/>. #
3741 # #
3742 ###############################################################################
3743-from tools.safe_eval import safe_eval as eval
3744-from osv import osv, fields
3745-import netsvc
3746+from tools.safe_eval import safe_eval
3747+from openerp.osv.orm import Model
3748+from openerp.osv import fields
3749+from openerp.osv.osv import except_osv
3750 from base_external_referentials.external_osv import ExternalSession
3751-from base_file_protocole.base_file_protocole import FileCsvReader, FileCsvWriter
3752+from base_file_protocole.base_file_protocole import FileCsvReader, FileCsvWriter, FileXlsReader
3753 from base_external_referentials.decorator import open_report
3754 from tempfile import TemporaryFile
3755 from encodings.aliases import aliases
3756 from tools.translate import _
3757+from openerp.tools.config import config
3758
3759
3760 #TODO implement the FileCsvWriter in base_file_protocole and remove import csv
3761@@ -35,9 +37,8 @@
3762
3763 class FileExchangeCsvReader(FileCsvReader):
3764 def __init__(self, f, pre_processing=None, **kwds):
3765- init = super(FileExchangeCsvReader, self).__init__(f, **kwds)
3766+ super(FileExchangeCsvReader, self).__init__(f, **kwds)
3767 self.pre_processing = pre_processing
3768- return init
3769
3770 def next(self):
3771 row = super(FileExchangeCsvReader, self).next()
3772@@ -47,10 +48,10 @@
3773 try:
3774 exec self.pre_processing in space
3775 except Exception, e:
3776- raise osv.except_osv(_('Error !'), _('Error can not apply the python action pre-processing value'))
3777+ raise except_osv(_('Error!'), _('Error can not apply the python action pre-processing value'))
3778 return row
3779
3780-class file_exchange(osv.osv):
3781+class file_exchange(Model):
3782 _name = "file.exchange"
3783 _description = "file exchange"
3784
3785@@ -70,13 +71,14 @@
3786 try:
3787 exec field.advanced_default_value in space
3788 except Exception, e:
3789- raise osv.except_osv(_('Error !'), _('Error when evaluating advanced default value: %s \n Exception: %s' %(fields.name,e)))
3790+ raise except_osv(_('Error!'),
3791+ _('Error when evaluating advanced default value: %s \n Exception: %s') % (fields.name,e))
3792 res[field.name] = space.get('result', False)
3793 elif field.default_value:
3794 res[field.name] = field.default_value
3795 return res
3796
3797- def _get_external_file_resources(self, cr, uid, external_session, filepath, filename, format,
3798+ def _get_external_file_resources(self, cr, uid, external_session, filepath, filename, format,
3799 fields_name=None, mapping=None, mapping_id=None, external_file=None, context=None):
3800 if not external_file:
3801 external_file = external_session.connection.get(filepath, filename)
3802@@ -84,14 +86,14 @@
3803 model_obj = self.pool.get(method.mapping_id.model_id.model)
3804 if format in ['csv_no_header','csv']:
3805 merge_key_id = self.pool.get('file.fields').search(cr, uid, [
3806- ('merge_key', '=', True),
3807- ('mapping_line_id.related_model_id', '=', method.mapping_id.model_id.id),
3808+ ('merge_key', '=', True),
3809+ ('mapping_line_id.related_model_id', '=', method.mapping_id.model_id.id),
3810 ('file_id', '=', method.id)
3811 ], context=context)
3812 merge_key = None
3813 if merge_key_id:
3814 merge_key = self.pool.get('file.fields').read(cr, uid, merge_key_id[0], ['name'], context=context)['name']
3815- mapping,mapping_id = model_obj._init_mapping(cr, uid, external_session.referential_id.id,
3816+ mapping,mapping_id = model_obj._init_mapping(cr, uid, external_session.referential_id.id,
3817 convertion_type='from_external_to_openerp',
3818 mapping_id=method.mapping_id.id,
3819 context=context)
3820@@ -102,8 +104,10 @@
3821 encoding=method.encoding,
3822 pre_processing=method.pre_processing)
3823 res = csv.reorganize(field_structure=mapping_tree, merge_keys=merge_keys, ref_field=merge_key)
3824+ elif format in ['xls']:
3825+ res = FileXlsReader(external_file.read()).read()
3826 return res
3827-
3828+
3829 def _get_mapping_tree(self, cr, uid, mapping_id, parent_name=None, grand_parent_name=None, context=None):
3830 mapping_tree = []
3831 result = []
3832@@ -171,7 +175,7 @@
3833 defaults = self._get_default_import_values(cr, uid, external_session, mapping_id, context=context)
3834 fields_name_ids = file_fields_obj.search(cr, uid, [['file_id', '=', method.id]], context=context)
3835 fields_name = [x['name'] for x in file_fields_obj.read(cr, uid, fields_name_ids, ['name'], context=context)]
3836- self._import_one_file(cr, uid, external_session, method_id, input_filename, defaults, mapping,
3837+ self._import_one_file(cr, uid, external_session, method_id, input_filename, defaults, mapping,
3838 mapping_id, fields_name, external_file=input_file, context=context)
3839 return True
3840
3841@@ -205,7 +209,7 @@
3842 return result
3843
3844 @open_report
3845- def _import_one_file(self, cr, uid, external_session, method_id, filename, defaults, mapping,
3846+ def _import_one_file(self, cr, uid, external_session, method_id, filename, defaults, mapping,
3847 mapping_id, fields_name, external_file=None, context=None):
3848 ids_imported = []
3849 method = self.browse(cr, uid, method_id, context=context)
3850@@ -218,8 +222,8 @@
3851 mapping_id=mapping_id,
3852 external_file=external_file,
3853 context=context)
3854- res = self.pool.get(method.mapping_id.model_id.model)._record_external_resources(cr, uid,
3855- external_session, resources,
3856+ res = self.pool.get(method.mapping_id.model_id.model)._record_external_resources(cr, uid,
3857+ external_session, resources,
3858 defaults=defaults,
3859 mapping=mapping,
3860 mapping_id=mapping_id,
3861@@ -234,7 +238,7 @@
3862 def _check_if_file_exist(self, cr, uid, external_session, folder_path, filename, context=None):
3863 exist = external_session.connection.search(folder_path, filename)
3864 if exist:
3865- raise osv.except_osv(_('Error !'), _('The file "%s" already exist in the folder "%s"' %(filename, folder_path)))
3866+ raise except_osv(_('Error!'), _('The file "%s" already exist in the folder "%s"' %(filename, folder_path)))
3867 return False
3868
3869 def _export_files(self, cr, uid, method_id, context=None):
3870@@ -248,7 +252,7 @@
3871 if 'hidden_field_to_split_' in key:
3872 if isinstance(value, list):
3873 if row_to_flat:
3874- raise osv.except_osv(_('Error !'), _('Can not flat two row in the same resource'))
3875+ raise except_osv(_('Error!'), _('Can not flat two row in the same resource'))
3876 row_to_flat = value
3877 elif isinstance(value, dict):
3878 for k,v in flat_resources([value])[0].items():
3879@@ -293,7 +297,7 @@
3880 ids_filter = "()" # In case not filter is filed in the form
3881 if method.search_filter != False:
3882 ids_filter = method.search_filter
3883- ids_to_export = model_obj.search(cr, uid, eval(ids_filter, {'context': context}), context=context)
3884+ ids_to_export = model_obj.search(cr, uid, safe_eval(ids_filter, {'context': context}), context=context)
3885 #=== Start mapping
3886 mapping,mapping_id = model_obj._init_mapping(cr, uid, external_session.referential_id.id,
3887 convertion_type='from_openerp_to_external',
3888@@ -343,12 +347,12 @@
3889 output_file.seek(0)
3890 method.start_action('action_after_all', model_obj, ids_to_export, context=context,external_session=external_session)
3891 output = self._send_output(cr, uid, external_session, method, filename, output_file, context=context)
3892-
3893+
3894 #Start linked task
3895 if method.linked_task:
3896 context['parent_ids'] = ids_to_export
3897 method.linked_task.start_task(context=context)
3898-
3899+
3900 return output
3901
3902 def _send_output(self, cr, uid, external_session, method, filename, output_file, context=None):
3903@@ -379,8 +383,10 @@
3904 try:
3905 exec action_code in space
3906 except Exception, e:
3907- raise osv.except_osv(_('Error !'), _("Error can not apply the python action '%s'"
3908- " for the method: '%s' \n Exception: '%s'" %(action_name, method.name,e)))
3909+ if config['debug_mode']: raise
3910+ raise except_osv(_('Error!'),
3911+ _("Error can not apply the python action '%s'"
3912+ " for the method: '%s' \n Exception: '%s'") % (action_name, method.name,e))
3913 if 'result' in space:
3914 return space['result']
3915 return True
3916@@ -405,7 +411,7 @@
3917 "and to be imported in the ERP ; OUT for files to be"
3918 "generated from the ERP and send to the other system")),
3919 'mapping_id':fields.many2one('external.mapping', 'External Mapping', require="True", domain="[('referential_id', '=', referential_id)]"),
3920- 'format' : fields.selection([('csv','CSV'),('csv_no_header','CSV WITHOUT HEADER')], 'File format'),
3921+ 'format' : fields.selection([('csv','CSV'),('csv_no_header','CSV WITHOUT HEADER'), ('xls', 'XLS')], 'File format'),
3922 'referential_id':fields.many2one('external.referential', 'Referential',help="Referential to use for connection and mapping", require=True),
3923 'scheduler':fields.many2one('ir.cron', 'Scheduler',help="Scheduler that will execute the cron task"),
3924 'search_filter': fields.char('Search Filter', size=256),
3925@@ -416,9 +422,9 @@
3926 'field_ids': fields.one2many('file.fields', 'file_id', 'Fields'),
3927 'action_before_all': fields.text('Action Before All', help="This python code will executed after the import/export"),
3928 'action_after_all': fields.text('Action After All', help="This python code will executed after the import/export"),
3929- 'action_before_each': fields.text('Action Before Each', help="This python code will executed after each element of the import/export"),
3930+ 'action_before_each': fields.text('Action Before Each', help="This python code will executed after each element of the import/export"),
3931 'action_after_each': fields.text('Action After Each', help="This python code will executed after each element of the import/export"),
3932- 'check_if_import': fields.text('Check If Import', help="This python code will be executed before each element of the import"),
3933+ 'check_if_import': fields.text('Check If Import', help="This python code will be executed before each element of the import"),
3934 'delimiter':fields.char('Fields delimiter', size=64, help="Delimiter used in the CSV file"),
3935 'lang': fields.many2one('res.lang', 'Language'),
3936 'import_default_fields':fields.one2many('file.default.import.values', 'file_id', 'Default Field'),
3937@@ -472,7 +478,7 @@
3938 }
3939 csv.writerow(row)
3940 return self.pool.get('pop.up.file').open_output_file(cr, uid, 'file.exchange.csv', output_file, 'File Exchange Export', context=context)
3941-
3942+
3943 # Method to export the mapping file
3944 def create_file_fields(self, cr, uid, id, context=None):
3945 if isinstance(id,list):
3946@@ -530,9 +536,8 @@
3947 field.write({'mapping_line_id': field_mapping_line_id}, context=context)
3948 return True
3949
3950-file_exchange()
3951
3952-class file_fields(osv.osv):
3953+class file_fields(Model):
3954 _name = "file.fields"
3955 _description = "file fields"
3956 _order='sequence'
3957@@ -587,9 +592,8 @@
3958 field_id = (file_name + '_' + field_name + '_' + sequence).replace('.','_')
3959 return field_id
3960
3961-file_fields()
3962
3963-class file_default_import_values(osv.osv):
3964+class file_default_import_values(Model):
3965 _name = "file.default.import.values"
3966 _description = "file default import values"
3967
3968
3969=== modified file 'file_exchange/file_exchange_osv.py'
3970--- file_exchange/file_exchange_osv.py 2012-05-24 09:56:58 +0000
3971+++ file_exchange/file_exchange_osv.py 2012-12-03 16:33:32 +0000
3972@@ -19,13 +19,12 @@
3973 # #
3974 ###############################################################################
3975
3976-from osv import osv, fields
3977+from openerp.osv.orm import Model
3978 from base_external_referentials.decorator import only_for_referential, catch_error_in_report
3979-import netsvc
3980-
3981-osv.osv._feo_record_one_external_resource = osv.osv._record_one_external_resource #feo mean file_exchange_original
3982-
3983-@only_for_referential(ref_categ ='File Exchange', super_function = osv.osv._feo_record_one_external_resource)
3984+
3985+Model._feo_record_one_external_resource = Model._record_one_external_resource #feo mean file_exchange_original
3986+
3987+@only_for_referential(ref_categ ='File Exchange', super_function = Model._feo_record_one_external_resource)
3988 @catch_error_in_report
3989 def _record_one_external_resource(self, cr, uid, external_session, resource, **kwargs):
3990 context=kwargs.get('context')
3991@@ -40,11 +39,11 @@
3992 method.start_action('action_after_each', self, [res_id], resource, context=context)
3993 return res
3994
3995-osv.osv._record_one_external_resource = _record_one_external_resource
3996-
3997-osv.osv._feo_get_default_import_values = osv.osv._get_default_import_values #feo mean file_exchange_original
3998-
3999-@only_for_referential(ref_categ ='File Exchange', super_function = osv.osv._feo_get_default_import_values)
4000+Model._record_one_external_resource = _record_one_external_resource
4001+
4002+Model._feo_get_default_import_values = Model._get_default_import_values #feo mean file_exchange_original
4003+
4004+@only_for_referential(ref_categ ='File Exchange', super_function = Model._feo_get_default_import_values)
4005 def _get_default_import_values(self, cr, uid, external_session, mapping_id=None, defaults=None, context=None):
4006 if not defaults:
4007 defaults = {}
4008@@ -62,12 +61,12 @@
4009 defaults[field.import_default_field.name] = str(field.import_default_value)
4010 return defaults
4011
4012-osv.osv._get_default_import_values = _get_default_import_values
4013+Model._get_default_import_values = _get_default_import_values
4014
4015 def _get_oe_resources_into_external_format(self, cr, uid, external_session, ids, mapping=None, mapping_id=None, mapping_line_filter_ids=None, fields=[], defaults=None, context=None):
4016 result = []
4017 for resource in self.read_w_order(cr, uid, ids, fields, context):
4018 result.append(self._transform_one_resource(cr, uid, external_session, 'from_openerp_to_external', resource, mapping, mapping_id, mapping_line_filter_ids=mapping_line_filter_ids, parent_data=None, previous_result=None, defaults=defaults, context=context))
4019 return result
4020-osv.osv._get_oe_resources_into_external_format = _get_oe_resources_into_external_format
4021+Model._get_oe_resources_into_external_format = _get_oe_resources_into_external_format
4022
4023
4024=== added file 'file_exchange/settings/external.referential.type.csv'
4025--- file_exchange/settings/external.referential.type.csv 1970-01-01 00:00:00 +0000
4026+++ file_exchange/settings/external.referential.type.csv 2012-12-03 16:33:32 +0000
4027@@ -0,0 +1,3 @@
4028+id,name,categ_id:id,code
4029+ref_type_FTP-file-exchange,FTP,file-exchange,FTP
4030+ref_type_SFTP-file-exchange,SFTP,file-exchange,SFTP
4031
4032=== added directory 'framework_helpers'
4033=== added file 'framework_helpers/__init__.py'
4034--- framework_helpers/__init__.py 1970-01-01 00:00:00 +0000
4035+++ framework_helpers/__init__.py 2012-12-03 16:33:32 +0000
4036@@ -0,0 +1,22 @@
4037+# -*- encoding: utf-8 -*-
4038+#################################################################################
4039+# #
4040+# framework_helpers for OpenERP #
4041+# Copyright (C) 2011 Akretion Benoît Guillot <benoit.guillot@akretion.com> #
4042+# #
4043+# This program is free software: you can redistribute it and/or modify #
4044+# it under the terms of the GNU Affero General Public License as #
4045+# published by the Free Software Foundation, either version 3 of the #
4046+# License, or (at your option) any later version. #
4047+# #
4048+# This program is distributed in the hope that it will be useful, #
4049+# but WITHOUT ANY WARRANTY; without even the implied warranty of #
4050+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
4051+# GNU Affero General Public License for more details. #
4052+# #
4053+# You should have received a copy of the GNU Affero General Public License #
4054+# along with this program. If not, see <http://www.gnu.org/licenses/>. #
4055+# #
4056+#################################################################################
4057+
4058+import context_managers
4059
4060=== added file 'framework_helpers/__openerp__.py'
4061--- framework_helpers/__openerp__.py 1970-01-01 00:00:00 +0000
4062+++ framework_helpers/__openerp__.py 2012-12-03 16:33:32 +0000
4063@@ -0,0 +1,37 @@
4064+# -*- encoding: utf-8 -*-
4065+#################################################################################
4066+# #
4067+# framework_helpers for OpenERP #
4068+# Copyright (C) 2012 Akretion Benoît Guillot <benoit.guillot@akretion.com> #
4069+# #
4070+# This program is free software: you can redistribute it and/or modify #
4071+# it under the terms of the GNU Affero General Public License as #
4072+# published by the Free Software Foundation, either version 3 of the #
4073+# License, or (at your option) any later version. #
4074+# #
4075+# This program is distributed in the hope that it will be useful, #
4076+# but WITHOUT ANY WARRANTY; without even the implied warranty of #
4077+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
4078+# GNU Affero General Public License for more details. #
4079+# #
4080+# You should have received a copy of the GNU Affero General Public License #
4081+# along with this program. If not, see <http://www.gnu.org/licenses/>. #
4082+# #
4083+#################################################################################
4084+
4085+{
4086+ 'name': 'framework_helpers',
4087+ 'version': '0.1',
4088+ 'category': 'Generic Modules/Others',
4089+ 'license': 'AGPL-3',
4090+ 'description': """This module provides methods for the framework.""",
4091+ 'author': 'Akretion',
4092+ 'website': 'http://www.akretion.com/',
4093+ 'depends': ['base'],
4094+ 'init_xml': [],
4095+ 'update_xml': [],
4096+ 'demo_xml': [],
4097+ 'installable': True,
4098+ 'active': False,
4099+}
4100+
4101
4102=== added file 'framework_helpers/context_managers.py'
4103--- framework_helpers/context_managers.py 1970-01-01 00:00:00 +0000
4104+++ framework_helpers/context_managers.py 2012-12-03 16:33:32 +0000
4105@@ -0,0 +1,66 @@
4106+# -*- encoding: utf-8 -*-
4107+#################################################################################
4108+# #
4109+# framework_helpers for OpenERP #
4110+# Copyright (C) 2011 Akretion Benoît Guillot <benoit.guillot@akretion.com> #
4111+# #
4112+# This program is free software: you can redistribute it and/or modify #
4113+# it under the terms of the GNU Affero General Public License as #
4114+# published by the Free Software Foundation, either version 3 of the #
4115+# License, or (at your option) any later version. #
4116+# #
4117+# This program is distributed in the hope that it will be useful, #
4118+# but WITHOUT ANY WARRANTY; without even the implied warranty of #
4119+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
4120+# GNU Affero General Public License for more details. #
4121+# #
4122+# You should have received a copy of the GNU Affero General Public License #
4123+# along with this program. If not, see <http://www.gnu.org/licenses/>. #
4124+# #
4125+#################################################################################
4126+
4127+import pooler
4128+from contextlib import contextmanager
4129+
4130+@contextmanager
4131+def commit_now(cr, logger, raise_error=False):
4132+ """
4133+ Context Manager to use in order to commit into a cursor
4134+ correctly with a try/except method and a rollback if necessary
4135+ :param cr cursor: cursor to commit
4136+ :param logger logger: logger used to logging the message
4137+ :param raise_error boolean: Set to true only if you want
4138+ to stop the process if an error occured
4139+ """
4140+ try:
4141+ yield cr
4142+ except Exception, e:
4143+ cr.rollback()
4144+ logger.exception(e)
4145+ if raise_error:
4146+ raise
4147+ else:
4148+ cr.commit()
4149+
4150+@contextmanager
4151+def new_cursor(cr, logger, raise_error=False):
4152+ """
4153+ Context Manager to use in order to commit into a new cursor
4154+ correctly with a try/except method and a rollback if necessary
4155+ :param cr cursor: cursor to copy
4156+ :param logger logger: logger used to logging the message
4157+ :param raise_error boolean: Set to true only if you want
4158+ to stop the process if an error occured
4159+ """
4160+ new_cr = pooler.get_db(cr.dbname).cursor()
4161+ try:
4162+ yield new_cr
4163+ except Exception, e:
4164+ new_cr.rollback()
4165+ logger.exception(e)
4166+ if raise_error:
4167+ raise
4168+ else:
4169+ new_cr.commit()
4170+ finally:
4171+ new_cr.close()
4172
4173=== modified file 'report_synchronizer/report_osv.py'
4174--- report_synchronizer/report_osv.py 2012-06-01 17:44:44 +0000
4175+++ report_synchronizer/report_osv.py 2012-12-03 16:33:32 +0000
4176@@ -19,19 +19,20 @@
4177 # #
4178 ###############################################################################
4179
4180-from osv import osv, fields
4181+from openerp.osv.orm import Model
4182 import netsvc
4183 from base_external_referentials.external_osv import extend
4184 from tempfile import TemporaryFile
4185
4186-@extend(osv.osv)
4187-def send_report(self, cr, uid, external_session, ids, report_name, file_name, path, context=None):
4188+@extend(Model)
4189+def send_report(self, cr, uid, external_session, ids, report_name, file_name, path, add_extension=True, context=None):
4190 service = netsvc.LocalService(report_name)
4191 result, format = service.create(cr, uid, ids, {'model': self._name}, context=context)
4192 output_file = TemporaryFile('w+b')
4193 output_file.write(result)
4194 output_file.seek(0)
4195- file_name = "%s.%s"%(file_name, format)
4196+ if add_extension:
4197+ file_name = "%s.%s"%(file_name, format)
4198 external_session.connection.send(path, file_name, output_file)
4199 return file_name
4200