← Back to team overview

savoirfairelinux-openerp team mailing list archive

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

 

Sébastien BEAU - http://www.akretion.com has proposed merging lp:~extra-addons-commiter/openobject-extension/oerp6.1-cleanning into lp:openobject-extension/oerp6.1-stable.

Requested reviews:
  extra-addons-commiter (extra-addons-commiter)

For more details, see:
https://code.launchpad.net/~extra-addons-commiter/openobject-extension/oerp6.1-cleanning/+merge/135018
-- 
https://code.launchpad.net/~extra-addons-commiter/openobject-extension/oerp6.1-cleanning/+merge/135018
Your team extra-addons-commiter is requested to review the proposed merge of lp:~extra-addons-commiter/openobject-extension/oerp6.1-cleanning into lp:openobject-extension/oerp6.1-stable.
=== modified file 'base_external_cron/__openerp__.py'
--- base_external_cron/__openerp__.py	2012-07-24 15:54:02 +0000
+++ base_external_cron/__openerp__.py	2012-11-19 23:44:21 +0000
@@ -29,9 +29,9 @@
     'description': """empty""",
     'author': 'Akretion',
     'website': 'http://www.akretion.com/',
-    'depends': ['base_external_referentials'], 
+    'depends': ['base_external_referentials'],
     'init_xml': [],
-    'update_xml': [ 
+    'update_xml': [
            'external_cron_view.xml',
     ],
     'demo_xml': [],

=== modified file 'base_external_cron/external_cron.py'
--- base_external_cron/external_cron.py	2012-08-24 00:40:58 +0000
+++ base_external_cron/external_cron.py	2012-11-19 23:44:21 +0000
@@ -19,6 +19,7 @@
 #                                                                             #
 ###############################################################################
 
+<<<<<<< TREE
 from osv import osv, fields
 import netsvc
 from base_external_referentials.external_osv import ExternalSession
@@ -26,27 +27,105 @@
 from ebaypyt import EbayWebService
 
 class external_cron(osv.osv):
+=======
+from openerp.osv.orm import Model, except_orm
+from openerp.osv import fields
+from tools.translate import _
+
+EXT_CRON_MINIMUM_FREQUENCY = 10
+
+
+class external_cron(Model):
+>>>>>>> MERGE-SOURCE
 
     _name = "external.cron"
     _description = "external.cron"
 
+<<<<<<< TREE
+=======
+    def _export_management_one_row(self, cr, uid, cron_id, field, arg, context=None):
+        """ set exported et readonly value"""
+        res = {}
+        domain = [('model','=','external.cron'),('res_id','=',cron_id)]
+        my_search = self.pool.get('ir.model.data').search(cr, uid, domain, context=context)
+        if len(my_search) > 0:
+            res[cron_id] = {'exported': True, 'readonly': False}
+        else:
+            res[cron_id] = {'exported': False, 'readonly': False}
+        return res
+
+    def _export_management(self, cr, uid, ids, field, arg, context=None):
+        res={}
+        for cron_id in ids:
+            res.update(self._export_management_one_row(cr, uid, cron_id, field, arg, context=context))
+        return res
+
+>>>>>>> MERGE-SOURCE
     _columns = {
         'name': fields.char('Name', size=50, required=True),
-        'active': fields.boolean('Active', help="The active field allows to hide the item in tree view without deleting it."),
+        'active': fields.boolean('Active',
+                help="The active field allows to hide the item in tree view without deleting it."),
         'period': fields.selection((('month','Month'), ('week','Week'), ('day','Day'),
-            ('minute','Minute')), 'Periodicity', help="Base unit periodicity used by cron"),
-        'frequency': fields.integer('Frequency', help="Interval cron in minutes. Set periodicity on 'minute'"),
-        'repeat': fields.datetime('Repeat',
-            help="Recurrency selection with datetime widget : if 'periodicity' is 'day' only hour indicate the external data; if is 'week'  "),
-        'report_type': fields.selection([('sale','Sale'), ('product','Product')],'Report', help="Report type name to cron"),
-        'referential_id':fields.many2one('external.referential', 'Referential', help="External referential"),
+            ('minute','Minute')), 'Periodicity', required=True,
+                                                help="Base unit periodicity used by cron"),
+        'frequency': fields.integer('Frequency (min.)',
+                                    help="Interval cron in minutes if periodicity is in 'minutes'"),
+        'repeat': fields.datetime('Repeat', help="Recurrency selection with datetime widget : \
+                    if 'periodicity' is 'day' only hour indicate the external data; if is 'week'"),
+        'report_type': fields.selection([('sale','Sale'), ('product','Product')],'Report',
+                                            required=True,  help="Report type name to cron"),
+        'referential_id':fields.many2one('external.referential', 'Referential', required=True,
+                                                                    help="External referential"),
+        'exported': fields.function(_export_management, multi='export', method=True, string='Exported', type='boolean',
+                    help="True if cron has been exported to external application with success and subsequently has an external referential in 'ir.model.data'"),
+        'readonly': fields.function(_export_management, multi='export', type='boolean', method=True, string='Read only', help='define form read only behavior'),
     }
 
     _defaults = {
-        'active': 1
+        'active': 1,
+        'name': 'external cron',
     }
 
+<<<<<<< TREE
+=======
+    def _check_field_frequency(self, cr, uid, ids, context=None):
+        for cron in self.browse(cr, uid, ids):
+            if cron.frequency <= EXT_CRON_MINIMUM_FREQUENCY and cron.period == 'minute':
+                raise except_orm(_('Invalid field value :'), _("'Frequency' field must be upper than %s minutes" %EXT_CRON_MINIMUM_FREQUENCY))
+        return True
+
+    def _count_duplicate_report(self, cr, uid, vals, context=None):
+        domain = []
+        for key, val in vals.items():
+            domain.append((key, '=', val))
+        domain.append(('active', '=', 'True'))
+        return len(self.search(cr, uid, domain, context=context))
+
+    def _check_field_active(self, cr, uid, ids, context=None):
+        """ """
+        for cron in self.browse(cr, uid, ids, context=context):
+            vals = {'report_type': cron.report_type, 'referential_id': cron.referential_id.id}
+            if cron.active == True:
+                report_count = self._count_duplicate_report(cr, uid, vals, context=context)
+                if report_count > 1:
+                    raise except_orm(_('Too many reports of the same type for this referential  :'),
+                        _("There are %s 'Reports' of '%s' type  with 'active' value checked. \nOnly 1 is authorized !" % (report_count, cron.report_type)))
+        return True
+
+    def copy(self, cr, uid, id, default=None, context=None):
+        row = self.browse(cr, uid, id, context=context)
+        if default is None:
+            default = {}
+        default_custom={'exported': False, 'active': False, 'name': row.name+' copy'}
+        default.update(default_custom)
+        return super(external_cron, self).copy(cr, uid, id, default, context=context)
+
+    _constraints = [
+        (_check_field_frequency, "Error message in raise", ['frequency']),
+        (_check_field_active, "Only one active cron per job", ['active']),
+    ]
+
+>>>>>>> MERGE-SOURCE
     def unlink(self, cr, uid, ids, context=None):
         self.ext_unlink(cr, uid, ids, context=context)
         return super(external_cron, self).unlink(cr, uid, ids, context=context)
-

=== modified file 'base_external_cron/external_cron_view.xml'
--- base_external_cron/external_cron_view.xml	2012-08-24 00:40:58 +0000
+++ base_external_cron/external_cron_view.xml	2012-11-19 23:44:21 +0000
@@ -8,8 +8,7 @@
 <openerp>
     <data>
 
-        <!-- VIEWS FOR THE OBJECT : external.cron -->
-        <!-- form -->
+        <!-- FORM -->
         <record id="external_cron_view_form" model="ir.ui.view">
             <field name="name">base_external_cron.external.cron.view_form</field>
             <field name="model">external.cron</field>
@@ -17,6 +16,7 @@
             <field name="type">form</field>
             <field name="arch" type="xml">
                 <form string="external.cron">
+<<<<<<< TREE
                     <field name="name" />
                     <field name="active" />
                     <field name="period" />
@@ -27,11 +27,24 @@
                     <field name="repeat" />
                     <field name="report_type" />
                     <field name="referential_id" />
+=======
+                    <group name="common">
+                        <field name="name" />
+                        <field name="active" attrs="{'readonly':[('readonly','=',True)]}"/>
+                        <field name="period" attrs="{'readonly':[('readonly','=',True)]}"/>
+                        <field name="report_type" attrs="{'readonly':[('readonly','=',True)]}"/>
+                        <field name="repeat" attrs="{'invisible':[('frequency','!=',0),('period','=','minute')], 'required': [('period','!=', 'minute')]}"/>
+                        <field name="frequency" attrs="{'invisible':[('period','!=','minute')],'readonly':[('readonly','=',True)]}"/>
+                        <field name="referential_id" attrs="{'readonly':[('readonly','=',True)]}"/>
+                        <field name="exported" />
+                        <field name="readonly" invisible="1" />
+                    </group>
+>>>>>>> MERGE-SOURCE
                 </form>
             </field>
         </record>
 
-        <!-- tree -->
+        <!-- TREE -->
         <record id="external_cron_view_tree" model="ir.ui.view">
             <field name="name">base_external_cron.external.cron.view_tree</field>
             <field name="model">external.cron</field>
@@ -43,18 +56,28 @@
                     <field name="active" />
                     <field name="period" />
                     <field name="report_type" />
-                    <field name="frequency" />
-                    <field name="repeat" />
+                    <field name="frequency" attrs="{'invisible':[('period','!=','minute')]}"/>
                     <field name="referential_id" />
+                    <field name="exported" string="exp."/>
                 </tree>
             </field>
         </record>
 
         <!-- Action used by menu -->
         <record id="action_external_cron" model="ir.actions.act_window">
+            <field name="help">
+'Repeat' field behavior : only visible if 'Periodicity' is in 'Month/Day/Week' -------
+'Repeat' format is 'mm/dd/YYYY HH:MM:SS' : example : 12/24/2013 12:05:32  (Tuesday) -------
+If 'Periodicity' is 'Month' : next cron will be each 24th day of the month at 12:05:32 -------
+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-------
+If 'Periodicity' is 'Week' : next cron will be each Tuesday at 12:05:32 -------
+If 'Periodicity' is 'Day' : next cron will be each day at 12:05:32 ----------------
+If 'Periodicity' is 'Minute' : next cron will be each X minutes (depends on 'frequency' field value)------
+            </field>
             <field name="name">External Cron</field>
             <field name="res_model">external.cron</field>
             <field name="view_type">form</field>
+            <field name="context">{'active_test': False}</field>
             <field name="view_mode">tree,form</field>
         </record>
 

=== modified file 'base_external_file_protocole/__openerp__.py'
--- base_external_file_protocole/__openerp__.py	2012-08-22 22:42:00 +0000
+++ base_external_file_protocole/__openerp__.py	2012-11-19 23:44:21 +0000
@@ -36,8 +36,11 @@
     'init_xml': [],
     'update_xml': [
         'file_buffer_view.xml',
+        'file_buffer_data.xml',
+        'external_referential_view.xml',
         'settings/external.referential.category.csv',
-        'file_buffer_data.xml',
+        'settings/external.referential.type.csv',
+        'settings/external.referential.version.csv',
     ],
     'demo_xml': [],
     'installable': True,

=== added file 'base_external_file_protocole/external_referential_view.xml'
--- base_external_file_protocole/external_referential_view.xml	1970-01-01 00:00:00 +0000
+++ base_external_file_protocole/external_referential_view.xml	2012-11-19 23:44:21 +0000
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  base_sale_report_synchronizer for OpenERP
+  Copyright (C) 2012 Akretion Sébastien BEAU <sebastien.beau@xxxxxxxxxxxx>
+  The licence is in the file __openerp__.py
+-->
+
+<openerp>
+    <data>
+        <record id="external_referential_form_view" model="ir.ui.view">
+            <field name="name">base_external_file_protocole.external_referential_form_view</field>
+            <field name="model">external.referential</field>
+            <field name="inherit_id" ref="base_external_referentials.external_referential_form_view" />
+            <field name="type">form</field>
+            <field name="arch" type="xml">
+                <field name="location" position="after">
+                    <field name="port" attrs="{'invisible': [['type_name', 'not in', ['SFTP', 'FTP']]],
+                                                'required': [['type_name', 'in', ['SFTP', 'FTP']]]}"/>
+                    <field name="home_folder" attrs="{'invisible': [['type_name', 'not in', ['SFTP', 'FTP', 'File System']]]}"/>
+                </field>
+            </field>
+        </record>
+    </data>
+</openerp>

=== modified file 'base_external_file_protocole/external_referentials.py'
--- base_external_file_protocole/external_referentials.py	2012-08-10 08:07:58 +0000
+++ base_external_file_protocole/external_referentials.py	2012-11-19 23:44:21 +0000
@@ -1,4 +1,4 @@
-    # -*- encoding: utf-8 -*-
+        # -*- encoding: utf-8 -*-
 ###############################################################################
 #                                                                             #
 #   file_exchange for OpenERP                                                 #
@@ -19,12 +19,21 @@
 #                                                                             #
 ###############################################################################
 
-from osv import osv, fields
-import netsvc
+from openerp.osv.orm import Model
+from openerp.osv import fields
+from openerp.osv.osv import except_osv
 from base_file_protocole.base_file_protocole import FileConnection
 from tools.translate import _
-
-class external_referential(osv.osv):
+from base_external_referentials.external_referentials import REF_VISIBLE_FIELDS
+
+REF_VISIBLE_FIELDS.update({
+    'SFTP': ['location', 'apiusername', 'apipass'],
+    'FTP': ['location', 'apiusername', 'apipass'],
+})
+
+
+
+class external_referential(Model):
     _inherit = "external.referential"
 
     def external_connection(self, cr, uid, id, debug=False, logger=False, context=None):
@@ -32,32 +41,25 @@
             id=id[0]
         referential = self.browse(cr, uid, id, context=context)
         try:
-            return FileConnection(referential.protocole, referential.location, referential.apiusername,\
+            return FileConnection(referential.type_id.code, referential.location, referential.apiusername,\
                             referential.apipass, port=referential. port, allow_dir_creation = True, \
                             home_folder=referential.home_folder)
         except Exception, e:
-            raise osv.except_osv(_("Base File Protocole Connection Error"), _("Could not connect to server\nCheck url & user & password.\n %s"%e))
+            raise except_osv(_("Base File Protocole Connection Error"),
+                             _("Could not connect to server\nCheck url & user & password.\n %s") % e)
 
     _columns={
-        'protocole': fields.selection([('ftp','ftp'), ('filestore', 'Filestore'), ('sftp', 'sftp')], 'Protocole'),
         'port': fields.integer('Port'),
         'home_folder': fields.char('Home Folder', size=64),
     }
 
-    def get_file_to_import(cr, uid, referential_id, mapping_id, context=None):
-        '''
-        return les file_buffer qui sont a l’état waiting pour le referential et le mapping_id choisi
-        '''
-
     def _prepare_external_referential_fieldnames(self, cr, uid, context=None):
         res = super(external_referential, self)._prepare_external_referential_fieldnames(cr, uid, context=context)
         res.append('protocole')
         return res
 
     def _prepare_external_referential_vals(self, cr, uid, referential, context=None):
-        res = super(external_referential, self)._prepare_external_referential_vals(cr, uid, mapping, context=context)
+        res = super(external_referential, self)._prepare_external_referential_vals(cr, uid, referential, context=context)
         res['protocole'] = referential.protocole
         return res
 
-external_referential()
-

=== modified file 'base_external_file_protocole/file_buffer.py'
--- base_external_file_protocole/file_buffer.py	2012-08-22 22:48:00 +0000
+++ base_external_file_protocole/file_buffer.py	2012-11-19 23:44:21 +0000
@@ -19,38 +19,41 @@
 #                                                                             #
 ###############################################################################
 
-
-from osv import osv, fields
+from openerp.osv.orm import Model
+from openerp.osv import fields
 import base64
 from base_external_referentials.external_osv import ExternalSession
 
-class file_buffer(osv.osv):
+class file_buffer(Model):
 
     _name = "file.buffer"
     _description = "File Buffer"
 
-
     _columns = {
         'name': fields.char('Name', size=64),
-        'file_id': fields.char('Ext. file', size=64),
-        'state': fields.selection((('waiting','Waiting'), ('running','Running'), ('done','Done')), 'State'),
+        'file_id': fields.char('Exch. file', size=64, help="Exchange id file"),
+        'state': fields.selection((('waiting','Waiting'), ('running','Running'), ('done','Done'),
+                                                                        ('fail','Fail')), 'State'),
         'active': fields.boolean('Active'),
-        'mapping_id': fields.many2one('external.mapping', 'Mapping',
-            help=""),
-        'job_ended': fields.datetime('Job ended'),
-        'referential_id': fields.related('mapping_id', 'referential_id', type='many2one', relation='external.referential', string='Ext. referential', store=True),
+        'mapping_id': fields.many2one('external.mapping', 'Mapping'),
+        'job_ended': fields.datetime('Job ended', help="GMT date given by external application"),
+        'referential_id': fields.related('shop_id', 'referential_id', type='many2one',
+                        relation='external.referential', string='Ext. referential', store=True),
         #This field add a dependency on sale (maybe move it into an other module if it's problematic)
         'shop_id': fields.many2one('sale.shop', 'Shop'),
+        'direction': fields.selection([('input', 'Input'),('output', 'Output')], 'Direction',
+                                      help='flow direction of the file'),
+        'response': fields.text('Response', help='External application response'),
     }
 
-    _order = 'name desc'
+    _order = 'job_ended desc'
 
     _defaults = {
         'active': 1,
         'state': 'waiting',
     }
 
-    def get_file(self, cr, uid, file_id, context=None):
+    def get_file(self, cr, uid, file_buffer_id, context=None):
         """
         Fonction that return the content of the attachment
         :param int file_id : id of the file buffer
@@ -58,13 +61,43 @@
         :return: the content attachment
         """
         attach_obj = self.pool.get('ir.attachment')
-        attachment_id = attach_obj.search(cr, uid, [('res_model','=','file.buffer'), ('res_id','=', file_id)])
+        attachment_id = attach_obj.search(cr, uid, [('res_model','=','file.buffer'),
+                                                                ('res_id','=', file_buffer_id)])
         if not attachment_id:
             return False
         else:
             attachment = attach_obj.browse(cr, uid, attachment_id[0], context=context)
             return base64.decodestring(attachment.datas)
 
+    def create_file_buffer_attachment(self, cr, uid, file_buffer_id, datas, file_name,
+                                      context=None, extension='csv', prefix_file_name='report'):
+        """
+        Create file attachment to file.buffer object
+        :param int file_buffer_id:
+        :param str datas: file content
+        :param str file_id: file name component
+        :param str extension: file extension
+        :param str prefix_file_name:
+        :rtype: boolean
+        :return: True
+        """
+        context.update({'default_res_id': file_buffer_id, 'default_res_model': 'file.buffer'})
+        datas_encoded = base64.encodestring(datas)
+        attach_name = prefix_file_name + '_' + file_name + '.' + extension
+        params_attachment = {'name': attach_name, 'datas': datas_encoded,
+                                                                    'datas_fname': attach_name}
+        attachment_id = self.pool.get('ir.attachment').create(cr, uid, params_attachment, context)
+
+        return True
+
+    def check_state_file_buffer_scheduler(self, cr, uid, domain=None, context=None):
+        if not domain: domain = []
+        domain.append(('state', '=', 'running'))
+        ids = self.search(cr, uid, domain, context=context)
+        if ids:
+            return self.check_state(cr, uid, ids, context=context)
+        return True
+
     def run_file_buffer_scheduler(self, cr, uid, domain=None, context=None):
         if not domain: domain = []
         domain.append(('state', '=', 'waiting'))
@@ -80,10 +113,11 @@
         if context is None: context = {}
         for filebuffer in self.browse(cr, uid, ids, context=context):
             external_session = ExternalSession(filebuffer.referential_id, filebuffer)
-            self._run(cr, uid, external_session, filebuffer, context=context) 
-            filebuffer.done()
+            self._run(cr, uid, external_session, filebuffer, context=context)
+            if filebuffer.direction == 'input':
+                filebuffer.done()
         return True
-    
+
     def _run(self, cr, uid, external_session, filebuffer, context=None):
         filebuffer._set_state('running', context=context)
 
@@ -93,3 +127,7 @@
     def _set_state(self, cr, uid, ids, state, context=None):
         for id in ids:
             self.write(cr, uid, id, {'state': state}, context=context)
+
+    def check_state(self, cr, uid, ids, context=None):
+        """ Inherit this function in your module """
+        return True

=== modified file 'base_external_file_protocole/file_buffer_data.xml'
--- base_external_file_protocole/file_buffer_data.xml	2012-08-22 22:42:00 +0000
+++ base_external_file_protocole/file_buffer_data.xml	2012-11-19 23:44:21 +0000
@@ -3,7 +3,7 @@
     <data noupdate="1">
 
         <record forcecreate="True" id="ir_cron_run_file_buffer_scheduler_action" model="ir.cron">
-            <field name="name">Proccess File Buffer</field>
+            <field name="name">File Buffer: process</field>
             <field eval="False" name="active"/>
             <field name="user_id" ref="base.user_root"/>
             <field name="interval_number">10</field>
@@ -15,5 +15,18 @@
             <field eval="'()'" name="args"/>
         </record>
 
+        <record forcecreate="True" id="ir_cron_check_state_file_buffer_scheduler_action" model="ir.cron">
+            <field name="name">File Buffer: check state (output buffer)</field>
+            <field eval="False" name="active"/>
+            <field name="user_id" ref="base.user_root"/>
+            <field name="interval_number">10</field>
+            <field name="interval_type">minutes</field>
+            <field name="numbercall">-1</field>
+            <field eval="False" name="doall"/>
+            <field eval="'file.buffer'" name="model"/>
+            <field eval="'check_state_file_buffer_scheduler'" name="function"/>
+            <field eval="'()'" name="args"/>
+        </record>
+
     </data>
 </openerp>

=== modified file 'base_external_file_protocole/file_buffer_view.xml'
--- base_external_file_protocole/file_buffer_view.xml	2012-08-22 22:36:44 +0000
+++ base_external_file_protocole/file_buffer_view.xml	2012-11-19 23:44:21 +0000
@@ -6,21 +6,30 @@
 
 <openerp>
     <data>
-
+<!-- SEARCH -->
 <record id="file_buffer_view_search" model="ir.ui.view">
     <field name="name">file.buffer.search</field>
     <field name="model">file.buffer</field>
     <field name="type">search</field>
     <field name="arch" type="xml">
-        <search string="Search Sales Order">
-            <filter icon="terp-document-new" name="wait" string="Waiting" domain="[('state','=','waiting')]"/>
-            <filter icon="terp-check" string="Done" domain="[('state','=','done')]"/>
+        <search string="Search Files Buffer">
+            <group>
+                <filter icon="kanban-pause" name="wait" string="Waiting" domain="[('state','=','waiting')]"/>
+                <filter icon="gtk-apply" string="Done" domain="[('state','=','done')]"/>
+                <filter icon="gtk-execute" string="Running" domain="[('state','=','running')]"/>
+                <filter icon="terp-gtk-stop" string="Fail" domain="[('state','=','fail')]"/>
+            </group>
+            <group>
+                <filter icon="gtk-go-down" string="In" domain="[('direction','=','input')]"/>
+                <filter icon="gtk-go-up" string="Out" domain="[('direction','=','output')]"/>
+                <field name="name" />
+                <field name="file_id" string="Exchange file"/>
+            </group>
        </search>
     </field>
 </record>
 
-
-<!-- VIEW FOR THE OBJECT : file_buffer -->
+<!-- FORM -->
 <record id="file_buffer_view_form" model="ir.ui.view">
     <field name="name">file_buffer.file_buffer.view_form</field>
     <field name="model">file.buffer</field>
@@ -29,18 +38,26 @@
     <field name="arch" type="xml">
     <form string="file_buffer">
         <field name="name" />
-        <field name="state" />
+        <field name="state" readonly="1"/>
         <field name="mapping_id" />
         <field name="file_id" />
-        <field name="referential_id"/>
+        <field name="referential_id" readonly="1"/>
         <field name="shop_id"/>
         <field name="job_ended" />
         <field name="active"/>
-        <button name="run" string="Run" colspan="2" type="object" />
+        <field name="direction" readonly="1" />
+        <newline />
+        <button name="run" string="Run" colspan="2" type="object" attrs="{'invisible':[('state','in', ('running','done'))]}"/>
+        <newline />
+        <button name="check_state" string="Check state" colspan="2" type="object" attrs="{'invisible':[('state','!=', 'running')]}"/>
+        <newline />
+        <separator string="External application response (for output direction)" colspan="4"/>
+        <field name="response" nolabel="1" readonly="1" colspan="4" />
     </form>
     </field>
 </record>
 
+<!-- TREE -->
 <record id="file_buffer_view_tree" model="ir.ui.view">
     <field name="name">file_buffer.file_buffer.view_tree</field>
     <field name="model">file.buffer</field>
@@ -54,6 +71,7 @@
             <field name="mapping_id" />
             <field name="file_id" />
             <field name="job_ended" />
+            <field name="direction" string="direct." />
             <field name="referential_id" string="ex ref"/>
             <button name="run" string="Run" icon="gtk-go-forward" type="object"/>
         </tree>

=== added file 'base_external_file_protocole/settings/external.referential.type.csv'
--- base_external_file_protocole/settings/external.referential.type.csv	1970-01-01 00:00:00 +0000
+++ base_external_file_protocole/settings/external.referential.type.csv	2012-11-19 23:44:21 +0000
@@ -0,0 +1,4 @@
+id,name,categ_id:id,code
+t-sftp,SFTP,file-protocole,sftp
+t-ftp,FTP,file-protocole,ftp
+t-filesystem,File System,file-protocole,filesystem

=== added file 'base_external_file_protocole/settings/external.referential.version.csv'
--- base_external_file_protocole/settings/external.referential.version.csv	1970-01-01 00:00:00 +0000
+++ base_external_file_protocole/settings/external.referential.version.csv	2012-11-19 23:44:21 +0000
@@ -0,0 +1,4 @@
+type_id:id,id,name,code
+t-sftp,v-stfp,.,.
+t-ftp,v-ftp,.,.
+t-filesystem,v-filesystem,.,.

=== modified file 'base_external_referentials/__openerp__.py'
--- base_external_referentials/__openerp__.py	2012-03-30 13:07:11 +0000
+++ base_external_referentials/__openerp__.py	2012-11-19 23:44:21 +0000
@@ -1,7 +1,7 @@
 # -*- encoding: utf-8 -*-
 ##############################################################################
 #
-#    OpenERP, Open Source Management Solution    
+#    OpenERP, Open Source Management Solution
 #    Copyright (C) 2009 Akretion (<http://www.akretion.com>). All Rights Reserved
 #    authors: Raphaël Valyi, Sharoon Thomas
 #
@@ -48,7 +48,7 @@
     """,
     'author': 'Raphaël Valyi (Akretion.com), Sharoon Thomas (Openlabs.co.in)',
     'website': 'http://www.akretion.com, http://openlabs.co.in/',
-    'depends': ['base','base_pop_up'],
+    'depends': ['base','base_pop_up', 'base_file_protocole', 'email_template'],
     'init_xml': [],
     'update_xml': [
         'external_referentials_view.xml',
@@ -57,6 +57,7 @@
         'security/ir.model.access.csv',
         'group_fields_view.xml',
         'security/base_external_referentials_security.xml',
+        'report_mail_template.xml',
     ],
     'demo_xml': [],
     'installable': True,

=== modified file 'base_external_referentials/decorator.py'
--- base_external_referentials/decorator.py	2012-08-21 07:39:24 +0000
+++ base_external_referentials/decorator.py	2012-11-19 23:44:21 +0000
@@ -19,7 +19,7 @@
 #                                                                             #
 ###############################################################################
 
-from osv import osv
+from openerp.osv.osv import except_osv
 import pooler
 from tools.translate import _
 from message_error import MappingError
@@ -61,7 +61,7 @@
                             original_func = class_func.__dict__.get("_original_func_before_wrap")
                             if original_func is func:
                                 use_next_class = True
-                    raise osv.except_osv(_("Not Implemented"), _("Not parent method found"))
+                    raise except_osv(_("Not Implemented"), _("Not parent method found"))
         wrapped._original_func_before_wrap = func
         return wrapped
     return decorator
@@ -75,7 +75,7 @@
     @functools.wraps(func)
     def wrapper(self, cr, uid, external_session, *args, **kwargs):
         #if not self._columns.get('referential_id'):
-        #    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,)))
+        #    raise except_osv(_("Not Implemented"), _("The field referential_id doesn't exist on the object %s. Reporting system can not be used" %(self._name,)))
 
         report_obj = self.pool.get('external.report')
         context = kwargs.get('context')
@@ -109,7 +109,7 @@
             external_session.logger.debug(_("There is no key report_id in the context, error will be not catch"))
             return func(self, cr, uid, external_session, resource, *args, **kwargs)
         if context.get('report_line_based_on'):
-            if context is None['report_line_based_on'] == self._name:
+            if not context['report_line_based_on'] == self._name:
                 return func(self, cr, uid, external_session, resource, *args, **kwargs)
         report_line_obj = self.pool.get('external.report.line')
         report_line_id = report_line_obj.start_log(
@@ -138,7 +138,7 @@
             import_cr.rollback()
             error_message = 'Error with xmlrpc protocole. Error details : error %s : %s'%(e.faultCode, e.faultString)
             report_line_obj.log_fail(cr, uid, external_session, report_line_id, error_message, context=context)
-        except osv.except_osv as e:
+        except except_osv as e:
             if config['debug_mode']: raise
             import_cr.rollback()
             error_message = '%s : %s'%(e.name, e.value)
@@ -157,10 +157,10 @@
         return response
     return wrapper
 
-#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)
+#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)
 def catch_action(func):
     """ This decorator open and close a new cursor and if an error occure it will generate a error line in the reporting system
-    The function must start with "self, cr, uid, object"
+    The function must start with "self, cr, uid, object_id"
     And the object must have a field call "referential_id" related to the object "external.referential"
     """
     @functools.wraps(func)
@@ -190,7 +190,7 @@
             import_cr.rollback()
             error_message = 'Error with xmlrpc protocole. Error details : error %s : %s'%(e.faultCode, e.faultString)
             report_line_obj.log_fail(cr, uid, None, report_line_id, error_message, context=context)
-        except osv.except_osv as e:
+        except except_osv as e:
             if config['debug_mode']: raise
             import_cr.rollback()
             error_message = '%s : %s'%(e.name, e.value)

=== modified file 'base_external_referentials/external_osv.py'
--- base_external_referentials/external_osv.py	2012-08-23 17:04:44 +0000
+++ base_external_referentials/external_osv.py	2012-11-19 23:44:21 +0000
@@ -21,14 +21,14 @@
 #
 ##############################################################################
 
-from osv import fields, osv
+from openerp.osv.orm import Model
+from openerp.osv.osv import except_osv
 import base64
+import urllib
 import time
 import netsvc
 from datetime import datetime
 import logging
-import pooler
-from collections import defaultdict
 from lxml import objectify
 from openerp.tools.config import config
 
@@ -45,16 +45,16 @@
 def extend(class_to_extend):
     """
     Decorator to use to extend a existing class with a new method
-    Example : 
-    @extend(osv.osv)
+    Example :
+    @extend(Model)
     def new_method(self, *args, **kwargs):
         print 'I am in the new_method', self._name
         return True
-    Will add the method new_method to the class osv.osv
+    Will add the method new_method to the class Model
     """
     def decorator(func):
         if hasattr(class_to_extend, func.func_name):
-            raise osv.except_osv(_("Developper Error"),
+            raise except_osv(_("Developper Error"),
                 _("You can extend the class %s with the method %s.",
                 "Indeed this method already exist use the decorator 'replace' instead"))
         setattr(class_to_extend, func.func_name, func)
@@ -64,33 +64,33 @@
 def override(class_to_extend, prefix):
     """
     Decorator for overiding an existing method in a class
-    
+
     Example of use:
-    
-    @override(osv.osv, 'magento_')
+
+    @override(Model, 'magento_')
     def write(self, *args, **kwargs):
         print 'I am in the write overwrited 1', self._name
-        return osv.osv.magento_write(self, *args, **kwargs)
+        return Model.magento_write(self, *args, **kwargs)
 
-    @override(osv.osv, 'amazon_')
+    @override(Model, 'amazon_')
     def write(self, *args, **kwargs):
         print 'I am in the write overwrited 2', self._name
-        return osv.osv.amazon_write(self, *args, **kwargs)
+        return Model.amazon_write(self, *args, **kwargs)
 
-    @override(osv.osv, 'ebay_')
+    @override(Model, 'ebay_')
     def write(self, *args, **kwargs):
         print 'I am in the write overwrited 3', self._name
-        return osv.osv.ebay_write(self, *args, **kwargs)
+        return Model.ebay_write(self, *args, **kwargs)
 
     """
     def decorator(func):
         if not hasattr(class_to_extend, func.func_name):
-            raise osv.except_osv(_("Developper Error"),
+            raise except_osv(_("Developper Error"),
                 _("You can replace the method %s of the class %s. "
                 "Indeed this method doesn't exist")%(func.func_name, class_to_extend))
         original_function_name = prefix + func.func_name
         if hasattr(class_to_extend, original_function_name):
-            raise osv.except_osv(_("Developper Error"),
+            raise except_osv(_("Developper Error"),
                 _("The method %s already exist. "
                 "Please change the prefix name")%original_function_name)
         setattr(class_to_extend, original_function_name, getattr(class_to_extend, func.func_name))
@@ -102,7 +102,7 @@
 class ExternalSession(object):
     def __init__(self, referential, sync_from_object=None):
         """External Session in an object to store the information about a connection with an
-        extenal system, like Magento, Prestashop, Ebay, ftp....
+        external system, like Magento, Prestashop, Ebay, ftp....
         This class have for fields
         - referential_id : a many2one related to the referential used for this connection
         - sync_from_object : a many2one related to the object that launch the synchronization
@@ -130,7 +130,7 @@
     """Resource class in a container for using other class like objectify as a dictionnary
     The implemented dict fonctionality are "get", "__getitem__", "keys"
     The original object is store in the data field
-    
+
     Example :
       resource = Resource(objectify_resource)
       my_keys = resource.keys()
@@ -168,7 +168,7 @@
 #
 ########################################################################################################################
 
-@extend(osv.osv)
+@extend(Model)
 def read_w_order(self, cr, uid, ids, fields_to_read=None, context=None, load='_classic_read'):
     """Read records with given ids with the given fields and return it respecting the order of the ids
     This is very usefull for synchronizing data in a special order with an external system
@@ -185,7 +185,7 @@
         resultat += [x for x in res if x['id'] == id]
     return resultat
 
-@extend(osv.osv)
+@extend(Model)
 def browse_w_order(self, cr, uid, ids, context=None, list_class=None, fields_process={}):
     """Fetch records as objects and return it respecting the order of the ids
     This is very usefull for synchronizing data in a special order with an external system
@@ -201,7 +201,7 @@
         resultat += [x for x in res if x.id == id]
     return resultat
 
-@extend(osv.osv)
+@extend(Model)
 def prefixed_id(self, id):
     """Return the prefixed_id for an id given
     :param str or int id: external id
@@ -212,10 +212,10 @@
     #is to avoid unique ir_model_data#name per module constraint violation.
     return self._name.replace('.', '_') + '/' + str(id)
 
-@extend(osv.osv)
+@extend(Model)
 def id_from_prefixed_id(self, prefixed_id):
     """Return the external id extracted from an prefixed_id
-    
+
     :param str prefixed_id: prefixed_id to process
     :rtype int/str
     :return the id extracted
@@ -226,7 +226,7 @@
     else:
         return res
 
-@extend(osv.osv)
+@extend(Model)
 def get_all_extid_from_referential(self, cr, uid, referential_id, context=None):
     """Returns the external ids of the ressource which have an ext_id in the referential
     :param int referential_id : id of the external referential
@@ -243,21 +243,21 @@
         return []
     return [int(oeid_to_extid[oe_id]) for oe_id in self.exists(cr, uid, oeid_to_extid.keys(), context=context)]
 
-@extend(osv.osv)
+@extend(Model)
 def get_all_oeid_from_referential(self, cr, uid, referential_id, context=None):
     """Returns the openerp ids of the ressource which have an ext_id in the referential
     :param int referential_id : id of the external referential
     :rtype: list
     :return: the list of all of the openerp ids which have an ext_id in the referential specified
     """
-    
+
     ir_model_data_obj = self.pool.get('ir.model.data')
     model_data_ids = ir_model_data_obj.search(cr, uid, [('model', '=', self._name), ('referential_id', '=', referential_id)])
     #because OpenERP might keep ir_model_data (is it a bug?) for deleted records, we check if record exists:
     claimed_oe_ids = [x['res_id'] for x in ir_model_data_obj.read(cr, uid, model_data_ids, ['res_id'], context=context)]
     return claimed_oe_ids and self.exists(cr, uid, claimed_oe_ids, context=context) or []
 
-@extend(osv.osv)
+@extend(Model)
 def get_or_create_extid(self, cr, uid, external_session, openerp_id, context=None):
     """Returns the external id of a resource by its OpenERP id.
     If not external id have been found, the resource will be automatically exported
@@ -272,14 +272,12 @@
     else:
         return self._export_one_resource(cr, uid, external_session, openerp_id, context=context)
 
-@extend(osv.osv)
+@extend(Model)
 def get_extid(self, cr, uid, openerp_id, referential_id, context=None):
     """Returns the external id of a resource by its OpenERP id.
-    Return False If not external id have been found
     :param int openerp_id : openerp id of the resource
-    :param int referential_id : referential id 
-    :return: the external id of the resource or False if not exist
-    :rtype: int 
+    :param int referential_id : referential id
+    :rtype: int
     """
     if isinstance(openerp_id, list):
         openerp_id = openerp_id[0]
@@ -291,17 +289,17 @@
     return False
 
 #TODO Deprecated remove for V7 version
-@extend(osv.osv)
+@extend(Model)
 def oeid_to_existing_extid(self, cr, uid, referential_id, openerp_id, context=None):
     """Returns the external id of a resource by its OpenERP id.
     Returns False if the resource id does not exists."""
     return self.get_extid(cr, uid, openerp_id, referential_id, context=context)
 
-osv.osv.oeid_to_extid = osv.osv.get_or_create_extid
+Model.oeid_to_extid = Model.get_or_create_extid
 ############## END OF DEPRECATED
 
 
-@extend(osv.osv)
+@extend(Model)
 def _get_expected_oeid(self, cr, uid, external_id, referential_id, context=None):
     """Returns the id of the entry in ir.model.data and the expected id of the resource in the current model
     Warning the expected_oe_id may not exists in the model, that's the res_id registered in ir.model.data
@@ -322,13 +320,13 @@
         expected_oe_id = model_data_obj.read(cr, uid, model_data_id, ['res_id'])['res_id']
     return model_data_id, expected_oe_id
 
-@extend(osv.osv)
+@extend(Model)
 def get_oeid(self, cr, uid, external_id, referential_id, context=None):
     """Returns the OpenERP id of a resource by its external id.
     Returns False if the resource does not exist.
-    
+
     :param int/str external_id : external id of the resource
-    :param int referential_id : referential id 
+    :param int referential_id : referential id
     :return: the openerp id of the resource or False if not exist
     :rtype: int
        """
@@ -342,11 +340,11 @@
             return expected_oe_id
     return False
 
-@extend(osv.osv)
+@extend(Model)
 def get_or_create_oeid(self, cr, uid, external_session, external_id, context=None):
     """Returns the OpenERP ID of a resource by its external id.
     Creates the resource from the external connection if the resource does not exist.
-    
+
     :param ExternalSession external_session : External_session that contain all params of connection
     :param int/str external_id : external id of the resource
     :return: the openerp id of the resource
@@ -360,14 +358,14 @@
     return False
 
 #TODO Deprecated remove for V7 version
-@extend(osv.osv)
+@extend(Model)
 def extid_to_existing_oeid(self, cr, uid, referential_id, external_id, context=None):
     """Returns the OpenERP id of a resource by its external id.
        Returns False if the resource does not exist."""
     res = self.get_oeid(cr, uid, external_id, referential_id, context=context)
     return res
 
-osv.osv.extid_to_oeid = osv.osv.get_or_create_oeid
+Model.extid_to_oeid = Model.get_or_create_oeid
 ############## END OF DEPRECATED
 
 
@@ -388,7 +386,7 @@
 ########################################################################################################################
 
 
-@extend(osv.osv)
+@extend(Model)
 def _get_filter(self, cr, uid, external_session, step, previous_filter=None, context=None):
     """Abstract function that return the filter
     Can be overwriten in your module
@@ -401,7 +399,7 @@
     """
     return None
 
-@extend(osv.osv)
+@extend(Model)
 def _get_external_resource_ids(self, cr, uid, external_session, resource_filter=None, mapping=None, context=None):
     """Abstract function that return the external resource ids
     Can be overwriten in your module
@@ -412,9 +410,9 @@
     :rtype: list
     :return: a list of external_id
     """
-    raise osv.except_osv(_("Not Implemented"), _("The method _get_external_resource_ids is not implemented in abstract base module!"))
+    raise except_osv(_("Not Implemented"), _("The method _get_external_resource_ids is not implemented in abstract base module!"))
 
-@extend(osv.osv)
+@extend(Model)
 def _get_default_import_values(self, cr, uid, external_session, mapping_id=None, defaults=None, context=None):
     """Abstract function that return the default value for on object
     Can be overwriten in your module
@@ -426,7 +424,7 @@
     """
     return defaults
 
-@extend(osv.osv)
+@extend(Model)
 def _get_import_step(self, cr, uid, external_session, context=None):
     """Abstract function that return the step for importing data
     Can be overwriten in your module
@@ -437,7 +435,7 @@
     """
     return 100
 
-@extend(osv.osv)
+@extend(Model)
 def _get_external_resources(self, cr, uid, external_session, external_id=None, resource_filter=None, mapping=None, fields=None, context=None):
     """Abstract function that return the external resource
     Can be overwriten in your module
@@ -456,7 +454,7 @@
 
     return getattr(external_session.connection, mapping[mapping_id]['external_get_method'])(mapping[mapping_id]['external_resource_name'], resource_filter)
 
-@extend(osv.osv)
+@extend(Model)
 def _get_mapping_id(self, cr, uid, referential_id, context=None):
     """Function that return the mapping id for the corresponding object
 
@@ -464,11 +462,14 @@
     :rtype integer
     :return the id of the mapping
     """
-    mapping_id = self.pool.get('external.mapping').search(cr, uid, [('model', '=', self._name), ('referential_id', '=', referential_id)], context=context)
+    mapping_id = self.pool.get('external.mapping').search(cr, uid, [('model', '=', self._name),
+                                                                    ('referential_id', '=', referential_id)],
+                                                          context=context)
     return mapping_id and mapping_id[0] or False
 
-@extend(osv.osv)
-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):
+@extend(Model)
+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):
     """Function to initialise mapping
     :param int referential_id: the referential id
     :param str convertion_type: the type of convertion 'from_external_to_openerp' or 'from_openerp_to_external'
@@ -483,11 +484,16 @@
     if not mapping_id:
         mapping_id = self._get_mapping_id(cr, uid, referential_id, context=context)
     if not mapping.get(mapping_id):
-        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)
+        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)
     return mapping, mapping_id
 
-@extend(osv.osv)
-def _get_mapping(self, cr, uid, referential_id, convertion_type='from_external_to_openerp', mapping_line_filter_ids=None, mapping_id=None, context=None):
+@extend(Model)
+def _get_mapping(self, cr, uid, referential_id, convertion_type='from_external_to_openerp',
+                 mapping_line_filter_ids=None, mapping_id=None, context=None):
     """Function that return the mapping line for the corresponding object
 
     :param  int referential_id: the referential id
@@ -500,7 +506,8 @@
     if not mapping_id:
         mapping_id = self._get_mapping_id(cr, uid, referential_id, context=context)
     if not mapping_id:
-        raise osv.except_osv(_('External Import Error'), _("The object %s doesn't have an external mapping" %self._name))
+        raise except_osv(_('External Import Error'),
+                         _("The object %s doesn't have an external mapping" % self._name))
     else:
         #If a mapping exists for current model, search for mapping lines
 
@@ -508,7 +515,9 @@
         mapping_line_filter = [('mapping_id', '=', mapping_id),
                             ('type', 'in', ['in_out', mapping_type])]
         if mapping_line_filter_ids:
-            mapping_line_filter += ['|', ('id', 'in', mapping_line_filter_ids), ('evaluation_type', '=', 'sub-mapping')]
+            mapping_line_filter += ['|',
+                                    ('id', 'in', mapping_line_filter_ids),
+                                    ('evaluation_type', '=', 'sub-mapping')]
         mapping_line_ids = self.pool.get('external.mapping.line').search(cr, uid, mapping_line_filter, context=context)
         if mapping_line_ids:
             mapping_lines = self.pool.get('external.mapping.line').read(cr, uid, mapping_line_ids, [], context=context)
@@ -521,7 +530,7 @@
         res['mapping_lines'] = mapping_lines
         return res
 
-@extend(osv.osv)
+@extend(Model)
 def import_resources(self, cr, uid, ids, resource_name, method="search_then_read", context=None):
     """Abstract function to import resources from a shop / a referential...
 
@@ -542,7 +551,8 @@
                 context['%s_id'%browse_record._name.replace('.', '_')] = browse_record.id
                 external_session = ExternalSession(browse_record.referential_id, browse_record)
             else:
-                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,)))
+                raise except_osv(_("Not Implemented"),
+                                     _("The field referential_id doesn't exist on the object %s. Reporting system can not be used") % (browse_record._name,))
         defaults = self.pool.get(resource_name)._get_default_import_values(cr, uid, external_session, context=context)
         res = self.pool.get(resource_name)._import_resources(cr, uid, external_session, defaults, method=method, context=context)
         for key in result:
@@ -550,7 +560,7 @@
     return result
 
 
-@extend(osv.osv)
+@extend(Model)
 def _import_resources(self, cr, uid, external_session, defaults=None, method="search_then_read", context=None):
     """Abstract function to import resources form a specific object (like shop, referential...)
 
@@ -592,11 +602,12 @@
             for ext_id in ext_ids:
                 #TODO import only the field needed to improve speed import ;)
                 resources = self._get_external_resources(cr, uid, external_session, ext_id, mapping=mapping, fields=None, context=context)
-                if not isinstance(resources, list):
-                    resources = [resources]
-                res = self._record_external_resources(cr, uid, external_session, resources, defaults=defaults, mapping=mapping, mapping_id=mapping_id, context=context)
-                for key in result:
-                    result[key].append(res.get(key, []))
+                if resources:
+                    if not isinstance(resources, list):
+                        resources = [resources]
+                    res = self._record_external_resources(cr, uid, external_session, resources, defaults=defaults, mapping=mapping, mapping_id=mapping_id, context=context)
+                    for key in result:
+                        result[key].append(res.get(key, []))
         elif method == 'search_read':
             while True:
                 resource_filter = self._get_filter(cr, uid, external_session, step, previous_filter=resource_filter, context=context)
@@ -614,14 +625,15 @@
             resource_filter = self._get_filter(cr, uid, external_session, step, previous_filter=resource_filter, context=context)
             #TODO import only the field needed to improve speed import ;)
             resources = self._get_external_resources(cr, uid, external_session, resource_filter=resource_filter, mapping=mapping, fields=None, context=context)
-            if not isinstance(resources, list):
-                resources = [resources]
-            res = self._record_external_resources(cr, uid, external_session, resources, defaults=defaults, mapping=mapping, mapping_id=mapping_id, context=context)
-            for key in result:
-                result[key].append(res.get(key, []))
+            if resources:
+                if not isinstance(resources, list):
+                    resources = [resources]
+                res = self._record_external_resources(cr, uid, external_session, resources, defaults=defaults, mapping=mapping, mapping_id=mapping_id, context=context)
+                for key in result:
+                    result[key].append(res.get(key, []))
     return result
 
-@extend(osv.osv)
+@extend(Model)
 def _import_one_resource(self, cr, uid, external_session, external_id, context=None):
     """Abstract function to import one resource
 
@@ -639,7 +651,7 @@
         id = res.get('write_id') or res.get('create_id')
     return id
 
-@extend(osv.osv)
+@extend(Model)
 def _record_external_resources(self, cr, uid, external_session, resources, defaults=None, mapping=None, mapping_id=None, context=None):
     """Abstract function to record external resources (this will convert the data and create/update the object in openerp)
 
@@ -651,6 +663,7 @@
     :rtype: dict
     :return: dictionary with the key "create_ids" and "write_ids" which containt the id created/written
     """
+    if context is None: context = {}
     result = {'write_ids': [], 'create_ids': []}
     mapping, mapping_id = self._init_mapping(cr, uid, external_session.referential_id.id, mapping=mapping, mapping_id=mapping_id, context=context)
     if mapping[mapping_id]['key_for_external_id']:
@@ -667,7 +680,7 @@
             if res.get('write_id'): result['write_ids'].append(res['write_id'])
     return result
 
-@extend(osv.osv)
+@extend(Model)
 def _record_one_external_resource(self, cr, uid, external_session, resource, defaults=None, mapping=None, mapping_id=None, context=None):
     """Used in _record_external_resources
     The resource will converted into OpenERP data by using the function _transform_external_resources
@@ -742,10 +755,10 @@
         return {'write_id' : existing_rec_id}
     return {}
 
-@extend(osv.osv)
+@extend(Model)
 def oe_update(self, cr, uid, external_session, existing_rec_id, vals, resource, defaults, context=None):
     """Update an existing resource in OpenERP
-    
+
     :param ExternalSession external_session : External_session that contain all params of connection
     :param int existing_rec_id: openerp id to update
     :param dict vals: vals to write
@@ -758,10 +771,10 @@
     context['referential_id'] = external_session.referential_id.id #did it's needed somewhere?
     return self.write(cr, uid, existing_rec_id, vals, context)
 
-@extend(osv.osv)
+@extend(Model)
 def oe_create(self, cr, uid, external_session, vals, resource, defaults, context=None):
     """Create an new resource in OpenERP
-    
+
     :param ExternalSession external_session : External_session that contain all params of connection
     :param dict vals: vals to create
     :param dict resource: resource to convert into OpenERP data
@@ -788,7 +801,7 @@
 #
 ########################################################################################################################
 
-@extend(osv.osv)
+@extend(Model)
 def _get_export_step(self, cr, uid, external_session, context=None):
     """Abstract function that return the step for importing data
     Can be overwriten in your module
@@ -799,7 +812,7 @@
     """
     return 10
 
-@extend(osv.osv)
+@extend(Model)
 def _get_default_export_values(self, cr, uid, external_session, mapping_id=None, defaults=None, context=None):
     """Abstract function that return the default value for on object
     Can be overwriten in your module
@@ -812,7 +825,7 @@
     """
     return defaults
 
-@extend(osv.osv)
+@extend(Model)
 def _get_last_exported_date(self, cr, uid, external_session, context=None):
     """Abstract function that return the last export date for on object
     Can be overwriten in your module
@@ -823,7 +836,7 @@
     """
     return False
 
-@extend(osv.osv)
+@extend(Model)
 def _set_last_exported_date(self, cr, uid, external_session, date, context=None):
     """Abstract function that update the last exported date
     Can be overwriten in your module
@@ -836,7 +849,7 @@
     return True
 
 #For now it's just support 1 level of inherit TODO make it recursive
-@extend(osv.osv)
+@extend(Model)
 def _get_query_and_params_for_ids_and_date(self, cr, uid, external_session, ids=None, last_exported_date=None, context=None):
     """Function that build the sql query for getting the ids and the udpate date of each record
 
@@ -899,7 +912,7 @@
     query += " order by update_date asc;"
     return query, params
 
-@extend(osv.osv)
+@extend(Model)
 def get_ids_and_update_date(self, cr, uid, external_session, ids=None, last_exported_date=None, context=None):
     """This function will return the list of ids and the update date of each record_dicts
 
@@ -909,6 +922,8 @@
     :rtype: tuple
     :return: an tuple of ids and ids_2_dates (dict with key => 'id' and val => 'last_update_date')
     """
+    if ids in [[], ()]:
+        return [], {}
     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)
     cr.execute(query, params)
     read = cr.dictfetchall()
@@ -921,13 +936,13 @@
 
 
 #Deprecated
-@extend(osv.osv)
+@extend(Model)
 def init_context_before_exporting_resource(self, cr, uid, external_session, object_id, resource_name, context=None):
     if self._name != 'external.referential' and 'referential_id' in self._columns.keys():
         context['%s_id'%self._name.replace('.', '_')] = object_id
     return context
 
-@extend(osv.osv)
+@extend(Model)
 def export_resources(self, cr, uid, ids, resource_name, context=None):
     """
     Abstract function to export resources from a shop / a referential...
@@ -944,7 +959,7 @@
             if hasattr(browse_record, 'referential_id'):
                 external_session = ExternalSession(browse_record.referential_id, browse_record)
             else:
-                raise osv.except_osv(_("Not Implemented"), _("The field referential_id doesn't exist on the object %s." %(browse_record._name,)))
+                raise except_osv(_("Not Implemented"), _("The field referential_id doesn't exist on the object %s." %(browse_record._name,)))
         context = self.init_context_before_exporting_resource(cr, uid, external_session, browse_record.id, resource_name, context=context)
         self.pool.get(resource_name)._export_resources(cr, uid, external_session, context=context)
     return True
@@ -952,7 +967,7 @@
 
 #TODO refactor update date,maybe it will be better to have an update date per resource
 #TODO deal correctly with multi resource
-@extend(osv.osv)
+@extend(Model)
 def send_to_external(self, cr, uid, external_session, resources, mapping, mapping_id, update_date=None, context=None):
     """Generic method that send the resource to an external referential
 
@@ -982,7 +997,7 @@
         self._set_last_exported_date(cr, uid, external_session, update_date, context=context)
     return ext_id
 
-@extend(osv.osv)
+@extend(Model)
 def ext_create(self, cr, uid, external_session, resources, mapping=None, mapping_id=None, context=None):
     res = {}
     mapping, mapping_id = self._init_mapping(cr, uid, external_session.referential_id.id, mapping=mapping, mapping_id=mapping_id, context=context)
@@ -991,12 +1006,12 @@
         res[resource_id] = getattr(external_session.connection, mapping[mapping_id]['external_create_method'])(mapping[mapping_id]['external_resource_name'], resource[resource.keys()[0]])
     return res
 
-@extend(osv.osv)
+@extend(Model)
 def ext_update(self, cr, uid, external_session, resources, mapping=None, mapping_id=None, context=None):
     """Not Implemented here"""
     return False
 
-@extend(osv.osv)
+@extend(Model)
 def ext_unlink(self, cr, uid, ids, context=None):
     ir_model_obj = self.pool.get('ir.model.data')
     for object_id in ids:
@@ -1011,24 +1026,24 @@
             ir_model.unlink()
     return True
 
-@extend(osv.osv)
+@extend(Model)
 def get_lang_to_export(self, cr, uid, external_session, context=None):
     """Get the list of lang to export
-    
+
     :param ExternalSession external_session : External_session that contain all params of connection
     :rtype: list
     return: the list of lang to export
     """
-    
+
     if context is None:
         return []
     else:
         return context.get('lang_to_export') or [context.get('lang')]
 
-@extend(osv.osv)
+@extend(Model)
 def _export_resources(self, cr, uid, external_session, method="onebyone", context=None):
     """Export resource
-    
+
     :param ExternalSession external_session : External_session that contain all params of connection
     :param str method: method to export data (for now only onebyone)
     :rtype: boolean
@@ -1065,12 +1080,12 @@
                 external_session.logger.info("Start to transform and send the ressource %s : %s"%(self._name, resource_id))
                 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)
         else:
-            raise osv.except_osv(_('Developper Error'), _('only method export onebyone is implemented in base_external_referentials'))
+            raise except_osv(_('Developper Error'), _('only method export onebyone is implemented in base_external_referentials'))
     #now = datetime.now().strftime(DEFAULT_SERVER_DATETIME_FORMAT)
     #self._set_last_exported_date(cr, uid, external_session, now, context=context)
     return True
 
-@extend(osv.osv)
+@extend(Model)
 def _transform_and_send_one_resource(self, cr, uid, external_session, resource, resource_id,
                             update_date, mapping, mapping_id, defaults=None, context=None):
     """Transform and send one resource
@@ -1093,7 +1108,7 @@
                                             defaults=defaults, context=context)
     return self.send_to_external(cr, uid, external_session, {resource_id : resource}, mapping, mapping_id, update_date, context=context)
 
-@extend(osv.osv)
+@extend(Model)
 def _export_one_resource(self, cr, uid, external_session, resource_id, context=None):
     """Export one resource
     Export an OpenERP resource into an external system
@@ -1115,7 +1130,7 @@
 
 #TODO finish docstring
 
-@extend(osv.osv)
+@extend(Model)
 def get_translatable_fields(self, cr, uid, fields, context=None):
     #TODO make fields parameter optionnal
     def is_translatable(field):
@@ -1132,7 +1147,7 @@
             untranslatable_fields.append(field)
     return translatable_fields, untranslatable_fields
 
-@extend(osv.osv)
+@extend(Model)
 def multi_lang_read(self, cr, uid, external_session, ids, fields_to_read, langs, resources=None, use_multi_lang = True, context=None):
     if not resources:
         resources = {}
@@ -1150,20 +1165,28 @@
             if not first and lang_support == 'fields_with_main_lang' or lang_support == 'fields_with_no_lang':
                 fields = translatable_fields
             ctx['lang'] = lang
+<<<<<<< TREE
             
         if fields:
             for resource in self.read(cr, uid, ids, fields, context=ctx):
                 if not resources.get(resource['id']): resources[resource['id']] = {}
                 resources[resource['id']][lang] = resource
+=======
+
+        if fields:
+            for resource in self.read(cr, uid, ids, fields, context=ctx):
+                if not resources.get(resource['id']): resources[resource['id']] = {}
+                resources[resource['id']][lang] = resource
+>>>>>>> MERGE-SOURCE
         first = False
     return resources
 
-@extend(osv.osv)
+@extend(Model)
 def full_read(self, cr, uid, external_session, ids, langs, resources, mapping=None, mapping_id=None, context=None):
     fields_to_read = self.get_field_to_export(cr, uid, ids, mapping, mapping_id, context=context)
     return self.multi_lang_read(cr, uid, external_session, ids, fields_to_read, langs, resources=resources, context=context)
 
-@extend(osv.osv)
+@extend(Model)
 def smart_read(self, cr, uid, external_session, ids, langs, resources, group_ids, inherits_group_ids, last_exported_date=None,
                                                                         mapping=None, mapping_id=None, context=None):
     if last_exported_date:
@@ -1188,11 +1211,11 @@
             resources = self.multi_lang_read(cr, uid, external_session, resource_ids, fields_to_read, langs, resources=resources, context=context)
     return resources
 
-@extend(osv.osv)
+@extend(Model)
 def get_field_to_export(self, cr, uid, ids, mapping, mapping_id, context=None):
     return list(set(self._columns.keys() + self._inherit_fields.keys()))
 
-@extend(osv.osv)
+@extend(Model)
 def _get_oe_resources(self, cr, uid, external_session, ids, langs, smart_export=None,
                                             last_exported_date=None, mapping=None, mapping_id=None, context=None):
     resources = None
@@ -1204,7 +1227,7 @@
     return resources
 
 
-@extend(osv.osv)
+@extend(Model)
 def _get_oeid_from_extid_or_alternative_keys(self, cr, uid, vals, external_id, referential_id, alternative_keys, context=None):
     """
     Used in ext_import in order to search the OpenERP resource to update when importing an external resource.
@@ -1242,7 +1265,7 @@
             expected_res_id = expected_res_id and expected_res_id[0] or False
     return existing_ir_model_data_id, expected_res_id
 
-@extend(osv.osv)
+@extend(Model)
 def _prepare_external_id_vals(self, cr, uid, res_id, ext_id, referential_id, context=None):
     """ Create an external reference for a resource id in the ir.model.data table"""
     ir_model_data_vals = {
@@ -1255,9 +1278,16 @@
                           }
     return ir_model_data_vals
 
-@extend(osv.osv)
+@extend(Model)
 def create_external_id_vals(self, cr, uid, existing_rec_id, external_id, referential_id, context=None):
-    """Add the external id in the table ir_model_data"""
+    """
+    Add the external id in the table ir_model_data
+    :param id existing_rec_id: erp id object
+    :param id external_id: external application id
+    :param id referential_id: external id
+    :rtype: int
+    :return:
+    """
     ir_model_data_vals = \
     self._prepare_external_id_vals(cr, uid, existing_rec_id,
                                    external_id, referential_id,
@@ -1280,7 +1310,7 @@
 #
 ########################################################################################################################
 
-@extend(osv.osv)
+@extend(Model)
 def _transform_resources(self, cr, uid, external_session, convertion_type, resources, mapping=None, mapping_id=None,
                     mapping_line_filter_ids=None, parent_data=None, defaults=None, context=None):
     """
@@ -1294,7 +1324,12 @@
     """
     result= []
     if resources:
-        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)
+        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)
         if mapping[mapping_id].get("mapping_lines"):
             for resource in resources:
                 result.append(self._transform_one_resource(cr, uid, external_session, convertion_type, resource,
@@ -1302,7 +1337,7 @@
                                                             previous_result=result, defaults=defaults, context=context))
     return result
 
-@extend(osv.osv)
+@extend(Model)
 def _transform_one_resource(self, cr, uid, external_session, convertion_type, resource, mapping=None, mapping_id=None,
                     mapping_line_filter_ids=None, parent_data=None, previous_result=None, defaults=None, context=None):
     """
@@ -1327,7 +1362,12 @@
         defaults = {}
 
     referential_id = external_session.referential_id.id
-    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)
+    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)
 
     mapping_lines = mapping[mapping_id].get("mapping_lines")
     key_for_external_id = mapping[mapping_id].get("key_for_external_id")
@@ -1350,7 +1390,11 @@
                 sub_mapping_list.append(mapping_line)
             else:
                 if mapping_line['evaluation_type'] == 'direct':
-                    vals[to_field] = self._transform_field(cr, uid, external_session, convertion_type, field_value, mapping_line, context=context)
+                    vals[to_field] = self._transform_field(cr, uid, external_session,
+                                                           convertion_type,
+                                                           field_value,
+                                                           mapping_line,
+                                                           context=context)
                 else:
                     #Build the space for expr
                     #Seb : removing ifield can be great ?
@@ -1364,7 +1408,8 @@
                              'referential_id': external_session.referential_id.id,
                              'defaults': defaults,
                              'context': context,
-                             'ifield': self._transform_field(cr, uid, external_session, convertion_type, field_value, mapping_line, context=context),
+                             'ifield': self._transform_field(cr, uid, external_session, convertion_type,
+                                                             field_value, mapping_line, context=context),
                              'conn': context.get('conn_obj', False),
                              'base64': base64,
                              'vals': vals,
@@ -1400,18 +1445,25 @@
             ext_id = ext_id.isdigit() and int(ext_id) or ext_id
         vals.update({'external_id': ext_id})
     if self._name in context.get('do_not_update', []):
-        # 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.
+        # 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.
         alternative_keys = mapping[mapping_id]['alternative_keys']
         existing_ir_model_data_id, existing_rec_id = self._get_oeid_from_extid_or_alternative_keys\
             (cr, uid, vals, ext_id, referential_id, alternative_keys, context=context)
         if existing_rec_id:
             return {}
     vals = self._merge_with_default_values(cr, uid, external_session, resource, vals, sub_mapping_list, defaults=defaults, context=context)
-    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)
+    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)
 
     return vals
 
-@extend(osv.osv)
+@extend(Model)
 def _transform_field(self, cr, uid, external_session, convertion_type, field_value, mapping_line, context=None):
     field = False
     external_type = mapping_line['external_type']
@@ -1420,7 +1472,8 @@
     if not (field_value is False or field_value is None):
         if internal_type == 'many2one' and mapping_line['evaluation_type']=='direct':
             if external_type not in ['int', 'unicode']:
-                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'],))
+                raise except_osv(_('User Error'),
+                                 _('Wrong external type for mapping %s. One2Many object must have for external type string or integer') % (mapping_line['name'],))
             if self._columns.get(internal_field):
                 related_obj_name = self._columns[internal_field]._obj
             else:
@@ -1468,6 +1521,14 @@
             if not hasattr(casted_field, '__iter__'):
                 casted_field = (casted_field,)
             field = list(casted_field)
+        elif external_type == 'url' and internal_type == "binary":
+            (filename, header) = urllib.urlretrieve(field_value)
+            try:
+                f = open(filename , 'rb')
+                data = f.read()
+            finally:
+                f.close()
+            return base64.encodestring(data)
         else:
             if external_type == 'float' and isinstance(field_value, (str, unicode)):
                 field_value = field_value.replace(',','.')
@@ -1513,10 +1574,12 @@
 
     return field
 
-@extend(osv.osv)
+@extend(Model)
 def _merge_with_default_values(self, cr, uid, external_session, ressource, vals, sub_mapping_list, defaults=None, context=None):
     """
-    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
+    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
 
     @param sub_mapping_list: list of sub-mapping to apply
     @param external_data: list of data to convert into OpenERP data
@@ -1531,8 +1594,9 @@
             vals[key] = defaults[key]
     return vals
 
-@extend(osv.osv)
-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):
+@extend(Model)
+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):
     """
     Used in _transform_one_external_resource in order to call the sub mapping
 
@@ -1639,7 +1703,8 @@
                     transform_args[4] = sub_resource
                     vals[to_field] = sub_mapping_obj._transform_one_resource(*transform_args, **transform_kwargs)
             else:
-                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'],))
+                raise except_osv(_('User Error'),
+                                     _('Error with mapping : %s. Sub mapping can be only apply on one2many, many2one or many2many fields') % (sub_mapping['name'],))
     return vals
 
 
@@ -1648,7 +1713,3 @@
 #                                           END GENERIC TRANSFORM FEATURES
 #
 ########################################################################################################################
-
-
-
-

=== modified file 'base_external_referentials/external_referentials.py'
--- base_external_referentials/external_referentials.py	2012-08-10 08:06:40 +0000
+++ base_external_referentials/external_referentials.py	2012-11-19 23:44:21 +0000
@@ -20,15 +20,25 @@
 #
 ##############################################################################
 
-from osv import fields, osv
-from sets import Set
-from tools.translate import _
+from openerp.osv.orm import Model
+from openerp.osv import fields
 from tempfile import TemporaryFile
 from base_file_protocole.base_file_protocole import FileCsvWriter
-import time
-
-
-class external_referential_category(osv.osv):
+from lxml import etree
+from openerp.osv import orm
+
+
+REF_FIELDS = ['location', 'apiusername', 'apipass']
+#In your custom module you can specify which field will be visible
+#example for making visible the fields location, apiusername and apipass
+#for the referential type Magento :
+#from base_external_referentials.external_referentials import REF_VISIBLE_FIELDS
+#REF_VISIBLE_FIELDS['Magento'] = ['location', 'apiusername', 'apipass']
+
+REF_VISIBLE_FIELDS = {}
+
+
+class external_referential_category(Model):
     _name = 'external.referential.category'
     _description = 'External Referential Category (Ex: e-commerce, crm, warehouse)'
 
@@ -46,9 +56,7 @@
             categ_id = referential_categ.name.replace('.','_').replace(' ','_')
         return categ_id
 
-external_referential_category()
-
-class external_referential_type(osv.osv):
+class external_referential_type(Model):
     _name = 'external.referential.type'
     _description = 'External Referential Type (Ex.Magento,Spree)'
 
@@ -68,9 +76,8 @@
             type_id = referential_type.code.replace('.','_').replace(' ','_')
         return type_id
 
-external_referential_type()
 
-class external_referential_version(osv.osv):
+class external_referential_version(Model):
     _name = 'external.referential.version'
     _description = 'External Referential Version (Ex: v1.5.0.0 +, v1.3.2.4 +)'
     _rec_name = 'full_name'
@@ -97,9 +104,8 @@
         'code': fields.char('code', size=64, required=True),
     }
 
-external_referential_version()
 
-class external_mapping_template(osv.osv):
+class external_mapping_template(Model):
     _name = "external.mapping.template"
     _description = "The source mapping records"
     _rec_name = 'model'
@@ -119,9 +125,8 @@
         'external_resource_name':fields.char('External Resource Name', size=64),
         'extra_name': fields.char('Extra Name', size=100),
                 }
-external_mapping_template()
 
-class external_mappinglines_template(osv.osv):
+class external_mappinglines_template(Model):
     _name = 'external.mappinglines.template'
     _description = 'The source mapping line records'
     _rec_name = 'name'
@@ -144,7 +149,7 @@
         'external_field': fields.char('External Field', size=128),
         'type': fields.selection([('in_out', 'External <-> OpenERP'), ('in', 'External -> OpenERP'), ('out', 'External <- OpenERP')], 'Type'),
         'evaluation_type': fields.selection([('function', 'Function'), ('sub-mapping','Sub Mapping Line'), ('direct', 'Direct Mapping')], 'Evalution Type', required=True),
-        'external_type': fields.selection([('datetime', 'Datetime'), ('unicode', 'String'), ('bool', 'Boolean'), ('int', 'Integer'), ('float', 'Float'), ('list', 'List'), ('dict', 'Dictionnary')], 'External Type', required=True),
+        'external_type': fields.selection([('url', 'URL'), ('datetime', 'Datetime'), ('unicode', 'String'), ('bool', 'Boolean'), ('int', 'Integer'), ('float', 'Float'), ('list', 'List'), ('dict', 'Dictionnary')], 'External Type', required=True),
         'datetime_format': fields.char('Datetime Format', size=32),
         'in_function': fields.text('Import in OpenERP Mapping Python Function'),
         'out_function': fields.text('Export from OpenERP Mapping Python Function'),
@@ -160,10 +165,9 @@
         'function_name': fields.char('Function Name', size=128),
         }
 
-external_mappinglines_template()
 
-class external_referential(osv.osv):
-    """External referential can have the option _lang_support. It can be equal to : 
+class external_referential(Model):
+    """External referential can have the option _lang_support. It can be equal to :
             - 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}, ...}
             - 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} ...}
             - all_fields : all the fields are in all languagues. example = {'lang_one' : {all_fields}, 'lang_two': {all_fields}...}"""
@@ -175,6 +179,11 @@
     #Only user that can write crypted field can read it
     _crypted_field = ['apiusername', 'apipass', 'location']
 
+
+    def onchange_version_id(self, cr, uid, ids, version_id, context=None):
+        version = self.pool.get('external.referential.version').browse(cr, uid, version_id, context=context)
+        return {'value': {'type_name': version.type_id.name}}
+
     def read(self,cr, uid, ids, fields=None, context=None, load='_classic_read'):
         canwrite = self.check_write(cr, uid, raise_exception=False)
         res = super(external_referential, self).read(cr, uid, ids, fields=fields, context=context, load=load)
@@ -185,6 +194,39 @@
                         val[crypted_field]='********'
         return res
 
+
+    def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False, submenu=False):
+        """
+        Override the original field view get in order to insert dynamically the various fields need
+        for the configuration of the referential
+        """
+        # use lxml to compose the arch XML
+        result = super(external_referential, self).fields_view_get(cr, uid,
+                                                                    view_id=view_id,
+                                                                    view_type=view_type,
+                                                                    context=context,
+                                                                    toolbar=toolbar,
+                                                                    submenu=submenu,
+                                                                )
+        if view_type == 'form':
+            eview = etree.fromstring(result['arch'])
+            toupdate_fields = []
+            for field_name in REF_FIELDS:
+                field = eview.xpath("//field[@name='%s']"%field_name)
+                if field:
+                    field = field[0]
+                    referentials = []
+                    for ref_type, visible_fields in REF_VISIBLE_FIELDS.items():
+                        if field_name in visible_fields:
+                            referentials.append(ref_type)
+                    field.set('attrs', """{
+                                    'invisible': [('type_name', 'not in', %s)],
+                                    'required': [('type_name', 'in', %s)]
+                                        }"""%(referentials, referentials))
+                    orm.setup_modifiers(field, field=result['fields'][field_name], context=context)
+                    result['arch'] = etree.tostring(eview, pretty_print=True)
+        return result
+
     def external_connection(self, cr, uid, referential, debug=False, context=None):
         """Should be overridden to provide valid external referential connection"""
         return False
@@ -271,10 +313,12 @@
     _columns = {
         'name': fields.char('Name', size=32, required=True),
         'type_id': fields.related('version_id', 'type_id', type='many2one', relation='external.referential.type', string='External Type'),
+        'type_name': fields.related('type_id', 'name', type='char', string='External Type Name',
+                                    store=True),
         'categ_id': fields.related('type_id', 'categ_id', type='many2one', relation='external.referential.category', string='External Category'),
         'categ_name': fields.related('categ_id', 'name', type='char', string='External Category Name'),
         'version_id': fields.many2one('external.referential.version', 'Referential Version', required=True),
-        'location': fields.char('Location', size=200, required=True),
+        'location': fields.char('Location', size=200),
         'apiusername': fields.char('User Name', size=64),
         'apipass': fields.char('Password', size=64),
         'mapping_ids': fields.one2many('external.mapping', 'referential_id', 'Mappings'),
@@ -487,9 +531,8 @@
             referential_id = referential.name.replace('.','_').replace(' ','_')
         return referential_id
 
-external_referential()
 
-class external_mapping_line(osv.osv):
+class external_mapping_line(Model):
     _name = 'external.mapping.line'
     _description = 'Field Mapping'
     _rec_name = 'name'
@@ -509,10 +552,8 @@
         'name': fields.function(_name_get_fnc, type="char", string='Name', size=256),
     }
 
-external_mapping_line()
-
-
-class external_mapping(osv.osv):
+
+class external_mapping(Model):
     _name = 'external.mapping'
     _description = 'External Mapping'
     _rec_name = 'model'
@@ -621,15 +662,20 @@
         ('ref_template_uniq', 'unique (referential_id, template_id)', 'A referential can not have various mapping imported from the same template')
     ]
 
-external_mapping()
-
-
-class external_mapping_line(osv.osv):
+    def copy(self, cr, uid, id, default=None, context=None):
+        if default is None:
+            default = {}
+
+        default['template_id'] = False
+
+        return super(external_mapping, self).copy(cr, uid, id, default=default, context=context)
+
+class external_mapping_line(Model): # FIXME : tidy up this remnant of old OERP version
     _inherit = 'external.mapping.line'
 
     _columns = {
         'template_id': fields.many2one('external.mappinglines.template', 'External Mapping Lines Template'),
-        'referential_id': fields.related('mapping_id', 'referential_id', type='many2one', relation='external.referential', string='Referential'),
+        'referential_id': fields.related('mapping_id', 'referential_id', type='many2one', relation='external.referential', string='Referential', store=True),
         'field_id': fields.many2one('ir.model.fields', 'OpenERP Field', ondelete='cascade'),
         'internal_field': fields.related('field_id', 'name', type='char', relation='ir.model.field', string='Field name',readonly=True),
         'external_field': fields.char('External Field', size=128, help=("When importing flat csv file from file exchange,"
@@ -637,7 +683,7 @@
         'mapping_id': fields.many2one('external.mapping', 'External Mapping', ondelete='cascade'),
         'related_model_id': fields.related('mapping_id', 'model_id', type='many2one', relation='ir.model', string='Related Model'),
         'type': fields.selection([('in_out', 'External <-> OpenERP'), ('in', 'External -> OpenERP'), ('out', 'External <- OpenERP')], 'Type'),
-        'external_type': fields.selection([('datetime', 'Datetime'), ('unicode', 'String'), ('bool', 'Boolean'), ('int', 'Integer'), ('float', 'Float'), ('list', 'List'), ('dict', 'Dictionnary')], 'External Type', required=True),
+        'external_type': fields.selection([('url', 'URL'),('datetime', 'Datetime'), ('unicode', 'String'), ('bool', 'Boolean'), ('int', 'Integer'), ('float', 'Float'), ('list', 'List'), ('dict', 'Dictionnary')], 'External Type', required=True),
         'datetime_format': fields.char('Datetime Format', size=32),
         'evaluation_type': fields.selection([('function', 'Function'), ('sub-mapping','Sub Mapping Line'), ('direct', 'Direct Mapping')], 'Evalution Type', required=True),
         'in_function': fields.text('Import in OpenERP Mapping Python Function'),
@@ -689,9 +735,16 @@
             line_id = (version_code + '_' + mapping_name + '_' + line_name).replace('.','_')
         return line_id
 
-external_mapping_line()
-
-class ir_model_data(osv.osv):
+    def copy(self, cr, uid, id, default=None, context=None):
+        if default is None:
+            default = {}
+
+        default['template_id'] = False
+
+        return super(external_mapping_line, self).copy(cr, uid, id, default=default, context=context)
+
+
+class ir_model_data(Model):
     _inherit = "ir.model.data"
 
     def init(self, cr):
@@ -728,7 +781,6 @@
     }
 
     _sql_constraints = [
-        ('external_reference_uniq_per_object', 'unique(model, res_id, referential_id)', 'You cannot have on record with multiple external id for a sae referential'),
+        ('external_reference_uniq_per_object', 'unique(model, res_id, referential_id)', 'You cannot have on record with multiple external id for a same referential'),
     ]
 
-ir_model_data()

=== modified file 'base_external_referentials/external_referentials_menu.xml'
--- base_external_referentials/external_referentials_menu.xml	2012-07-20 15:13:11 +0000
+++ base_external_referentials/external_referentials_menu.xml	2012-11-19 23:44:21 +0000
@@ -16,8 +16,7 @@
             <field name="search_view_id" ref="external_referential_search_view"/>
         </record>
 
-        <menuitem id="menu_external_referential" name="External Referentials" parent="ir_ui_menu_external_referentials" />
-        <menuitem id="menu_all_external_referential" name="All Referentials" parent="menu_external_referential" action="act_window_external_referential" />
+        <menuitem id="menu_external_referential" name="External Referentials" parent="ir_ui_menu_external_referentials" action="act_window_external_referential"/>
         <!-- External Referentials Types -->
 
         <record id="ir_actions_act_window_external_type" model="ir.actions.act_window">

=== modified file 'base_external_referentials/external_referentials_view.xml'
--- base_external_referentials/external_referentials_view.xml	2012-06-27 14:27:22 +0000
+++ base_external_referentials/external_referentials_view.xml	2012-11-19 23:44:21 +0000
@@ -25,30 +25,27 @@
             <field name="type">form</field>
             <field name="arch" type="xml">
                 <form>
-                    <group col="4" colspan="4">
+                    <group col="6" colspan="4" name='name'>
+                        <separator string="Configuration" colspan="6"/>
                         <field name="name" attrs="{'readonly':[('create_date','!=',False)]}"/>
+                        <field name="version_id" on_change="onchange_version_id(version_id)"/>
+                        <field name="debug"/>
+                        <field name="location"/>
+                        <field name="apiusername"/>
+                        <field name="apipass"/>
                         <field name="create_date" invisible="True"/>
-                        <notebook colspan="4">
-                            <page string="General">
-                                <field name="version_id"/>
-                                <field name="location"/>
-                                <field name="categ_name" invisible="True"/>
-                            </page>
-                            <page string="Authentication">
-                                <field name="apiusername" />
-                                <field name="apipass" />
-                            <!-- TODO improve view -->
-                                <field name="debug" />
-                            </page>
-                        </notebook>
+                        <field name="categ_name" invisible="True"/>
+                        <field name="type_name" invisible="True" readonly="1"/>
                     </group>
                     <group col="4" colspan="4">
                         <separator string="Core Components" colspan="4" />
                         <notebook colspan="4">
                             <page string="Referential Actions">
-                                <separator string="Compulsory" colspan="4" />
-                                <button name="refresh_mapping" string="1 - Reload Referential Mapping Templates" colspan="2" type="object" />
-                                <button name="import_referentials" string="2 - Synchronize Referential Settings" colspan="2" type="object" attrs="{'readonly':[('mapping_ids','=',[])]}"/>
+                                <group name="compulsory" col="4" colspan="4">
+                                    <separator string="Compulsory" colspan="4" />
+                                    <button name="refresh_mapping" string="1 - Reload Referential Mapping Templates" colspan="2" type="object" />
+                                    <button name="import_referentials" string="2 - Synchronize Referential Settings" colspan="2" type="object" attrs="{'readonly':[('mapping_ids','=',[])]}"/>
+                                </group>
                             </page>
                             <page string="CSV file generation" groups="base_external_referentials.group_export_mapping" >
                                 <button name="build_external_ref_categ" string="1- Export category" colspan="1" type="object" />

=== modified file 'base_external_referentials/group_fields.py'
--- base_external_referentials/group_fields.py	2012-06-27 14:27:22 +0000
+++ base_external_referentials/group_fields.py	2012-11-19 23:44:21 +0000
@@ -19,11 +19,12 @@
 #                                                                             #
 ###############################################################################
 
-
-from osv import osv, fields
-
-
-class group_fields(osv.osv):
+from openerp.osv.orm import Model
+from openerp.osv import fields
+from openerp.osv.osv import except_osv
+from openerp.tools.translate import _
+
+class group_fields(Model):
     _name = 'group.fields'
     _description = 'trigger last write date by group of field'
 
@@ -64,10 +65,10 @@
 
     def write(self, cr, uid, ids, vals, context=None):
         if vals.get('column_name'):
-            raise osv.except_osv(_("User Error"), _("Changing Column name is not supported yet"))
+            raise except_osv(_("User Error"), _("Changing Column name is not supported yet"))
         return super(group_fields, self).write(cr, uid, ids, vals, context=context)
 
-class ir_model_fields(osv.osv):
+class ir_model_fields(Model):
     _inherit = "ir.model.fields"
 
     _columns = {

=== added file 'base_external_referentials/i18n/fr.po'
--- base_external_referentials/i18n/fr.po	1970-01-01 00:00:00 +0000
+++ base_external_referentials/i18n/fr.po	2012-11-19 23:44:21 +0000
@@ -0,0 +1,2334 @@
+# Translation of OpenERP Server.
+# This file contains the translation of the following modules:
+#	* base_external_referentials
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: OpenERP Server 6.1\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2012-10-24 13:11+0000\n"
+"PO-Revision-Date: 2012-10-24 13:11+0000\n"
+"Last-Translator: <Benoît Guillot>\n"
+"Language-Team: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: \n"
+
+#. module: base_external_referentials
+#: field:external.referential.type,code:0
+#: field:external.referential.version,code:0
+msgid "code"
+msgstr "code"
+
+#. module: base_external_referentials
+#: view:external.mapping.line:0
+msgid "Mapping line"
+msgstr "Ligne de mapping"
+
+#. module: base_external_referentials
+#: field:external.mapping.line,selected:0
+msgid "Selected"
+msgstr "Sélectionné"
+
+#. module: base_external_referentials
+#: code:addons/base_external_referentials/decorator.py:78
+#, python-format
+msgid "The field referential_id doesn't exist on the object %s. Reporting system can not be used\" %(self._name,)))\n"
+"\n"
+"        report_obj = self.pool.get('external.report')\n"
+"        context = kwargs.get('context')\n"
+"        if context is None:\n"
+"            context={}\n"
+"            kwargs['context'] = context\n"
+"\n"
+"        #Start the report\n"
+"        report_id = report_obj.start_report(cr, uid, external_session, id=None, action=func.__name__, action_on=self._name, context=context)\n"
+"\n"
+"        #Execute the original function and add the report_id to the context\n"
+"        context['report_id'] = report_id\n"
+"        response = func(self, cr, uid, external_session, *args, **kwargs)\n"
+"\n"
+"        #Close the report\n"
+"        report_obj.end_report(cr, uid, external_session, report_id, context=context)\n"
+"\n"
+"        return response\n"
+"    return wrapper\n"
+"\n"
+"\n"
+"def catch_error_in_report(func):\n"
+"    \" This decorator open and close a new cursor and if an error occure it will generate a error line in the reporting system\n"
+"    The function must start with \"self, cr, uid, object\"\n"
+"    And the object must have a field call \"referential_id\" related to the object \"external.referential\"\"\n"
+"    @functools.wraps(func)\n"
+"    def wrapper(self, cr, uid, external_session, resource, *args, **kwargs):\n"
+"        context = kwargs.get('context')\n"
+"        if not (context and context.get('report_id')):\n"
+"            external_session.logger.debug(_(\"There is no key report_id in the context, error will be not catch"
+msgstr "The field referential_id doesn't exist on the object %s. Reporting system can not be used\" %(self._name,)))\n"
+"\n"
+"        report_obj = self.pool.get('external.report')\n"
+"        context = kwargs.get('context')\n"
+"        if context is None:\n"
+"            context={}\n"
+"            kwargs['context'] = context\n"
+"\n"
+"        #Start the report\n"
+"        report_id = report_obj.start_report(cr, uid, external_session, id=None, action=func.__name__, action_on=self._name, context=context)\n"
+"\n"
+"        #Execute the original function and add the report_id to the context\n"
+"        context['report_id'] = report_id\n"
+"        response = func(self, cr, uid, external_session, *args, **kwargs)\n"
+"\n"
+"        #Close the report\n"
+"        report_obj.end_report(cr, uid, external_session, report_id, context=context)\n"
+"\n"
+"        return response\n"
+"    return wrapper\n"
+"\n"
+"\n"
+"def catch_error_in_report(func):\n"
+"    \" This decorator open and close a new cursor and if an error occure it will generate a error line in the reporting system\n"
+"    The function must start with \"self, cr, uid, object\"\n"
+"    And the object must have a field call \"referential_id\" related to the object \"external.referential\"\"\n"
+"    @functools.wraps(func)\n"
+"    def wrapper(self, cr, uid, external_session, resource, *args, **kwargs):\n"
+"        context = kwargs.get('context')\n"
+"        if not (context and context.get('report_id')):\n"
+"            external_session.logger.debug(_(\"There is no key report_id in the context, error will be not catch"
+
+#. module: base_external_referentials
+#: help:external.mapping.line,external_field:0
+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'"
+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."
+
+#. module: base_external_referentials
+#: model:ir.model,name:base_external_referentials.model_external_referential_type
+msgid "External Referential Type (Ex.Magento,Spree)"
+msgstr "Type de référentiel externe (Ex.Magento,Spree)"
+
+#. module: base_external_referentials
+#: view:group.fields:0
+#: model:ir.actions.act_window,name:base_external_referentials.group_field_action_open_form
+msgid "Group fields"
+msgstr "Champs groupés"
+
+#. module: base_external_referentials
+#: view:external.referential:0
+msgid "CSV file generation"
+msgstr "Génération de fichiers CSV"
+
+#. module: base_external_referentials
+#: view:external.report.line:0
+msgid "Action On Model"
+msgstr "Action sur le modèle"
+
+#. module: base_external_referentials
+#: code:addons/base_external_referentials/external_osv.py:413
+#, python-format
+msgid "The method _get_external_resource_ids is not implemented in abstract base module!"
+msgstr "La méthode _get_external_resource_ids n'est pas implémentée dans le module d'abstraction!"
+
+#. module: base_external_referentials
+#: code:addons/base_external_referentials/external_osv.py:1468
+#, python-format
+msgid "Wrong external type for mapping %s. One2Many object must have for external type string or integer"
+msgstr "Mauvais type externe pour le mapping %s. Les objects One2Many doivent avoir pour type externe string ou integer"
+
+#. module: base_external_referentials
+#: field:external.report.line,args:0
+msgid "Args"
+msgstr "Args"
+
+#. module: base_external_referentials
+#: sql_constraint:ir.model.data:0
+msgid "You cannot have multiple records with the same external ID in the same module!"
+msgstr "Vous ne pouvez pas avoir plusieurs enregistrements avec le même ID externe dans le même module!"
+
+#. module: base_external_referentials
+#: field:external.mapping.line,related_model_id:0
+msgid "Related Model"
+msgstr "Modèle lié"
+
+#. module: base_external_referentials
+#: model:ir.actions.act_window,name:base_external_referentials.ext_sale_order
+msgid "External Order"
+msgstr "Commande externe"
+
+#. module: base_external_referentials
+#: code:addons/base_external_referentials/external_osv.py:94
+#, python-format
+msgid "The method %s already exist. Please change the prefix name"
+msgstr "La méthode %s existe déjà. Veuillez changer le nom préfixé"
+
+#. module: base_external_referentials
+#: field:external.mapping,model:0
+#: field:external.mapping.template,model:0
+msgid "Model Name"
+msgstr "Nom du modèle"
+
+#. module: base_external_referentials
+#: field:external.report,history_ids:0
+msgid "History"
+msgstr "Historique"
+
+#. module: base_external_referentials
+#: view:external.referential:0
+msgid "Compulsory"
+msgstr "Obligatoire"
+
+#. module: base_external_referentials
+#: view:external.report:0
+msgid "Retry All Failed"
+msgstr "Réessayer tous les échecs"
+
+#. module: base_external_referentials
+#: code:addons/base_external_referentials/external_osv.py:1467
+#: code:addons/base_external_referentials/external_osv.py:1698
+#: code:addons/base_external_referentials/group_fields.py:68
+#, python-format
+msgid "User Error"
+msgstr "Erreur utilisateur"
+
+#. module: base_external_referentials
+#: model:ir.model,name:base_external_referentials.model_external_mapping_template
+msgid "The source mapping records"
+msgstr "Enregistrement du mapping source"
+
+#. module: base_external_referentials
+#: view:external.referential.type:0
+msgid "External Referential Types"
+msgstr "Types de référentiel externe"
+
+#. module: base_external_referentials
+#: model:ir.actions.act_window,name:base_external_referentials.ir_actions_act_window_external_mapping_line
+#: model:ir.ui.menu,name:base_external_referentials.ir_ui_menu_external_mapping_lines
+msgid "External Mapping Lines"
+msgstr "Lignes de mapping externes"
+
+#. module: base_external_referentials
+#: field:external.referential,categ_id:0
+#: model:ir.actions.act_window,name:base_external_referentials.ext_product_category
+msgid "External Category"
+msgstr "Catégorie externe"
+
+#. module: base_external_referentials
+#: code:addons/base_external_referentials/external_osv.py:510
+#, python-format
+msgid "The object %s doesn't have an external mapping\" % self._name))\n"
+"    else:\n"
+"        #If a mapping exists for current model, search for mapping lines\n"
+"\n"
+"        mapping_type = convertion_type == 'from_external_to_openerp' and 'in' or 'out'\n"
+"        mapping_line_filter = [('mapping_id', '=', mapping_id),\n"
+"                            ('type', 'in', ['in_out', mapping_type])]\n"
+"        if mapping_line_filter_ids:\n"
+"            mapping_line_filter += ['|',\n"
+"                                    ('id', 'in', mapping_line_filter_ids),\n"
+"                                    ('evaluation_type', '=', 'sub-mapping')]\n"
+"        mapping_line_ids = self.pool.get('external.mapping.line').search(cr, uid, mapping_line_filter, context=context)\n"
+"        if mapping_line_ids:\n"
+"            mapping_lines = self.pool.get('external.mapping.line').read(cr, uid, mapping_line_ids, [], context=context)\n"
+"        else:\n"
+"            mapping_lines = []\n"
+"        res = self.pool.get('external.mapping').read(cr, uid, mapping_id, context=context)\n"
+"        alternative_key = [x['internal_field'] for x in mapping_lines if x['alternative_key']]\n"
+"        res['alternative_keys'] = alternative_key or False\n"
+"        res['key_for_external_id'] = res['key_for_external_id'] or 'id'\n"
+"        res['mapping_lines'] = mapping_lines\n"
+"        return res\n"
+"\n"
+"@extend(Model)\n"
+"def import_resources(self, cr, uid, ids, resource_name, method=\"search_then_read\", context=None):\n"
+"    \"Abstract function to import resources from a shop / a referential...\n"
+"\n"
+"    :param list ids: list of id\n"
+"    :param str ressource_name: the resource name to import\n"
+"    :param str method: method used for importing the resource (search_then_read,\n"
+"                            search_then_read_no_loop, search_read, search_read_no_loop )\n"
+"    :rtype: dict\n"
+"    :return: dictionary with the key \"create_ids\" and \"write_ids\" which containt the id created/written\n"
+"    \"\n"
+"    if context is None: context={}\n"
+"    result = {\"create_ids\" : [], \"write_ids\" : []}\n"
+"    for browse_record in self.browse(cr, uid, ids, context=context):\n"
+"        if browse_record._name == 'external.referential':\n"
+"            external_session = ExternalSession(browse_record, browse_record)\n"
+"        else:\n"
+"            if hasattr(browse_record, 'referential_id'):\n"
+"                context['%s_id'%browse_record._name.replace('.', '_')] = browse_record.id\n"
+"                external_session = ExternalSession(browse_record.referential_id, browse_record)\n"
+"            else:\n"
+"                raise except_osv(_(\"Not Implemented"
+msgstr "The object %s doesn't have an external mapping\" % self._name))\n"
+"    else:\n"
+"        #If a mapping exists for current model, search for mapping lines\n"
+"\n"
+"        mapping_type = convertion_type == 'from_external_to_openerp' and 'in' or 'out'\n"
+"        mapping_line_filter = [('mapping_id', '=', mapping_id),\n"
+"                            ('type', 'in', ['in_out', mapping_type])]\n"
+"        if mapping_line_filter_ids:\n"
+"            mapping_line_filter += ['|',\n"
+"                                    ('id', 'in', mapping_line_filter_ids),\n"
+"                                    ('evaluation_type', '=', 'sub-mapping')]\n"
+"        mapping_line_ids = self.pool.get('external.mapping.line').search(cr, uid, mapping_line_filter, context=context)\n"
+"        if mapping_line_ids:\n"
+"            mapping_lines = self.pool.get('external.mapping.line').read(cr, uid, mapping_line_ids, [], context=context)\n"
+"        else:\n"
+"            mapping_lines = []\n"
+"        res = self.pool.get('external.mapping').read(cr, uid, mapping_id, context=context)\n"
+"        alternative_key = [x['internal_field'] for x in mapping_lines if x['alternative_key']]\n"
+"        res['alternative_keys'] = alternative_key or False\n"
+"        res['key_for_external_id'] = res['key_for_external_id'] or 'id'\n"
+"        res['mapping_lines'] = mapping_lines\n"
+"        return res\n"
+"\n"
+"@extend(Model)\n"
+"def import_resources(self, cr, uid, ids, resource_name, method=\"search_then_read\", context=None):\n"
+"    \"Abstract function to import resources from a shop / a referential...\n"
+"\n"
+"    :param list ids: list of id\n"
+"    :param str ressource_name: the resource name to import\n"
+"    :param str method: method used for importing the resource (search_then_read,\n"
+"                            search_then_read_no_loop, search_read, search_read_no_loop )\n"
+"    :rtype: dict\n"
+"    :return: dictionary with the key \"create_ids\" and \"write_ids\" which containt the id created/written\n"
+"    \"\n"
+"    if context is None: context={}\n"
+"    result = {\"create_ids\" : [], \"write_ids\" : []}\n"
+"    for browse_record in self.browse(cr, uid, ids, context=context):\n"
+"        if browse_record._name == 'external.referential':\n"
+"            external_session = ExternalSession(browse_record, browse_record)\n"
+"        else:\n"
+"            if hasattr(browse_record, 'referential_id'):\n"
+"                context['%s_id'%browse_record._name.replace('.', '_')] = browse_record.id\n"
+"                external_session = ExternalSession(browse_record.referential_id, browse_record)\n"
+"            else:\n"
+"                raise except_osv(_(\"Not Implemented"
+
+#. module: base_external_referentials
+#: model:ir.model,name:base_external_referentials.model_ir_model
+msgid "Models"
+msgstr "Modèles"
+
+#. module: base_external_referentials
+#: view:external.report.history:0
+#: view:external.report.line:0
+msgid "Report"
+msgstr "Rapport"
+
+#. module: base_external_referentials
+#: model:ir.model,name:base_external_referentials.model_external_referential_category
+msgid "External Referential Category (Ex: e-commerce, crm, warehouse)"
+msgstr "Catégorie du référentiel externe (Ex: e-commerce, crm, entrepôt)"
+
+#. module: base_external_referentials
+#: view:external.mapping.line:0
+msgid "Other Information"
+msgstr "Autre information"
+
+#. module: base_external_referentials
+#: field:external.referential,debug:0
+msgid "Debug"
+msgstr "Debug"
+
+#. module: base_external_referentials
+#: view:external.report.history:0
+#: view:external.report.line:0
+msgid "Failures"
+msgstr "Echecs"
+
+#. module: base_external_referentials
+#: model:ir.model,name:base_external_referentials.model_external_mappinglines_template
+msgid "The source mapping line records"
+msgstr "Enregistrement de la ligne de mapping source"
+
+#. module: base_external_referentials
+#: view:external.referential:0
+msgid "2- Export type"
+msgstr "2- Export du type de référentiel"
+
+#. module: base_external_referentials
+#: field:external.mapping,external_done_method:0
+#: field:external.mapping.template,external_done_method:0
+msgid "Done Method"
+msgstr "Méthode de finalisation"
+
+#. module: base_external_referentials
+#: model:ir.model,name:base_external_referentials.model_external_mapping_line
+msgid "Field Mapping"
+msgstr "Mapping du champ"
+
+#. module: base_external_referentials
+#: field:external.referential.version,name:0
+msgid "name"
+msgstr "Nom"
+
+#. module: base_external_referentials
+#: constraint:external.referential:0
+msgid "The name cannot contain a dot!"
+msgstr "Le nom ne doit pas contenir de point!"
+
+#. module: base_external_referentials
+#: model:ir.actions.act_window,name:base_external_referentials.ir_actions_act_window_external_type
+#: model:ir.ui.menu,name:base_external_referentials.ir_ui_menu_external_types
+msgid "External Referentials Types"
+msgstr "Types de référentiels externes"
+
+#. module: base_external_referentials
+#: field:external.mapping,related_model_ids:0
+msgid "Related Inherited Models"
+msgstr "Modèles liés hérités"
+
+#. module: base_external_referentials
+#: view:external.report:0
+msgid "External Referential Reports"
+msgstr "Rapports des référentiels externes"
+
+#. module: base_external_referentials
+#: field:external.mapping,external_create_method:0
+#: field:external.mapping.template,external_create_method:0
+msgid "Create Method"
+msgstr "Méthode de création"
+
+#. module: base_external_referentials
+#: selection:external.mapping.line,external_type:0
+#: selection:external.mappinglines.template,external_type:0
+msgid "Datetime"
+msgstr "Datetime"
+
+#. module: base_external_referentials
+#: field:ir.model.data,referential_id:0
+msgid "Ext. Referential"
+msgstr "Référentiel externe"
+
+#. module: base_external_referentials
+#: code:addons/base_external_referentials/external_osv.py:715
+#, python-format
+msgid "The object imported need an external_id, maybe the mapping doesn't exist for the object : %s\" %self._name))\n"
+"\n"
+"    if existing_rec_id:\n"
+"        if not self._name in context.get('do_not_update', []):\n"
+"            if self.oe_update(cr, uid, external_session, existing_rec_id, vals, resource, defaults=defaults, context=context):\n"
+"                written = True\n"
+"    else:\n"
+"        existing_rec_id = self.oe_create(cr, uid,  external_session, vals, resource, defaults, context=context)\n"
+"        created = True\n"
+"\n"
+"    if external_id_ok:\n"
+"        if existing_ir_model_data_id:\n"
+"            if created:\n"
+"                # means the external ressource is registred in ir.model.data but the ressource doesn't exist\n"
+"                # in this case we have to update the ir.model.data in order to point to the ressource created\n"
+"                self.pool.get('ir.model.data').write(cr, uid, existing_ir_model_data_id, {'res_id': existing_rec_id}, context=context)\n"
+"        else:\n"
+"            ir_model_data_vals =             self.create_external_id_vals(cr, uid, existing_rec_id, external_id, referential_id, context=context)\n"
+"            if not created:\n"
+"                # means the external resource is bound to an already existing resource\n"
+"                # but not registered in ir.model.data, we log it to inform the success of the binding\n"
+"                external_session.logger.info(\"Bound in OpenERP %s from External Ref with external_id %s and OpenERP id %s successfully\" %(self._name, external_id, existing_rec_id))\n"
+"\n"
+"    if created:\n"
+"        if external_id:\n"
+"            external_session.logger.info((\"Created in OpenERP %s from External Ref withexternal_id %s and OpenERP id %s successfully\" %(self._name, external_id_ok and str(external_id), existing_rec_id)))\n"
+"        elif alternative_keys:\n"
+"            external_session.logger.info((\"Created in OpenERP %s from External Ref withalternative_keys %s and OpenERP id %s successfully\" %(self._name, external_id_ok and str (vals.get(alternative_keys)), existing_rec_id)))\n"
+"        return {'create_id' : existing_rec_id}\n"
+"    elif written:\n"
+"        if external_id:\n"
+"            external_session.logger.info((\"Updated in OpenERP %s from External Ref withexternal_id %s and OpenERP id %s successfully\" %(self._name, external_id_ok and str(external_id), existing_rec_id)))\n"
+"        elif alternative_keys:\n"
+"            external_session.logger.info((\"Updated in OpenERP %s from External Ref withalternative_keys %s and OpenERP id %s successfully\" %(self._name, external_id_ok and str (vals.get(alternative_keys)), existing_rec_id)))\n"
+"        return {'write_id' : existing_rec_id}\n"
+"    return {}\n"
+"\n"
+"@extend(Model)\n"
+"def oe_update(self, cr, uid, external_session, existing_rec_id, vals, resource, defaults, context=None):\n"
+"    \"Update an existing resource in OpenERP\n"
+"\n"
+"    :param ExternalSession external_session : External_session that contain all params of connection\n"
+"    :param int existing_rec_id: openerp id to update\n"
+"    :param dict vals: vals to write\n"
+"    :param dict resource: resource to convert into OpenERP data\n"
+"    :param dict defaults: default values\n"
+"    :rtype boolean\n"
+"    :return: True\n"
+"    \"\n"
+"    if context is None: context={}\n"
+"    context['referential_id'] = external_session.referential_id.id #did it's needed somewhere?\n"
+"    return self.write(cr, uid, existing_rec_id, vals, context)\n"
+"\n"
+"@extend(Model)\n"
+"def oe_create(self, cr, uid, external_session, vals, resource, defaults, context=None):\n"
+"    \"Create an new resource in OpenERP\n"
+"\n"
+"    :param ExternalSession external_session : External_session that contain all params of connection\n"
+"    :param dict vals: vals to create\n"
+"    :param dict resource: resource to convert into OpenERP data\n"
+"    :param dict defaults: default values\n"
+"    :rtype int\n"
+"    :return: the id of the resource created\n"
+"    \"\n"
+"    if context is None: context={}\n"
+"    context['referential_id'] = external_session.referential_id.id  #did it's needed somewhere?\n"
+"    return self.create(cr, uid, vals, context)\n"
+"\n"
+"########################################################################################################################\n"
+"#\n"
+"#                                             END OF IMPORT FEATURES\n"
+"#\n"
+"########################################################################################################################\n"
+"\n"
+"\n"
+"\n"
+"\n"
+"########################################################################################################################\n"
+"#\n"
+"#                                             EXPORT FEATURES\n"
+"#\n"
+"########################################################################################################################\n"
+"\n"
+"@extend(Model)\n"
+"def _get_export_step(self, cr, uid, external_session, context=None):\n"
+"    \"Abstract function that return the step for importing data\n"
+"    Can be overwriten in your module\n"
+"\n"
+"    :param ExternalSession external_session : External_session that contain all params of connection\n"
+"    :rtype: int\n"
+"    :return: a integer that corespond to the limit of object to import\n"
+"    \"\n"
+"    return 10\n"
+"\n"
+"@extend(Model)\n"
+"def _get_default_export_values(self, cr, uid, external_session, mapping_id=None, defaults=None, context=None):\n"
+"    \"Abstract function that return the default value for on object\n"
+"    Can be overwriten in your module\n"
+"\n"
+"    :param ExternalSession external_session : External_session that contain all params of connection\n"
+"    :param int mapping_id: mapping id\n"
+"    :param dict defaults: default values\n"
+"    :rtype: dict\n"
+"    :return: a dictionnary of default values\n"
+"    \"\n"
+"    return defaults\n"
+"\n"
+"@extend(Model)\n"
+"def _get_last_exported_date(self, cr, uid, external_session, context=None):\n"
+"    \"Abstract function that return the last export date for on object\n"
+"    Can be overwriten in your module\n"
+"\n"
+"    :param ExternalSession external_session : External_session that contain all params of connection\n"
+"    :rtype: str\n"
+"    :return: the last export date or False\n"
+"    \"\n"
+"    return False\n"
+"\n"
+"@extend(Model)\n"
+"def _set_last_exported_date(self, cr, uid, external_session, date, context=None):\n"
+"    \"Abstract function that update the last exported date\n"
+"    Can be overwriten in your module\n"
+"\n"
+"    :param ExternalSession external_session : External_session that contain all params of connection\n"
+"    :param date : date\n"
+"    :rtype: boolean\n"
+"    :return: True\n"
+"    \"\n"
+"    return True\n"
+"\n"
+"#For now it's just support 1 level of inherit TODO make it recursive\n"
+"@extend(Model)\n"
+"def _get_query_and_params_for_ids_and_date(self, cr, uid, external_session, ids=None, last_exported_date=None, context=None):\n"
+"    \"Function that build the sql query for getting the ids and the udpate date of each record\n"
+"\n"
+"    :param ExternalSession external_session : External_session that contain all params of connection\n"
+"    :param list ids : if not empty the ids will be used in the sql request in order to filter the record\n"
+"    :param str last_exported_date : last exported date\n"
+"    :rtype: tuple\n"
+"    :return: an tuple of query and params\n"
+"    \"\n"
+"    object_table = self._table\n"
+"    params = ()\n"
+"    if not self._inherits:\n"
+"        greatest = \"GREATEST(%(object_table)s.write_date, %(object_table)s.create_date)\"                        %{'object_table': object_table}\n"
+"\n"
+"        query = \"\n"
+"            SELECT %(greatest)s as update_date, %(object_table)s.id as id, ir_model_data.res_id\n"
+"                FROM %(object_table)s\n"
+"            LEFT JOIN ir_model_data\n"
+"                ON %(object_table)s.id = ir_model_data.res_id\n"
+"                AND ir_model_data.model = '%(object_name)s'\n"
+"                AND ir_model_data.module = 'extref/%(ref_name)s'\n"
+"            \"%{\n"
+"                    'greatest': greatest,\n"
+"                    'object_table': object_table,\n"
+"                    'object_name': self._name,\n"
+"                    'ref_name': external_session.referential_id.name,\n"
+"            }\n"
+"    else:\n"
+"        inherits_object_table = self.pool.get(self._inherits.keys()[0])._table\n"
+"        join_field = self._inherits[self._inherits.keys()[0]]\n"
+"\n"
+"        greatest = \"GREATEST(%(object_table)s.write_date, %(object_table)s.create_date,\n"
+"                    %(inherits_object_table)s.write_date, %(inherits_object_table)s.create_date)\"                     %{'object_table': object_table, 'inherits_object_table': inherits_object_table}\n"
+"\n"
+"        query = \"\n"
+"            select %(greatest)s as update_date, %(object_table)s.id as id, ir_model_data.res_id\n"
+"                from %(object_table)s\n"
+"                    join %(inherits_object_table)s on %(inherits_object_table)s.id = %(object_table)s.%(join_field)s\n"
+"                    LEFT JOIN ir_model_data\n"
+"                        ON %(object_table)s.id = ir_model_data.res_id\n"
+"                        AND ir_model_data.model = '%(object_name)s'\n"
+"                        AND ir_model_data.module = 'extref/%(ref_name)s'\n"
+"            \" %{\n"
+"                    'greatest': greatest,\n"
+"                    'object_table': object_table,\n"
+"                    'inherits_object_table': inherits_object_table,\n"
+"                    'join_field': join_field,\n"
+"                    'object_name': self._name,\n"
+"                    'ref_name': external_session.referential_id.name,\n"
+"                }\n"
+"    if ids:\n"
+"        query += \" WHERE \" + object_table + \".id in %s\"\n"
+"        params += (tuple(ids),)\n"
+"    if last_exported_date:\n"
+"        query += (ids and \" AND (\" or \" WHERE ("
+msgstr "The object imported need an external_id, maybe the mapping doesn't exist for the object : %s\" %self._name))\n"
+"\n"
+"    if existing_rec_id:\n"
+"        if not self._name in context.get('do_not_update', []):\n"
+"            if self.oe_update(cr, uid, external_session, existing_rec_id, vals, resource, defaults=defaults, context=context):\n"
+"                written = True\n"
+"    else:\n"
+"        existing_rec_id = self.oe_create(cr, uid,  external_session, vals, resource, defaults, context=context)\n"
+"        created = True\n"
+"\n"
+"    if external_id_ok:\n"
+"        if existing_ir_model_data_id:\n"
+"            if created:\n"
+"                # means the external ressource is registred in ir.model.data but the ressource doesn't exist\n"
+"                # in this case we have to update the ir.model.data in order to point to the ressource created\n"
+"                self.pool.get('ir.model.data').write(cr, uid, existing_ir_model_data_id, {'res_id': existing_rec_id}, context=context)\n"
+"        else:\n"
+"            ir_model_data_vals =             self.create_external_id_vals(cr, uid, existing_rec_id, external_id, referential_id, context=context)\n"
+"            if not created:\n"
+"                # means the external resource is bound to an already existing resource\n"
+"                # but not registered in ir.model.data, we log it to inform the success of the binding\n"
+"                external_session.logger.info(\"Bound in OpenERP %s from External Ref with external_id %s and OpenERP id %s successfully\" %(self._name, external_id, existing_rec_id))\n"
+"\n"
+"    if created:\n"
+"        if external_id:\n"
+"            external_session.logger.info((\"Created in OpenERP %s from External Ref withexternal_id %s and OpenERP id %s successfully\" %(self._name, external_id_ok and str(external_id), existing_rec_id)))\n"
+"        elif alternative_keys:\n"
+"            external_session.logger.info((\"Created in OpenERP %s from External Ref withalternative_keys %s and OpenERP id %s successfully\" %(self._name, external_id_ok and str (vals.get(alternative_keys)), existing_rec_id)))\n"
+"        return {'create_id' : existing_rec_id}\n"
+"    elif written:\n"
+"        if external_id:\n"
+"            external_session.logger.info((\"Updated in OpenERP %s from External Ref withexternal_id %s and OpenERP id %s successfully\" %(self._name, external_id_ok and str(external_id), existing_rec_id)))\n"
+"        elif alternative_keys:\n"
+"            external_session.logger.info((\"Updated in OpenERP %s from External Ref withalternative_keys %s and OpenERP id %s successfully\" %(self._name, external_id_ok and str (vals.get(alternative_keys)), existing_rec_id)))\n"
+"        return {'write_id' : existing_rec_id}\n"
+"    return {}\n"
+"\n"
+"@extend(Model)\n"
+"def oe_update(self, cr, uid, external_session, existing_rec_id, vals, resource, defaults, context=None):\n"
+"    \"Update an existing resource in OpenERP\n"
+"\n"
+"    :param ExternalSession external_session : External_session that contain all params of connection\n"
+"    :param int existing_rec_id: openerp id to update\n"
+"    :param dict vals: vals to write\n"
+"    :param dict resource: resource to convert into OpenERP data\n"
+"    :param dict defaults: default values\n"
+"    :rtype boolean\n"
+"    :return: True\n"
+"    \"\n"
+"    if context is None: context={}\n"
+"    context['referential_id'] = external_session.referential_id.id #did it's needed somewhere?\n"
+"    return self.write(cr, uid, existing_rec_id, vals, context)\n"
+"\n"
+"@extend(Model)\n"
+"def oe_create(self, cr, uid, external_session, vals, resource, defaults, context=None):\n"
+"    \"Create an new resource in OpenERP\n"
+"\n"
+"    :param ExternalSession external_session : External_session that contain all params of connection\n"
+"    :param dict vals: vals to create\n"
+"    :param dict resource: resource to convert into OpenERP data\n"
+"    :param dict defaults: default values\n"
+"    :rtype int\n"
+"    :return: the id of the resource created\n"
+"    \"\n"
+"    if context is None: context={}\n"
+"    context['referential_id'] = external_session.referential_id.id  #did it's needed somewhere?\n"
+"    return self.create(cr, uid, vals, context)\n"
+"\n"
+"########################################################################################################################\n"
+"#\n"
+"#                                             END OF IMPORT FEATURES\n"
+"#\n"
+"########################################################################################################################\n"
+"\n"
+"\n"
+"\n"
+"\n"
+"########################################################################################################################\n"
+"#\n"
+"#                                             EXPORT FEATURES\n"
+"#\n"
+"########################################################################################################################\n"
+"\n"
+"@extend(Model)\n"
+"def _get_export_step(self, cr, uid, external_session, context=None):\n"
+"    \"Abstract function that return the step for importing data\n"
+"    Can be overwriten in your module\n"
+"\n"
+"    :param ExternalSession external_session : External_session that contain all params of connection\n"
+"    :rtype: int\n"
+"    :return: a integer that corespond to the limit of object to import\n"
+"    \"\n"
+"    return 10\n"
+"\n"
+"@extend(Model)\n"
+"def _get_default_export_values(self, cr, uid, external_session, mapping_id=None, defaults=None, context=None):\n"
+"    \"Abstract function that return the default value for on object\n"
+"    Can be overwriten in your module\n"
+"\n"
+"    :param ExternalSession external_session : External_session that contain all params of connection\n"
+"    :param int mapping_id: mapping id\n"
+"    :param dict defaults: default values\n"
+"    :rtype: dict\n"
+"    :return: a dictionnary of default values\n"
+"    \"\n"
+"    return defaults\n"
+"\n"
+"@extend(Model)\n"
+"def _get_last_exported_date(self, cr, uid, external_session, context=None):\n"
+"    \"Abstract function that return the last export date for on object\n"
+"    Can be overwriten in your module\n"
+"\n"
+"    :param ExternalSession external_session : External_session that contain all params of connection\n"
+"    :rtype: str\n"
+"    :return: the last export date or False\n"
+"    \"\n"
+"    return False\n"
+"\n"
+"@extend(Model)\n"
+"def _set_last_exported_date(self, cr, uid, external_session, date, context=None):\n"
+"    \"Abstract function that update the last exported date\n"
+"    Can be overwriten in your module\n"
+"\n"
+"    :param ExternalSession external_session : External_session that contain all params of connection\n"
+"    :param date : date\n"
+"    :rtype: boolean\n"
+"    :return: True\n"
+"    \"\n"
+"    return True\n"
+"\n"
+"#For now it's just support 1 level of inherit TODO make it recursive\n"
+"@extend(Model)\n"
+"def _get_query_and_params_for_ids_and_date(self, cr, uid, external_session, ids=None, last_exported_date=None, context=None):\n"
+"    \"Function that build the sql query for getting the ids and the udpate date of each record\n"
+"\n"
+"    :param ExternalSession external_session : External_session that contain all params of connection\n"
+"    :param list ids : if not empty the ids will be used in the sql request in order to filter the record\n"
+"    :param str last_exported_date : last exported date\n"
+"    :rtype: tuple\n"
+"    :return: an tuple of query and params\n"
+"    \"\n"
+"    object_table = self._table\n"
+"    params = ()\n"
+"    if not self._inherits:\n"
+"        greatest = \"GREATEST(%(object_table)s.write_date, %(object_table)s.create_date)\"                        %{'object_table': object_table}\n"
+"\n"
+"        query = \"\n"
+"            SELECT %(greatest)s as update_date, %(object_table)s.id as id, ir_model_data.res_id\n"
+"                FROM %(object_table)s\n"
+"            LEFT JOIN ir_model_data\n"
+"                ON %(object_table)s.id = ir_model_data.res_id\n"
+"                AND ir_model_data.model = '%(object_name)s'\n"
+"                AND ir_model_data.module = 'extref/%(ref_name)s'\n"
+"            \"%{\n"
+"                    'greatest': greatest,\n"
+"                    'object_table': object_table,\n"
+"                    'object_name': self._name,\n"
+"                    'ref_name': external_session.referential_id.name,\n"
+"            }\n"
+"    else:\n"
+"        inherits_object_table = self.pool.get(self._inherits.keys()[0])._table\n"
+"        join_field = self._inherits[self._inherits.keys()[0]]\n"
+"\n"
+"        greatest = \"GREATEST(%(object_table)s.write_date, %(object_table)s.create_date,\n"
+"                    %(inherits_object_table)s.write_date, %(inherits_object_table)s.create_date)\"                     %{'object_table': object_table, 'inherits_object_table': inherits_object_table}\n"
+"\n"
+"        query = \"\n"
+"            select %(greatest)s as update_date, %(object_table)s.id as id, ir_model_data.res_id\n"
+"                from %(object_table)s\n"
+"                    join %(inherits_object_table)s on %(inherits_object_table)s.id = %(object_table)s.%(join_field)s\n"
+"                    LEFT JOIN ir_model_data\n"
+"                        ON %(object_table)s.id = ir_model_data.res_id\n"
+"                        AND ir_model_data.model = '%(object_name)s'\n"
+"                        AND ir_model_data.module = 'extref/%(ref_name)s'\n"
+"            \" %{\n"
+"                    'greatest': greatest,\n"
+"                    'object_table': object_table,\n"
+"                    'inherits_object_table': inherits_object_table,\n"
+"                    'join_field': join_field,\n"
+"                    'object_name': self._name,\n"
+"                    'ref_name': external_session.referential_id.name,\n"
+"                }\n"
+"    if ids:\n"
+"        query += \" WHERE \" + object_table + \".id in %s\"\n"
+"        params += (tuple(ids),)\n"
+"    if last_exported_date:\n"
+"        query += (ids and \" AND (\" or \" WHERE ("
+
+#. module: base_external_referentials
+#: help:external.mapping.line,selected:0
+msgid "to select for mapping"
+msgstr "A selectionner pour mapper"
+
+#. module: base_external_referentials
+#: field:external.referential,version_id:0
+msgid "Referential Version"
+msgstr "Version du référentiel"
+
+#. module: base_external_referentials
+#: view:external.report.line:0
+msgid "Retry"
+msgstr "Réessayer"
+
+#. module: base_external_referentials
+#: field:external.report.history,end_date:0
+msgid "End Date"
+msgstr "Date de fin"
+
+#. module: base_external_referentials
+#: selection:external.report.line,state:0
+msgid "Failed"
+msgstr "Echecs"
+
+#. module: base_external_referentials
+#: view:external.mapping:0
+#: field:external.mapping.line,referential_id:0
+msgid "Referential"
+msgstr "Référentiel"
+
+#. module: base_external_referentials
+#: view:external.referential:0
+msgid "Referential Actions"
+msgstr "Actions du référentiel"
+
+#. module: base_external_referentials
+#: field:external.referential,location:0
+msgid "Location"
+msgstr "Emplacement"
+
+#. module: base_external_referentials
+#: selection:external.mapping.line,evaluation_type:0
+#: selection:external.mappinglines.template,evaluation_type:0
+msgid "Sub Mapping Line"
+msgstr "Ligne de sous-mapping"
+
+#. module: base_external_referentials
+#: field:external.report,failed_line_ids:0
+msgid "Failed Report Lines"
+msgstr "Lignes de rapport en échecs"
+
+#. module: base_external_referentials
+#: selection:external.mapping.line,external_type:0
+#: selection:external.mappinglines.template,external_type:0
+msgid "Dictionnary"
+msgstr "Dictionnary"
+
+#. module: base_external_referentials
+#: field:external.mapping,key_for_external_id:0
+#: field:external.mapping.template,key_for_external_id:0
+msgid "External field used as key"
+msgstr "Champ externe utilisé comme clé"
+
+#. module: base_external_referentials
+#: field:external.mapping.line,type:0
+#: field:external.mappinglines.template,type:0
+#: field:external.referential.version,type_id:0
+msgid "Type"
+msgstr "Type"
+
+#. module: base_external_referentials
+#: field:external.mapping.line,field_id:0
+#: field:external.mappinglines.template,field_id:0
+msgid "OpenERP Field"
+msgstr "Champ d'OpenERP"
+
+#. module: base_external_referentials
+#: field:external.mapping.line,name:0
+#: field:external.mappinglines.template,name:0
+#: field:external.referential,name:0
+#: field:external.referential.category,name:0
+#: field:external.referential.type,name:0
+#: field:external.report,name:0
+#: field:group.fields,name:0
+msgid "Name"
+msgstr "Nom"
+
+#. module: base_external_referentials
+#: selection:external.mapping.line,type:0
+#: selection:external.mappinglines.template,type:0
+msgid "External -> OpenERP"
+msgstr "Externe -> OpenERP"
+
+#. module: base_external_referentials
+#: selection:external.mapping.line,external_type:0
+#: selection:external.mappinglines.template,external_type:0
+msgid "String"
+msgstr "String"
+
+#. module: base_external_referentials
+#: field:external.referential,create_date:0
+msgid "Creation Date"
+msgstr "Date de création"
+
+#. module: base_external_referentials
+#: view:external.report.line:0
+#: field:external.report.line,error_message:0
+msgid "Error Message"
+msgstr "Message d'erreur"
+
+#. module: base_external_referentials
+#: field:external.mapping,external_get_method:0
+#: field:external.mapping.template,external_get_method:0
+msgid "Get Method"
+msgstr "Méthode d'optention"
+
+#. module: base_external_referentials
+#: code:addons/base_external_referentials/group_fields.py:68
+#, python-format
+msgid "Changing Column name is not supported yet"
+msgstr "Le changement de nom de colonne n'est pas supporté pour l'instant"
+
+#. module: base_external_referentials
+#: field:external.mapping,extra_name:0
+#: field:external.mapping.template,extra_name:0
+msgid "Extra Name"
+msgstr "Nom supplémentaire"
+
+#. module: base_external_referentials
+#: view:external.mapping.line:0
+msgid "Internal fields"
+msgstr "Field interne"
+
+#. module: base_external_referentials
+#: view:external.referential:0
+msgid "Configuration"
+msgstr "Configuration"
+
+#. module: base_external_referentials
+#: model:ir.ui.menu,name:base_external_referentials.ir_ui_menu_group_fields
+msgid "Group Fields"
+msgstr "Groupe de champs"
+
+#. module: base_external_referentials
+#: field:external.mapping,mapping_ids:0
+msgid "Mappings Lines"
+msgstr "Lignes de mapping"
+
+#. module: base_external_referentials
+#: field:ir.model.fields,group_fields_id:0
+msgid "Trigger Group"
+msgstr "Trigger Group"
+
+#. module: base_external_referentials
+#: field:external.mapping,template_id:0
+msgid "External Mapping Template"
+msgstr "Template de mapping"
+
+#. module: base_external_referentials
+#: field:external.referential.type,version_ids:0
+msgid "Versions"
+msgstr "Versions"
+
+#. module: base_external_referentials
+#: view:external.report:0
+#: model:ir.actions.act_window,name:base_external_referentials.ir_actions_act_window_external_report
+msgid "External Reports"
+msgstr "Rapports externes"
+
+#. module: base_external_referentials
+#: code:addons/base_external_referentials/external_osv.py:1432
+#, python-format
+msgid "Invalid format for the variable result."
+msgstr "Le format de la variable result est incorrect."
+
+#. module: base_external_referentials
+#: field:external.report.line,traceback:0
+msgid "Traceback"
+msgstr "Traceback"
+
+#. module: base_external_referentials
+#: selection:external.mapping.line,type:0
+#: selection:external.mappinglines.template,type:0
+msgid "External <- OpenERP"
+msgstr "Externe <- OpenERP"
+
+#. module: base_external_referentials
+#: field:external.mapping,referential_id:0
+#: view:external.referential:0
+#: view:external.referential.type:0
+#: view:external.report:0
+#: field:external.report,referential_id:0
+#: model:ir.model,name:base_external_referentials.model_external_referential
+msgid "External Referential"
+msgstr "Référentiel externe"
+
+#. module: base_external_referentials
+#: field:external.mapping.line,child_mapping_id:0
+#: field:external.mappinglines.template,child_mapping_id:0
+msgid "Child Mapping"
+msgstr "Mapping enfant"
+
+#. module: base_external_referentials
+#: field:external.mapping.line,sequence:0
+#: field:external.mappinglines.template,sequence:0
+msgid "Sequence"
+msgstr "Séquence"
+
+#. module: base_external_referentials
+#: code:addons/base_external_referentials/decorator.py:64
+#: code:addons/base_external_referentials/decorator.py:78
+#: code:addons/base_external_referentials/external_osv.py:413
+#: code:addons/base_external_referentials/external_osv.py:962
+#, python-format
+msgid "Not Implemented"
+msgstr "Non implémenté"
+
+#. module: base_external_referentials
+#: view:external.report.line:0
+#: field:external.report.line,resource:0
+#: field:external.report.line,resource_text:0
+msgid "External Data"
+msgstr "Données externe"
+
+#. module: base_external_referentials
+#: view:external.mapping.line:0
+#: field:external.referential.version,full_name:0
+msgid "Full Name"
+msgstr "Nom entier"
+
+#. module: base_external_referentials
+#: field:external.referential,categ_name:0
+msgid "External Category Name"
+msgstr "Nom de la catégorie du référentiel"
+
+#. module: base_external_referentials
+#: view:external.mapping.line:0
+#: field:external.mapping.line,in_function:0
+#: field:external.mappinglines.template,in_function:0
+msgid "Import in OpenERP Mapping Python Function"
+msgstr "Import in OpenERP Mapping Python Function"
+
+#. module: base_external_referentials
+#: selection:external.mapping.line,evaluation_type:0
+#: selection:external.mappinglines.template,evaluation_type:0
+msgid "Direct Mapping"
+msgstr "Direct Mapping"
+
+#. module: base_external_referentials
+#: view:external.referential:0
+msgid "Core Components"
+msgstr "Composants du coeur"
+
+#. module: base_external_referentials
+#: sql_constraint:external.mapping.line:0
+msgid "A referential can not have various mapping line imported from the same template mapping line"
+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"
+
+#. module: base_external_referentials
+#: view:external.referential:0
+msgid "6- Export mapping lines"
+msgstr "6- Export des lignes de mapping"
+
+#. module: base_external_referentials
+#: view:external.mapping:0
+#: view:external.mapping.line:0
+#: view:external.referential:0
+#: view:external.referential.type:0
+#: view:external.report:0
+#: view:external.report.history:0
+#: view:external.report.line:0
+#: view:group.fields:0
+msgid "Group by..."
+msgstr "Regrouper par..."
+
+#. module: base_external_referentials
+#: field:external.mapping,external_resource_name:0
+#: field:external.mapping.template,external_resource_name:0
+msgid "External Resource Name"
+msgstr "Nom de la resource externe"
+
+#. module: base_external_referentials
+#: sql_constraint:external.mapping:0
+msgid "A referential can not have various mapping imported from the same template"
+msgstr "Un référentiel ne peut pas avoir de différents mapping importés depuis le même template"
+
+#. module: base_external_referentials
+#: field:external.report.history,start_date:0
+msgid "Start Date"
+msgstr "Date de départ"
+
+#. module: base_external_referentials
+#: code:addons/base_external_referentials/external_osv.py:1083
+#, python-format
+msgid "only method export onebyone is implemented in base_external_referentials"
+msgstr "Seule la méthode d'export un par un est implémenté dans base_external_referentials"
+
+#. module: base_external_referentials
+#: model:ir.actions.act_window,name:base_external_referentials.act_window_external_referential
+#: model:ir.ui.menu,name:base_external_referentials.ir_ui_menu_external_referentials
+#: model:ir.ui.menu,name:base_external_referentials.menu_external_referential
+msgid "External Referentials"
+msgstr "Référentiels externes"
+
+#. module: base_external_referentials
+#: code:addons/base_external_referentials/external_osv.py:1699
+#, python-format
+msgid "Error with mapping : %s. Sub mapping can be only apply on one2many, many2one or many2many fields"
+msgstr "Erreur avec le mapping : %s. Un sous-mapping ne peut être appliqué seulement sur des champs : one2many, many2one ou many2many"
+
+#. module: base_external_referentials
+#: selection:external.mapping.line,type:0
+#: selection:external.mappinglines.template,type:0
+msgid "External <-> OpenERP"
+msgstr "Externe <-> OpenERP"
+
+#. module: base_external_referentials
+#: view:external.referential:0
+#: field:external.referential.type,categ_id:0
+msgid "Category"
+msgstr "Catégorie"
+
+#. module: base_external_referentials
+#: field:external.referential,mapping_ids:0
+msgid "Mappings"
+msgstr "Mappings"
+
+#. module: base_external_referentials
+#: selection:external.mapping.line,external_type:0
+#: selection:external.mappinglines.template,external_type:0
+msgid "URL"
+msgstr "URL"
+
+#. module: base_external_referentials
+#: view:external.mapping:0
+#: view:external.referential:0
+msgid "Object Mappings"
+msgstr "Object du mapping"
+
+#. module: base_external_referentials
+#: model:ir.model,name:base_external_referentials.model_ir_model_data
+msgid "ir.model.data"
+msgstr "ir.model.data"
+
+#. module: base_external_referentials
+#: field:external.mapping,external_search_method:0
+#: field:external.mapping.template,external_search_method:0
+msgid "Search Method"
+msgstr "Méthode de recherche"
+
+#. module: base_external_referentials
+#: model:ir.actions.act_window,name:base_external_referentials.ext_res_partner
+msgid "External Partner"
+msgstr "Partenaire externe"
+
+#. module: base_external_referentials
+#: view:external.report.history:0
+#: view:external.report.line:0
+#: model:ir.actions.act_window,name:base_external_referentials.ir_actions_act_window_external_report_history
+#: model:ir.model,name:base_external_referentials.model_external_report_history
+#: model:ir.ui.menu,name:base_external_referentials.ir_ui_menu_external_report_history
+msgid "External Report History"
+msgstr "Historique des rapports externes"
+
+#. module: base_external_referentials
+#: field:external.mapping.line,datetime_format:0
+#: field:external.mappinglines.template,datetime_format:0
+msgid "Datetime Format"
+msgstr "Datetime Format"
+
+#. module: base_external_referentials
+#: model:ir.actions.act_window,name:base_external_referentials.ext_product_product
+msgid "External Product"
+msgstr "Produit externe"
+
+#. module: base_external_referentials
+#: field:external.report.line,state:0
+msgid "Status"
+msgstr "Status"
+
+#. module: base_external_referentials
+#: sql_constraint:ir.model:0
+msgid "Each model must be unique!"
+msgstr "Chaque modèle doit être unique!"
+
+#. module: base_external_referentials
+#: field:external.mapping.template,version_id:0
+#: field:external.mappinglines.template,version_id:0
+msgid "External Referential Version"
+msgstr "Version du référentiel externe"
+
+#. module: base_external_referentials
+#: sql_constraint:external.referential:0
+msgid "Referential names must be unique !"
+msgstr "Les noms des référentiels doivent être unique !"
+
+#. module: base_external_referentials
+#: field:external.mapping,external_list_method:0
+#: field:external.mapping.template,external_list_method:0
+msgid "List Method"
+msgstr "Méthode de listage"
+
+#. module: base_external_referentials
+#: code:addons/base_external_referentials/external_osv.py:57
+#: code:addons/base_external_referentials/external_osv.py:88
+#: code:addons/base_external_referentials/external_osv.py:93
+#: code:addons/base_external_referentials/external_osv.py:1083
+#, python-format
+msgid "Developper Error"
+msgstr "Erreur développeur"
+
+#. module: base_external_referentials
+#: view:external.referential:0
+msgid "1 - Reload Referential Mapping Templates"
+msgstr "1 - Rechercher les templates de mapping externe"
+
+#. module: base_external_referentials
+#: field:external.referential,apiusername:0
+msgid "User Name"
+msgstr "Nom d'utilisateur"
+
+#. module: base_external_referentials
+#: help:external.mapping,related_model_ids:0
+msgid "potentially inherited through '_inherits' model, used for mapping field selection"
+msgstr "potentielement héritable grâce au modèle '_inherits', utilisé pour la séléction des champs de mapping"
+
+#. module: base_external_referentials
+#: view:external.referential:0
+msgid "1- Export category"
+msgstr "1- Export de la catégorie"
+
+#. module: base_external_referentials
+#: model:res.groups,name:base_external_referentials.group_export_mapping
+msgid "Export Mapping Manager"
+msgstr "Responsable des mappings d'export"
+
+#. module: base_external_referentials
+#: view:external.report.history:0
+#: view:external.report.line:0
+#: field:external.report.line,date:0
+msgid "Date"
+msgstr "Date"
+
+#. module: base_external_referentials
+#: selection:external.mapping.line,external_type:0
+#: selection:external.mappinglines.template,external_type:0
+msgid "Integer"
+msgstr "Integer"
+
+#. module: base_external_referentials
+#: field:external.report,sync_from_object_id:0
+msgid "Sync From Object ID"
+msgstr "Synchro depuis l'ID d'objet"
+
+#. module: base_external_referentials
+#: code:addons/base_external_referentials/external_osv.py:555
+#, python-format
+msgid "The field referential_id doesn't exist on the object %s. Reporting system can not be used"
+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é"
+
+#. module: base_external_referentials
+#: field:external.referential,type_name:0
+msgid "External Type Name"
+msgstr "Nom du type  de référentiel externe"
+
+#. module: base_external_referentials
+#: field:external.report.history,user_id:0
+msgid "User"
+msgstr "Utilisateur"
+
+#. module: base_external_referentials
+#: field:external.mapping.line,external_field:0
+#: field:external.mappinglines.template,external_field:0
+msgid "External Field"
+msgstr "Champ externe"
+
+#. module: base_external_referentials
+#: view:external.report.history:0
+#: view:external.report.line:0
+#: selection:external.report.line,state:0
+msgid "Success"
+msgstr "Succès"
+
+#. module: base_external_referentials
+#: field:external.report,email_tmpl_id:0
+msgid "Email Template"
+msgstr "Email Template"
+
+#. module: base_external_referentials
+#: code:addons/base_external_referentials/external_osv.py:58
+#, python-format
+msgid "You can extend the class %s with the method %s.\",\n"
+"                \"Indeed this method already exist use the decorator 'replace' instead"
+msgstr "Vous pouvez étendre la classe %s avec la méthode %s.\",\n"
+"                \"En effet, cette méthode éxiste déjà. Veuillez utiliser le décorateur 'replace' à la place"
+
+#. module: base_external_referentials
+#: code:addons/base_external_referentials/external_osv.py:509
+#, python-format
+msgid "External Import Error"
+msgstr "Erreur d'import externe"
+
+#. module: base_external_referentials
+#: field:external.mapping.line,alternative_key:0
+#: field:external.mappinglines.template,alternative_key:0
+msgid "Alternative Key"
+msgstr "Alternative Key"
+
+#. module: base_external_referentials
+#: code:addons/base_external_referentials/external_osv.py:962
+#, python-format
+msgid "The field referential_id doesn't exist on the object %s.\" %(browse_record._name,)))\n"
+"        context = self.init_context_before_exporting_resource(cr, uid, external_session, browse_record.id, resource_name, context=context)\n"
+"        self.pool.get(resource_name)._export_resources(cr, uid, external_session, context=context)\n"
+"    return True\n"
+"\n"
+"\n"
+"#TODO refactor update date,maybe it will be better to have an update date per resource\n"
+"#TODO deal correctly with multi resource\n"
+"@extend(Model)\n"
+"def send_to_external(self, cr, uid, external_session, resources, mapping, mapping_id, update_date=None, context=None):\n"
+"    \"Generic method that send the resource to an external referential\n"
+"\n"
+"    :param ExternalSession external_session : External_session that contain all params of connection\n"
+"    :param list resources: list of resources to export\n"
+"    :param dict mapping: dictionnary of mapping, the key is the mapping id\n"
+"    :param date update_date: if not empty the update date will be write in the last update date of the objec\n"
+"    :rtype: int/str\n"
+"    :return: the external resource exported\n"
+"\n"
+"    \"\n"
+"    resources_to_update = {}\n"
+"    resources_to_create = {}\n"
+"    for resource_id, resource in resources.items():\n"
+"        ext_id = self.get_extid(cr, uid, resource_id, external_session.referential_id.id, context=context)\n"
+"        if ext_id:\n"
+"            for lang in resource:\n"
+"                resource[lang]['ext_id'] = ext_id\n"
+"            resources_to_update[resource_id] = resource\n"
+"        else:\n"
+"            resources_to_create[resource_id] = resource\n"
+"    self.ext_update(cr, uid, external_session, resources_to_update, mapping, mapping_id, context=context)\n"
+"    ext_create_ids = self.ext_create(cr, uid, external_session, resources_to_create, mapping, mapping_id, context=context)\n"
+"    for rec_id, ext_id in ext_create_ids.items():\n"
+"        self.create_external_id_vals(cr, uid, rec_id, ext_id, external_session.referential_id.id, context=context)\n"
+"    if update_date and self._get_last_exported_date(cr, uid, external_session, context=context) < update_date:\n"
+"        self._set_last_exported_date(cr, uid, external_session, update_date, context=context)\n"
+"    return ext_id\n"
+"\n"
+"@extend(Model)\n"
+"def ext_create(self, cr, uid, external_session, resources, mapping=None, mapping_id=None, context=None):\n"
+"    res = {}\n"
+"    mapping, mapping_id = self._init_mapping(cr, uid, external_session.referential_id.id, mapping=mapping, mapping_id=mapping_id, context=context)\n"
+"    for resource_id, resource in resources.items():\n"
+"        # TODO support multilanguages. for now we only export the first one\n"
+"        res[resource_id] = getattr(external_session.connection, mapping[mapping_id]['external_create_method'])(mapping[mapping_id]['external_resource_name'], resource[resource.keys()[0]])\n"
+"    return res\n"
+"\n"
+"@extend(Model)\n"
+"def ext_update(self, cr, uid, external_session, resources, mapping=None, mapping_id=None, context=None):\n"
+"    \"Not Implemented here\"\n"
+"    return False\n"
+"\n"
+"@extend(Model)\n"
+"def ext_unlink(self, cr, uid, ids, context=None):\n"
+"    ir_model_obj = self.pool.get('ir.model.data')\n"
+"    for object_id in ids:\n"
+"        ir_model_ids = ir_model_obj.search(cr, uid, [('res_id','=',object_id),('model','=',self._name)])\n"
+"        for ir_model in ir_model_obj.browse(cr, uid, ir_model_ids, context=context):\n"
+"            ext_id = self.id_from_prefixed_id(ir_model.name)\n"
+"            ref_id = ir_model.referential_id.id\n"
+"            external_session = ExternalSession(ir_model.referential_id)\n"
+"            mapping = self._get_mapping(cr, uid, ref_id)\n"
+"            getattr(external_session.connection, mapping['external_delete_method'])(mapping['external_resource_name'], ext_id)\n"
+"            #commit_now(ir_model.unlink())\n"
+"            ir_model.unlink()\n"
+"    return True\n"
+"\n"
+"@extend(Model)\n"
+"def get_lang_to_export(self, cr, uid, external_session, context=None):\n"
+"    \"Get the list of lang to export\n"
+"\n"
+"    :param ExternalSession external_session : External_session that contain all params of connection\n"
+"    :rtype: list\n"
+"    return: the list of lang to export\n"
+"    \"\n"
+"\n"
+"    if context is None:\n"
+"        return []\n"
+"    else:\n"
+"        return context.get('lang_to_export') or [context.get('lang')]\n"
+"\n"
+"@extend(Model)\n"
+"def _export_resources(self, cr, uid, external_session, method=\"onebyone\", context=None):\n"
+"    \"Export resource\n"
+"\n"
+"    :param ExternalSession external_session : External_session that contain all params of connection\n"
+"    :param str method: method to export data (for now only onebyone)\n"
+"    :rtype: boolean\n"
+"    return: True\n"
+"    \"\n"
+"    external_session.logger.info(\"Start to export the ressource %s\"%(self._name,))\n"
+"    defaults = self._get_default_export_values(cr, uid, external_session, context=context)\n"
+"    mapping, mapping_id = self._init_mapping(cr, uid, external_session.referential_id.id, convertion_type='from_openerp_to_external', context=context)\n"
+"    last_exported_date = self._get_last_exported_date(cr, uid, external_session, context=context)\n"
+"    external_session.logger.info(\"Retrieve the list of ids to export for the ressource %s\"%(self._name))\n"
+"    ids, ids_2_date = self.get_ids_and_update_date(cr, uid, external_session, last_exported_date=last_exported_date, context=context)\n"
+"    external_session.logger.info(\"%s %s ressource will be exported\"%((ids and len(ids) or 0), self._name))\n"
+"    step = self._get_export_step(cr, uid, external_session, context=context)\n"
+"\n"
+"    group_obj = self.pool.get('group.fields')\n"
+"    group_ids = group_obj.search(cr, uid, [['model_id', '=', self._name]], context=context)\n"
+"    if self._inherits:\n"
+"        inherits_group_ids = group_obj.search(cr, uid, [['model_id', '=',self._inherits.keys()[0]]], context=context)\n"
+"    else:\n"
+"        inherits_group_ids=[]\n"
+"    smart_export =  context.get('smart_export') and (group_ids or inherits_group_ids) and {'group_ids': group_ids, 'inherits_group_ids': inherits_group_ids}\n"
+"\n"
+"    langs = self.get_lang_to_export(cr, uid, external_session, context=context)\n"
+"\n"
+"    while ids:\n"
+"        ids_to_process = ids[0:step]\n"
+"        ids = ids[step:]\n"
+"        external_session.logger.info(\"Start to read the ressource %s : %s\"%(self._name, ids_to_process))\n"
+"        resources = self._get_oe_resources(cr, uid, external_session, ids_to_process, langs=langs,\n"
+"                                    smart_export=smart_export, last_exported_date=last_exported_date,\n"
+"                                    mapping=mapping, mapping_id=mapping_id, context=context)\n"
+"        if method == 'onebyone':\n"
+"            for resource_id in ids_to_process:\n"
+"                external_session.logger.info(\"Start to transform and send the ressource %s : %s\"%(self._name, resource_id))\n"
+"                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)\n"
+"        else:\n"
+"            raise except_osv(_('Developper Error'), _('only method export onebyone is implemented in base_external_referentials'))\n"
+"    #now = datetime.now().strftime(DEFAULT_SERVER_DATETIME_FORMAT)\n"
+"    #self._set_last_exported_date(cr, uid, external_session, now, context=context)\n"
+"    return True\n"
+"\n"
+"@extend(Model)\n"
+"def _transform_and_send_one_resource(self, cr, uid, external_session, resource, resource_id,\n"
+"                            update_date, mapping, mapping_id, defaults=None, context=None):\n"
+"    \"Transform and send one resource\n"
+"    The resource will converted into External format by using the function _transform_one_resource\n"
+"    And then send to the external system using the method send_to_external\n"
+"\n"
+"    :param ExternalSession external_session : External_session that contain all params of connection\n"
+"    :param dict resource: resource to convert into OpenERP data\n"
+"    :param int resource_id: openerp id of the resource to send\n"
+"    :param str method: method to export data (for now only onebyone)\n"
+"    :param dict mapping: dictionnary of mapping, the key is the mapping id\n"
+"    :param int mapping_id: mapping id\n"
+"    :param dict defaults: default values\n"
+"    :rtype: str/int\n"
+"    :return: the external id\n"
+"    \"\n"
+"    for key_lang in resource:\n"
+"        resource[key_lang] = self._transform_one_resource(cr, uid, external_session, 'from_openerp_to_external',\n"
+"                                            resource[key_lang], mapping=mapping, mapping_id=mapping_id,\n"
+"                                            defaults=defaults, context=context)\n"
+"    return self.send_to_external(cr, uid, external_session, {resource_id : resource}, mapping, mapping_id, update_date, context=context)\n"
+"\n"
+"@extend(Model)\n"
+"def _export_one_resource(self, cr, uid, external_session, resource_id, context=None):\n"
+"    \"Export one resource\n"
+"    Export an OpenERP resource into an external system\n"
+"\n"
+"    :param ExternalSession external_session : External_session that contain all params of connection\n"
+"    :param int resource_id: openerp id of the resource to send\n"
+"    :rtype: str/int\n"
+"    :return: the external id\n"
+"    \"\n"
+"    defaults = self._get_default_export_values(cr, uid, external_session, context=context)\n"
+"    mapping, mapping_id = self._init_mapping(cr, uid, external_session.referential_id.id, convertion_type='from_openerp_to_external', context=context)\n"
+"    langs = self.get_lang_to_export(cr, uid, external_session, context=context)\n"
+"    resource = self._get_oe_resources(cr, uid, external_session, [resource_id], langs=langs,\n"
+"                                smart_export=False, last_exported_date=False,\n"
+"                                mapping=mapping, mapping_id=mapping_id, context=context)[resource_id]\n"
+"    return self._transform_and_send_one_resource(cr, uid, external_session, resource, resource_id,\n"
+"                            False, mapping, mapping_id, defaults=defaults, context=context)\n"
+"\n"
+"\n"
+"#TODO finish docstring\n"
+"\n"
+"@extend(Model)\n"
+"def get_translatable_fields(self, cr, uid, fields, context=None):\n"
+"    #TODO make fields parameter optionnal\n"
+"    def is_translatable(field):\n"
+"        if self._columns.get(field):\n"
+"            return self._columns[field].translate\n"
+"        else:\n"
+"            return self._inherit_fields[field][2].translate\n"
+"    translatable_fields = []\n"
+"    untranslatable_fields = []\n"
+"    for field in fields:\n"
+"        if is_translatable(field):\n"
+"            translatable_fields.append(field)\n"
+"        else:\n"
+"            untranslatable_fields.append(field)\n"
+"    return translatable_fields, untranslatable_fields\n"
+"\n"
+"@extend(Model)\n"
+"def multi_lang_read(self, cr, uid, external_session, ids, fields_to_read, langs, resources=None, use_multi_lang = True, context=None):\n"
+"    if not resources:\n"
+"        resources = {}\n"
+"    translatable_fields, untranslatable_fields = self.get_translatable_fields(cr, uid, fields_to_read, context=context)\n"
+"    lang_support = external_session.referential_id._lang_support\n"
+"    if lang_support == 'fields_with_no_lang':\n"
+"        langs.insert(0, 'no_lang')\n"
+"    first=True\n"
+"    fields = fields_to_read\n"
+"    for lang in langs:\n"
+"        ctx = context.copy()\n"
+"        if lang == 'no_lang':\n"
+"            fields = untranslatable_fields\n"
+"        else:\n"
+"            if not first and lang_support == 'fields_with_main_lang' or lang_support == 'fields_with_no_lang':\n"
+"                fields = translatable_fields\n"
+"            ctx['lang'] = lang\n"
+"\n"
+"        if fields:\n"
+"            for resource in self.read(cr, uid, ids, fields, context=ctx):\n"
+"                if not resources.get(resource['id']): resources[resource['id']] = {}\n"
+"                resources[resource['id']][lang] = resource\n"
+"        first = False\n"
+"    return resources\n"
+"\n"
+"@extend(Model)\n"
+"def full_read(self, cr, uid, external_session, ids, langs, resources, mapping=None, mapping_id=None, context=None):\n"
+"    fields_to_read = self.get_field_to_export(cr, uid, ids, mapping, mapping_id, context=context)\n"
+"    return self.multi_lang_read(cr, uid, external_session, ids, fields_to_read, langs, resources=resources, context=context)\n"
+"\n"
+"@extend(Model)\n"
+"def smart_read(self, cr, uid, external_session, ids, langs, resources, group_ids, inherits_group_ids, last_exported_date=None,\n"
+"                                                                        mapping=None, mapping_id=None, context=None):\n"
+"    if last_exported_date:\n"
+"        search_filter = []\n"
+"        if group_ids:\n"
+"            if inherits_group_ids:\n"
+"                search_filter = ['|', ['x_last_update', '>=', last_exported_date], ['%s.x_last_update'%self._inherits[self._inherits.keys()[0]], '>=', last_exported_date]]\n"
+"        if inherits_group_ids:\n"
+"            search_filter = [['%s.x_last_update'%self._inherits[self._inherits.keys()[0]], '>=', last_exported_date]]\n"
+"        resource_ids_full_read = self.search(cr, uid, search_filter, context=context)\n"
+"        resource_ids_partial_read = [id for id in ids if not id in resource_ids_full_read]\n"
+"    else:\n"
+"        resource_ids_full_read = ids\n"
+"        resource_ids_partial_read = []\n"
+"\n"
+"    resources = self.full_read(cr, uid, external_session, resource_ids_full_read, langs, resources, context=context)\n"
+"\n"
+"    if resource_ids_partial_read:\n"
+"        for group in self.pool.get('group.fields').browse(cr, uid, group_ids, context=context):\n"
+"            resource_ids = self.search(cr, uid, [[group.column_name, '>=', last_exported_date],['id', 'in', resource_ids_partial_read]], context=context)\n"
+"            fields_to_read = [field.name for field in group.field_ids]\n"
+"            resources = self.multi_lang_read(cr, uid, external_session, resource_ids, fields_to_read, langs, resources=resources, context=context)\n"
+"    return resources\n"
+"\n"
+"@extend(Model)\n"
+"def get_field_to_export(self, cr, uid, ids, mapping, mapping_id, context=None):\n"
+"    return list(set(self._columns.keys() + self._inherit_fields.keys()))\n"
+"\n"
+"@extend(Model)\n"
+"def _get_oe_resources(self, cr, uid, external_session, ids, langs, smart_export=None,\n"
+"                                            last_exported_date=None, mapping=None, mapping_id=None, context=None):\n"
+"    resources = None\n"
+"    if smart_export:\n"
+"        resources = self.smart_read(cr, uid, external_session, ids, langs, resources, smart_export['group_ids'], smart_export['inherits_group_ids'],\n"
+"                            last_exported_date=last_exported_date, mapping=mapping, mapping_id=mapping_id, context=context)\n"
+"    else:\n"
+"        resources = self.full_read(cr, uid, external_session, ids, langs, resources, mapping=mapping, mapping_id=mapping_id, context=context)\n"
+"    return resources\n"
+"\n"
+"\n"
+"@extend(Model)\n"
+"def _get_oeid_from_extid_or_alternative_keys(self, cr, uid, vals, external_id, referential_id, alternative_keys, context=None):\n"
+"    \"\n"
+"    Used in ext_import in order to search the OpenERP resource to update when importing an external resource.\n"
+"    It searches the reference in ir.model.data and returns the id in ir.model.data and the id of the\n"
+"    current's model resource, if it really exists (it may not exists, see below)\n"
+"\n"
+"    As OpenERP cleans up ir_model_data which res_id records have been deleted only at server update\n"
+"    because that would be a perf penalty, so we take care of it here.\n"
+"\n"
+"    This method can also be used by inheriting, in order to find and bind resources by another way than ir.model.data when\n"
+"    the resource is not already imported.\n"
+"    As instance, search and bind partners by their mails. In such case, it must returns False for the ir_model_data.id and\n"
+"    the partner to bind for the resource id\n"
+"\n"
+"    @param vals: vals to create in OpenERP, already evaluated by _transform_one_external_resource\n"
+"    @param external_id: external id of the resource to create\n"
+"    @param referential_id: external referential id from where we import the resource\n"
+"    @return: tuple of (ir.model.data id / False: external id to create in ir.model.data, model resource id / False: resource to create)\n"
+"    \"\n"
+"    existing_ir_model_data_id = expected_res_id = False\n"
+"    if not (external_id is None or external_id is False):\n"
+"        existing_ir_model_data_id, expected_res_id = self._get_expected_oeid        (cr, uid, external_id, referential_id, context=context)\n"
+"\n"
+"    if not expected_res_id and alternative_keys:\n"
+"        domain = []\n"
+"        if 'active' in self._columns.keys():\n"
+"            domain = ['|', ('active', '=', False), ('active', '=', True)]\n"
+"        for alternative_key in alternative_keys:\n"
+"            if vals.get(alternative_key):\n"
+"                exp = type(vals[alternative_key]) in (str, unicode) and \"=ilike\" or \"=\"\n"
+"                domain.append((alternative_key, exp, vals[alternative_key]))\n"
+"        if domain:\n"
+"            expected_res_id = self.search(cr, uid, domain, context=context)\n"
+"            expected_res_id = expected_res_id and expected_res_id[0] or False\n"
+"    return existing_ir_model_data_id, expected_res_id\n"
+"\n"
+"@extend(Model)\n"
+"def _prepare_external_id_vals(self, cr, uid, res_id, ext_id, referential_id, context=None):\n"
+"    \" Create an external reference for a resource id in the ir.model.data table\"\n"
+"    ir_model_data_vals = {\n"
+"                            'name': self.prefixed_id(ext_id),\n"
+"                            'model': self._name,\n"
+"                            'res_id': res_id,\n"
+"                            'referential_id': referential_id,\n"
+"                            'module': 'extref/' + self.pool.get('external.referential').                            read(cr, uid, referential_id, ['name'])['name']\n"
+"                          }\n"
+"    return ir_model_data_vals\n"
+"\n"
+"@extend(Model)\n"
+"def create_external_id_vals(self, cr, uid, existing_rec_id, external_id, referential_id, context=None):\n"
+"    \"\n"
+"    Add the external id in the table ir_model_data\n"
+"    :param id existing_rec_id: erp id object\n"
+"    :param id external_id: external application id\n"
+"    :param id referential_id: external id\n"
+"    :rtype: int\n"
+"    :return:\n"
+"    \"\n"
+"    ir_model_data_vals =     self._prepare_external_id_vals(cr, uid, existing_rec_id,\n"
+"                                   external_id, referential_id,\n"
+"                                   context=context)\n"
+"    return self.pool.get('ir.model.data').create(cr, uid, ir_model_data_vals, context=context)\n"
+"\n"
+"########################################################################################################################\n"
+"#\n"
+"#                                             END OF EXPORT FEATURES\n"
+"#\n"
+"########################################################################################################################\n"
+"\n"
+"\n"
+"\n"
+"\n"
+"\n"
+"########################################################################################################################\n"
+"#\n"
+"#                                             GENERIC TRANSFORM FEATURES\n"
+"#\n"
+"########################################################################################################################\n"
+"\n"
+"@extend(Model)\n"
+"def _transform_resources(self, cr, uid, external_session, convertion_type, resources, mapping=None, mapping_id=None,\n"
+"                    mapping_line_filter_ids=None, parent_data=None, defaults=None, context=None):\n"
+"    \"\n"
+"    Used in ext_import in order to convert all of the external data into OpenERP data\n"
+"\n"
+"    @param external_data: list of external_data to convert into OpenERP data\n"
+"    @param referential_id: external referential id from where we import the resource\n"
+"    @param parent_data: data of the parent, only use when a mapping line have the type 'sub mapping'\n"
+"    @param defaults: defaults value for data converted\n"
+"    @return: list of the line converted into OpenERP value\n"
+"    \"\n"
+"    result= []\n"
+"    if resources:\n"
+"        mapping, mapping_id = self._init_mapping(cr, uid, external_session.referential_id.id,\n"
+"                                                 convertion_type=convertion_type,\n"
+"                                                 mapping_line_filter_ids=mapping_line_filter_ids,\n"
+"                                                 mapping=mapping,\n"
+"                                                 mapping_id=mapping_id,\n"
+"                                                 context=context)\n"
+"        if mapping[mapping_id].get(\"mapping_lines"
+msgstr "The field referential_id doesn't exist on the object %s.\" %(browse_record._name,)))\n"
+"        context = self.init_context_before_exporting_resource(cr, uid, external_session, browse_record.id, resource_name, context=context)\n"
+"        self.pool.get(resource_name)._export_resources(cr, uid, external_session, context=context)\n"
+"    return True\n"
+"\n"
+"\n"
+"#TODO refactor update date,maybe it will be better to have an update date per resource\n"
+"#TODO deal correctly with multi resource\n"
+"@extend(Model)\n"
+"def send_to_external(self, cr, uid, external_session, resources, mapping, mapping_id, update_date=None, context=None):\n"
+"    \"Generic method that send the resource to an external referential\n"
+"\n"
+"    :param ExternalSession external_session : External_session that contain all params of connection\n"
+"    :param list resources: list of resources to export\n"
+"    :param dict mapping: dictionnary of mapping, the key is the mapping id\n"
+"    :param date update_date: if not empty the update date will be write in the last update date of the objec\n"
+"    :rtype: int/str\n"
+"    :return: the external resource exported\n"
+"\n"
+"    \"\n"
+"    resources_to_update = {}\n"
+"    resources_to_create = {}\n"
+"    for resource_id, resource in resources.items():\n"
+"        ext_id = self.get_extid(cr, uid, resource_id, external_session.referential_id.id, context=context)\n"
+"        if ext_id:\n"
+"            for lang in resource:\n"
+"                resource[lang]['ext_id'] = ext_id\n"
+"            resources_to_update[resource_id] = resource\n"
+"        else:\n"
+"            resources_to_create[resource_id] = resource\n"
+"    self.ext_update(cr, uid, external_session, resources_to_update, mapping, mapping_id, context=context)\n"
+"    ext_create_ids = self.ext_create(cr, uid, external_session, resources_to_create, mapping, mapping_id, context=context)\n"
+"    for rec_id, ext_id in ext_create_ids.items():\n"
+"        self.create_external_id_vals(cr, uid, rec_id, ext_id, external_session.referential_id.id, context=context)\n"
+"    if update_date and self._get_last_exported_date(cr, uid, external_session, context=context) < update_date:\n"
+"        self._set_last_exported_date(cr, uid, external_session, update_date, context=context)\n"
+"    return ext_id\n"
+"\n"
+"@extend(Model)\n"
+"def ext_create(self, cr, uid, external_session, resources, mapping=None, mapping_id=None, context=None):\n"
+"    res = {}\n"
+"    mapping, mapping_id = self._init_mapping(cr, uid, external_session.referential_id.id, mapping=mapping, mapping_id=mapping_id, context=context)\n"
+"    for resource_id, resource in resources.items():\n"
+"        # TODO support multilanguages. for now we only export the first one\n"
+"        res[resource_id] = getattr(external_session.connection, mapping[mapping_id]['external_create_method'])(mapping[mapping_id]['external_resource_name'], resource[resource.keys()[0]])\n"
+"    return res\n"
+"\n"
+"@extend(Model)\n"
+"def ext_update(self, cr, uid, external_session, resources, mapping=None, mapping_id=None, context=None):\n"
+"    \"Not Implemented here\"\n"
+"    return False\n"
+"\n"
+"@extend(Model)\n"
+"def ext_unlink(self, cr, uid, ids, context=None):\n"
+"    ir_model_obj = self.pool.get('ir.model.data')\n"
+"    for object_id in ids:\n"
+"        ir_model_ids = ir_model_obj.search(cr, uid, [('res_id','=',object_id),('model','=',self._name)])\n"
+"        for ir_model in ir_model_obj.browse(cr, uid, ir_model_ids, context=context):\n"
+"            ext_id = self.id_from_prefixed_id(ir_model.name)\n"
+"            ref_id = ir_model.referential_id.id\n"
+"            external_session = ExternalSession(ir_model.referential_id)\n"
+"            mapping = self._get_mapping(cr, uid, ref_id)\n"
+"            getattr(external_session.connection, mapping['external_delete_method'])(mapping['external_resource_name'], ext_id)\n"
+"            #commit_now(ir_model.unlink())\n"
+"            ir_model.unlink()\n"
+"    return True\n"
+"\n"
+"@extend(Model)\n"
+"def get_lang_to_export(self, cr, uid, external_session, context=None):\n"
+"    \"Get the list of lang to export\n"
+"\n"
+"    :param ExternalSession external_session : External_session that contain all params of connection\n"
+"    :rtype: list\n"
+"    return: the list of lang to export\n"
+"    \"\n"
+"\n"
+"    if context is None:\n"
+"        return []\n"
+"    else:\n"
+"        return context.get('lang_to_export') or [context.get('lang')]\n"
+"\n"
+"@extend(Model)\n"
+"def _export_resources(self, cr, uid, external_session, method=\"onebyone\", context=None):\n"
+"    \"Export resource\n"
+"\n"
+"    :param ExternalSession external_session : External_session that contain all params of connection\n"
+"    :param str method: method to export data (for now only onebyone)\n"
+"    :rtype: boolean\n"
+"    return: True\n"
+"    \"\n"
+"    external_session.logger.info(\"Start to export the ressource %s\"%(self._name,))\n"
+"    defaults = self._get_default_export_values(cr, uid, external_session, context=context)\n"
+"    mapping, mapping_id = self._init_mapping(cr, uid, external_session.referential_id.id, convertion_type='from_openerp_to_external', context=context)\n"
+"    last_exported_date = self._get_last_exported_date(cr, uid, external_session, context=context)\n"
+"    external_session.logger.info(\"Retrieve the list of ids to export for the ressource %s\"%(self._name))\n"
+"    ids, ids_2_date = self.get_ids_and_update_date(cr, uid, external_session, last_exported_date=last_exported_date, context=context)\n"
+"    external_session.logger.info(\"%s %s ressource will be exported\"%((ids and len(ids) or 0), self._name))\n"
+"    step = self._get_export_step(cr, uid, external_session, context=context)\n"
+"\n"
+"    group_obj = self.pool.get('group.fields')\n"
+"    group_ids = group_obj.search(cr, uid, [['model_id', '=', self._name]], context=context)\n"
+"    if self._inherits:\n"
+"        inherits_group_ids = group_obj.search(cr, uid, [['model_id', '=',self._inherits.keys()[0]]], context=context)\n"
+"    else:\n"
+"        inherits_group_ids=[]\n"
+"    smart_export =  context.get('smart_export') and (group_ids or inherits_group_ids) and {'group_ids': group_ids, 'inherits_group_ids': inherits_group_ids}\n"
+"\n"
+"    langs = self.get_lang_to_export(cr, uid, external_session, context=context)\n"
+"\n"
+"    while ids:\n"
+"        ids_to_process = ids[0:step]\n"
+"        ids = ids[step:]\n"
+"        external_session.logger.info(\"Start to read the ressource %s : %s\"%(self._name, ids_to_process))\n"
+"        resources = self._get_oe_resources(cr, uid, external_session, ids_to_process, langs=langs,\n"
+"                                    smart_export=smart_export, last_exported_date=last_exported_date,\n"
+"                                    mapping=mapping, mapping_id=mapping_id, context=context)\n"
+"        if method == 'onebyone':\n"
+"            for resource_id in ids_to_process:\n"
+"                external_session.logger.info(\"Start to transform and send the ressource %s : %s\"%(self._name, resource_id))\n"
+"                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)\n"
+"        else:\n"
+"            raise except_osv(_('Developper Error'), _('only method export onebyone is implemented in base_external_referentials'))\n"
+"    #now = datetime.now().strftime(DEFAULT_SERVER_DATETIME_FORMAT)\n"
+"    #self._set_last_exported_date(cr, uid, external_session, now, context=context)\n"
+"    return True\n"
+"\n"
+"@extend(Model)\n"
+"def _transform_and_send_one_resource(self, cr, uid, external_session, resource, resource_id,\n"
+"                            update_date, mapping, mapping_id, defaults=None, context=None):\n"
+"    \"Transform and send one resource\n"
+"    The resource will converted into External format by using the function _transform_one_resource\n"
+"    And then send to the external system using the method send_to_external\n"
+"\n"
+"    :param ExternalSession external_session : External_session that contain all params of connection\n"
+"    :param dict resource: resource to convert into OpenERP data\n"
+"    :param int resource_id: openerp id of the resource to send\n"
+"    :param str method: method to export data (for now only onebyone)\n"
+"    :param dict mapping: dictionnary of mapping, the key is the mapping id\n"
+"    :param int mapping_id: mapping id\n"
+"    :param dict defaults: default values\n"
+"    :rtype: str/int\n"
+"    :return: the external id\n"
+"    \"\n"
+"    for key_lang in resource:\n"
+"        resource[key_lang] = self._transform_one_resource(cr, uid, external_session, 'from_openerp_to_external',\n"
+"                                            resource[key_lang], mapping=mapping, mapping_id=mapping_id,\n"
+"                                            defaults=defaults, context=context)\n"
+"    return self.send_to_external(cr, uid, external_session, {resource_id : resource}, mapping, mapping_id, update_date, context=context)\n"
+"\n"
+"@extend(Model)\n"
+"def _export_one_resource(self, cr, uid, external_session, resource_id, context=None):\n"
+"    \"Export one resource\n"
+"    Export an OpenERP resource into an external system\n"
+"\n"
+"    :param ExternalSession external_session : External_session that contain all params of connection\n"
+"    :param int resource_id: openerp id of the resource to send\n"
+"    :rtype: str/int\n"
+"    :return: the external id\n"
+"    \"\n"
+"    defaults = self._get_default_export_values(cr, uid, external_session, context=context)\n"
+"    mapping, mapping_id = self._init_mapping(cr, uid, external_session.referential_id.id, convertion_type='from_openerp_to_external', context=context)\n"
+"    langs = self.get_lang_to_export(cr, uid, external_session, context=context)\n"
+"    resource = self._get_oe_resources(cr, uid, external_session, [resource_id], langs=langs,\n"
+"                                smart_export=False, last_exported_date=False,\n"
+"                                mapping=mapping, mapping_id=mapping_id, context=context)[resource_id]\n"
+"    return self._transform_and_send_one_resource(cr, uid, external_session, resource, resource_id,\n"
+"                            False, mapping, mapping_id, defaults=defaults, context=context)\n"
+"\n"
+"\n"
+"#TODO finish docstring\n"
+"\n"
+"@extend(Model)\n"
+"def get_translatable_fields(self, cr, uid, fields, context=None):\n"
+"    #TODO make fields parameter optionnal\n"
+"    def is_translatable(field):\n"
+"        if self._columns.get(field):\n"
+"            return self._columns[field].translate\n"
+"        else:\n"
+"            return self._inherit_fields[field][2].translate\n"
+"    translatable_fields = []\n"
+"    untranslatable_fields = []\n"
+"    for field in fields:\n"
+"        if is_translatable(field):\n"
+"            translatable_fields.append(field)\n"
+"        else:\n"
+"            untranslatable_fields.append(field)\n"
+"    return translatable_fields, untranslatable_fields\n"
+"\n"
+"@extend(Model)\n"
+"def multi_lang_read(self, cr, uid, external_session, ids, fields_to_read, langs, resources=None, use_multi_lang = True, context=None):\n"
+"    if not resources:\n"
+"        resources = {}\n"
+"    translatable_fields, untranslatable_fields = self.get_translatable_fields(cr, uid, fields_to_read, context=context)\n"
+"    lang_support = external_session.referential_id._lang_support\n"
+"    if lang_support == 'fields_with_no_lang':\n"
+"        langs.insert(0, 'no_lang')\n"
+"    first=True\n"
+"    fields = fields_to_read\n"
+"    for lang in langs:\n"
+"        ctx = context.copy()\n"
+"        if lang == 'no_lang':\n"
+"            fields = untranslatable_fields\n"
+"        else:\n"
+"            if not first and lang_support == 'fields_with_main_lang' or lang_support == 'fields_with_no_lang':\n"
+"                fields = translatable_fields\n"
+"            ctx['lang'] = lang\n"
+"\n"
+"        if fields:\n"
+"            for resource in self.read(cr, uid, ids, fields, context=ctx):\n"
+"                if not resources.get(resource['id']): resources[resource['id']] = {}\n"
+"                resources[resource['id']][lang] = resource\n"
+"        first = False\n"
+"    return resources\n"
+"\n"
+"@extend(Model)\n"
+"def full_read(self, cr, uid, external_session, ids, langs, resources, mapping=None, mapping_id=None, context=None):\n"
+"    fields_to_read = self.get_field_to_export(cr, uid, ids, mapping, mapping_id, context=context)\n"
+"    return self.multi_lang_read(cr, uid, external_session, ids, fields_to_read, langs, resources=resources, context=context)\n"
+"\n"
+"@extend(Model)\n"
+"def smart_read(self, cr, uid, external_session, ids, langs, resources, group_ids, inherits_group_ids, last_exported_date=None,\n"
+"                                                                        mapping=None, mapping_id=None, context=None):\n"
+"    if last_exported_date:\n"
+"        search_filter = []\n"
+"        if group_ids:\n"
+"            if inherits_group_ids:\n"
+"                search_filter = ['|', ['x_last_update', '>=', last_exported_date], ['%s.x_last_update'%self._inherits[self._inherits.keys()[0]], '>=', last_exported_date]]\n"
+"        if inherits_group_ids:\n"
+"            search_filter = [['%s.x_last_update'%self._inherits[self._inherits.keys()[0]], '>=', last_exported_date]]\n"
+"        resource_ids_full_read = self.search(cr, uid, search_filter, context=context)\n"
+"        resource_ids_partial_read = [id for id in ids if not id in resource_ids_full_read]\n"
+"    else:\n"
+"        resource_ids_full_read = ids\n"
+"        resource_ids_partial_read = []\n"
+"\n"
+"    resources = self.full_read(cr, uid, external_session, resource_ids_full_read, langs, resources, context=context)\n"
+"\n"
+"    if resource_ids_partial_read:\n"
+"        for group in self.pool.get('group.fields').browse(cr, uid, group_ids, context=context):\n"
+"            resource_ids = self.search(cr, uid, [[group.column_name, '>=', last_exported_date],['id', 'in', resource_ids_partial_read]], context=context)\n"
+"            fields_to_read = [field.name for field in group.field_ids]\n"
+"            resources = self.multi_lang_read(cr, uid, external_session, resource_ids, fields_to_read, langs, resources=resources, context=context)\n"
+"    return resources\n"
+"\n"
+"@extend(Model)\n"
+"def get_field_to_export(self, cr, uid, ids, mapping, mapping_id, context=None):\n"
+"    return list(set(self._columns.keys() + self._inherit_fields.keys()))\n"
+"\n"
+"@extend(Model)\n"
+"def _get_oe_resources(self, cr, uid, external_session, ids, langs, smart_export=None,\n"
+"                                            last_exported_date=None, mapping=None, mapping_id=None, context=None):\n"
+"    resources = None\n"
+"    if smart_export:\n"
+"        resources = self.smart_read(cr, uid, external_session, ids, langs, resources, smart_export['group_ids'], smart_export['inherits_group_ids'],\n"
+"                            last_exported_date=last_exported_date, mapping=mapping, mapping_id=mapping_id, context=context)\n"
+"    else:\n"
+"        resources = self.full_read(cr, uid, external_session, ids, langs, resources, mapping=mapping, mapping_id=mapping_id, context=context)\n"
+"    return resources\n"
+"\n"
+"\n"
+"@extend(Model)\n"
+"def _get_oeid_from_extid_or_alternative_keys(self, cr, uid, vals, external_id, referential_id, alternative_keys, context=None):\n"
+"    \"\n"
+"    Used in ext_import in order to search the OpenERP resource to update when importing an external resource.\n"
+"    It searches the reference in ir.model.data and returns the id in ir.model.data and the id of the\n"
+"    current's model resource, if it really exists (it may not exists, see below)\n"
+"\n"
+"    As OpenERP cleans up ir_model_data which res_id records have been deleted only at server update\n"
+"    because that would be a perf penalty, so we take care of it here.\n"
+"\n"
+"    This method can also be used by inheriting, in order to find and bind resources by another way than ir.model.data when\n"
+"    the resource is not already imported.\n"
+"    As instance, search and bind partners by their mails. In such case, it must returns False for the ir_model_data.id and\n"
+"    the partner to bind for the resource id\n"
+"\n"
+"    @param vals: vals to create in OpenERP, already evaluated by _transform_one_external_resource\n"
+"    @param external_id: external id of the resource to create\n"
+"    @param referential_id: external referential id from where we import the resource\n"
+"    @return: tuple of (ir.model.data id / False: external id to create in ir.model.data, model resource id / False: resource to create)\n"
+"    \"\n"
+"    existing_ir_model_data_id = expected_res_id = False\n"
+"    if not (external_id is None or external_id is False):\n"
+"        existing_ir_model_data_id, expected_res_id = self._get_expected_oeid        (cr, uid, external_id, referential_id, context=context)\n"
+"\n"
+"    if not expected_res_id and alternative_keys:\n"
+"        domain = []\n"
+"        if 'active' in self._columns.keys():\n"
+"            domain = ['|', ('active', '=', False), ('active', '=', True)]\n"
+"        for alternative_key in alternative_keys:\n"
+"            if vals.get(alternative_key):\n"
+"                exp = type(vals[alternative_key]) in (str, unicode) and \"=ilike\" or \"=\"\n"
+"                domain.append((alternative_key, exp, vals[alternative_key]))\n"
+"        if domain:\n"
+"            expected_res_id = self.search(cr, uid, domain, context=context)\n"
+"            expected_res_id = expected_res_id and expected_res_id[0] or False\n"
+"    return existing_ir_model_data_id, expected_res_id\n"
+"\n"
+"@extend(Model)\n"
+"def _prepare_external_id_vals(self, cr, uid, res_id, ext_id, referential_id, context=None):\n"
+"    \" Create an external reference for a resource id in the ir.model.data table\"\n"
+"    ir_model_data_vals = {\n"
+"                            'name': self.prefixed_id(ext_id),\n"
+"                            'model': self._name,\n"
+"                            'res_id': res_id,\n"
+"                            'referential_id': referential_id,\n"
+"                            'module': 'extref/' + self.pool.get('external.referential').                            read(cr, uid, referential_id, ['name'])['name']\n"
+"                          }\n"
+"    return ir_model_data_vals\n"
+"\n"
+"@extend(Model)\n"
+"def create_external_id_vals(self, cr, uid, existing_rec_id, external_id, referential_id, context=None):\n"
+"    \"\n"
+"    Add the external id in the table ir_model_data\n"
+"    :param id existing_rec_id: erp id object\n"
+"    :param id external_id: external application id\n"
+"    :param id referential_id: external id\n"
+"    :rtype: int\n"
+"    :return:\n"
+"    \"\n"
+"    ir_model_data_vals =     self._prepare_external_id_vals(cr, uid, existing_rec_id,\n"
+"                                   external_id, referential_id,\n"
+"                                   context=context)\n"
+"    return self.pool.get('ir.model.data').create(cr, uid, ir_model_data_vals, context=context)\n"
+"\n"
+"########################################################################################################################\n"
+"#\n"
+"#                                             END OF EXPORT FEATURES\n"
+"#\n"
+"########################################################################################################################\n"
+"\n"
+"\n"
+"\n"
+"\n"
+"\n"
+"########################################################################################################################\n"
+"#\n"
+"#                                             GENERIC TRANSFORM FEATURES\n"
+"#\n"
+"########################################################################################################################\n"
+"\n"
+"@extend(Model)\n"
+"def _transform_resources(self, cr, uid, external_session, convertion_type, resources, mapping=None, mapping_id=None,\n"
+"                    mapping_line_filter_ids=None, parent_data=None, defaults=None, context=None):\n"
+"    \"\n"
+"    Used in ext_import in order to convert all of the external data into OpenERP data\n"
+"\n"
+"    @param external_data: list of external_data to convert into OpenERP data\n"
+"    @param referential_id: external referential id from where we import the resource\n"
+"    @param parent_data: data of the parent, only use when a mapping line have the type 'sub mapping'\n"
+"    @param defaults: defaults value for data converted\n"
+"    @return: list of the line converted into OpenERP value\n"
+"    \"\n"
+"    result= []\n"
+"    if resources:\n"
+"        mapping, mapping_id = self._init_mapping(cr, uid, external_session.referential_id.id,\n"
+"                                                 convertion_type=convertion_type,\n"
+"                                                 mapping_line_filter_ids=mapping_line_filter_ids,\n"
+"                                                 mapping=mapping,\n"
+"                                                 mapping_id=mapping_id,\n"
+"                                                 context=context)\n"
+"        if mapping[mapping_id].get(\"mapping_lines"
+
+#. module: base_external_referentials
+#: field:external.report,action:0
+#: view:external.report.line:0
+#: field:external.report.line,action:0
+msgid "Action"
+msgstr "Action"
+
+#. module: base_external_referentials
+#: field:external.report,line_ids:0
+msgid "Report Lines"
+msgstr "Lignes de rapports"
+
+#. module: base_external_referentials
+#: view:external.report:0
+msgid "Delete All Failed"
+msgstr "Supprimer tous les échecs"
+
+#. module: base_external_referentials
+#: view:external.referential:0
+msgid "3- Export version"
+msgstr "3- Export de la version du référentiel"
+
+#. module: base_external_referentials
+#: view:external.mapping.line:0
+#: field:external.mapping.line,out_function:0
+#: field:external.mappinglines.template,out_function:0
+msgid "Export from OpenERP Mapping Python Function"
+msgstr "Export from OpenERP Mapping Python Function"
+
+#. module: base_external_referentials
+#: view:external.mapping:0
+#: view:external.mapping.line:0
+#: field:external.mapping.line,mapping_id:0
+#: field:external.mappinglines.template,mapping_id:0
+#: model:ir.model,name:base_external_referentials.model_external_mapping
+msgid "External Mapping"
+msgstr "Mapping externe"
+
+#. module: base_external_referentials
+#: view:external.referential:0
+msgid "2 - Synchronize Referential Settings"
+msgstr "2 - Synchroniser les paramètres du référentiel"
+
+#. module: base_external_referentials
+#: field:external.mapping,external_delete_method:0
+#: field:external.mapping.template,external_delete_method:0
+msgid "Delete Method"
+msgstr "Méthode de suppression"
+
+#. module: base_external_referentials
+#: field:external.report.history,report_id:0
+#: field:external.report.line,report_id:0
+#: model:ir.model,name:base_external_referentials.model_external_report
+#: model:ir.ui.menu,name:base_external_referentials.ir_ui_menu_external_report
+msgid "External Report"
+msgstr "Rapports externes"
+
+#. module: base_external_referentials
+#: model:ir.model,name:base_external_referentials.model_external_referential_version
+msgid "External Referential Version (Ex: v1.5.0.0 +, v1.3.2.4 +)"
+msgstr "Version du référentiel externe (Ex: v1.5.0.0 +, v1.3.2.4 +)"
+
+#. module: base_external_referentials
+#: selection:external.mapping.line,external_type:0
+#: selection:external.mappinglines.template,external_type:0
+msgid "Float"
+msgstr "Float"
+
+#. module: base_external_referentials
+#: field:external.report,action_on:0
+#: field:external.report.line,action_on:0
+msgid "Action On"
+msgstr "Action sur"
+
+#. module: base_external_referentials
+#: view:external.report.line:0
+#: field:external.report.line,kwargs_text:0
+msgid "Kwargs Data"
+msgstr "Kwargs Data"
+
+#. module: base_external_referentials
+#: view:external.report.line:0
+#: field:external.report.line,args_text:0
+msgid "Args Data"
+msgstr "Args Data"
+
+#. module: base_external_referentials
+#: model:ir.actions.act_window,name:base_external_referentials.ext_sale_shop
+msgid "External Shop"
+msgstr "Boutique externe"
+
+#. module: base_external_referentials
+#: model:ir.model,name:base_external_referentials.model_group_fields
+msgid "trigger last write date by group of field"
+msgstr "trigger last write date by group of field"
+
+#. module: base_external_referentials
+#: field:external.report.line,kwargs:0
+msgid "Kwargs"
+msgstr "Kwargs"
+
+#. module: base_external_referentials
+#: help:external.mapping,extra_name:0
+msgid "In case you need to make many mappings on the same object"
+msgstr "En cas de besoin de créer plusieurs mappings pour le même objet"
+
+#. module: base_external_referentials
+#: selection:external.mapping.line,evaluation_type:0
+#: selection:external.mappinglines.template,evaluation_type:0
+msgid "Function"
+msgstr "Fonction"
+
+#. module: base_external_referentials
+#: field:external.report.line,res_id:0
+msgid "Resource Id"
+msgstr "Resource Id"
+
+#. module: base_external_referentials
+#: code:addons/base_external_referentials/decorator.py:64
+#, python-format
+msgid "Not parent method found"
+msgstr "Aucune méthode parent n'a été trouvée"
+
+#. module: base_external_referentials
+#: help:external.referential,create_date:0
+msgid "Date on which external referential is created."
+msgstr "Date de création du référentiel externe."
+
+#. module: base_external_referentials
+#: field:external.mapping.line,internal_field:0
+msgid "Field name"
+msgstr "Nom du champ"
+
+#. module: base_external_referentials
+#: view:external.mapping:0
+#: view:external.referential:0
+msgid "Add all object fields"
+msgstr "Ajouter tous les champs de l'objet"
+
+#. module: base_external_referentials
+#: field:external.mapping.line,internal_type:0
+msgid "Internal Type"
+msgstr "Type interne"
+
+#. module: base_external_referentials
+#: help:external.mapping.line,alternative_key:0
+#: help:external.mappinglines.template,alternative_key:0
+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"
+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"
+
+#. module: base_external_referentials
+#: field:external.referential,apipass:0
+msgid "Password"
+msgstr "Mot de passe"
+
+#. module: base_external_referentials
+#: view:external.mapping:0
+#: view:external.referential:0
+msgid "Export mapping file"
+msgstr "Export des fichers de mapping"
+
+#. module: base_external_referentials
+#: field:external.referential.category,type_ids:0
+msgid "Types"
+msgstr "Types"
+
+#. module: base_external_referentials
+#: field:external.report,sync_from_object_model:0
+msgid "Sync From Object"
+msgstr "Synchro depuis l'objet"
+
+#. module: base_external_referentials
+#: model:ir.actions.act_window,name:base_external_referentials.ext_res_partner_address
+msgid "External Address"
+msgstr "Adresse externe"
+
+#. module: base_external_referentials
+#: code:addons/base_external_referentials/external_osv.py:89
+#, python-format
+msgid "You can replace the method %s of the class %s. Indeed this method doesn't exist"
+msgstr "vous pouvez remplacer la méthode %s de la classe %s. En effet, cette méthode n'existe pas"
+
+#. module: base_external_referentials
+#: field:external.mapping.line,function_name:0
+#: field:external.mappinglines.template,function_name:0
+msgid "Function Name"
+msgstr "Function Name"
+
+#. module: base_external_referentials
+#: field:external.report.history,count_success:0
+msgid "Count Success"
+msgstr "Somme des succès"
+
+#. module: base_external_referentials
+#: model:ir.actions.act_window,name:base_external_referentials.ir_actions_act_window_external_mapping
+#: model:ir.ui.menu,name:base_external_referentials.ir_ui_menu_external_mappings
+msgid "External Mappings"
+msgstr "Mappings externes"
+
+#. module: base_external_referentials
+#: field:external.report.history,count_failed:0
+msgid "Count Failed"
+msgstr "Somme des échecs"
+
+#. module: base_external_referentials
+#: field:group.fields,field_ids:0
+#: model:ir.model,name:base_external_referentials.model_ir_model_fields
+msgid "Fields"
+msgstr "Champs"
+
+#. module: base_external_referentials
+#: selection:external.mapping.line,external_type:0
+#: selection:external.mappinglines.template,external_type:0
+msgid "List"
+msgstr "List"
+
+#. module: base_external_referentials
+#: field:external.mapping.line,external_type:0
+#: field:external.mappinglines.template,external_type:0
+#: field:external.referential,type_id:0
+msgid "External Type"
+msgstr "Type externe"
+
+#. module: base_external_referentials
+#: help:external.mapping.line,child_mapping_id:0
+#: help:external.mappinglines.template,child_mapping_id:0
+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"
+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."
+
+#. module: base_external_referentials
+#: view:group.fields:0
+#: field:group.fields,model_id:0
+msgid "Model"
+msgstr "Modèle"
+
+#. module: base_external_referentials
+#: field:external.mapping,external_update_method:0
+#: field:external.mapping.template,external_update_method:0
+msgid "Update Method"
+msgstr "Méthode de mise à jour"
+
+#. module: base_external_referentials
+#: view:external.report.line:0
+msgid "External Report Line"
+msgstr "Ligne de rapport externe"
+
+#. module: base_external_referentials
+#: field:external.mapping,model_id:0
+#: field:external.mapping.template,model_id:0
+msgid "OpenERP Model"
+msgstr "Modèle OpenERP"
+
+#. module: base_external_referentials
+#: sql_constraint:ir.model.data:0
+msgid "You cannot have on record with multiple external id for a same referential"
+msgstr "Vous ne pouvez pas avoir un enregistrement avec plusieurs id externe pour un même référentiel"
+
+#. module: base_external_referentials
+#: field:external.report.line,exception_type:0
+msgid "Exception Type"
+msgstr "Type d'exception"
+
+#. module: base_external_referentials
+#: field:external.report.line,external_id:0
+msgid "External ID"
+msgstr "ID externe"
+
+#. module: base_external_referentials
+#: view:external.referential:0
+msgid "5- Export mapping template"
+msgstr "5- Export des template de mapping"
+
+#. module: base_external_referentials
+#: field:external.mapping.line,template_id:0
+msgid "External Mapping Lines Template"
+msgstr "Template de lignes de mapping externe"
+
+#. module: base_external_referentials
+#: help:external.referential,debug:0
+msgid "If debug mode is active all request between the external referential and OpenERP will be in the log"
+msgstr "Si le mode debug est activé, toutes les requètes entre le référentiel externe et OpenERP apparaitront dans les logs"
+
+#. module: base_external_referentials
+#: selection:external.mapping.line,external_type:0
+#: selection:external.mappinglines.template,external_type:0
+msgid "Boolean"
+msgstr "Boolean"
+
+#. module: base_external_referentials
+#: field:group.fields,column_name:0
+msgid "Column Name"
+msgstr "Nom de la colonne"
+
+#. module: base_external_referentials
+#: field:external.mapping.line,evaluation_type:0
+#: field:external.mappinglines.template,evaluation_type:0
+msgid "Evalution Type"
+msgstr "Type pour l'évaluation"
+
+#. module: base_external_referentials
+#: view:external.referential:0
+msgid "4- Export referential"
+msgstr "4- Export du référentiel"
+
+#. module: base_external_referentials
+#: view:external.mapping.line:0
+msgid "External fields"
+msgstr "Champs externes"
+
+#. module: base_external_referentials
+#: view:external.report.line:0
+#: model:ir.actions.act_window,name:base_external_referentials.ir_actions_act_window_external_report_line
+#: model:ir.model,name:base_external_referentials.model_external_report_line
+#: model:ir.ui.menu,name:base_external_referentials.ir_ui_menu_external_report_line
+msgid "External Report Lines"
+msgstr "Lignes des rapports externes"
+

=== modified file 'base_external_referentials/ir_model.py'
--- base_external_referentials/ir_model.py	2012-03-14 13:44:15 +0000
+++ base_external_referentials/ir_model.py	2012-11-19 23:44:21 +0000
@@ -19,17 +19,30 @@
 #                                                                             #
 ###############################################################################
 
-from osv import osv
-
-
-class ir_model(osv.osv):
+from openerp.osv.orm import Model
+
+
+class ir_model(Model):
     _inherit='ir.model'
 
     def create_external_link(self, cr, uid, model_id, context=None):
         model = self.pool.get('ir.model').browse(cr, uid, model_id, context=context)
-        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'}
+        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',
+                }
         xml_id = "ext_" + model.model.replace(".", "_")
-        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')
+        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')
         value = 'ir.actions.act_window,'+str(ir_model_data_id)
-        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)
+        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)
 

=== modified file 'base_external_referentials/message_error.py'
--- base_external_referentials/message_error.py	2012-02-06 14:48:49 +0000
+++ base_external_referentials/message_error.py	2012-11-19 23:44:21 +0000
@@ -26,12 +26,14 @@
         self.mapping_name = mapping_name
         self.mapping_object = mapping_object
     def __str__(self):
-        return repr('the mapping line : %s for the object %s have an error : %s'%(self.mapping_name, self.mapping_object, self.value))
+        return 'the mapping line: %s for the object %s has this error: %s' % (self.mapping_name,
+                                                                             self.mapping_object,
+                                                                             self.value)
 
 
 class ExtConnError(Exception):
      def __init__(self, value):
          self.value = value
      def __str__(self):
-         return repr(self.value)
+         return str(self.value)
 

=== modified file 'base_external_referentials/report.py'
--- base_external_referentials/report.py	2012-08-21 07:39:24 +0000
+++ base_external_referentials/report.py	2012-11-19 23:44:21 +0000
@@ -18,19 +18,23 @@
 #
 ##############################################################################
 import time
-import pooler
 import logging
 import sys
 import traceback
-from osv import osv, fields
-from tools.translate import _
-from tools.safe_eval import safe_eval
+from openerp.osv.orm import Model
+from openerp.osv import fields
 from tools import DEFAULT_SERVER_DATETIME_FORMAT
 import simplejson
 from base_external_referentials.external_osv import ExternalSession
 from base_external_referentials.decorator import commit_now
 
-class external_report(osv.osv):
+MODEL_WITH_UNIQUE_REPORT_LINE = [
+    'product.product',
+    'product.category',
+    ]
+
+
+class external_report(Model):
     _name = 'external.report'
     _description = 'External Report'
     _order = 'name desc'
@@ -49,7 +53,7 @@
 
     _columns = {
         'name': fields.function(_get_full_name, store=True, type='char', size=256, string='Name'),
-        'action': fields.char('Action', size=32, required=True, readonly=True),
+        'action': fields.char('Action', size=256, required=True, readonly=True),
         'action_on': fields.many2one('ir.model', 'Action On',required=True, readonly=True),
         'sync_from_object_model': fields.many2one('ir.model', 'Sync From Object',
                                                         required=True, readonly=True),
@@ -60,6 +64,7 @@
         'failed_line_ids': fields.one2many('external.report.line', 'report_id',
                                         'Failed Report Lines', domain=[('state', '!=', 'success')]),
         'history_ids': fields.one2many('external.report.history','report_id', 'History'),
+        '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"),
     }
 
     def _get_report(self, cr, uid, action, action_on, sync_from_object, context=None):
@@ -104,7 +109,7 @@
             'action_on': action_on_model_id,
             'sync_from_object_model': model_id,
             'sync_from_object_id': sync_from_object.id,
-            'referential_id': sync_from_object._name == 'external.referential' and sync_from_object.id or sync_from_object.referential_id.id,
+            'referential_id': sync_from_object.id if sync_from_object._name == 'external.referential' else sync_from_object.referential_id.id,
         }
 
     @commit_now
@@ -161,10 +166,8 @@
                 self.pool.get('external.report.line').unlink(cr, uid, failed_line_ids, context=context)
         return True
 
-external_report()
-
-
-class external_report_history(osv.osv):
+
+class external_report_history(Model):
     _name = 'external.report.history'
     _description = 'External Report History'
     _rec_name = 'report_id'
@@ -203,10 +206,8 @@
         self.write(cr, uid, history_id, vals, context=context)
         return True
 
-external_report_history()
-
-
-class external_report_lines(osv.osv):
+
+class external_report_lines(Model):
     _name = 'external.report.line'
     _description = 'External Report Lines'
     _rec_name = 'res_id'
@@ -238,7 +239,7 @@
         'state': fields.selection((('success', 'Success'),
                                    ('fail', 'Failed')),
                                    'Status', required=True, readonly=True),
-        'action': fields.char('Action', size=32, required=True, readonly=True),
+        'action': fields.char('Action', size=256, required=True, readonly=True),
         'action_on': fields.many2one('ir.model', 'Action On',required=True, readonly=True),
         'res_id': fields.integer('Resource Id', readonly=True),
         'date': fields.datetime('Date', required=True, readonly=True),
@@ -258,6 +259,18 @@
         "date": lambda *a: time.strftime(DEFAULT_SERVER_DATETIME_FORMAT)
     }
 
+    def get_existing_line_id(self, cr, uid, action_on, action, res_id=None, external_id=None, context=None):
+        if context.get('retry_report_line_id'):
+            return context['retry_report_line_id']
+        elif action_on in MODEL_WITH_UNIQUE_REPORT_LINE:
+            existing_line_id = self.search(cr, uid, [
+                              ('action_on', '=', action_on),
+                              ('action', '=', action),
+                              ('res_id', '=', res_id),
+                              ('external_id', '=', external_id),
+                        ], context=context)
+            return existing_line_id and existing_line_id[0] or False
+        return False
 
     #TODO
     #1 - Did it usefull to log sucessfull entry?
@@ -267,7 +280,8 @@
     def start_log(self, cr, uid, action_on, action, res_id=None,
                   external_id=None, resource=None, args=None, kwargs=None):
         context = kwargs.get('context') or {}
-        existing_line_id = context.get('retry_report_line_id', False)
+        existing_line_id = self.get_existing_line_id(cr, uid,action_on, action,
+                                          res_id=res_id, external_id=external_id, context=context)
         report_id = context.get('report_id')
 
         if existing_line_id:
@@ -296,11 +310,17 @@
                         })
         return existing_line_id
 
-    @commit_now
     def log_fail(self, cr, uid, external_session, report_line_id, error_message, context=None):
+        self._log_fail(cr, uid, external_session, report_line_id, error_message, context=context)
+        if not context.get('no_mail'):
+            self._send_mail(cr, uid, report_line_id, context=context)
+        return True
+
+    @commit_now
+    def _log_fail(self, cr, uid, external_session, report_line_id, error_message, context=None):
         exc_type, exc_value, exc_traceback = sys.exc_info()
-
-        external_session and external_session.logger.exception(error_message)
+        if external_session:
+            external_session.logger.exception(error_message)
         self.write(cr, uid, report_line_id, {
                             'error_message': error_message,
                             'exception_type': exc_type,
@@ -314,6 +334,14 @@
         return True
 
     @commit_now
+    def _send_mail(self, cr, uid, report_line_id, context=None):
+        line = self.browse(cr, uid, report_line_id, context=context)
+        if line.report_id.email_tmpl_id:
+            self.pool.get('email.template').send_mail(cr, uid, line.report_id.email_tmpl_id.id,\
+                                                  report_line_id, force_send=True, context=context)
+        return True
+    
+    @commit_now
     def log_success(self, cr, uid, external_session, report_line_id, context=None):
         self.write(cr, uid, report_line_id, {'state': 'success'}, context=context)
         if external_session and external_session.tmp.get('history_id'):
@@ -337,6 +365,8 @@
                 if not kwargs.get('context', False):
                     kwargs['context']={}
 
+                #don't send email when retry
+                kwargs['context']['no_mail'] = True
                 # keep the id of the line to update it with the result
                 kwargs['context']['retry_report_line_id'] = log.id
 
@@ -344,6 +374,8 @@
             else:
                 if not kwargs.get('context', False):
                     kwargs['context']={}
+                #don't send email when retry
+                kwargs['context']['no_mail'] = True
                 kwargs['context']['retry_report_line_id'] = log.id
                 method(cr, uid, *args, **kwargs)
         return True
@@ -361,4 +393,3 @@
 
         return res
 
-external_report_lines()

=== added file 'base_external_referentials/report_mail_template.xml'
--- base_external_referentials/report_mail_template.xml	1970-01-01 00:00:00 +0000
+++ base_external_referentials/report_mail_template.xml	2012-11-19 23:44:21 +0000
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  crm_claim_categ_as_name for OpenERP
+  Copyright (C) 2012 Akretion Benoît GUILLOT <benoit.guillot@xxxxxxxxxxxx>
+  The licence is in the file __openerp__.py
+-->
+<openerp>
+    <data noupdate="1">
+
+        <!--Email template -->
+        <record id="email_template_report" model="email.template">
+            <field name="name">Reporting error</field>
+            <field name="email_from">${object.company_id.email or ''}</field>
+            <field name="subject">${object.company_id.name} Error with ${object.report_id.name or '' })</field>
+            <field name="email_to">${object.company_id.email or ''}</field>
+            <field name="model_id" ref="base_external_referentials.model_external_report_line"/>
+            <field name="auto_delete" eval="True"/>
+            <field name="lang">${object.company_id.partner_id.lang}</field>
+            <field name="body_html"><![CDATA[]]></field>
+            <field name="body_text"><![CDATA[
+An error occurred during the import of the ${object.report_id.action_on}
+
+The message is : ${object.error_message}]]></field>
+        </record>
+    </data>
+</openerp>

=== modified file 'base_external_referentials/report_view.xml'
--- base_external_referentials/report_view.xml	2012-08-19 21:30:31 +0000
+++ base_external_referentials/report_view.xml	2012-11-19 23:44:21 +0000
@@ -16,6 +16,7 @@
           <field name="sync_from_object_model"/>
           <field name="sync_from_object_id"/>
           <field name="referential_id"/>
+          <field name="email_tmpl_id"/>
           <newline/>
           <field name="failed_line_ids" nolabel="1" colspan="4"/>
           <button name="retry_failed_lines" string="Retry All Failed" icon="gtk-go-forward" type="object" colspan="2"/>

=== modified file 'base_file_protocole/__openerp__.py'
--- base_file_protocole/__openerp__.py	2012-02-20 03:02:09 +0000
+++ base_file_protocole/__openerp__.py	2012-11-19 23:44:21 +0000
@@ -27,9 +27,9 @@
     'description': """empty""",
     'author': 'Akretion',
     'website': 'http://www.akretion.com/',
-    'depends': ['base'], 
+    'depends': ['base'],
     'init_xml': [],
-    'update_xml': [ 
+    'update_xml': [
     ],
     'demo_xml': [],
     'installable': True,

=== modified file 'base_file_protocole/base_file_protocole.py'
--- base_file_protocole/base_file_protocole.py	2012-08-21 05:41:58 +0000
+++ base_file_protocole/base_file_protocole.py	2012-11-19 23:44:21 +0000
@@ -19,17 +19,20 @@
 #                                                                             #
 ###############################################################################
 
-from osv import osv, fields
-import netsvc
 from tempfile import TemporaryFile
-from ftplib import FTP
-import sys
+import ftplib
 import os
-import shutil
 import csv
 import paramiko
 import errno
 import functools
+import logging
+
+_logger = logging.getLogger(__name__)
+try:
+    import xlrd
+except ImportError:
+    _logger.warning('You must install xlrd, if you need to read xls file')
 
 def open_and_close_connection(func):
     """
@@ -50,7 +53,8 @@
     return wrapper
 
 # Extend paramiko lib with the method mkdirs
-def mkdirs(self, path, mode=511):
+def stfp_mkdirs(self, path, mode=511):
+    current_dir = self.getcwd()
     try:
         self.stat(path)
     except IOError, e:
@@ -63,7 +67,26 @@
                     self.mkdir(path, mode)
                 else:
                     raise
-paramiko.SFTPClient.mkdirs = mkdirs
+    self.stat(current_dir)
+paramiko.SFTPClient.mkdirs = stfp_mkdirs
+
+# Extend ftplib with the method mkdirs
+def ftp_mkdirs(self, path):
+    current_dir = self.pwd()
+    try:
+        self.cwd(path)
+    except ftplib.error_perm, e:
+        if "550" in str(e):
+            try:
+                self.mkd(path)
+            except ftplib.error_perm, e:
+                if "550" in str(e):
+                    self.mkdirs(os.path.dirname(path))
+                    self.mkd(path)
+                else:
+                    raise
+    self.cwd(current_dir)
+ftplib.FTP.mkdirs = ftp_mkdirs
 
 
 class FileConnection(object):
@@ -75,15 +98,16 @@
         self.protocole = protocole
         self.allow_dir_creation = allow_dir_creation
         self.location = location
-        self.home_folder = home_folder
+        self.home_folder = home_folder or '/'
         self.port = port
         self.user = user
         self.pwd = pwd
+        self.connection = None
 
 
     def connect(self):
         if self.is_('ftp'):
-            self.connection = FTP(self.location)
+            self.connection = ftplib.FTP(self.location)
             self.connection.login(self.user, self.pwd)
         elif self.is_('sftp'):
             transport = paramiko.Transport((self.location, self.port or 22))
@@ -91,12 +115,15 @@
             self.connection = paramiko.SFTPClient.from_transport(transport)
 
     def close(self):
-        if self.is_('ftp') or self.is_('sftp'):
+        if self.is_('ftp') or self.is_('sftp') and self.connection is not None:
             self.connection.close()
 
     @open_and_close_connection
     def send(self, filepath, filename, output_file, create_patch=None):
         if self.is_('ftp'):
+            filepath = os.path.join(self.home_folder, filepath)
+            if self.allow_dir_creation:
+                self.connection.mkdirs(filepath)
             self.connection.cwd(filepath)
             self.connection.storbinary('STOR ' + filename, output_file)
             output_file.close()
@@ -157,7 +184,7 @@
     which is encoded in the given encoding.
     """
 
-    def __init__(self, f, encoding="utf-8", **kwds):            
+    def __init__(self, f, encoding="utf-8", **kwds):
         self.encoding = encoding
         self.reader = csv.DictReader(f, **kwds)
 
@@ -177,7 +204,7 @@
 
     def reorganize(self, field_structure=None, merge_keys=None, ref_field=None):
         """
-        Function to reorganize the resource from the csv. It uses the mapping (field_structure) 
+        Function to reorganize the resource from the csv. It uses the mapping (field_structure)
         to deal with the different architecture of an object (sale order with sale order line ...)
         the ref_field is used to merge the different lines (sale order with several sale order lines)
         """
@@ -236,3 +263,27 @@
     def writerows(self, rows):
         for row in rows:
             self.writerow(row)
+
+
+class FileXlsReader(object):
+
+    def __init__(self, file_contents):
+        self.file_contents = file_contents
+
+    def read(self):
+        wb = xlrd.open_workbook(file_contents=self.file_contents)
+        sheet_name = wb.sheet_names()[0]
+        sh = wb.sheet_by_name(sheet_name)
+        header = sh.row_values(0)
+        result = []
+        for rownum in range(1, sh.nrows):
+            row = {}
+            index = 0
+            for val in sh.row_values(rownum):
+                row[header[index]] = val
+                index += 1
+            result.append(row)
+        return result
+
+
+

=== modified file 'base_onchange_player/__init__.py'
--- base_onchange_player/__init__.py	2011-12-21 10:11:00 +0000
+++ base_onchange_player/__init__.py	2012-11-19 23:44:21 +0000
@@ -2,7 +2,8 @@
 #################################################################################
 #                                                                               #
 #    base_onchange_player for OpenERP                                           #
-#    Copyright (C) 2011 Akretion Sébastien BEAU <sebastien.beau@xxxxxxxxxxxx>   #
+#    Copyright (C) 2011 Akretion http://www.akretion.com/                       #
+#    @author Sébastien BEAU <sebastien.beau@xxxxxxxxxxxx>                       #
 #                                                                               #
 #    This program is free software: you can redistribute it and/or modify       #
 #    it under the terms of the GNU Affero General Public License as             #
@@ -22,6 +23,3 @@
 
 import onchange_osv
 
-
-
-

=== modified file 'base_onchange_player/__openerp__.py'
--- base_onchange_player/__openerp__.py	2011-12-21 10:11:00 +0000
+++ base_onchange_player/__openerp__.py	2012-11-19 23:44:21 +0000
@@ -2,7 +2,8 @@
 #################################################################################
 #                                                                               #
 #    base_onchange_player for OpenERP                                           #
-#    Copyright (C) 2011 Akretion Sébastien BEAU <sebastien.beau@xxxxxxxxxxxx>   #
+#    Copyright (C) 2011 Akretion http://www.akretion.com/                       #
+#    @author Sébastien BEAU <sebastien.beau@xxxxxxxxxxxx>                       #
 #                                                                               #
 #    This program is free software: you can redistribute it and/or modify       #
 #    it under the terms of the GNU Affero General Public License as             #
@@ -25,15 +26,15 @@
     'version': '0.1',
     'category': 'ORM Extention',
     'license': 'AGPL-3',
-    '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.
-        A sample of call is done in the module base_sale_multichannels
+    '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.
+
+To get an example of how you should use this code, look at the module base_sale_multichannels.
         """,
     'author': 'Akretion',
     'website': 'http://www.akretion.com/',
-    'depends': ['base'], 
+    'depends': ['base'],
     'init_xml': [],
-    'update_xml': [
-    ],
+    'update_xml': [],
     'demo_xml': [],
     'installable': True,
     'active': False,

=== modified file 'base_onchange_player/onchange_osv.py'
--- base_onchange_player/onchange_osv.py	2012-08-21 06:04:49 +0000
+++ base_onchange_player/onchange_osv.py	2012-11-19 23:44:21 +0000
@@ -2,7 +2,8 @@
 ################################################################################
 #                                                                              #
 #    base_onchange_player for OpenERP                                          #
-#    Copyright (C) 2011 Akretion Sébastien BEAU <sebastien.beau@xxxxxxxxxxxx>  #
+#    Copyright (C) 2011 Akretion http://www.akretion.com/                      #
+#    @author Sébastien BEAU <sebastien.beau@xxxxxxxxxxxx>                      #
 #                                                                              #
 #    This program is free software: you can redistribute it and/or modify      #
 #    it under the terms of the GNU Affero General Public License as            #
@@ -19,45 +20,47 @@
 #                                                                              #
 ################################################################################
 
-from osv import osv
-import netsvc
+from openerp.osv.orm import Model
+from openerp.osv.osv import except_osv
 from tools.translate import _
 from openerp.tools.config import config
 
 def call_onchange(self, cr, uid, onchange_name, vals, defaults=None, **kwargs):
     """
-    Used in base_sale_multichannel in order to call onchange method on sale_order_line and sale_order
-    In order to call onchange you must have to create a function "_get_kwargs_my_onchange_name"
-    that will return the kwargs for your onchange
+    Used in base_sale_multichannel in order to call onchange method on sale_order_line and sale_order.
+    In order to call onchange, you must have to create a function "_get_kwargs_my_onchange_name"
+    that will return the kwargs for your onchange.
 
-    @param onchange_name: string that contain the onchange method to call
-    @param vals: dictionnary of value that have been filled for the object
+    @param onchange_name: string that contains the onchange method to call
+    @param vals: dictionnary of values that has been filled for the object
     @param defaults: dictionnary of defaults values for the object
-    @return: dictionary of line updated with the value returned by the onchange
+    @return: dictionary of lines updated with the values returned by the onchange
     """
-    if not defaults:
-        defaults={}
+    if defaults is None:
+        defaults = {}
     vals_with_default = defaults.copy()
     vals_with_default.update(vals)
     try :
-        kwargs2 = eval("self._get_kwargs_%s"%onchange_name)(cr, uid, vals_with_default, **kwargs)
+        args2, kwargs2 = getattr(self, "_get_params_%s" % onchange_name)(cr, uid, vals_with_default, **kwargs)
     except Exception, e:
         if config['debug_mode']: raise
-        raise osv.except_osv(_('On Change Player'), _("Error when trying to get the kwargs for the onchange %s on \
-                                                    the object %s. Error message : %s" %(onchange_name, self._name, e)))
+        raise except_osv(_('On Change Player'),
+                         _("Error when trying to get the params for the onchange %s on "
+                           "the object %s. Error message : %s") % (onchange_name, self._name, e))
     try :
-        res = eval("self.%s"%onchange_name)(cr, uid, **kwargs2)
+        res = getattr(self, onchange_name)(cr, uid, *args2, **kwargs2)
         for key in res['value']:
             if not key in vals:
-                # If the value is false and the field is not a boolean we don't pass it as it useless
-                # If it's a problem for you please contact me sebastien.beau@xxxxxxxxxxxx, 
-                # because pass empty value will provoque some conflict with magentoerpconnect. Thanks
+                # If the value is false and the field is not a boolean, we don't pass it as it is useless
+                # If it's a problem for you, please contact me sebastien.beau@xxxxxxxxxxxx,
+                # because passing empty value will trigger a conflict with magentoerpconnect. Thanks.
                 if res['value'][key] or self._columns[key]._type == 'bool':
                     vals[key] = res['value'][key]
     except Exception, e:
         if config['debug_mode']: raise
-        raise osv.except_osv(_('On Change Player'), _("Error when trying to playing the onchange %s on the object %s. \
-                                                                Error message : %s" %(onchange_name, self._name, e)))
+        raise except_osv(_('On Change Player'),
+                         _("Error when trying to play the onchange %s on the object %s. "
+                           "Error message : %s") % (onchange_name, self._name, e))
     return vals
 
-osv.osv.call_onchange = call_onchange
+Model.call_onchange = call_onchange

=== modified file 'base_pop_up/__openerp__.py'
--- base_pop_up/__openerp__.py	2012-05-19 10:43:23 +0000
+++ base_pop_up/__openerp__.py	2012-11-19 23:44:21 +0000
@@ -28,9 +28,9 @@
     'description': """empty""",
     'author': 'Akretion',
     'website': 'http://www.akretion.com/',
-    'depends': ['base'], 
+    'depends': ['base'],
     'init_xml': [],
-    'update_xml': [ 
+    'update_xml': [
            'pop_up_file_view.xml',
     ],
     'demo_xml': [],

=== modified file 'base_pop_up/pop_up_file.py'
--- base_pop_up/pop_up_file.py	2012-05-19 10:43:23 +0000
+++ base_pop_up/pop_up_file.py	2012-11-19 23:44:21 +0000
@@ -20,12 +20,12 @@
 #                                                                               #
 #################################################################################
 
-from osv import osv, fields
-import netsvc
+from openerp.osv.orm import TransientModel
+from osv import fields
 import base64
 from tempfile import TemporaryFile
 
-class pop_up_file(osv.osv_memory):
+class pop_up_file(TransientModel):
     _name = "pop.up.file"
     _description = "Output File"
 

=== modified file 'base_scheduler_creator/schedulder_creator.py'
--- base_scheduler_creator/schedulder_creator.py	2012-05-19 16:31:30 +0000
+++ base_scheduler_creator/schedulder_creator.py	2012-11-19 23:44:21 +0000
@@ -19,18 +19,19 @@
 #
 #########################################################################
 
-from osv import fields,osv
+from openerp.osv.orm import TransientModel
+from openerp.osv.osv import except_osv
 from tools.translate import _
 
-class scheduler_creator_wizard(osv.osv_memory):
+class scheduler_creator_wizard(TransientModel):
     _name = 'scheduler.creator.wizard'
     _description = 'scheduler creator wizard'
-    
+
     def action_create(self, cr, uid, id, context):
         for id in context['active_ids']:
             if context.get('object_link', False) and self.pool.get(context['object_link']).read(cr, uid, id, ['scheduler'], context)['scheduler']:
-                raise osv.except_osv(_('USER ERROR'), _('A scheduler already exists !'))
-            
+                raise except_osv(_('USER ERROR'), _('A scheduler already exists !'))
+
             vals = {'name':self.pool.get(context['object_link']).read(cr, uid, id, ['name'], context)['name'],
                     'active':False,
                     'user_id':uid,
@@ -46,5 +47,3 @@
             if context.get('object_link', False):
                 self.pool.get(context['object_link']).write(cr, uid, id, {'scheduler' : cron_id}, context)
         return {'type': 'ir.actions.act_window_close'}
-
-scheduler_creator_wizard()

=== modified file 'file_exchange/__openerp__.py'
--- file_exchange/__openerp__.py	2012-07-06 08:43:37 +0000
+++ file_exchange/__openerp__.py	2012-11-19 23:44:21 +0000
@@ -36,6 +36,7 @@
         'file_exchange_view.xml',
         'file_exchange_menu.xml',
         'settings/external.referential.category.csv',
+        'settings/external.referential.type.csv',
         'security/file_exchange_security.xml',
         'security/file_exchange_security.xml',
         'security/ir.model.access.csv',

=== modified file 'file_exchange/file_exchange.py'
--- file_exchange/file_exchange.py	2012-08-21 07:39:24 +0000
+++ file_exchange/file_exchange.py	2012-11-19 23:44:21 +0000
@@ -19,15 +19,17 @@
 #   along with this program.  If not, see <http://www.gnu.org/licenses/>.     #
 #                                                                             #
 ###############################################################################
-from tools.safe_eval import safe_eval as eval
-from osv import osv, fields
-import netsvc
+from tools.safe_eval import safe_eval
+from openerp.osv.orm import Model
+from openerp.osv import fields
+from openerp.osv.osv import except_osv
 from base_external_referentials.external_osv import ExternalSession
-from base_file_protocole.base_file_protocole import FileCsvReader, FileCsvWriter
+from base_file_protocole.base_file_protocole import FileCsvReader, FileCsvWriter, FileXlsReader
 from base_external_referentials.decorator import open_report
 from tempfile import TemporaryFile
 from encodings.aliases import aliases
 from tools.translate import _
+from openerp.tools.config import config
 
 
 #TODO implement the FileCsvWriter in base_file_protocole and remove import csv
@@ -35,9 +37,8 @@
 
 class FileExchangeCsvReader(FileCsvReader):
     def __init__(self, f, pre_processing=None, **kwds):
-        init = super(FileExchangeCsvReader, self).__init__(f, **kwds)
+        super(FileExchangeCsvReader, self).__init__(f, **kwds)
         self.pre_processing = pre_processing
-        return init
 
     def next(self):
         row = super(FileExchangeCsvReader, self).next()
@@ -47,10 +48,10 @@
             try:
                 exec self.pre_processing in space
             except Exception, e:
-                raise osv.except_osv(_('Error !'), _('Error can not apply the python action pre-processing value'))
+                raise except_osv(_('Error !'), _('Error can not apply the python action pre-processing value'))
         return row
 
-class file_exchange(osv.osv):
+class file_exchange(Model):
     _name = "file.exchange"
     _description = "file exchange"
 
@@ -70,13 +71,14 @@
                 try:
                     exec field.advanced_default_value in space
                 except Exception, e:
-                    raise osv.except_osv(_('Error !'), _('Error when evaluating advanced default value: %s \n Exception: %s' %(fields.name,e)))
+                    raise except_osv(_('Error !'),
+                                     _('Error when evaluating advanced default value: %s \n Exception: %s') % (fields.name,e))
                 res[field.name] = space.get('result', False)
             elif field.default_value:
                 res[field.name] = field.default_value
         return res
 
-    def _get_external_file_resources(self, cr, uid, external_session, filepath, filename, format, 
+    def _get_external_file_resources(self, cr, uid, external_session, filepath, filename, format,
                     fields_name=None, mapping=None, mapping_id=None, external_file=None, context=None):
         if not external_file:
             external_file = external_session.connection.get(filepath, filename)
@@ -84,14 +86,14 @@
         model_obj = self.pool.get(method.mapping_id.model_id.model)
         if format in ['csv_no_header','csv']:
             merge_key_id = self.pool.get('file.fields').search(cr, uid, [
-                                ('merge_key', '=', True), 
-                                ('mapping_line_id.related_model_id', '=', method.mapping_id.model_id.id), 
+                                ('merge_key', '=', True),
+                                ('mapping_line_id.related_model_id', '=', method.mapping_id.model_id.id),
                                 ('file_id', '=', method.id)
                             ], context=context)
             merge_key = None
             if merge_key_id:
                 merge_key = self.pool.get('file.fields').read(cr, uid, merge_key_id[0], ['name'], context=context)['name']
-            mapping,mapping_id = model_obj._init_mapping(cr, uid, external_session.referential_id.id, 
+            mapping,mapping_id = model_obj._init_mapping(cr, uid, external_session.referential_id.id,
                                                         convertion_type='from_external_to_openerp',
                                                         mapping_id=method.mapping_id.id,
                                                         context=context)
@@ -102,8 +104,10 @@
                                         encoding=method.encoding,
                                         pre_processing=method.pre_processing)
             res = csv.reorganize(field_structure=mapping_tree, merge_keys=merge_keys, ref_field=merge_key)
+        elif format in ['xls']:
+            res = FileXlsReader(external_file.read()).read()
         return res
-    
+
     def _get_mapping_tree(self, cr, uid, mapping_id, parent_name=None, grand_parent_name=None, context=None):
         mapping_tree = []
         result = []
@@ -171,7 +175,7 @@
         defaults = self._get_default_import_values(cr, uid, external_session, mapping_id, context=context)
         fields_name_ids = file_fields_obj.search(cr, uid, [['file_id', '=', method.id]], context=context)
         fields_name = [x['name'] for x in file_fields_obj.read(cr, uid, fields_name_ids, ['name'], context=context)]
-        self._import_one_file(cr, uid, external_session, method_id, input_filename, defaults, mapping, 
+        self._import_one_file(cr, uid, external_session, method_id, input_filename, defaults, mapping,
                                             mapping_id, fields_name, external_file=input_file, context=context)
         return True
 
@@ -205,7 +209,7 @@
         return result
 
     @open_report
-    def _import_one_file(self, cr, uid, external_session, method_id, filename, defaults, mapping, 
+    def _import_one_file(self, cr, uid, external_session, method_id, filename, defaults, mapping,
                                             mapping_id, fields_name, external_file=None, context=None):
         ids_imported = []
         method = self.browse(cr, uid, method_id, context=context)
@@ -218,8 +222,8 @@
                                                         mapping_id=mapping_id,
                                                         external_file=external_file,
                                                         context=context)
-        res = self.pool.get(method.mapping_id.model_id.model)._record_external_resources(cr, uid, 
-                                                                        external_session, resources, 
+        res = self.pool.get(method.mapping_id.model_id.model)._record_external_resources(cr, uid,
+                                                                        external_session, resources,
                                                                         defaults=defaults,
                                                                         mapping=mapping,
                                                                         mapping_id=mapping_id,
@@ -234,7 +238,7 @@
     def _check_if_file_exist(self, cr, uid, external_session, folder_path, filename, context=None):
         exist = external_session.connection.search(folder_path, filename)
         if exist:
-            raise osv.except_osv(_('Error !'), _('The file "%s" already exist in the folder "%s"' %(filename, folder_path)))
+            raise except_osv(_('Error !'), _('The file "%s" already exist in the folder "%s"' %(filename, folder_path)))
         return False
 
     def _export_files(self, cr, uid, method_id, context=None):
@@ -248,7 +252,7 @@
                         if 'hidden_field_to_split_' in key:
                             if isinstance(value, list):
                                 if row_to_flat:
-                                    raise osv.except_osv(_('Error !'), _('Can not flat two row in the same resource'))
+                                    raise except_osv(_('Error !'), _('Can not flat two row in the same resource'))
                                 row_to_flat = value
                             elif isinstance(value, dict):
                                 for k,v in flat_resources([value])[0].items():
@@ -293,7 +297,7 @@
         ids_filter = "()" # In case not filter is filed in the form
         if method.search_filter != False:
             ids_filter = method.search_filter
-        ids_to_export = model_obj.search(cr, uid, eval(ids_filter, {'context': context}), context=context)
+        ids_to_export = model_obj.search(cr, uid, safe_eval(ids_filter, {'context': context}), context=context)
     #=== Start mapping
         mapping,mapping_id = model_obj._init_mapping(cr, uid, external_session.referential_id.id,
                                                     convertion_type='from_openerp_to_external',
@@ -343,12 +347,12 @@
         output_file.seek(0)
         method.start_action('action_after_all', model_obj, ids_to_export, context=context,external_session=external_session)
         output = self._send_output(cr, uid, external_session, method, filename, output_file, context=context)
-        
+
         #Start linked task
         if method.linked_task:
             context['parent_ids'] = ids_to_export
             method.linked_task.start_task(context=context)
-        
+
         return output
 
     def _send_output(self, cr, uid, external_session, method, filename, output_file, context=None):
@@ -379,8 +383,10 @@
             try:
                 exec action_code in space
             except Exception, e:
-                raise osv.except_osv(_('Error !'), _("Error can not apply the python action '%s'" 
-                                                " for the method: '%s' \n Exception: '%s'" %(action_name, method.name,e)))
+                if config['debug_mode']: raise
+                raise except_osv(_('Error !'),
+                                 _("Error can not apply the python action '%s'"
+                                   " for the method: '%s' \n Exception: '%s'") % (action_name, method.name,e))
             if 'result' in space:
                 return space['result']
         return True
@@ -405,7 +411,7 @@
                                                                 "and to be imported in the ERP ; OUT for files to be"
                                                                 "generated from the ERP and send to the other system")),
         'mapping_id':fields.many2one('external.mapping', 'External Mapping', require="True", domain="[('referential_id', '=', referential_id)]"),
-        'format' : fields.selection([('csv','CSV'),('csv_no_header','CSV WITHOUT HEADER')], 'File format'),
+        'format' : fields.selection([('csv','CSV'),('csv_no_header','CSV WITHOUT HEADER'), ('xls', 'XLS')], 'File format'),
         'referential_id':fields.many2one('external.referential', 'Referential',help="Referential to use for connection and mapping", require=True),
         'scheduler':fields.many2one('ir.cron', 'Scheduler',help="Scheduler that will execute the cron task"),
         'search_filter':  fields.char('Search Filter', size=256),
@@ -416,9 +422,9 @@
         'field_ids': fields.one2many('file.fields', 'file_id', 'Fields'),
         'action_before_all': fields.text('Action Before All', help="This python code will executed after the import/export"),
         'action_after_all': fields.text('Action After All', help="This python code will executed after the import/export"),
-        'action_before_each': fields.text('Action Before Each', help="This python code will executed after each element of the import/export"), 
+        'action_before_each': fields.text('Action Before Each', help="This python code will executed after each element of the import/export"),
         'action_after_each': fields.text('Action After Each', help="This python code will executed after each element of the import/export"),
-        'check_if_import': fields.text('Check If Import', help="This python code will be executed before each element of the import"), 
+        'check_if_import': fields.text('Check If Import', help="This python code will be executed before each element of the import"),
         'delimiter':fields.char('Fields delimiter', size=64, help="Delimiter used in the CSV file"),
         'lang': fields.many2one('res.lang', 'Language'),
         'import_default_fields':fields.one2many('file.default.import.values', 'file_id', 'Default Field'),
@@ -472,7 +478,7 @@
         }
         csv.writerow(row)
         return self.pool.get('pop.up.file').open_output_file(cr, uid, 'file.exchange.csv', output_file, 'File Exchange Export', context=context)
-        
+
     # Method to export the mapping file
     def create_file_fields(self, cr, uid, id, context=None):
         if isinstance(id,list):
@@ -530,9 +536,8 @@
                     field.write({'mapping_line_id': field_mapping_line_id}, context=context)
         return True
 
-file_exchange()
 
-class file_fields(osv.osv):
+class file_fields(Model):
     _name = "file.fields"
     _description = "file fields"
     _order='sequence'
@@ -587,9 +592,8 @@
             field_id = (file_name + '_' + field_name + '_' + sequence).replace('.','_')
         return field_id
 
-file_fields()
 
-class file_default_import_values(osv.osv):
+class file_default_import_values(Model):
     _name = "file.default.import.values"
     _description = "file default import values"
 

=== modified file 'file_exchange/file_exchange_osv.py'
--- file_exchange/file_exchange_osv.py	2012-05-24 09:56:58 +0000
+++ file_exchange/file_exchange_osv.py	2012-11-19 23:44:21 +0000
@@ -19,13 +19,12 @@
 #                                                                             #
 ###############################################################################
 
-from osv import osv, fields
+from openerp.osv.orm import Model
 from base_external_referentials.decorator import only_for_referential, catch_error_in_report
-import netsvc
-
-osv.osv._feo_record_one_external_resource = osv.osv._record_one_external_resource #feo mean file_exchange_original
-
-@only_for_referential(ref_categ ='File Exchange', super_function = osv.osv._feo_record_one_external_resource)
+
+Model._feo_record_one_external_resource = Model._record_one_external_resource #feo mean file_exchange_original
+
+@only_for_referential(ref_categ ='File Exchange', super_function = Model._feo_record_one_external_resource)
 @catch_error_in_report
 def _record_one_external_resource(self, cr, uid, external_session, resource, **kwargs):
     context=kwargs.get('context')
@@ -40,11 +39,11 @@
             method.start_action('action_after_each', self, [res_id], resource, context=context)
     return res
 
-osv.osv._record_one_external_resource = _record_one_external_resource
-
-osv.osv._feo_get_default_import_values = osv.osv._get_default_import_values #feo mean file_exchange_original
-
-@only_for_referential(ref_categ ='File Exchange', super_function = osv.osv._feo_get_default_import_values)
+Model._record_one_external_resource = _record_one_external_resource
+
+Model._feo_get_default_import_values = Model._get_default_import_values #feo mean file_exchange_original
+
+@only_for_referential(ref_categ ='File Exchange', super_function = Model._feo_get_default_import_values)
 def _get_default_import_values(self, cr, uid, external_session, mapping_id=None, defaults=None, context=None):
     if not defaults:
         defaults = {}
@@ -62,12 +61,12 @@
                 defaults[field.import_default_field.name] = str(field.import_default_value)
     return defaults
 
-osv.osv._get_default_import_values = _get_default_import_values
+Model._get_default_import_values = _get_default_import_values
 
 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):
     result = []
     for resource in self.read_w_order(cr, uid, ids, fields, context):
         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))
     return result
-osv.osv._get_oe_resources_into_external_format = _get_oe_resources_into_external_format
+Model._get_oe_resources_into_external_format = _get_oe_resources_into_external_format
 

=== added file 'file_exchange/settings/external.referential.type.csv'
--- file_exchange/settings/external.referential.type.csv	1970-01-01 00:00:00 +0000
+++ file_exchange/settings/external.referential.type.csv	2012-11-19 23:44:21 +0000
@@ -0,0 +1,3 @@
+id,name,categ_id:id,code
+ref_type_FTP-file-exchange,FTP,file-exchange,FTP
+ref_type_SFTP-file-exchange,SFTP,file-exchange,SFTP

=== added directory 'framework_helpers'
=== added file 'framework_helpers/__init__.py'
--- framework_helpers/__init__.py	1970-01-01 00:00:00 +0000
+++ framework_helpers/__init__.py	2012-11-19 23:44:21 +0000
@@ -0,0 +1,22 @@
+# -*- encoding: utf-8 -*-
+#################################################################################
+#                                                                               #
+#    framework_helpers for OpenERP                                              #
+#    Copyright (C) 2011 Akretion Benoît Guillot <benoit.guillot@xxxxxxxxxxxx>   #
+#                                                                               #
+#    This program is free software: you can redistribute it and/or modify       #
+#    it under the terms of the GNU Affero General Public License as             #
+#    published by the Free Software Foundation, either version 3 of the         #
+#    License, or (at your option) any later version.                            #
+#                                                                               #
+#    This program is distributed in the hope that it will be useful,            #
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of             #
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the              #
+#    GNU Affero General Public License for more details.                        #
+#                                                                               #
+#    You should have received a copy of the GNU Affero General Public License   #
+#    along with this program.  If not, see <http://www.gnu.org/licenses/>.      #
+#                                                                               #
+#################################################################################
+
+import context_managers

=== added file 'framework_helpers/__openerp__.py'
--- framework_helpers/__openerp__.py	1970-01-01 00:00:00 +0000
+++ framework_helpers/__openerp__.py	2012-11-19 23:44:21 +0000
@@ -0,0 +1,37 @@
+# -*- encoding: utf-8 -*-
+#################################################################################
+#                                                                               #
+#    framework_helpers for OpenERP                                              #
+#    Copyright (C) 2012 Akretion Benoît Guillot <benoit.guillot@xxxxxxxxxxxx>   #
+#                                                                               #
+#    This program is free software: you can redistribute it and/or modify       #
+#    it under the terms of the GNU Affero General Public License as             #
+#    published by the Free Software Foundation, either version 3 of the         #
+#    License, or (at your option) any later version.                            #
+#                                                                               #
+#    This program is distributed in the hope that it will be useful,            #
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of             #
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the              #
+#    GNU Affero General Public License for more details.                        #
+#                                                                               #
+#    You should have received a copy of the GNU Affero General Public License   #
+#    along with this program.  If not, see <http://www.gnu.org/licenses/>.      #
+#                                                                               #
+#################################################################################
+
+{
+    'name': 'framework_helpers',
+    'version': '0.1',
+    'category': 'Generic Modules/Others',
+    'license': 'AGPL-3',
+    'description': """This module provides methods to """,
+    'author': 'Akretion',
+    'website': 'http://www.akretion.com/',
+    'depends': ['base'], 
+    'init_xml': [],
+    'update_xml': [],
+    'demo_xml': [],
+    'installable': True,
+    'active': False,
+}
+

=== added file 'framework_helpers/context_managers.py'
--- framework_helpers/context_managers.py	1970-01-01 00:00:00 +0000
+++ framework_helpers/context_managers.py	2012-11-19 23:44:21 +0000
@@ -0,0 +1,66 @@
+# -*- encoding: utf-8 -*-
+#################################################################################
+#                                                                               #
+#    framework_helpers for OpenERP                                              #
+#    Copyright (C) 2011 Akretion Benoît Guillot <benoit.guillot@xxxxxxxxxxxx>   #
+#                                                                               #
+#    This program is free software: you can redistribute it and/or modify       #
+#    it under the terms of the GNU Affero General Public License as             #
+#    published by the Free Software Foundation, either version 3 of the         #
+#    License, or (at your option) any later version.                            #
+#                                                                               #
+#    This program is distributed in the hope that it will be useful,            #
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of             #
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the              #
+#    GNU Affero General Public License for more details.                        #
+#                                                                               #
+#    You should have received a copy of the GNU Affero General Public License   #
+#    along with this program.  If not, see <http://www.gnu.org/licenses/>.      #
+#                                                                               #
+#################################################################################
+
+import pooler
+from contextlib import contextmanager
+
+@contextmanager
+def commit_now(cr, logger, raise_error=False):
+    """
+    Context Manager to use in order to commit into a cursor
+    correctly with a try/except method and a rollback if necessary
+    :param cr cursor: cursor to commit
+    :param logger logger: logger used to logging the message
+    :param raise_error boolean: Set to true only if you want
+             to stop the process if an error occured
+    """
+    try:
+        yield cr
+    except Exception, e:
+        cr.rollback()
+        logger.exception(e)
+        if raise_error:
+            raise
+    else:
+        cr.commit()
+
+@contextmanager
+def new_cursor(cr, logger, raise_error=False):
+    """
+    Context Manager to use in order to commit into a new cursor
+    correctly with a try/except method and a rollback if necessary
+    :param cr cursor: cursor to copy
+    :param logger logger: logger used to logging the message
+    :param raise_error boolean: Set to true only if you want
+             to stop the process if an error occured
+    """
+    new_cr = pooler.get_db(cr.dbname).cursor()
+    try:
+        yield new_cr
+    except Exception, e:
+        new_cr.rollback()
+        logger.exception(e)
+        if raise_error:
+            raise
+    else:
+        new_cr.commit()
+    finally:
+        new_cr.close()

=== modified file 'report_synchronizer/report_osv.py'
--- report_synchronizer/report_osv.py	2012-06-01 17:44:44 +0000
+++ report_synchronizer/report_osv.py	2012-11-19 23:44:21 +0000
@@ -19,19 +19,20 @@
 #                                                                             #
 ###############################################################################
 
-from osv import osv, fields
+from openerp.osv.orm import Model
 import netsvc
 from base_external_referentials.external_osv import extend
 from tempfile import TemporaryFile
 
-@extend(osv.osv)
-def send_report(self, cr, uid, external_session, ids, report_name, file_name, path, context=None):
+@extend(Model)
+def send_report(self, cr, uid, external_session, ids, report_name, file_name, path, add_extension=True, context=None):
     service = netsvc.LocalService(report_name)
     result, format = service.create(cr, uid, ids, {'model': self._name}, context=context)
     output_file = TemporaryFile('w+b')
     output_file.write(result)
     output_file.seek(0)
-    file_name = "%s.%s"%(file_name, format)
+    if add_extension:
+        file_name = "%s.%s"%(file_name, format)
     external_session.connection.send(path, file_name, output_file)
     return file_name