savoirfairelinux-openerp team mailing list archive
-
savoirfairelinux-openerp team
-
Mailing list archive
-
Message #00004
[Merge] lp:~openerp-chinese-team/e-commerce-addons/chinese_translation into lp:e-commerce-addons/oerp6.1-stable
Joshua Jan(SHINEIT) has proposed merging lp:~openerp-chinese-team/e-commerce-addons/chinese_translation into lp:e-commerce-addons/oerp6.1-stable.
Requested reviews:
extra-addons-commiter (extra-addons-commiter)
For more details, see:
https://code.launchpad.net/~openerp-chinese-team/e-commerce-addons/chinese_translation/+merge/124088
Hi all,
This is the Chinese translation for base_external_referentials.
Joshua
--
https://code.launchpad.net/~openerp-chinese-team/e-commerce-addons/chinese_translation/+merge/124088
Your team extra-addons-commiter is requested to review the proposed merge of lp:~openerp-chinese-team/e-commerce-addons/chinese_translation into lp:e-commerce-addons/oerp6.1-stable.
=== added directory 'base_external_cron'
=== added file 'base_external_cron/__init__.py'
--- base_external_cron/__init__.py 1970-01-01 00:00:00 +0000
+++ base_external_cron/__init__.py 2012-09-13 01:56:18 +0000
@@ -0,0 +1,28 @@
+# -*- encoding: utf-8 -*-
+###############################################################################
+# #
+# base_external_cron for OpenERP #
+# Copyright (C) 2012 Akretion David BEAL <david.beal@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 external_cron
+
+
+
+
=== added file 'base_external_cron/__openerp__.py'
--- base_external_cron/__openerp__.py 1970-01-01 00:00:00 +0000
+++ base_external_cron/__openerp__.py 2012-09-13 01:56:18 +0000
@@ -0,0 +1,41 @@
+# -*- encoding: utf-8 -*-
+###############################################################################
+# #
+# base_external_cron for OpenERP #
+# Copyright (C) 2012 Akretion David BEAL <david.beal@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': 'base_external_cron',
+ 'version': '0.1',
+ 'category': 'Generic Modules/Others',
+ 'license': 'AGPL-3',
+ 'description': """empty""",
+ 'author': 'Akretion',
+ 'website': 'http://www.akretion.com/',
+ 'depends': ['base_external_referentials'],
+ 'init_xml': [],
+ 'update_xml': [
+ 'external_cron_view.xml',
+ ],
+ 'demo_xml': [],
+ 'installable': True,
+ 'active': False,
+}
+
=== added file 'base_external_cron/external_cron.py'
--- base_external_cron/external_cron.py 1970-01-01 00:00:00 +0000
+++ base_external_cron/external_cron.py 2012-09-13 01:56:18 +0000
@@ -0,0 +1,52 @@
+# -*- encoding: utf-8 -*-
+###############################################################################
+# #
+# base_external_cron for OpenERP #
+# Copyright (C) 2012 Akretion David BEAL <david.beal@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/>. #
+# #
+###############################################################################
+
+from osv import osv, fields
+import netsvc
+from base_external_referentials.external_osv import ExternalSession
+import sys
+from ebaypyt import EbayWebService
+
+class external_cron(osv.osv):
+
+ _name = "external.cron"
+ _description = "external.cron"
+
+ _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."),
+ '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"),
+ }
+
+ _defaults = {
+ 'active': 1
+ }
+
+ 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)
+
=== added file 'base_external_cron/external_cron_view.xml'
--- base_external_cron/external_cron_view.xml 1970-01-01 00:00:00 +0000
+++ base_external_cron/external_cron_view.xml 2012-09-13 01:56:18 +0000
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ base_external_cron for OpenERP
+ Copyright (C) 2012 Akretion David BEAL <david.beal@xxxxxxxxxxxx>
+ The licence is in the file __openerp__.py
+-->
+
+<openerp>
+ <data>
+
+ <!-- VIEWS FOR THE OBJECT : external.cron -->
+ <!-- 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>
+ <field eval="16" name="priority"/>
+ <field name="type">form</field>
+ <field name="arch" type="xml">
+ <form string="external.cron">
+ <field name="name" />
+ <field name="active" />
+ <field name="period" />
+ <field name="frequency" />
+<!--
+ <field name="repeat" readonly="1" />
+-->
+ <field name="repeat" />
+ <field name="report_type" />
+ <field name="referential_id" />
+ </form>
+ </field>
+ </record>
+
+ <!-- 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>
+ <field eval="16" name="priority"/>
+ <field name="type">tree</field>
+ <field name="arch" type="xml">
+ <tree string="external.cron">
+ <field name="name" />
+ <field name="active" />
+ <field name="period" />
+ <field name="report_type" />
+ <field name="frequency" />
+ <field name="repeat" />
+ <field name="referential_id" />
+ </tree>
+ </field>
+ </record>
+
+ <!-- Action used by menu -->
+ <record id="action_external_cron" model="ir.actions.act_window">
+ <field name="name">External Cron</field>
+ <field name="res_model">external.cron</field>
+ <field name="view_type">form</field>
+ <field name="view_mode">tree,form</field>
+ </record>
+
+ <menuitem id="act_menu_external_cron" action="action_external_cron"
+ parent="base_external_referentials.ir_ui_menu_external_referentials" sequence="30" />
+
+ </data>
+</openerp>
=== added directory 'base_external_file_protocole'
=== added file 'base_external_file_protocole/__init__.py'
--- base_external_file_protocole/__init__.py 1970-01-01 00:00:00 +0000
+++ base_external_file_protocole/__init__.py 2012-09-13 01:56:18 +0000
@@ -0,0 +1,24 @@
+# -*- encoding: utf-8 -*-
+###############################################################################
+# #
+# base_external_file_protocole for OpenERP #
+# Copyright (C) 2012 Akretion Emmanuel Samyn <emmanuel.samyn@xxxxxxxxxxxx> #
+# Copyright (C) 2012 Akretion Sebastien 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 #
+# 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 external_referentials
+import file_buffer
+import sale
=== added file 'base_external_file_protocole/__openerp__.py'
--- base_external_file_protocole/__openerp__.py 1970-01-01 00:00:00 +0000
+++ base_external_file_protocole/__openerp__.py 2012-09-13 01:56:18 +0000
@@ -0,0 +1,46 @@
+# -*- encoding: utf-8 -*-
+###############################################################################
+# #
+# base_external_file_protocole for OpenERP #
+# Copyright (C) 2012 Akretion Emmanuel Samyn <emmanuel.samyn@xxxxxxxxxxxx> #
+# Copyright (C) 2012 Akretion Sebastien 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 #
+# 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': 'base_external_file_protocole',
+ 'version': '0.1',
+ 'category': 'Generic Modules/Others',
+ 'license': 'AGPL-3',
+ 'description': """
+Definition : an abstract module taht add a file protocole on the external referential.
+It use in base_sale_multichannel to send the invoice, the rma report.
+Also it's used in file_exchange
+""",
+ 'author': 'Akretion',
+ 'website': 'http://www.akretion.com/',
+ 'depends': ['base_external_referentials', 'base_file_protocole', 'sale'],
+ 'init_xml': [],
+ 'update_xml': [
+ 'file_buffer_view.xml',
+ 'settings/external.referential.category.csv',
+ 'file_buffer_data.xml',
+ ],
+ 'demo_xml': [],
+ 'installable': True,
+ 'active': False,
+}
+
=== added file 'base_external_file_protocole/external_referentials.py'
--- base_external_file_protocole/external_referentials.py 1970-01-01 00:00:00 +0000
+++ base_external_file_protocole/external_referentials.py 2012-09-13 01:56:18 +0000
@@ -0,0 +1,63 @@
+ # -*- encoding: utf-8 -*-
+###############################################################################
+# #
+# file_exchange for OpenERP #
+# Copyright (C) 2011 Akretion 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 #
+# 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/>. #
+# #
+###############################################################################
+
+from osv import osv, fields
+import netsvc
+from base_file_protocole.base_file_protocole import FileConnection
+from tools.translate import _
+
+class external_referential(osv.osv):
+ _inherit = "external.referential"
+
+ def external_connection(self, cr, uid, id, debug=False, logger=False, context=None):
+ if isinstance(id, list):
+ id=id[0]
+ referential = self.browse(cr, uid, id, context=context)
+ try:
+ return FileConnection(referential.protocole, 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))
+
+ _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['protocole'] = referential.protocole
+ return res
+
+external_referential()
+
=== added file 'base_external_file_protocole/file_buffer.py'
--- base_external_file_protocole/file_buffer.py 1970-01-01 00:00:00 +0000
+++ base_external_file_protocole/file_buffer.py 2012-09-13 01:56:18 +0000
@@ -0,0 +1,95 @@
+# -*- encoding: utf-8 -*-
+###############################################################################
+# #
+# file_buffer for OpenERP #
+# Copyright (C) 2012 Akretion David BEAL <david.beal@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/>. #
+# #
+###############################################################################
+
+
+from osv import osv, fields
+import base64
+from base_external_referentials.external_osv import ExternalSession
+
+class file_buffer(osv.osv):
+
+ _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'),
+ '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),
+ #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'),
+ }
+
+ _order = 'name desc'
+
+ _defaults = {
+ 'active': 1,
+ 'state': 'waiting',
+ }
+
+ def get_file(self, cr, uid, file_id, context=None):
+ """
+ Fonction that return the content of the attachment
+ :param int file_id : id of the file buffer
+ :rtype: str
+ :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)])
+ if not attachment_id:
+ return False
+ else:
+ attachment = attach_obj.browse(cr, uid, attachment_id[0], context=context)
+ return base64.decodestring(attachment.datas)
+
+ def run_file_buffer_scheduler(self, cr, uid, domain=None, context=None):
+ if not domain: domain = []
+ domain.append(('state', '=', 'waiting'))
+ ids = self.search(cr, uid, domain, context=context)
+ if ids:
+ return self.run(cr, uid, ids, context=context)
+ return True
+
+ def run(self, cr, uid, ids, context=None):
+ """
+ Run the process for each file buffer
+ """
+ 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()
+ return True
+
+ def _run(self, cr, uid, external_session, filebuffer, context=None):
+ filebuffer._set_state('running', context=context)
+
+ def done(self, cr, uid, ids, context=None):
+ self._set_state(cr, uid, ids, 'done', context=context)
+
+ def _set_state(self, cr, uid, ids, state, context=None):
+ for id in ids:
+ self.write(cr, uid, id, {'state': state}, context=context)
=== added file 'base_external_file_protocole/file_buffer_data.xml'
--- base_external_file_protocole/file_buffer_data.xml 1970-01-01 00:00:00 +0000
+++ base_external_file_protocole/file_buffer_data.xml 2012-09-13 01:56:18 +0000
@@ -0,0 +1,19 @@
+<?xml version="1.0"?>
+<openerp>
+ <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 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="'run_file_buffer_scheduler'" name="function"/>
+ <field eval="'()'" name="args"/>
+ </record>
+
+ </data>
+</openerp>
=== added file 'base_external_file_protocole/file_buffer_view.xml'
--- base_external_file_protocole/file_buffer_view.xml 1970-01-01 00:00:00 +0000
+++ base_external_file_protocole/file_buffer_view.xml 2012-09-13 01:56:18 +0000
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ file_buffer for OpenERP
+ Copyright (C) 2012 Akretion David BEAL <david.beal@xxxxxxxxxxxx>
+ The licence is in the file __openerp__.py -->
+
+<openerp>
+ <data>
+
+<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>
+ </field>
+</record>
+
+
+<!-- VIEW FOR THE OBJECT : file_buffer -->
+<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>
+ <field eval="16" name="priority"/>
+ <field name="type">form</field>
+ <field name="arch" type="xml">
+ <form string="file_buffer">
+ <field name="name" />
+ <field name="state" />
+ <field name="mapping_id" />
+ <field name="file_id" />
+ <field name="referential_id"/>
+ <field name="shop_id"/>
+ <field name="job_ended" />
+ <field name="active"/>
+ <button name="run" string="Run" colspan="2" type="object" />
+ </form>
+ </field>
+</record>
+
+<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>
+ <field eval="16" name="priority"/>
+ <field name="type">tree</field>
+ <field name="arch" type="xml">
+ <tree string="file_buffer">
+ <field name="name" />
+ <field name="state" />
+ <field name="active" string="act." />
+ <field name="mapping_id" />
+ <field name="file_id" />
+ <field name="job_ended" />
+ <field name="referential_id" string="ex ref"/>
+ <button name="run" string="Run" icon="gtk-go-forward" type="object"/>
+ </tree>
+ </field>
+</record>
+
+<!-- Action used by menu -->
+<record id="action_external_file_buffer" model="ir.actions.act_window">
+ <field name="name">File buffer</field>
+ <field name="res_model">file.buffer</field>
+ <field name="view_type">form</field>
+ <field name="view_mode">tree,form</field>
+ <field name="context">{"search_default_wait":1}</field>
+</record>
+
+<menuitem id="act_menu_external_file_buffer" action="action_external_file_buffer" parent="base_external_referentials.ir_ui_menu_external_referentials" sequence="25" />
+
+
+ </data>
+</openerp>
=== added directory 'base_external_file_protocole/settings'
=== added file 'base_external_file_protocole/settings/external.referential.category.csv'
--- base_external_file_protocole/settings/external.referential.category.csv 1970-01-01 00:00:00 +0000
+++ base_external_file_protocole/settings/external.referential.category.csv 2012-09-13 01:56:18 +0000
@@ -0,0 +1,2 @@
+"id","name"
+"file-protocole","File Protocole"
=== added directory 'base_external_referentials'
=== added file 'base_external_referentials/__init__.py'
--- base_external_referentials/__init__.py 1970-01-01 00:00:00 +0000
+++ base_external_referentials/__init__.py 2012-09-13 01:56:18 +0000
@@ -0,0 +1,6 @@
+import external_referentials
+import external_osv
+import report
+import ir_model
+import decorator
+import group_fields
=== added file 'base_external_referentials/__openerp__.py'
--- base_external_referentials/__openerp__.py 1970-01-01 00:00:00 +0000
+++ base_external_referentials/__openerp__.py 2012-09-13 01:56:18 +0000
@@ -0,0 +1,65 @@
+# -*- encoding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2009 Akretion (<http://www.akretion.com>). All Rights Reserved
+# authors: Raphaël Valyi, Sharoon Thomas
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+
+{
+ 'name': 'Base External Referentials',
+ 'version': '1.0',
+ 'category': 'Generic Modules/Base',
+ 'description': """
+Definition : a referential is an external system that will interacts with OpenERP
+Goal : store external system connection details and objects fields mapping
+
+This module provide an abstract common minimal base to add any additional external id columns
+to some OpenObject table, pointing to some external referential.
+A referential is abstract and minimal at this stage, it only has:
+* a name
+* a location (possibly webservice URL, database connection URL...); the connection method will tell it...
+* referential credentials (user name + password)
+* placeholders for custom in and out mapping for OpenERP object fields.
+
+OpenERP already has limited supported to external ids using the ir_model_data and the id
+fields in the loaded data such as XML or CSV. We think that's OK to store all referential ids
+into the same ir_model_data table: yes it makes it large, but synchronisation operations involve
+a network bottleneck anyway, so it's largely OK and negligible to have a large table here.
+The existing ir_model_data feature of OpenERP is mostly thought as an mono-external referential
+(even if the module key of ir_model_data plays some referential scoping role). Here we just push
+the concept further to assume multiple external ids for OpenERP entities and add the possibility
+to customize their field mapping directly in OpenERP to accomodate the external systems.
+ """,
+ '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'],
+ 'init_xml': [],
+ 'update_xml': [
+ 'external_referentials_view.xml',
+ 'report_view.xml',
+ 'external_referentials_menu.xml',
+ 'security/ir.model.access.csv',
+ 'group_fields_view.xml',
+ 'security/base_external_referentials_security.xml',
+ ],
+ 'demo_xml': [],
+ 'installable': True,
+ 'certificate': '',
+}
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
=== added file 'base_external_referentials/decorator.py'
--- base_external_referentials/decorator.py 1970-01-01 00:00:00 +0000
+++ base_external_referentials/decorator.py 2012-09-13 01:56:18 +0000
@@ -0,0 +1,233 @@
+# -*- encoding: utf-8 -*-
+###############################################################################
+# #
+# base_external_referentials for OpenERP #
+# Copyright (C) 2011 Akretion 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 #
+# 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/>. #
+# #
+###############################################################################
+
+from osv import osv
+import pooler
+from tools.translate import _
+from message_error import MappingError
+import functools
+import xmlrpclib
+from openerp.tools.config import config
+
+#TODO refactor me we should create 2 decorator
+# 1 only_for_referential
+# 2 only_for_referential_category
+def only_for_referential(ref_type=None, ref_categ=None, super_function=None):
+ """
+ This decorator will execute the code of the function decorated only if
+ the referential_type match with the referential_type pass in the context
+ If not super method will be call.
+ argument must be the referential or the referential_id or the external_session
+ """
+ def decorator(func):
+ @functools.wraps(func)
+ def wrapped(self, cr, uid, argument, *args, **kwargs):
+ if self._name == 'external.referential' and (isinstance(argument, list) or isinstance(argument, int)):
+ referential_id = isinstance(argument, list) and argument[0] or argument
+ referential = self.browse(cr, uid, referential_id)
+ else:
+ referential = argument.referential_id
+ if ref_type and referential.type_id.name.lower() == ref_type.lower() or ref_categ and referential.categ_id.name.lower() == ref_categ.lower():
+ return func(self, cr, uid, argument, *args, **kwargs)
+ else:
+ if super_function:
+ return super_function(self, cr, uid, argument, *args, **kwargs)
+ else:
+ name = func.__name__
+ use_next_class = False
+ for base in self.__class__.mro()[1:]:
+ if use_next_class and hasattr(base, name):
+ return getattr(base, name)(self, cr, uid, argument, *args, **kwargs)
+ class_func = base.__dict__.get(name)
+ if class_func:
+ 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"))
+ wrapped._original_func_before_wrap = func
+ return wrapped
+ return decorator
+
+
+def open_report(func):
+ """ This decorator will start and close a report for the function call
+ The function must start with "self, cr, uid, object"
+ And the object must have a field call "referential_id" related to the object "external.referential"
+ """
+ @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,)))
+
+ report_obj = self.pool.get('external.report')
+ context = kwargs.get('context')
+ if context is None:
+ context={}
+ kwargs['context'] = context
+
+ #Start the report
+ report_id = report_obj.start_report(cr, uid, external_session, id=None, action=func.__name__, action_on=self._name, context=context)
+
+ #Execute the original function and add the report_id to the context
+ context['report_id'] = report_id
+ response = func(self, cr, uid, external_session, *args, **kwargs)
+
+ #Close the report
+ report_obj.end_report(cr, uid, external_session, report_id, context=context)
+
+ return response
+ return wrapper
+
+
+def catch_error_in_report(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"
+ And the object must have a field call "referential_id" related to the object "external.referential"
+ """
+ @functools.wraps(func)
+ def wrapper(self, cr, uid, external_session, resource, *args, **kwargs):
+ context = kwargs.get('context')
+ if not (context and context.get('report_id')):
+ 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:
+ 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(
+ cr,
+ uid,
+ self._name,
+ func.__name__,
+ #TODO manage external id and res_id in a good way
+ external_id=context.get('external_id_key_for_report') and resource.get(context.get('external_id_key_for_report')),
+ res_id= not context.get('external_id_key_for_report') and args and args[0],
+ resource=resource,
+ args = args,
+ kwargs = kwargs,
+ )
+ import_cr = pooler.get_db(cr.dbname).cursor()
+ response = False
+ try:
+ response = func(self, import_cr, uid, external_session, resource, *args, **kwargs)
+ except MappingError as e:
+ if config['debug_mode']: raise
+ import_cr.rollback()
+ error_message = 'Error with the mapping : %s. Error details : %s'%(e.mapping_name, e.value),
+ report_line_obj.log_fail(cr, uid, external_session, report_line_id, error_message, context=context)
+ except xmlrpclib.Fault as e:
+ if config['debug_mode']: raise
+ 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:
+ if config['debug_mode']: raise
+ import_cr.rollback()
+ error_message = '%s : %s'%(e.name, e.value)
+ report_line_obj.log_fail(cr, uid, external_session, report_line_id, error_message, context=context)
+ except Exception as e:
+ if config['debug_mode']: raise
+ #TODO write correctly the message in the report
+ import_cr.rollback()
+ error_message = str(e)
+ report_line_obj.log_fail(cr, uid, external_session, report_line_id, error_message, context=context)
+ else:
+ report_line_obj.log_success(cr, uid, external_session, report_line_id, context=context)
+ import_cr.commit()
+ finally:
+ import_cr.close()
+ 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)
+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"
+ And the object must have a field call "referential_id" related to the object "external.referential"
+ """
+ @functools.wraps(func)
+ def wrapper(self, cr, uid, *args, **kwargs):
+ context = kwargs.get('context', {})
+ report_line_obj = self.pool.get('external.report.line')
+ report_line_id = report_line_obj.start_log(
+ cr,
+ uid,
+ self._name,
+ func.__name__,
+ res_id= args[0],
+ args = args,
+ kwargs = kwargs,
+ )
+ import_cr = pooler.get_db(cr.dbname).cursor()
+ response = False
+ try:
+ response = func(self, import_cr, uid, *args, **kwargs)
+ except MappingError as e:
+ if config['debug_mode']: raise
+ import_cr.rollback()
+ error_message = 'Error with the mapping : %s. Error details : %s'%(e.mapping_name, e.value),
+ report_line_obj.log_fail(cr, uid, None, report_line_id, error_message, context=context)
+ except xmlrpclib.Fault as e:
+ if config['debug_mode']: raise
+ 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:
+ if config['debug_mode']: raise
+ import_cr.rollback()
+ error_message = '%s : %s'%(e.name, e.value)
+ report_line_obj.log_fail(cr, uid, None, report_line_id, error_message, context=context)
+ except Exception as e:
+ if config['debug_mode']: raise
+ #TODO write correctly the message in the report
+ import_cr.rollback()
+ error_message = str(e)
+ report_line_obj.log_fail(cr, uid, None, report_line_id, error_message, context=context)
+ else:
+ report_line_obj.log_success(cr, uid, None, report_line_id, context=context)
+ import_cr.commit()
+ finally:
+ import_cr.close()
+ return response
+ return wrapper
+
+
+
+def commit_now(func):
+ """ This decorator open and close a new cursor and if an error occure it raise an error
+ The function must start with "self, cr"
+ """
+ @functools.wraps(func)
+ def wrapper(self, cr, *args, **kwargs):
+ new_cr = pooler.get_db(cr.dbname).cursor()
+ try:
+ response = func(self, new_cr, *args, **kwargs)
+ except:
+ new_cr.rollback()
+ raise
+ else:
+ new_cr.commit()
+ finally:
+ new_cr.close()
+ return response
+ return wrapper
+
+
=== added file 'base_external_referentials/external_osv.py'
--- base_external_referentials/external_osv.py 1970-01-01 00:00:00 +0000
+++ base_external_referentials/external_osv.py 2012-09-13 01:56:18 +0000
@@ -0,0 +1,1653 @@
+# -*- encoding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>). All Rights Reserved
+# Sharoon Thomas, Raphaël Valyi
+# Copyright (C) 2011-2012 Camptocamp Guewen Baconnier
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+from osv import fields, osv
+import base64
+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
+
+from message_error import MappingError, ExtConnError
+from tools.translate import _
+from tools import DEFAULT_SERVER_DATETIME_FORMAT, DEFAULT_SERVER_DATE_FORMAT
+#TODO fix me import do not work
+#from base_external_referentials.decorator import commit_now
+
+#TODO refactor the mapping are stored in a dictionnary to avoid useless read during all of the process.
+#It should be better to use the orm cache or something similare
+
+
+def extend(class_to_extend):
+ """
+ Decorator to use to extend a existing class with a new method
+ Example :
+ @extend(osv.osv)
+ 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
+ """
+ def decorator(func):
+ if hasattr(class_to_extend, func.func_name):
+ raise osv.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)
+ return class_to_extend
+ return decorator
+
+def override(class_to_extend, prefix):
+ """
+ Decorator for overiding an existing method in a class
+
+ Example of use:
+
+ @override(osv.osv, 'magento_')
+ def write(self, *args, **kwargs):
+ print 'I am in the write overwrited 1', self._name
+ return osv.osv.magento_write(self, *args, **kwargs)
+
+ @override(osv.osv, 'amazon_')
+ def write(self, *args, **kwargs):
+ print 'I am in the write overwrited 2', self._name
+ return osv.osv.amazon_write(self, *args, **kwargs)
+
+ @override(osv.osv, 'ebay_')
+ def write(self, *args, **kwargs):
+ print 'I am in the write overwrited 3', self._name
+ return osv.osv.ebay_write(self, *args, **kwargs)
+
+ """
+ def decorator(func):
+ if not hasattr(class_to_extend, func.func_name):
+ raise osv.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"),
+ _("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))
+ setattr(class_to_extend, func.func_name, func)
+ return class_to_extend
+ return decorator
+
+
+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....
+ 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
+ for example if you import the product from the shop, the shop will be store in this field1
+ - debug : boolean to active or not the debug
+ - connection : the connection object of the external system
+ - tmp : a temporary dict to store data
+ """
+ self.referential_id = referential
+ self.sync_from_object = sync_from_object or referential
+ self.debug = referential.debug
+ self.logger = logging.getLogger(referential.name)
+ self.connection = referential.external_connection(debug=self.debug, logger = self.logger)
+ self.tmp = {}
+
+ def is_type(self, referential_type):
+ return self.referential_id.type_id.name.lower() == referential_type.lower()
+
+ def is_categ(self, referential_category):
+ return self.referential_id.categ_id.name.lower() == referential_category.lower()
+
+
+#TODO think about the generic method to use
+class Resource(object):
+ """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()
+ one_key = my_keys[0]
+ my_item = resource[one_key]
+ my_item = resource.get(one_key)
+ """
+ def __init__(self, data):
+ self.data = data
+
+ def get(self, key):
+ if isinstance(self.data, objectify.ObjectifiedElement):
+ if key in self.data.__dict__:
+ result = self.data.__dict__.get(key)
+ else:
+ return None
+ if hasattr(result, 'pyval'):
+ return result.pyval
+ else:
+ return Resource(result)
+
+ def __getitem__(self, key):
+ if isinstance(self.data, objectify.ObjectifiedElement):
+ return self.get(key)
+
+ def keys(self):
+ if isinstance(self.data, objectify.ObjectifiedElement):
+ return self.data.__dict__.keys()
+
+
+
+########################################################################################################################
+#
+# BASIC FEATURES
+#
+########################################################################################################################
+
+@extend(osv.osv)
+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
+
+ :param list ids: list of the ids of the records to read
+ :param list fields_to_read: optional list of field names to return (default: all fields would be returned)
+ :param dict context: context arguments, like lang, time zone
+ :rtype: [{‘name_of_the_field’: value, ...}, ...]
+ :return: ordered list of dictionaries((dictionary per record asked)) with requested field values
+ """
+ res = self.read(cr, uid, ids, fields_to_read, context, load)
+ resultat = []
+ for id in ids:
+ resultat += [x for x in res if x['id'] == id]
+ return resultat
+
+@extend(osv.osv)
+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
+
+ :param list ids: id or list of ids.
+ :param dict context: context arguments, like lang, time zone
+ :rtype: list of objects requested
+ :return: ordered list of object
+ """
+ res = self.browse(cr, uid, ids, context, list_class, fields_process)
+ resultat = []
+ for id in ids:
+ resultat += [x for x in res if x.id == id]
+ return resultat
+
+@extend(osv.osv)
+def prefixed_id(self, id):
+ """Return the prefixed_id for an id given
+ :param str or int id: external id
+ :rtype str
+ :return the prefixed id
+ """
+ #The reason why we don't just use the external id and put the model as the prefix
+ #is to avoid unique ir_model_data#name per module constraint violation.
+ return self._name.replace('.', '_') + '/' + str(id)
+
+@extend(osv.osv)
+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
+ """
+ res = prefixed_id.split(self._name.replace('.', '_') + '/')[1]
+ if res.isdigit():
+ return int(res)
+ else:
+ return res
+
+@extend(osv.osv)
+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
+ :rtype: list
+ :return: the list of all of the external_ids from 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:
+ oeid_to_extid = {}
+ for data in ir_model_data_obj.read(cr, uid, model_data_ids, ['res_id', 'name'], context=context):
+ oeid_to_extid[data['res_id']] = self.id_from_prefixed_id(data['name'])
+ if not oeid_to_extid:
+ 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)
+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)
+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
+ :param ExternalSession external_session : External_session that contain all params of connection
+ :param int openerp_id : openerp id of the resource
+ :return: the external id of the resource
+ :rtype: int
+ """
+ res = self.get_extid(cr, uid, openerp_id, external_session.referential_id.id, context=context)
+ if res is not False:
+ return res
+ else:
+ return self._export_one_resource(cr, uid, external_session, openerp_id, context=context)
+
+@extend(osv.osv)
+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
+ """
+ if isinstance(openerp_id, list):
+ openerp_id = openerp_id[0]
+ model_data_ids = self.pool.get('ir.model.data').search(cr, uid, [('model', '=', self._name), ('res_id', '=', openerp_id), ('referential_id', '=', referential_id)])
+ if model_data_ids and len(model_data_ids) > 0:
+ prefixed_id = self.pool.get('ir.model.data').read(cr, uid, model_data_ids[0], ['name'])['name']
+ ext_id = self.id_from_prefixed_id(prefixed_id)
+ return ext_id
+ return False
+
+#TODO Deprecated remove for V7 version
+@extend(osv.osv)
+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
+############## END OF DEPRECATED
+
+
+@extend(osv.osv)
+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
+
+ :param int/str external_id: id in the external referential
+ :param int referential_id: id of the external referential
+ :return: tuple of (ir.model.data entry id, expected resource id in the current model)
+ :rtype: tuple
+ """
+ model_data_obj = self.pool.get('ir.model.data')
+ model_data_ids = model_data_obj.search(cr, uid,
+ [('name', '=', self.prefixed_id(external_id)),
+ ('model', '=', self._name),
+ ('referential_id', '=', referential_id)], context=context)
+ model_data_id = model_data_ids and model_data_ids[0] or False
+ expected_oe_id = False
+ if model_data_id:
+ 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)
+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
+ :return: the openerp id of the resource or False if not exist
+ :rtype: int
+ """
+ if external_id:
+ ir_model_data_id, expected_oe_id = self._get_expected_oeid\
+ (cr, uid, external_id, referential_id, context=context)
+ # Note: OpenERP cleans up ir_model_data which res_id records have been deleted
+ # only at server update because that would be a perf penalty, we returns the res_id only if
+ # really existing and we delete the ir_model_data unused
+ if expected_oe_id and self.exists(cr, uid, expected_oe_id, context=context):
+ return expected_oe_id
+ return False
+
+@extend(osv.osv)
+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
+ :rtype: int
+ """
+ if external_id:
+ existing_id = self.get_oeid(cr, uid, external_id, external_session.referential_id.id, context=context)
+ if existing_id:
+ return existing_id
+ return self._import_one_resource(cr, uid, external_session, external_id, context=context)
+ return False
+
+#TODO Deprecated remove for V7 version
+@extend(osv.osv)
+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
+############## END OF DEPRECATED
+
+
+########################################################################################################################
+#
+# END OF BASIC FEATURES
+#
+########################################################################################################################
+
+
+
+
+
+########################################################################################################################
+#
+# IMPORT FEATURES
+#
+########################################################################################################################
+
+
+@extend(osv.osv)
+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
+
+ :param ExternalSession external_session : External_session that contain all params of connection
+ :param int step: Step the of the import, 100 meant you will import data per 100
+ :param dict previous_filter: the previous filter
+ :rtype: dict
+ :return: dictionary with a filter
+ """
+ return None
+
+@extend(osv.osv)
+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
+
+ :param ExternalSession external_session : External_session that contain all params of connection
+ :param dict resource_filter: the filter to apply to the external search method
+ :param dict mapping: dictionnary of mapping, the key is the mapping id
+ :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!"))
+
+@extend(osv.osv)
+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
+
+ :param ExternalSession external_session : External_session that contain all params of connection
+ :param int mapping_id: id of the mapping
+ :rtype: dict
+ :return: a dictionnary of default values
+ """
+ return defaults
+
+@extend(osv.osv)
+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
+
+ :param ExternalSession external_session : External_session that contain all params of connection
+ :rtype: int
+ :return: a integer that corespond to the limit of object to import
+ """
+ return 100
+
+@extend(osv.osv)
+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
+
+ :param ExternalSession external_session : External_session that contain all params of connection
+ :param int external_id : resource external id to import
+ :param dict resource_filter: the filter to apply to the external search method
+ :param dict mapping: dictionnary of mapping, the key is the openerp object's name
+ :param list fields: list of field to read
+ :rtype: list
+ :return: a list of dict that contain resource information
+ """
+ mapping, mapping_id = self._init_mapping(cr, uid, external_session.referential_id.id, mapping=mapping, context=context)
+ if not resource_filter: resource_filter = {}
+ if external_id: resource_filter[mapping[mapping_id]['key_for_external_id']] = external_id
+
+ return getattr(external_session.connection, mapping[mapping_id]['external_get_method'])(mapping[mapping_id]['external_resource_name'], resource_filter)
+
+@extend(osv.osv)
+def _get_mapping_id(self, cr, uid, referential_id, context=None):
+ """Function that return the mapping id for the corresponding object
+
+ :param int referential_id: the referential id
+ :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)
+ 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):
+ """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'
+ :param list mapping_line_filter_ids: list of mappin line allowed to used
+ :param dict mapping: dict of mapping already loaded
+ :param int mapping_id: mapping id
+ :rtype int
+ :return the id of the mapping
+ """
+ if not mapping:
+ mapping={}
+ 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)
+ 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):
+ """Function that return the mapping line for the corresponding object
+
+ :param int referential_id: the referential id
+ :param str convertion_type: the type of convertion 'from_external_to_openerp' or 'from_openerp_to_external'
+ :param list mapping_line_filter_ids: list of mappin line allowed to used
+ :param int mapping_id: mapping id
+ :rtype: dict
+ :return: dictionary with the key "mapping_lines" and "key_for_external_id"
+ """
+ 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))
+ else:
+ #If a mapping exists for current model, search for mapping lines
+
+ mapping_type = convertion_type == 'from_external_to_openerp' and 'in' or 'out'
+ 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_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)
+ else:
+ mapping_lines = []
+ res = self.pool.get('external.mapping').read(cr, uid, mapping_id, context=context)
+ alternative_key = [x['internal_field'] for x in mapping_lines if x['alternative_key']]
+ res['alternative_keys'] = alternative_key or False
+ res['key_for_external_id'] = res['key_for_external_id'] or 'id'
+ res['mapping_lines'] = mapping_lines
+ return res
+
+@extend(osv.osv)
+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...
+
+ :param list ids: list of id
+ :param str ressource_name: the resource name to import
+ :param str method: method used for importing the resource (search_then_read,
+ search_then_read_no_loop, search_read, search_read_no_loop )
+ :rtype: dict
+ :return: dictionary with the key "create_ids" and "write_ids" which containt the id created/written
+ """
+ if context is None: context={}
+ result = {"create_ids" : [], "write_ids" : []}
+ for browse_record in self.browse(cr, uid, ids, context=context):
+ if browse_record._name == 'external.referential':
+ external_session = ExternalSession(browse_record, browse_record)
+ else:
+ if hasattr(browse_record, 'referential_id'):
+ 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,)))
+ 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:
+ result[key].append(res.get(key, []))
+ return result
+
+
+@extend(osv.osv)
+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...)
+
+ :param ExternalSession external_session : External_session that contain all params of connection
+ :param dict defaults: default value for the resource to create
+ :param str method: method used for importing the resource (
+ search_then_read,
+ search_then_read_no_loop,
+ search_read,
+ search_read_no_loop )
+ :rtype: dict
+ :return: dictionary with the key "create_ids" and "write_ids" which containt the id created/written
+ """
+ external_session.logger.info("Start to import the ressource %s"%(self._name,))
+ result = {"create_ids" : [], "write_ids" : []}
+ mapping, mapping_id = self._init_mapping(cr, uid, external_session.referential_id.id, context=context)
+ if mapping[mapping_id].get('mapping_lines'):
+ step = self._get_import_step(cr, uid, external_session, context=context)
+ resource_filter = None
+ #TODO refactor improve and simplify this code
+ if method == 'search_then_read':
+ while True:
+ resource_filter = self._get_filter(cr, uid, external_session, step, previous_filter=resource_filter, context=context)
+ ext_ids = self._get_external_resource_ids(cr, uid, external_session, resource_filter, mapping=mapping, context=context)
+ if not ext_ids:
+ break
+ 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, []))
+ elif method == 'search_then_read_no_loop':
+ #Magento API do not support step import so we can not use a loop
+ resource_filter = self._get_filter(cr, uid, external_session, step, previous_filter=resource_filter, context=context)
+ ext_ids = self._get_external_resource_ids(cr, uid, external_session, resource_filter, mapping=mapping, context=context)
+ 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, []))
+ elif method == 'search_read':
+ while True:
+ 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 resources:
+ break
+ 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_no_loop':
+ #Magento API do not support step import so we can not use a loop
+ 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, []))
+ return result
+
+@extend(osv.osv)
+def _import_one_resource(self, cr, uid, external_session, external_id, context=None):
+ """Abstract function to import one resource
+
+ :param ExternalSession external_session : External_session that contain all params of connection
+ :param int external_id : resource external id to import
+ :return: the openerp id of the resource imported
+ :rtype: int
+ """
+ resources = self._get_external_resources(cr, uid, external_session, external_id, context=context)
+ if isinstance(resources, list):
+ res = self._record_external_resources(cr, uid, external_session, resources, context=context)
+ id = res.get('write_ids') and res['write_ids'][0] or res['create_ids'][0]
+ else:
+ res = self._record_one_external_resource(cr, uid, external_session, resources, context=context)
+ id = res.get('write_id') or res.get('create_id')
+ return id
+
+@extend(osv.osv)
+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)
+
+ :param ExternalSession external_session : External_session that contain all params of connection
+ :param list resource: list of resource to import
+ :param dict defaults: default value for the resource to create
+ :param dict mapping: dictionnary of mapping, the key is the mapping id
+ :param int mapping_id: mapping id
+ :rtype: dict
+ :return: dictionary with the key "create_ids" and "write_ids" which containt the id created/written
+ """
+ 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']:
+ context['external_id_key_for_report'] = mapping[mapping_id]['key_for_external_id']
+ else:
+ for field in mapping[mapping_id]['mapping_lines']:
+ if field['alternative_key']:
+ context['external_id_key_for_report'] = field['external_field']
+ break
+ for resource in resources:
+ res = self._record_one_external_resource(cr, uid, external_session, resource, defaults=defaults, mapping=mapping, mapping_id=mapping_id, context=context)
+ if res:
+ if res.get('create_id'): result['create_ids'].append(res['create_id'])
+ if res.get('write_id'): result['write_ids'].append(res['write_id'])
+ return result
+
+@extend(osv.osv)
+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
+ And then created or updated, and an external id will be added into the table ir.model.data
+
+ :param ExternalSession external_session : External_session that contain all params of connection
+ :param dict resource: resource to convert into OpenERP data
+ :param dict defaults: default values
+ :param dict mapping: dictionnary of mapping, the key is the mapping id
+ :param int mapping_id: mapping id
+ :rtype: dict
+ :return: dictionary with the key "create_id" and "write_id" which containt the id created/written
+ """
+ mapping, mapping_id = self._init_mapping(cr, uid, external_session.referential_id.id, mapping=mapping, mapping_id=mapping_id, context=context)
+ written = created = False
+ vals = self._transform_one_resource(cr, uid, external_session, 'from_external_to_openerp', resource, mapping=mapping, mapping_id=mapping_id, defaults=defaults, context=context)
+ if not vals:
+ # for example in the case of an update on existing resource if update is not wanted vals will be {}
+ return {}
+ referential_id = external_session.referential_id.id
+ external_id = vals.get('external_id')
+ external_id_ok = not (external_id is None or external_id is False)
+ alternative_keys = mapping[mapping_id]['alternative_keys']
+ existing_rec_id = False
+ existing_ir_model_data_id = False
+ if external_id_ok:
+ del vals['external_id']
+ existing_ir_model_data_id, existing_rec_id = self._get_oeid_from_extid_or_alternative_keys\
+ (cr, uid, vals, external_id, referential_id, alternative_keys, context=context)
+
+ if not (external_id_ok or alternative_keys):
+ external_session.logger.warning(_("The object imported need an external_id, maybe the mapping doesn't exist for the object : %s" %self._name))
+
+ if existing_rec_id:
+ if not self._name in context.get('do_not_update', []):
+ if self.oe_update(cr, uid, external_session, existing_rec_id, vals, resource, defaults=defaults, context=context):
+ written = True
+ else:
+ existing_rec_id = self.oe_create(cr, uid, external_session, vals, resource, defaults, context=context)
+ created = True
+
+ if external_id_ok:
+ if existing_ir_model_data_id:
+ if created:
+ # means the external ressource is registred in ir.model.data but the ressource doesn't exist
+ # in this case we have to update the ir.model.data in order to point to the ressource created
+ self.pool.get('ir.model.data').write(cr, uid, existing_ir_model_data_id, {'res_id': existing_rec_id}, context=context)
+ else:
+ ir_model_data_vals = \
+ self.create_external_id_vals(cr, uid, existing_rec_id, external_id, referential_id, context=context)
+ if not created:
+ # means the external resource is bound to an already existing resource
+ # but not registered in ir.model.data, we log it to inform the success of the binding
+ 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))
+
+ if created:
+ if external_id:
+ external_session.logger.info(("Created in OpenERP %s from External Ref with"
+ "external_id %s and OpenERP id %s successfully" %(self._name, external_id_ok and str(external_id), existing_rec_id)))
+ elif alternative_keys:
+ external_session.logger.info(("Created in OpenERP %s from External Ref with"
+ "alternative_keys %s and OpenERP id %s successfully" %(self._name, external_id_ok and str (vals.get(alternative_keys)), existing_rec_id)))
+ return {'create_id' : existing_rec_id}
+ elif written:
+ if external_id:
+ external_session.logger.info(("Updated in OpenERP %s from External Ref with"
+ "external_id %s and OpenERP id %s successfully" %(self._name, external_id_ok and str(external_id), existing_rec_id)))
+ elif alternative_keys:
+ external_session.logger.info(("Updated in OpenERP %s from External Ref with"
+ "alternative_keys %s and OpenERP id %s successfully" %(self._name, external_id_ok and str (vals.get(alternative_keys)), existing_rec_id)))
+ return {'write_id' : existing_rec_id}
+ return {}
+
+@extend(osv.osv)
+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
+ :param dict resource: resource to convert into OpenERP data
+ :param dict defaults: default values
+ :rtype boolean
+ :return: True
+ """
+ if context is None: context={}
+ 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)
+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
+ :param dict defaults: default values
+ :rtype int
+ :return: the id of the resource created
+ """
+ if context is None: context={}
+ context['referential_id'] = external_session.referential_id.id #did it's needed somewhere?
+ return self.create(cr, uid, vals, context)
+
+########################################################################################################################
+#
+# END OF IMPORT FEATURES
+#
+########################################################################################################################
+
+
+
+
+########################################################################################################################
+#
+# EXPORT FEATURES
+#
+########################################################################################################################
+
+@extend(osv.osv)
+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
+
+ :param ExternalSession external_session : External_session that contain all params of connection
+ :rtype: int
+ :return: a integer that corespond to the limit of object to import
+ """
+ return 10
+
+@extend(osv.osv)
+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
+
+ :param ExternalSession external_session : External_session that contain all params of connection
+ :param int mapping_id: mapping id
+ :param dict defaults: default values
+ :rtype: dict
+ :return: a dictionnary of default values
+ """
+ return defaults
+
+@extend(osv.osv)
+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
+
+ :param ExternalSession external_session : External_session that contain all params of connection
+ :rtype: str
+ :return: the last export date or False
+ """
+ return False
+
+@extend(osv.osv)
+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
+
+ :param ExternalSession external_session : External_session that contain all params of connection
+ :param date : date
+ :rtype: boolean
+ :return: True
+ """
+ return True
+
+#For now it's just support 1 level of inherit TODO make it recursive
+@extend(osv.osv)
+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
+
+ :param ExternalSession external_session : External_session that contain all params of connection
+ :param list ids : if not empty the ids will be used in the sql request in order to filter the record
+ :param str last_exported_date : last exported date
+ :rtype: tuple
+ :return: an tuple of query and params
+ """
+ object_table = self._table
+ params = ()
+ if not self._inherits:
+ greatest = "GREATEST(%(object_table)s.write_date, %(object_table)s.create_date)"\
+ %{'object_table': object_table}
+
+ query = """
+ SELECT %(greatest)s as update_date, %(object_table)s.id as id, ir_model_data.res_id
+ FROM %(object_table)s
+ LEFT JOIN ir_model_data
+ ON %(object_table)s.id = ir_model_data.res_id
+ AND ir_model_data.model = '%(object_name)s'
+ AND ir_model_data.module = 'extref/%(ref_name)s'
+ """%{
+ 'greatest': greatest,
+ 'object_table': object_table,
+ 'object_name': self._name,
+ 'ref_name': external_session.referential_id.name,
+ }
+ else:
+ inherits_object_table = self.pool.get(self._inherits.keys()[0])._table
+ join_field = self._inherits[self._inherits.keys()[0]]
+
+ greatest = """GREATEST(%(object_table)s.write_date, %(object_table)s.create_date,
+ %(inherits_object_table)s.write_date, %(inherits_object_table)s.create_date)""" \
+ %{'object_table': object_table, 'inherits_object_table': inherits_object_table}
+
+ query = """
+ select %(greatest)s as update_date, %(object_table)s.id as id, ir_model_data.res_id
+ from %(object_table)s
+ join %(inherits_object_table)s on %(inherits_object_table)s.id = %(object_table)s.%(join_field)s
+ LEFT JOIN ir_model_data
+ ON %(object_table)s.id = ir_model_data.res_id
+ AND ir_model_data.model = '%(object_name)s'
+ AND ir_model_data.module = 'extref/%(ref_name)s'
+ """ %{
+ 'greatest': greatest,
+ 'object_table': object_table,
+ 'inherits_object_table': inherits_object_table,
+ 'join_field': join_field,
+ 'object_name': self._name,
+ 'ref_name': external_session.referential_id.name,
+ }
+ if ids:
+ query += " WHERE " + object_table + ".id in %s"
+ params += (tuple(ids),)
+ if last_exported_date:
+ query += (ids and " AND (" or " WHERE (") + greatest + " > %s or ir_model_data.res_id is NULL)"
+ params += (last_exported_date,)
+
+ query += " order by update_date asc;"
+ return query, params
+
+@extend(osv.osv)
+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
+
+ :param ExternalSession external_session : External_session that contain all params of connection
+ :param list ids : if not empty the ids will be used in the sql request in order to filter the record
+ :param str last_exported_date : last exported date
+ :rtype: tuple
+ :return: an tuple of ids and ids_2_dates (dict with key => 'id' and val => 'last_update_date')
+ """
+ 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()
+ ids = []
+ ids_2_dates = {}
+ for data in read:
+ ids.append(data['id'])
+ ids_2_dates[data['id']] = data['update_date']
+ return ids, ids_2_dates
+
+
+#Deprecated
+@extend(osv.osv)
+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)
+def export_resources(self, cr, uid, ids, resource_name, context=None):
+ """
+ Abstract function to export resources from a shop / a referential...
+
+ :param list ids: list of id
+ :param string ressource_name: the resource name to import
+ :return: True
+ :rtype: boolean
+ """
+ for browse_record in self.browse(cr, uid, ids, context=context):
+ if browse_record._name == 'external.referential':
+ external_session = ExternalSession(browse_record, browse_record)
+ else:
+ 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,)))
+ 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
+
+
+#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)
+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
+
+ :param ExternalSession external_session : External_session that contain all params of connection
+ :param list resources: list of resources to export
+ :param dict mapping: dictionnary of mapping, the key is the mapping id
+ :param date update_date: if not empty the update date will be write in the last update date of the objec
+ :rtype: int/str
+ :return: the external resource exported
+
+ """
+ resources_to_update = {}
+ resources_to_create = {}
+ for resource_id, resource in resources.items():
+ ext_id = self.get_extid(cr, uid, resource_id, external_session.referential_id.id, context=context)
+ if ext_id:
+ for lang in resource:
+ resource[lang]['ext_id'] = ext_id
+ resources_to_update[resource_id] = resource
+ else:
+ resources_to_create[resource_id] = resource
+ self.ext_update(cr, uid, external_session, resources_to_update, mapping, mapping_id, context=context)
+ ext_create_ids = self.ext_create(cr, uid, external_session, resources_to_create, mapping, mapping_id, context=context)
+ for rec_id, ext_id in ext_create_ids.items():
+ self.create_external_id_vals(cr, uid, rec_id, ext_id, external_session.referential_id.id, context=context)
+ if update_date and self._get_last_exported_date(cr, uid, external_session, context=context) < update_date:
+ self._set_last_exported_date(cr, uid, external_session, update_date, context=context)
+ return ext_id
+
+@extend(osv.osv)
+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)
+ for resource_id, resource in resources.items():
+ # TODO support multilanguages. for now we only export the first one
+ 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)
+def ext_update(self, cr, uid, external_session, resources, mapping=None, mapping_id=None, context=None):
+ """Not Implemented here"""
+ return False
+
+@extend(osv.osv)
+def ext_unlink(self, cr, uid, ids, context=None):
+ ir_model_obj = self.pool.get('ir.model.data')
+ for object_id in ids:
+ ir_model_ids = ir_model_obj.search(cr, uid, [('res_id','=',object_id),('model','=',self._name)])
+ for ir_model in ir_model_obj.browse(cr, uid, ir_model_ids, context=context):
+ ext_id = self.id_from_prefixed_id(ir_model.name)
+ ref_id = ir_model.referential_id.id
+ external_session = ExternalSession(ir_model.referential_id)
+ mapping = self._get_mapping(cr, uid, ref_id)
+ getattr(external_session.connection, mapping['external_delete_method'])(mapping['external_resource_name'], ext_id)
+ #commit_now(ir_model.unlink())
+ ir_model.unlink()
+ return True
+
+@extend(osv.osv)
+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)
+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
+ return: True
+ """
+ external_session.logger.info("Start to export the ressource %s"%(self._name,))
+ defaults = self._get_default_export_values(cr, uid, external_session, context=context)
+ mapping, mapping_id = self._init_mapping(cr, uid, external_session.referential_id.id, convertion_type='from_openerp_to_external', context=context)
+ last_exported_date = self._get_last_exported_date(cr, uid, external_session, context=context)
+ external_session.logger.info("Retrieve the list of ids to export for the ressource %s"%(self._name))
+ ids, ids_2_date = self.get_ids_and_update_date(cr, uid, external_session, last_exported_date=last_exported_date, context=context)
+ external_session.logger.info("%s %s ressource will be exported"%((ids and len(ids) or 0), self._name))
+ step = self._get_export_step(cr, uid, external_session, context=context)
+
+ group_obj = self.pool.get('group.fields')
+ group_ids = group_obj.search(cr, uid, [['model_id', '=', self._name]], context=context)
+ if self._inherits:
+ inherits_group_ids = group_obj.search(cr, uid, [['model_id', '=',self._inherits.keys()[0]]], context=context)
+ else:
+ inherits_group_ids=[]
+ smart_export = context.get('smart_export') and (group_ids or inherits_group_ids) and {'group_ids': group_ids, 'inherits_group_ids': inherits_group_ids}
+
+ langs = self.get_lang_to_export(cr, uid, external_session, context=context)
+
+ while ids:
+ ids_to_process = ids[0:step]
+ ids = ids[step:]
+ external_session.logger.info("Start to read the ressource %s : %s"%(self._name, ids_to_process))
+ resources = self._get_oe_resources(cr, uid, external_session, ids_to_process, langs=langs,
+ smart_export=smart_export, last_exported_date=last_exported_date,
+ mapping=mapping, mapping_id=mapping_id, context=context)
+ if method == 'onebyone':
+ for resource_id in ids_to_process:
+ 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'))
+ #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)
+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
+ The resource will converted into External format by using the function _transform_one_resource
+ And then send to the external system using the method send_to_external
+
+ :param ExternalSession external_session : External_session that contain all params of connection
+ :param dict resource: resource to convert into OpenERP data
+ :param int resource_id: openerp id of the resource to send
+ :param str method: method to export data (for now only onebyone)
+ :param dict mapping: dictionnary of mapping, the key is the mapping id
+ :param int mapping_id: mapping id
+ :param dict defaults: default values
+ :rtype: str/int
+ :return: the external id
+ """
+ for key_lang in resource:
+ resource[key_lang] = self._transform_one_resource(cr, uid, external_session, 'from_openerp_to_external',
+ resource[key_lang], mapping=mapping, mapping_id=mapping_id,
+ 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)
+def _export_one_resource(self, cr, uid, external_session, resource_id, context=None):
+ """Export one resource
+ Export an OpenERP resource into an external system
+
+ :param ExternalSession external_session : External_session that contain all params of connection
+ :param int resource_id: openerp id of the resource to send
+ :rtype: str/int
+ :return: the external id
+ """
+ defaults = self._get_default_export_values(cr, uid, external_session, context=context)
+ mapping, mapping_id = self._init_mapping(cr, uid, external_session.referential_id.id, convertion_type='from_openerp_to_external', context=context)
+ langs = self.get_lang_to_export(cr, uid, external_session, context=context)
+ resource = self._get_oe_resources(cr, uid, external_session, [resource_id], langs=langs,
+ smart_export=False, last_exported_date=False,
+ mapping=mapping, mapping_id=mapping_id, context=context)[resource_id]
+ return self._transform_and_send_one_resource(cr, uid, external_session, resource, resource_id,
+ False, mapping, mapping_id, defaults=defaults, context=context)
+
+
+#TODO finish docstring
+
+@extend(osv.osv)
+def get_translatable_fields(self, cr, uid, fields, context=None):
+ #TODO make fields parameter optionnal
+ def is_translatable(field):
+ if self._columns.get(field):
+ return self._columns[field].translate
+ else:
+ return self._inherit_fields[field][2].translate
+ translatable_fields = []
+ untranslatable_fields = []
+ for field in fields:
+ if is_translatable(field):
+ translatable_fields.append(field)
+ else:
+ untranslatable_fields.append(field)
+ return translatable_fields, untranslatable_fields
+
+@extend(osv.osv)
+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 = {}
+ translatable_fields, untranslatable_fields = self.get_translatable_fields(cr, uid, fields_to_read, context=context)
+ lang_support = external_session.referential_id._lang_support
+ if lang_support == 'fields_with_no_lang':
+ langs.insert(0, 'no_lang')
+ first=True
+ fields = fields_to_read
+ for lang in langs:
+ ctx = context.copy()
+ if lang == 'no_lang':
+ fields = untranslatable_fields
+ else:
+ if not first and lang_support == 'fields_with_main_lang' or lang_support == 'fields_with_no_lang':
+ fields = translatable_fields
+ ctx['lang'] = lang
+
+ 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
+ first = False
+ return resources
+
+@extend(osv.osv)
+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)
+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:
+ search_filter = []
+ if group_ids:
+ if inherits_group_ids:
+ search_filter = ['|', ['x_last_update', '>=', last_exported_date], ['%s.x_last_update'%self._inherits[self._inherits.keys()[0]], '>=', last_exported_date]]
+ if inherits_group_ids:
+ search_filter = [['%s.x_last_update'%self._inherits[self._inherits.keys()[0]], '>=', last_exported_date]]
+ resource_ids_full_read = self.search(cr, uid, search_filter, context=context)
+ resource_ids_partial_read = [id for id in ids if not id in resource_ids_full_read]
+ else:
+ resource_ids_full_read = ids
+ resource_ids_partial_read = []
+
+ resources = self.full_read(cr, uid, external_session, resource_ids_full_read, langs, resources, context=context)
+
+ if resource_ids_partial_read:
+ for group in self.pool.get('group.fields').browse(cr, uid, group_ids, context=context):
+ resource_ids = self.search(cr, uid, [[group.column_name, '>=', last_exported_date],['id', 'in', resource_ids_partial_read]], context=context)
+ fields_to_read = [field.name for field in group.field_ids]
+ resources = self.multi_lang_read(cr, uid, external_session, resource_ids, fields_to_read, langs, resources=resources, context=context)
+ return resources
+
+@extend(osv.osv)
+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)
+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
+ if smart_export:
+ resources = self.smart_read(cr, uid, external_session, ids, langs, resources, smart_export['group_ids'], smart_export['inherits_group_ids'],
+ last_exported_date=last_exported_date, mapping=mapping, mapping_id=mapping_id, context=context)
+ else:
+ resources = self.full_read(cr, uid, external_session, ids, langs, resources, mapping=mapping, mapping_id=mapping_id, context=context)
+ return resources
+
+
+@extend(osv.osv)
+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.
+ It searches the reference in ir.model.data and returns the id in ir.model.data and the id of the
+ current's model resource, if it really exists (it may not exists, see below)
+
+ As OpenERP cleans up ir_model_data which res_id records have been deleted only at server update
+ because that would be a perf penalty, so we take care of it here.
+
+ This method can also be used by inheriting, in order to find and bind resources by another way than ir.model.data when
+ the resource is not already imported.
+ As instance, search and bind partners by their mails. In such case, it must returns False for the ir_model_data.id and
+ the partner to bind for the resource id
+
+ @param vals: vals to create in OpenERP, already evaluated by _transform_one_external_resource
+ @param external_id: external id of the resource to create
+ @param referential_id: external referential id from where we import the resource
+ @return: tuple of (ir.model.data id / False: external id to create in ir.model.data, model resource id / False: resource to create)
+ """
+ existing_ir_model_data_id = expected_res_id = False
+ if not (external_id is None or external_id is False):
+ existing_ir_model_data_id, expected_res_id = self._get_expected_oeid\
+ (cr, uid, external_id, referential_id, context=context)
+
+ if not expected_res_id and alternative_keys:
+ domain = []
+ if 'active' in self._columns.keys():
+ domain = ['|', ('active', '=', False), ('active', '=', True)]
+ for alternative_key in alternative_keys:
+ if vals.get(alternative_key):
+ exp = type(vals[alternative_key]) in (str, unicode) and "=ilike" or "="
+ domain.append((alternative_key, exp, vals[alternative_key]))
+ if domain:
+ expected_res_id = self.search(cr, uid, domain, context=context)
+ 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)
+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 = {
+ 'name': self.prefixed_id(ext_id),
+ 'model': self._name,
+ 'res_id': res_id,
+ 'referential_id': referential_id,
+ 'module': 'extref/' + self.pool.get('external.referential').\
+ read(cr, uid, referential_id, ['name'])['name']
+ }
+ return ir_model_data_vals
+
+@extend(osv.osv)
+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"""
+ ir_model_data_vals = \
+ self._prepare_external_id_vals(cr, uid, existing_rec_id,
+ external_id, referential_id,
+ context=context)
+ return self.pool.get('ir.model.data').create(cr, uid, ir_model_data_vals, context=context)
+
+########################################################################################################################
+#
+# END OF EXPORT FEATURES
+#
+########################################################################################################################
+
+
+
+
+
+########################################################################################################################
+#
+# GENERIC TRANSFORM FEATURES
+#
+########################################################################################################################
+
+@extend(osv.osv)
+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):
+ """
+ Used in ext_import in order to convert all of the external data into OpenERP data
+
+ @param external_data: list of external_data to convert into OpenERP data
+ @param referential_id: external referential id from where we import the resource
+ @param parent_data: data of the parent, only use when a mapping line have the type 'sub mapping'
+ @param defaults: defaults value for data converted
+ @return: list of the line converted into OpenERP value
+ """
+ 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)
+ if mapping[mapping_id].get("mapping_lines"):
+ for resource in resources:
+ result.append(self._transform_one_resource(cr, uid, external_session, convertion_type, resource,
+ mapping, mapping_id, mapping_line_filter_ids, parent_data=parent_data,
+ previous_result=result, defaults=defaults, context=context))
+ return result
+
+@extend(osv.osv)
+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):
+ """
+ Used in _transform_external_resources in order to convert external row of data into OpenERP data
+
+ @param referential_id: external referential id from where we import the resource
+ @param resource: a dictionnary of data, an lxml.objectify object...
+ @param mapping dict: dictionnary of mapping {'product.product' : {'mapping_lines' : [...], 'key_for_external_id':'...'}}
+ @param previous_result: list of the previous line converted. This is not used here but it's necessary for playing on change on sale order line
+ @param defaults: defaults value for the data imported
+ @return: dictionary of converted data in OpenERP format
+ """
+
+ #Encapsulation of the resource if it not a dictionnary
+ #So we can use the same method to read it
+ if not isinstance(resource, dict):
+ resource = Resource(resource)
+
+ if context is None:
+ context = {}
+ if defaults is None:
+ 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_lines = mapping[mapping_id].get("mapping_lines")
+ key_for_external_id = mapping[mapping_id].get("key_for_external_id")
+
+ vals = {} #Dictionary for create record
+ sub_mapping_list=[]
+ for mapping_line in mapping_lines:
+ if convertion_type == 'from_external_to_openerp':
+ from_field = mapping_line['external_field']
+ if not from_field and mapping_line['evaluation_type'] != 'function':
+ from_field = "%s_%s" %(mapping_line['child_mapping_id'][1], mapping_line['child_mapping_id'][0])
+ to_field = mapping_line['internal_field']
+ elif convertion_type == 'from_openerp_to_external':
+ from_field = mapping_line['internal_field']
+ to_field = mapping_line['external_field']
+
+ if mapping_line['evaluation_type'] == 'function' or from_field in resource.keys(): #function field should be always played as they can depend on every field
+ field_value = resource.get(from_field)
+ if mapping_line['evaluation_type'] == 'sub-mapping':
+ 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)
+ else:
+ #Build the space for expr
+ #Seb : removing ifield can be great ?
+ space = {'self': self,
+ 'cr': cr,
+ 'uid': uid,
+ 'external_session': external_session,
+ 'resource': resource,
+ 'data': resource, #only for compatibility with the old version => deprecated
+ 'parent_resource': parent_data, #TODO rename parent_data to parent_resource
+ '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),
+ 'conn': context.get('conn_obj', False),
+ 'base64': base64,
+ 'vals': vals,
+ 'previous_result': previous_result,
+ }
+ #The expression should return value in list of tuple format
+ #eg[('name','Sharoon'),('age',20)] -> vals = {'name':'Sharoon', 'age':20}
+ if convertion_type == 'from_external_to_openerp':
+ mapping_function_key = 'in_function'
+ else:
+ mapping_function_key = 'out_function'
+ try:
+ exec mapping_line[mapping_function_key] in space
+ except Exception, e:
+ #del(space['__builtins__'])
+ if config['debug_mode']: raise
+ raise MappingError(e, mapping_line['name'], self._name)
+
+ result = space.get('result', False)
+ # Check if result returned by the mapping function is correct : [('field1', value), ('field2', value))]
+ # And fill the vals dict with the results
+ if result:
+ if isinstance(result, list):
+ for each_tuple in result:
+ if isinstance(each_tuple, tuple) and len(each_tuple) == 2:
+ vals[each_tuple[0]] = each_tuple[1]
+ else:
+ raise MappingError(_('Invalid format for the variable result.'), mapping_line['external_field'], self._name)
+ ext_id = False
+ if convertion_type == 'from_external_to_openerp' and key_for_external_id and resource.get(key_for_external_id):
+ ext_id = resource[key_for_external_id]
+ if isinstance(ext_id, str):
+ 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.
+ 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)
+
+ return vals
+
+@extend(osv.osv)
+def _transform_field(self, cr, uid, external_session, convertion_type, field_value, mapping_line, context=None):
+ field = False
+ external_type = mapping_line['external_type']
+ internal_type = mapping_line['internal_type']
+ internal_field = mapping_line['internal_field']
+ 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'],))
+ if self._columns.get(internal_field):
+ related_obj_name = self._columns[internal_field]._obj
+ else:
+ related_obj_name = self._inherit_fields[internal_field][2]._obj
+ related_obj = self.pool.get(related_obj_name)
+ if convertion_type == 'from_external_to_openerp':
+ if external_type == 'unicode':
+ #TODO it can be great if we can search on other field
+ related_obj.search(cr, uid, [(related_obj._rec_name, '=', field_value)], context=context)
+ else:
+ return related_obj.get_or_create_oeid(cr, uid, external_session, field_value, context=context)
+ else:
+ if external_type == 'unicode':
+ #TODO it can be great if we can return on other field and not only the name
+ return field_value[1]
+ else:
+ return related_obj.get_or_create_extid(cr, uid,external_session, field_value[0], context=context)
+
+ elif external_type == "datetime":
+ if not field_value:
+ field_value = False
+ else:
+ datetime_format = mapping_line['datetime_format']
+ if convertion_type == 'from_external_to_openerp':
+ datetime_value = datetime.strptime(field_value, datetime_format)
+ if internal_type == 'date':
+ return datetime_value.strftime(DEFAULT_SERVER_DATE_FORMAT)
+ elif internal_type == 'datetime':
+ return datetime_value.strftime(DEFAULT_SERVER_DATETIME_FORMAT)
+ else:
+ if internal_type == 'date':
+ datetime_value = datetime.strptime(field_value, DEFAULT_SERVER_DATE_FORMAT)
+ elif internal_type == 'datetime':
+ datetime_value = datetime.strptime(field_value, DEFAULT_SERVER_DATETIME_FORMAT)
+ return datetime_value.strftime(datetime_format)
+
+ elif external_type == 'list' and isinstance(field_value, (str, unicode)):
+ # external data sometimes returns ',1,2,3' for a list...
+ if field_value:
+ casted_field = eval(field_value.strip(','))
+ else:
+ casted_field= []
+ # For a list, external data may returns something like '1,2,3' but also '1' if only
+ # one item has been selected. So if the casted field is not iterable, we put it in a tuple: (1,)
+ if not hasattr(casted_field, '__iter__'):
+ casted_field = (casted_field,)
+ field = list(casted_field)
+ else:
+ if external_type == 'float' and isinstance(field_value, (str, unicode)):
+ field_value = field_value.replace(',','.')
+ if not field_value:
+ field_value = 0
+ field = eval(external_type)(field_value)
+ if field in ['None', 'False']:
+ field = False
+
+ #Set correct empty value for each type
+ if field is False or field is None:
+ empty_value = {
+ 'integer': 0,
+ 'unicode': '',
+ 'char': '',
+ 'date': False,
+ 'int': 0,
+ 'float': 0,
+ 'list': [],
+ 'dict': {},
+ 'boolean': False,
+ 'many2one': False,
+ 'one2many': [],
+ 'many2many': [],
+ # external types
+ 'text': '',
+ 'textarea': '',
+ 'selection': 0,
+ 'multiselect': [],
+ }
+ if convertion_type == 'from_external_to_openerp':
+ empty_value['datetime'] = False
+ else:
+ empty_value['datetime'] = ''
+ if internal_type and convertion_type == 'from_external_to_openerp':
+ field = empty_value[internal_type]
+ elif external_type:
+ # if the type is not specified in empty_value,
+ # then we consider it will be False, if it
+ # should not for an external_type, please add it
+ # in empty_value
+ field = empty_value.get(external_type, False)
+
+ return field
+
+@extend(osv.osv)
+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
+
+ @param sub_mapping_list: list of sub-mapping to apply
+ @param external_data: list of data to convert into OpenERP data
+ @param referential_id: external referential id from where we import the resource
+ @param vals: dictionnary of value previously converted
+ @param defauls: defaults value for the data imported
+ @return: dictionary of converted data in OpenERP format
+ """
+ if not defaults: return vals
+ for key in defaults:
+ if not key in vals:
+ 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):
+ """
+ Used in _transform_one_external_resource in order to call the sub mapping
+
+ @param sub_mapping_list: list of sub-mapping to apply
+ @param resource: resource encapsulated in the object Resource or a dictionnary
+ @param referential_id: external referential id from where we import the resource
+ @param vals: dictionnary of value previously converted
+ @param defauls: defaults value for the data imported
+ @return: dictionary of converted data in OpenERP format
+ """
+ if not defaults:
+ defaults={}
+ ir_model_field_obj = self.pool.get('ir.model.fields')
+ for sub_mapping in sub_mapping_list:
+ sub_object_name = sub_mapping['child_mapping_id'][1]
+ sub_mapping_id = sub_mapping['child_mapping_id'][0]
+ if convertion_type == 'from_external_to_openerp':
+ from_field = sub_mapping['external_field']
+ if not from_field:
+ from_field = "%s_%s" %(sub_object_name, sub_mapping_id)
+ to_field = sub_mapping['internal_field']
+
+ elif convertion_type == 'from_openerp_to_external':
+ from_field = sub_mapping['internal_field']
+ to_field = sub_mapping['external_field'] or 'hidden_field_to_split_%s'%from_field # if the field doesn't have any name we assume at that we will split it
+
+ field_value = resource[from_field]
+ sub_mapping_obj = self.pool.get(sub_object_name)
+ sub_mapping_defaults = sub_mapping_obj._get_default_import_values(cr, uid, external_session, sub_mapping_id, defaults.get(to_field), context=context)
+
+ if field_value:
+ transform_args = [cr, uid, external_session, convertion_type, field_value]
+ transform_kwargs = {
+ 'defaults': sub_mapping_defaults,
+ 'mapping': mapping,
+ 'mapping_id': sub_mapping_id,
+ 'mapping_line_filter_ids': mapping_line_filter_ids,
+ 'parent_data': vals,
+ 'context': context,
+ }
+
+ if sub_mapping['internal_type'] in ['one2many', 'many2many']:
+ if not isinstance(field_value, list):
+ transform_args[4] = [field_value]
+ if not to_field in vals:
+ vals[to_field] = []
+ if convertion_type == 'from_external_to_openerp':
+ lines = sub_mapping_obj._transform_resources(*transform_args, **transform_kwargs)
+ else:
+ mapping, sub_mapping_id = self._init_mapping(cr, uid, external_session.referential_id.id, \
+ convertion_type=convertion_type,
+ mapping=mapping,
+ mapping_id=sub_mapping_id,
+ context=context)
+ field_to_read = [x['internal_field'] for x in mapping[sub_mapping_id]['mapping_lines']]
+ sub_resources = sub_mapping_obj.read(cr, uid, field_value, field_to_read, context=context)
+ transform_args[4] = sub_resources
+ lines = sub_mapping_obj._transform_resources(*transform_args, **transform_kwargs)
+ for line in lines:
+ if 'external_id' in line:
+ del line['external_id']
+ if convertion_type == 'from_external_to_openerp':
+ if sub_mapping['internal_type'] == 'one2many':
+ #TODO refactor to search the id and alternative keys before the update
+ external_id = vals.get('external_id')
+ alternative_keys = mapping[mapping_id]['alternative_keys']
+ #search id of the parent
+ existing_ir_model_data_id, existing_rec_id = \
+ self._get_oeid_from_extid_or_alternative_keys(
+ cr, uid, vals, external_id,
+ external_session.referential_id.id,
+ alternative_keys, context=context)
+ vals_to_append = (0, 0, line)
+ if existing_rec_id:
+ sub_external_id = line.get('external_id')
+ if mapping[sub_mapping_id].get('alternative_keys'):
+ sub_alternative_keys = list(mapping[sub_mapping_id]['alternative_keys'])
+ if self._columns.get(to_field):
+ related_field = self._columns[to_field]._fields_id
+ elif self._inherit_fields.get(to_field):
+ related_field = self._inherit_fields[to_field][2]._fields_id
+ sub_alternative_keys.append(related_field)
+ line[related_field] = existing_rec_id
+ #search id of the sub_mapping related to the id of the parent
+ sub_existing_ir_model_data_id, sub_existing_rec_id = \
+ sub_mapping_obj._get_oeid_from_extid_or_alternative_keys(
+ cr, uid, line, sub_external_id,
+ external_session.referential_id.id,
+ sub_alternative_keys, context=context)
+ del line[related_field]
+ if sub_existing_rec_id:
+ vals_to_append = (1, sub_existing_rec_id, line)
+ vals[to_field].append(vals_to_append)
+ else:
+ vals[to_field].append(line)
+
+ elif sub_mapping['internal_type'] == 'many2one':
+ if convertion_type == 'from_external_to_openerp':
+ res = sub_mapping_obj._record_one_external_resource(cr, uid, external_session, field_value,
+ defaults=sub_mapping_defaults, mapping=mapping, mapping_id=sub_mapping_id, context=context)
+ vals[to_field] = res.get('write_id') or res.get('create_id')
+ else:
+ sub_resource = sub_mapping_obj.read(cr, uid, field_value[0], context=context)
+ 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'],))
+ return vals
+
+
+########################################################################################################################
+#
+# END GENERIC TRANSFORM FEATURES
+#
+########################################################################################################################
+
+
+
+
=== added file 'base_external_referentials/external_referentials.py'
--- base_external_referentials/external_referentials.py 1970-01-01 00:00:00 +0000
+++ base_external_referentials/external_referentials.py 2012-09-13 01:56:18 +0000
@@ -0,0 +1,734 @@
+# -*- encoding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>). All Rights Reserved
+# $Id$
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+from osv import fields, osv
+from sets import Set
+from tools.translate import _
+from tempfile import TemporaryFile
+from base_file_protocole.base_file_protocole import FileCsvWriter
+import time
+
+
+class external_referential_category(osv.osv):
+ _name = 'external.referential.category'
+ _description = 'External Referential Category (Ex: e-commerce, crm, warehouse)'
+
+ _columns = {
+ 'name': fields.char('Name', size=64, required=True), #dont allow creation of type from frontend
+ 'type_ids': fields.one2many('external.referential.type', 'categ_id', 'Types', required=True)
+ }
+
+ def get_absolute_id(self, cr, uid, id, context=None):
+ if isinstance(id,list):
+ id = id[0]
+ referential_categ = self.browse(cr, uid, id, context=context)
+ categ_id = referential_categ.get_external_id(context=context)[referential_categ.id]
+ if not categ_id:
+ categ_id = referential_categ.name.replace('.','_').replace(' ','_')
+ return categ_id
+
+external_referential_category()
+
+class external_referential_type(osv.osv):
+ _name = 'external.referential.type'
+ _description = 'External Referential Type (Ex.Magento,Spree)'
+
+ _columns = {
+ 'name': fields.char('Name', size=64, required=True), #dont allow creation of type from frontend
+ 'categ_id': fields.many2one('external.referential.category', 'Category', required=True),
+ 'version_ids': fields.one2many('external.referential.version', 'type_id', 'Versions', required=True),
+ 'code': fields.char('code', size=64, required=True),
+ }
+
+ def get_absolute_id(self, cr, uid, id, context=None):
+ if isinstance(id,list):
+ id = id[0]
+ referential_type = self.browse(cr, uid, id, context=context)
+ type_id = referential_type.get_external_id(context=context)[referential_type.id]
+ if not type_id:
+ type_id = referential_type.code.replace('.','_').replace(' ','_')
+ return type_id
+
+external_referential_type()
+
+class external_referential_version(osv.osv):
+ _name = 'external.referential.version'
+ _description = 'External Referential Version (Ex: v1.5.0.0 +, v1.3.2.4 +)'
+ _rec_name = 'full_name'
+
+ def get_absolute_id(self, cr, uid, id, context=None):
+ if isinstance(id,list):
+ id = id[0]
+ version = self.browse(cr, uid, id, context=context)
+ version_id = version.get_external_id(context=context)[version.id]
+ if not version_id:
+ version_id = version.code.replace('.','_').replace(' ','_')
+ return version_id
+
+ def _get_full_name(self, cr, uid, ids, name, arg, context=None):
+ res = {}
+ for version in self.read(cr, uid, ids, ['name', 'type_id'], context=context):
+ res[version['id']] = '%s %s'%(version['type_id'][1], version['name'])
+ return res
+
+ _columns = {
+ 'full_name': fields.function(_get_full_name, store=True, type='char', size=64, string='Full Name'),
+ 'name': fields.char('name', size=64, required=True),
+ 'type_id': fields.many2one('external.referential.type', 'Type', required=True),
+ 'code': fields.char('code', size=64, required=True),
+ }
+
+external_referential_version()
+
+class external_mapping_template(osv.osv):
+ _name = "external.mapping.template"
+ _description = "The source mapping records"
+ _rec_name = 'model'
+
+ _columns = {
+ 'version_id':fields.many2one('external.referential.version', 'External Referential Version', ondelete='cascade'),
+ 'model_id': fields.many2one('ir.model', 'OpenERP Model', required=True, ondelete='cascade'),
+ 'model':fields.related('model_id', 'model', type='char', string='Model Name'),
+ 'external_list_method': fields.char('List Method', size=64),
+ 'external_search_method': fields.char('Search Method', size=64),
+ 'external_get_method': fields.char('Get Method', size=64),
+ 'external_update_method': fields.char('Update Method', size=64),
+ 'external_create_method': fields.char('Create Method', size=64),
+ 'external_delete_method': fields.char('Delete Method', size=64),
+ 'external_done_method': fields.char('Done Method', size=64),
+ 'key_for_external_id':fields.char('External field used as key', size=64),
+ '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):
+ _name = 'external.mappinglines.template'
+ _description = 'The source mapping line records'
+ _rec_name = 'name'
+
+ def _name_get_fnc(self, cr, uid, ids, name, arg, context=None):
+ res = {}
+ for mapping_line in self.browse(cr, uid, ids, context):
+ res[mapping_line.id] = mapping_line.evaluation_type == 'function' \
+ and mapping_line.function_name \
+ or mapping_line.external_field \
+ or mapping_line.field_id.name
+ return res
+
+ _columns = {
+ 'name': fields.function(_name_get_fnc, type="char", string='Name'),
+ 'sequence': fields.integer('Sequence'),
+ 'version_id':fields.many2one('external.referential.version', 'External Referential Version', ondelete='cascade'),
+ 'field_id': fields.many2one('ir.model.fields', 'OpenERP Field', ondelete='cascade'),
+ 'mapping_id': fields.many2one('external.mapping.template', 'External Mapping', ondelete='cascade'),
+ '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),
+ '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'),
+ 'child_mapping_id': fields.many2one('external.mapping.template', 'Child Mapping', ondelete='cascade',
+ help=('This give you the possibility to import data with a structure of Parent/child'
+ 'For example when you import a sale order, the sale order is the parent of the sale order line'
+ 'In this case you have to select the child mapping in order to convert the data'
+ )
+ ),
+ 'alternative_key': fields.boolean('Alternative Key', help=("Only one field can be selected as alternative key,"
+ "if no external id was found for the record the alternative key"
+ "will be used to identify the resource")),
+ '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 :
+ - 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}...}"""
+ _name = 'external.referential'
+ _description = 'External Referential'
+
+ _lang_support = 'fields_with_main_lang'
+
+ #Only user that can write crypted field can read it
+ _crypted_field = ['apiusername', 'apipass', 'location']
+
+ 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)
+ if not canwrite:
+ for val in res:
+ for crypted_field in self._crypted_field:
+ if val.get(crypted_field):
+ val[crypted_field]='********'
+ return res
+
+ def external_connection(self, cr, uid, referential, debug=False, context=None):
+ """Should be overridden to provide valid external referential connection"""
+ return False
+
+ def import_referentials(self, cr, uid, ids, context=None):
+ self.import_resources(cr, uid, ids, 'external.referential', context=context)
+ return True
+
+ def _prepare_mapping_vals(self, cr, uid, referential_id, mapping_vals, context=None):
+ return {
+ 'referential_id': referential_id,
+ 'template_id': mapping_vals['id'],
+ 'model_id': mapping_vals['model_id'][0] or False,
+ 'external_list_method': mapping_vals['external_list_method'],
+ 'external_search_method': mapping_vals['external_search_method'],
+ 'external_get_method': mapping_vals['external_get_method'],
+ 'external_update_method': mapping_vals['external_update_method'],
+ 'external_create_method': mapping_vals['external_create_method'],
+ 'external_delete_method': mapping_vals['external_delete_method'],
+ 'external_done_method': mapping_vals['external_done_method'],
+ 'key_for_external_id': mapping_vals['key_for_external_id'],
+ 'external_resource_name': mapping_vals['external_resource_name'],
+ 'extra_name': mapping_vals['extra_name'],
+ }
+
+ def _prepare_mapping_line_vals(self, cr, uid, mapping_id, mapping_line_vals, context=None):
+ return {
+ 'sequence': mapping_line_vals['sequence'] or 0,
+ 'external_field': mapping_line_vals['external_field'],
+ 'template_id': mapping_line_vals['id'],
+ 'mapping_id': mapping_id,
+ 'type': mapping_line_vals['type'],
+ 'evaluation_type': mapping_line_vals['evaluation_type'],
+ 'external_type': mapping_line_vals['external_type'],
+ 'datetime_format': mapping_line_vals['datetime_format'],
+ 'in_function': mapping_line_vals['in_function'],
+ 'out_function': mapping_line_vals['out_function'],
+ 'field_id': mapping_line_vals['field_id'] and mapping_line_vals['field_id'][0] or False,
+ 'alternative_key': mapping_line_vals['alternative_key'],
+ 'function_name': mapping_line_vals['function_name'],
+ }
+
+ def refresh_mapping(self, cr, uid, ids, context=None):
+ #This function will reinstate mapping & mapping_lines for registered objects
+ for id in ids:
+ ext_ref = self.browse(cr, uid, id)
+ mappings_obj = self.pool.get('external.mapping')
+ mapping_line_obj = self.pool.get('external.mapping.line')
+ mapping_tmpl_obj = self.pool.get('external.mapping.template')
+
+ existing_mapping_line_ids = mapping_line_obj.search(cr, uid, [['mapping_id.referential_id', '=', id], ['template_id', '!=', False]], context=context)
+ mapping_line_obj.unlink(cr, uid, existing_mapping_line_ids)
+
+ link_parent_child_mapping = []
+ template_mapping_id_to_mapping_id = {}
+ #Fetch mapping lines now
+ mapping_src_ids = self.pool.get('external.mapping.template').search(cr, uid, [('version_id', '=', ext_ref.version_id.id)])
+ for each_mapping_rec in self.pool.get('external.mapping.template').read(cr, uid, mapping_src_ids, []):
+ existing_ids = mappings_obj.search(cr, uid, [('referential_id', '=', id), ('template_id', '=', each_mapping_rec['id'])])
+ vals = self._prepare_mapping_vals(cr, uid, id, each_mapping_rec, context=context)
+
+ if len(existing_ids) == 0:
+ mapping_id = mappings_obj.create(cr, uid, vals)
+ else:
+ mapping_id = existing_ids[0]
+ self.pool.get('external.mapping').write(cr, uid, mapping_id, vals, context=context)
+
+ template_mapping_id_to_mapping_id[each_mapping_rec['id']] = mapping_id
+ #Now create mapping lines of the created mapping model
+ mapping_lines_src_ids = self.pool.get('external.mappinglines.template').search(cr, uid, [('mapping_id', '=', each_mapping_rec['id'])])
+ for each_mapping_line_rec in self.pool.get('external.mappinglines.template').read(cr, uid, mapping_lines_src_ids, []):
+ vals = self._prepare_mapping_line_vals(cr, uid, mapping_id, each_mapping_line_rec, context=context)
+ mapping_line_id = mapping_line_obj.create(cr, uid, vals)
+ if each_mapping_line_rec['child_mapping_id']:
+ link_parent_child_mapping.append([mapping_line_id, each_mapping_line_rec['child_mapping_id'][0]])
+
+ #Now link the sub-mapping to the corresponding child
+ for mapping_line_id, mapping_tmpl_id in link_parent_child_mapping:
+ mapping_id = template_mapping_id_to_mapping_id[mapping_tmpl_id]
+ mapping_line_obj.write(cr, uid, mapping_line_id, {'child_mapping_id': mapping_id}, context=context)
+ return True
+
+
+ _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'),
+ '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),
+ 'apiusername': fields.char('User Name', size=64),
+ 'apipass': fields.char('Password', size=64),
+ 'mapping_ids': fields.one2many('external.mapping', 'referential_id', 'Mappings'),
+ 'create_date': fields.datetime('Creation Date', readonly=True, help="Date on which external referential is created."),
+ 'debug': fields.boolean('Debug', help='If debug mode is active all request between the external referential and OpenERP will be in the log')
+ }
+
+ _sql_constraints = [
+ ('name_uniq', 'unique (name)', 'Referential names must be unique !')
+ ]
+
+ def _test_dot_in_name(self, cr, uid, ids, context=None):
+ for referential in self.browse(cr, uid, ids):
+ if '.' in referential.name:
+ return False
+ return True
+
+ # Method to export external referential category
+ def build_external_ref_categ(self, cr, uid, id, context=None):
+ if isinstance(id,list):
+ id = id[0]
+ output_file = TemporaryFile('w+b')
+ fieldnames = ['id', 'name']
+ csv = FileCsvWriter(output_file, fieldnames, encoding="utf-8", writeheader=True, delimiter=',', quotechar='"')
+
+ referential = self.browse(cr, uid, id, context=context)
+ row = {
+ 'id': referential.type_id.categ_id.name,
+ 'name': referential.type_id.categ_id.name,
+ }
+ csv.writerow(row)
+ return self.pool.get('pop.up.file').open_output_file(cr, uid, 'external.referential.category.csv', output_file, 'Referential category export', context=context)
+
+ # Method to export external referential type
+ def build_external_ref_type(self, cr, uid, id, context=None):
+ if isinstance(id,list):
+ id = id[0]
+ output_file = TemporaryFile('w+b')
+ fieldnames = ['id', 'name', 'categ_id:id', 'code']
+ csv = FileCsvWriter(output_file, fieldnames, encoding="utf-8", writeheader=True, delimiter=',', quotechar='"')
+
+ referential = self.browse(cr, uid, id, context=context)
+ row = {
+ 'id': referential.type_id.get_absolute_id(context=context),
+ 'name': referential.type_id.name,
+ 'categ_id:id': referential.categ_id.get_absolute_id(context=context),
+ 'code': referential.type_id.code,
+ }
+ csv.writerow(row)
+ return self.pool.get('pop.up.file').open_output_file(cr, uid, 'external.referential.type.csv', output_file, 'Referential Type Export', context=context)
+
+ # Method to export external referential version
+ def build_external_ref_version(self, cr, uid, id, context=None):
+ if isinstance(id,list):
+ id = id[0]
+ output_file = TemporaryFile('w+b')
+ fieldnames = ['id','name','type_id:id', 'code']
+ csv = FileCsvWriter(output_file, fieldnames, encoding="utf-8", writeheader=True, delimiter=',', quotechar='"')
+
+ referential = self.browse(cr, uid, id, context=context)
+ row = {
+ 'id': referential.version_id.get_absolute_id(context=context),
+ 'name': referential.version_id.name,
+ 'type_id:id': referential.type_id.get_absolute_id(context=context),
+ 'code': referential.version_id.code,
+ }
+ csv.writerow(row)
+ return self.pool.get('pop.up.file').open_output_file(cr, uid, 'external.referential.version.csv', output_file, 'Referential Version Export', context=context)
+
+ def _prepare_external_referential_fieldnames(self, cr, uid, context=None):
+ return ['id', 'name', 'version_id:id','location','apiusername','apipass','debug']
+
+ def _prepare_external_referential_vals(self, cr, uid, referential, context=None):
+ return {
+ 'id': referential.get_absolute_id(context=context),
+ 'name': referential.name,
+ 'version_id:id': referential.version_id.get_absolute_id(context=context),
+ 'location': referential.location,
+ 'apiusername': referential.apiusername,
+ 'apipass': referential.apipass,
+ 'debug': referential.debug,
+ }
+
+ # Method to export external referential
+ def build_external_ref(self, cr, uid, id, context=None):
+ if isinstance(id,list):
+ id = id[0]
+ output_file = TemporaryFile('w+b')
+ fieldnames = self._prepare_external_referential_fieldnames(cr, uid, context=context)
+ csv = FileCsvWriter(output_file, fieldnames, encoding="utf-8", writeheader=True, delimiter=',', quotechar='"')
+
+ referential = self.browse(cr, uid, id, context=context)
+ row = self._prepare_external_referential_vals(cr, uid, referential, context=context)
+ csv.writerow(row)
+ return self.pool.get('pop.up.file').open_output_file(cr, uid, 'external.referential.csv', output_file, 'Referential Type Export', context=context)
+
+ def _prepare_mapping_fieldnames(self, cr, uid, context=None):
+ return [
+ 'id',
+ 'version_id:id',
+ 'model_id:id',
+ 'extra_name',
+ 'external_resource_name',
+ 'key_for_external_id',
+ 'external_list_method',
+ 'external_search_method',
+ 'external_get_method',
+ 'external_update_method',
+ 'external_create_method',
+ 'external_delete_method',
+ 'external_done_method',
+ ]
+
+ def _prepare_mapping_template_vals(self, cr, uid, mapping, context=None):
+ return {
+ 'id': mapping.get_absolute_id(context=context),
+ 'model_id:id': mapping.model_id.get_external_id(context=context)[mapping.model_id.id],
+ 'extra_name': mapping.extra_name or '',
+ 'external_list_method': mapping.external_list_method or '',
+ 'external_search_method': mapping.external_search_method or '',
+ 'external_get_method': mapping.external_get_method or '',
+ 'external_update_method': mapping.external_update_method or '',
+ 'external_create_method': mapping.external_create_method or '',
+ 'external_delete_method': mapping.external_delete_method or '',
+ 'external_done_method': mapping.external_done_method or '',
+ 'key_for_external_id': mapping.key_for_external_id or '',
+ 'external_resource_name': mapping.external_resource_name or '',
+ 'version_id:id': mapping.referential_id.version_id.get_absolute_id(context=context), # USEFULL ???
+ }
+
+ # Method to export external referential type
+ def build_external_mapping_template(self, cr, uid, id, context=None):
+ if isinstance(id,list):
+ id = id[0]
+ output_file = TemporaryFile('w+b')
+ fieldnames = self._prepare_mapping_fieldnames(cr, uid, context=context)
+
+ csv = FileCsvWriter(output_file, fieldnames, encoding="utf-8", writeheader=True, delimiter=',', quotechar='"')
+
+ referential = self.browse(cr, uid, id, context=context)
+ for mapping in referential.mapping_ids:
+ row = self._prepare_mapping_template_vals(cr, uid, mapping, context=context)
+ csv.writerow(row)
+ return self.pool.get('pop.up.file').open_output_file(cr, uid, 'external.mapping.template.csv', output_file, 'Mapping Template Export', context=context)
+
+ def _prepare_mappingline_fieldnames(self, cr, uid, context=None):
+ return [
+ 'id',
+ 'mapping_id:id',
+ 'sequence',
+ 'type',
+ 'evaluation_type',
+ 'field_id:id',
+ 'external_field',
+ 'external_type',
+ 'datetime_format',
+ 'function_name',
+ 'in_function',
+ 'out_function',
+ 'child_mapping_id:id',
+ 'alternative_key',
+ ]
+
+ def _prepare_mappingline_template_vals(self, cr, uid, line, context=None):
+ return {
+ 'id': line.get_absolute_id(context=context),
+ 'sequence': line.sequence or 0,
+ 'type': line.type or '',
+ 'evaluation_type': line.evaluation_type or '',
+ 'external_field': line.external_field or '',
+ 'field_id:id': line.field_id and line.field_id.get_external_id(context=context)[line.field_id.id],
+ 'external_type': line.external_type or '',
+ 'alternative_key': str(line.alternative_key) or '',
+ 'mapping_id:id': line.mapping_id.get_absolute_id(context=context),
+ 'function_name': line.function_name or '',
+ 'in_function': line.in_function or '',
+ 'out_function': line.out_function or '',
+ 'child_mapping_id:id': line.child_mapping_id and line.child_mapping_id.get_absolute_id(context=context) or '',
+ 'datetime_format': line.datetime_format or '',
+ }
+
+ # Method to export external referential type
+ def build_external_mapping_lines(self, cr, uid, id, context=None):
+ if isinstance(id,list):
+ id = id[0]
+ output_file = TemporaryFile('w+b')
+ fieldnames = self._prepare_mappingline_fieldnames(cr, uid, context=context)
+
+ csv = FileCsvWriter(output_file, fieldnames, encoding="utf-8", writeheader=True, delimiter=',', quotechar='"')
+
+ referential = self.browse(cr, uid, id, context=context)
+ for mapping in referential.mapping_ids:
+ for line in mapping.mapping_ids:
+ row = self._prepare_mappingline_template_vals(cr, uid, line, context=context)
+ csv.writerow(row)
+ return self.pool.get('pop.up.file').open_output_file(cr, uid, 'external.mappinglines.template.csv', output_file, 'Mapping Template Export', context=context)
+
+ _constraints = [
+ (_test_dot_in_name, 'The name cannot contain a dot!', ['name']),
+ ]
+
+ #TODO warning on name change if mapping exist: Implemented in attrs
+
+ def get_absolute_id(self, cr, uid, id, context=None):
+ if isinstance(id,list):
+ id = id[0]
+ referential = self.browse(cr, uid, id, context=context)
+ referential_id = referential.get_external_id(context=context)[referential.id]
+ if not referential_id:
+ referential_id = referential.name.replace('.','_').replace(' ','_')
+ return referential_id
+
+external_referential()
+
+class external_mapping_line(osv.osv):
+ _name = 'external.mapping.line'
+ _description = 'Field Mapping'
+ _rec_name = 'name'
+
+ def _name_get_fnc(self, cr, uid, ids, name, arg, context=None):
+ res = {}
+ for mapping_line in self.browse(cr, uid, ids, context):
+ res[mapping_line.id] = (mapping_line.evaluation_type == 'function' \
+ and mapping_line.function_name \
+ or mapping_line.external_field \
+ or mapping_line.field_id.name) \
+ + (mapping_line.mapping_id.extra_name \
+ and ('=>' + mapping_line.mapping_id.extra_name) or '')
+ return res
+
+ _columns = {
+ 'name': fields.function(_name_get_fnc, type="char", string='Name', size=256),
+ }
+
+external_mapping_line()
+
+
+class external_mapping(osv.osv):
+ _name = 'external.mapping'
+ _description = 'External Mapping'
+ _rec_name = 'model'
+
+ def _get_related_model_ids(self, cr, uid, ids, name, arg, context=None):
+ "Used to retrieve model field one can map without ambiguity. Fields come from Inherited objects"
+ res = {}
+ for mapping in self.browse(cr, uid, ids, context): #FIXME: could be fully recursive instead of only 1 level
+ main_model = mapping.model_id.model
+ inherits_model = [x for x in self.pool.get(main_model)._inherits]
+ model_ids = [mapping.model_id.id] + self.pool.get('ir.model').search(cr, uid, [['model','in', inherits_model]], context=context)
+ res[mapping.id] = model_ids
+ return res
+
+ def _related_model_ids(self, cr, uid, model, context=None):
+ inherits_model = [x for x in self.pool.get(model.model)._inherits]
+ model_ids = [model.id] + self.pool.get('ir.model').search(cr, uid, [['model','in', inherits_model]], context=context)
+ return model_ids
+
+ def model_id_change(self, cr, uid, ids, model_id=None, context=None):
+ if model_id:
+ model = self.pool.get('ir.model').browse(cr, uid, model_id, context=context)
+ return {'value': {'related_model_ids': self._related_model_ids(cr, uid, model, context=context)}}
+ else:
+ return {}
+
+ def create(self, cr, uid, vals, context=None):
+ res = super(external_mapping, self).create(cr, uid, vals, context)
+ self.pool.get('ir.model').create_external_link(cr, uid, vals['model_id'], context=context)
+ return res
+
+ def write(self, cr, uid, ids, vals, context=None):
+ res = super(external_mapping, self).write(cr, uid, ids, vals, context=context)
+ if vals.get('model_id'):
+ self.pool.get('ir.model').create_external_link(cr, uid, vals['model_id'], context=context)
+ return res
+
+ _columns = {
+ 'extra_name': fields.char('Extra Name', size=100, help="In case you need to make many mappings on the same object"),
+ 'template_id': fields.many2one('external.mapping.template', 'External Mapping Template'),
+ 'referential_id': fields.many2one('external.referential', 'External Referential', required=True, ondelete='cascade'),
+ 'model_id': fields.many2one('ir.model', 'OpenERP Model', required=True, ondelete='cascade'),
+ 'model':fields.related('model_id', 'model', type='char', string='Model Name'),
+ 'related_model_ids': fields.function(_get_related_model_ids, type="many2many", relation="ir.model", string='Related Inherited Models', help="potentially inherited through '_inherits' model, used for mapping field selection"),
+ 'external_list_method': fields.char('List Method', size=64),
+ 'external_search_method': fields.char('Search Method', size=64),
+ 'external_get_method': fields.char('Get Method', size=64),
+ 'external_update_method': fields.char('Update Method', size=64),
+ 'external_create_method': fields.char('Create Method', size=64),
+ 'external_delete_method': fields.char('Delete Method', size=64),
+ 'external_done_method': fields.char('Done Method', size=64),
+ 'mapping_ids': fields.one2many('external.mapping.line', 'mapping_id', 'Mappings Lines'),
+ 'key_for_external_id':fields.char('External field used as key', size=64),
+ 'external_resource_name':fields.char('External Resource Name', size=64),
+ }
+
+ # Method to set mapping with all object files
+ def add_all_fields(self, cr, uid, ids, context=None):
+ mapping_line_obj = self.pool.get('external.mapping.line')
+ mapping = self.browse(cr, uid, ids)[0]
+ for field in mapping.model_id.field_id:
+ vals = {'mapping_id': mapping.id,
+ 'field_id': field.id,
+ 'type' : 'in_out',
+ }
+ mapping_line_obj.create(cr, uid, vals)
+ return True
+
+ # Method to export the mapping file
+ def create_mapping_file(self, cr, uid, id, context=None):
+ if isinstance(id,list):
+ id = id[0]
+ output_file = TemporaryFile('w+b')
+ fieldnames = self.pool.get('external.referential')._prepare_mappingline_fieldnames(cr, uid, context=context)
+ csv = FileCsvWriter(output_file, fieldnames, encoding="utf-8", writeheader=True, delimiter=',', quotechar='"')
+
+ mapping = self.browse(cr, uid, id, context=context)
+ for line in mapping.mapping_ids:
+ row =self.pool.get('external.referential')._prepare_mappingline_template_vals(cr, uid, line, context=context)
+ csv.writerow(row)
+ return self.pool.get('pop.up.file').open_output_file(cr, uid, 'external.mappinglines.template.csv', output_file, 'Mapping Line Export', context=context)
+
+ def get_absolute_id(self, cr, uid, id, context=None):
+ if isinstance(id,list):
+ id = id[0]
+ mapping = self.browse(cr, uid, id, context=context)
+ if mapping.template_id:
+ mapping_id = mapping.template_id.get_external_id(context=context)[mapping.template_id.id]
+ else:
+ version_code = mapping.referential_id.version_id.code.replace(' ','_')
+ mapping_name = mapping.model + (mapping.extra_name and ('_' + mapping.extra_name) or '')
+ mapping_id = (version_code + '_' + mapping_name).replace('.','_')
+ return mapping_id
+
+ def _get_related_child_mapping_ids(self, cr, uid, ids, context=None):
+ res = []
+ tmp_res = []
+ for parent_mapping in self.browse(cr, uid, ids, context=context):
+ for child in parent_mapping.mapping_ids:
+ if child.evaluation_type == 'sub-mapping':
+ res.append(child.child_mapping_id.id)
+ tmp_res += (self._get_related_child_mapping_ids(cr, uid, [child.child_mapping_id.id], context=context))
+ return res + tmp_res
+
+ _sql_constraints = [
+ ('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):
+ _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'),
+ '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,"
+ "you can leave this field empty, because this field doesn't exist in your csv file'")),
+ '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),
+ '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'),
+ 'out_function': fields.text('Export from OpenERP Mapping Python Function'),
+ 'sequence': fields.integer('Sequence', required=True),
+ 'selected': fields.boolean('Selected', help="to select for mapping"),
+ 'child_mapping_id': fields.many2one('external.mapping', 'Child Mapping',
+ help=('This give you the possibility to import data with a structure of Parent/child'
+ 'For example when you import a sale order, the sale order is the parent of the sale order line'
+ 'In this case you have to select the child mapping in order to convert the data'
+ )
+ ),
+ 'alternative_key': fields.boolean('Alternative Key', help=("Only one field can be selected as alternative key,"
+ "if no external id was found for the record the alternative key"
+ "will be used to identify the resource")),
+ 'internal_type': fields.related('field_id','ttype', type="char", relation='ir.model.field', string='Internal Type'),
+ 'function_name': fields.char('Function Name', size=128),
+ }
+
+ _defaults = {
+ 'type' : lambda * a: 'in_out',
+ 'external_type': lambda *a: 'unicode',
+ 'evaluation_type': lambda *a: 'direct',
+ }
+
+ def _check_mapping_line_name(self, cr, uid, ids):
+ for mapping_line in self.browse(cr, uid, ids):
+ if (not mapping_line.field_id) and (not mapping_line.external_field):
+ return False
+ return True
+
+
+ _sql_constraints = [
+ ('ref_template_uniq', 'unique (referential_id, template_id)', 'A referential can not have various mapping line imported from the same template mapping line')
+ ]
+ _order = 'sequence asc'
+ #TODO add constraint: not both field_id and external_field null
+
+ def get_absolute_id(self, cr, uid, id, context=None):
+ if isinstance(id,list):
+ id = id[0]
+ line = self.browse(cr, uid, id, context=context)
+ if line.template_id:
+ line_id = line.template_id.get_external_id(context=context)[line.template_id.id]
+ else:
+ version_code = line.referential_id.version_id.code.replace(' ','_')
+ mapping_name = line.mapping_id.model + (line.mapping_id.extra_name and ('_' + line.mapping_id.extra_name) or '')
+ line_name = line.name
+ line_id = (version_code + '_' + mapping_name + '_' + line_name).replace('.','_')
+ return line_id
+
+external_mapping_line()
+
+class ir_model_data(osv.osv):
+ _inherit = "ir.model.data"
+
+ def init(self, cr):
+ #FIXME: migration workaround: we changed the ir_model_data usage to make standard CSV import work again
+ cr.execute("select name from external_referential;")
+ referentials = cr.fetchall()
+ for tuple in referentials:
+ name = "extref." + tuple[0]
+ cr.execute("update ir_model_data set name = replace(name, '_mag_order', '/mag_order') where module = %s;", (name,))
+ cr.execute("update ir_model_data set name = regexp_replace(name, '_([1-9])', E'/\\\\1') where module = %s;", (name,))
+ cr.execute("update ir_model_data set name = replace(name, '.', '_') where module = %s;", (name,))
+ cr.execute("update ir_model_data set module = replace(module, '.','/') where module = %s;", (name,))
+ return True
+
+ def _get_referential_id(self, cr, uid, ids, name, arg, context=None):
+ res = {}
+ for model_data in self.browse(cr, uid, ids, context):
+ s = model_data.module.split('/') #we assume a module name with a '/' means external referential
+ if len(s) > 1:
+ ref_ids = self.pool.get('external.referential').search(cr, uid, [['name', '=', s[1]]])
+ if ref_ids:
+ res[model_data.id] = ref_ids[0]
+ else:
+ res[model_data.id] = False
+ else:
+ res[model_data.id] = False
+ return res
+
+ _columns = {
+ 'referential_id': fields.function(_get_referential_id, type="many2one", relation='external.referential', string='Ext. Referential', store=True),
+ #'referential_id':fields.many2one('external.referential', 'Ext. Referential'),
+ #'create_date': fields.datetime('Created date', readonly=True), #TODO used?
+ #'write_date': fields.datetime('Updated date', readonly=True), #TODO used?
+ }
+
+ _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'),
+ ]
+
+ir_model_data()
=== added file 'base_external_referentials/external_referentials_menu.xml'
--- base_external_referentials/external_referentials_menu.xml 1970-01-01 00:00:00 +0000
+++ base_external_referentials/external_referentials_menu.xml 2012-09-13 01:56:18 +0000
@@ -0,0 +1,101 @@
+<?xml version="1.0" encoding="utf-8"?>
+<openerp>
+ <data>
+
+ <menuitem id="ir_ui_menu_external_referentials" name="External Referentials" parent="base.menu_administration" />
+
+ <!-- External Referentials -->
+
+ <record id="act_window_external_referential" model="ir.actions.act_window">
+ <field name="name">External Referentials</field>
+ <field name="type">ir.actions.act_window</field>
+ <field name="res_model">external.referential</field>
+ <field name="view_type">form</field>
+ <field name="context">{}</field>
+ <field name="view_id" ref="external_referential_tree_view"/>
+ <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" />
+ <!-- External Referentials Types -->
+
+ <record id="ir_actions_act_window_external_type" model="ir.actions.act_window">
+ <field name="name">External Referentials Types</field>
+ <field name="type">ir.actions.act_window</field>
+ <field name="res_model">external.referential.type</field>
+ <field name="view_type">form</field>
+ <field name="view_id" ref="external_referential_type_tree_view"/>
+ <field name="search_view_id" ref="external_referential_type_search_form_view"/>
+ </record>
+
+ <menuitem id="ir_ui_menu_external_types" name="External Referentials Types" parent="ir_ui_menu_external_referentials" action="ir_actions_act_window_external_type" />
+
+ <!-- External Mappings -->
+
+ <record id="ir_actions_act_window_external_mapping" model="ir.actions.act_window">
+ <field name="name">External Mappings</field>
+ <field name="type">ir.actions.act_window</field>
+ <field name="res_model">external.mapping</field>
+ <field name="view_type">form</field>
+ <field name="view_id" ref="external_mapping_tree_view"/>
+ <field name="search_view_id" ref="external_mapping_search_view"/>
+ </record>
+
+ <menuitem id="ir_ui_menu_external_mappings" name="External Mappings" parent="ir_ui_menu_external_referentials" action="ir_actions_act_window_external_mapping" />
+
+ <!-- External Mapping Lines-->
+
+ <record id="ir_actions_act_window_external_mapping_line" model="ir.actions.act_window">
+ <field name="name">External Mapping Lines</field>
+ <field name="type">ir.actions.act_window</field>
+ <field name="res_model">external.mapping.line</field>
+ <field name="view_type">form</field>
+ <field name="view_id" ref="external_mapping_line_tree_view"/>
+ <field name="search_view_id" ref="external_mapping_line_search_view"/>
+ </record>
+
+ <menuitem id="ir_ui_menu_external_mapping_lines" name="External Mapping Lines" parent="ir_ui_menu_external_referentials" action="ir_actions_act_window_external_mapping_line" />
+
+ <!-- External Report -->
+
+ <record id="ir_actions_act_window_external_report" model="ir.actions.act_window">
+ <field name="name">External Reports</field>
+ <field name="type">ir.actions.act_window</field>
+ <field name="res_model">external.report</field>
+ <field name="view_type">form</field>
+ <field name="view_id" ref="external_report_tree_view"/>
+ <field name="search_view_id" ref="external_report_search_form_view"/>
+ </record>
+
+ <menuitem id="ir_ui_menu_external_report" name="External Report" parent="ir_ui_menu_external_referentials" action="ir_actions_act_window_external_report" />
+
+ <!-- External Report History -->
+
+ <record id="ir_actions_act_window_external_report_history" model="ir.actions.act_window">
+ <field name="name">External Report History</field>
+ <field name="type">ir.actions.act_window</field>
+ <field name="res_model">external.report.history</field>
+ <field name="view_type">form</field>
+ <field name="view_id" ref="external_report_history_tree_view"/>
+ <field name="search_view_id" ref="external_report_history_search_view"/>
+ </record>
+
+ <menuitem id="ir_ui_menu_external_report_history" name="External Report History" parent="ir_ui_menu_external_referentials" action="ir_actions_act_window_external_report_history" />
+
+ <!-- External Report Line -->
+
+ <record id="ir_actions_act_window_external_report_line" model="ir.actions.act_window">
+ <field name="name">External Report Lines</field>
+ <field name="type">ir.actions.act_window</field>
+ <field name="res_model">external.report.line</field>
+ <field name="view_type">form</field>
+ <field name="context">{'main_view': True}</field>
+ <field name="view_id" ref="external_report_line_tree_view"/>
+ <field name="search_view_id" ref="external_report_line_search_view"/>
+ </record>
+
+ <menuitem id="ir_ui_menu_external_report_line" name="External Report Lines" parent="ir_ui_menu_external_referentials" action="ir_actions_act_window_external_report_line" />
+
+ </data>
+</openerp>
=== added file 'base_external_referentials/external_referentials_view.xml'
--- base_external_referentials/external_referentials_view.xml 1970-01-01 00:00:00 +0000
+++ base_external_referentials/external_referentials_view.xml 2012-09-13 01:56:18 +0000
@@ -0,0 +1,321 @@
+<?xml version="1.0" encoding="utf-8"?>
+<openerp>
+ <data>
+
+ <record model="ir.ui.view" id="external_referential_search_view">
+ <field name="name">external.referential.search.view</field>
+ <field name="model">external.referential</field>
+ <field name="type">search</field>
+ <field name="arch" type="xml">
+ <search string="External Referential">
+ <field name="name"/>
+ <field name="type_id"/>
+ <field name="categ_id"/>
+ <newline/>
+ <group expand='0' string='Group by...' groups="base.group_extended">
+ <filter string='Category' icon="terp-stock_symbol-selection" domain="[]" context="{'group_by' : 'categ_id'}" />
+ </group>
+ </search>
+ </field>
+ </record>
+
+ <record model="ir.ui.view" id="external_referential_form_view">
+ <field name="name">external_referential_form_view</field>
+ <field name="model">external.referential</field>
+ <field name="type">form</field>
+ <field name="arch" type="xml">
+ <form>
+ <group col="4" colspan="4">
+ <field name="name" attrs="{'readonly':[('create_date','!=',False)]}"/>
+ <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>
+ </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','=',[])]}"/>
+ </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" />
+ <button name="build_external_ref_type" string="2- Export type" colspan="1" type="object" />
+ <button name="build_external_ref_version" string="3- Export version" colspan="1" type="object" />
+ <button name="build_external_ref" string="4- Export referential" colspan="1" type="object" />
+ <button name="build_external_mapping_template" string="5- Export mapping template" colspan="1" type="object" />
+ <button name="build_external_mapping_lines" string="6- Export mapping lines" colspan="1" type="object" />
+ </page>
+ </notebook>
+ </group>
+ <field name="mapping_ids" widget="one2many_list" nolabel="1">
+ <tree string="Object Mappings">
+ <field name="model_id" />
+ <field name="extra_name" />
+<!-- <field name="related_model_ids" invisible="1" />-->
+<!-- <field name="mapping_ids" />-->
+ </tree>
+ <form string="Object Mappings">
+ <field name="model_id" on_change="model_id_change(model_id)" />
+ <field name="extra_name" />
+ <field name="related_model_ids" invisible="1" />
+ <group col="4" colspan="4">
+ <field name="external_list_method" />
+ <field name="external_search_method" />
+ <field name="external_get_method" />
+ <field name="external_update_method" />
+ <field name="external_create_method" />
+ <field name="external_delete_method" />
+ <field name="external_done_method" />
+ <field name="key_for_external_id" />
+ <field name="external_resource_name" />
+ </group>
+ <button name="add_all_fields" string="Add all object fields" colspan="2" type="object" />
+ <button name="create_mapping_file" string="Export mapping file" colspan="2" type="object" groups="base_external_referentials.group_export_mapping"/>
+ <field colspan="4" name="mapping_ids" widget="one2many_list" nolabel="1" context="{'model_id':model_id}" />
+ </form>
+ </field>
+ </form>
+ </field>
+ </record>
+
+<!-- External mapping line search views -->
+ <record model="ir.ui.view" id="external_mapping_line_search_view">
+ <field name="name">external.mapping_line.search.view</field>
+ <field name="model">external.mapping.line</field>
+ <field name="type">search</field>
+ <field name="arch" type="xml">
+ <search string="Mapping line">
+ <field name="external_field"/>
+ <field name="name"/>
+ <field name="mapping_id" />
+ <newline/>
+ <group expand='0' string='Group by...' groups="base.group_extended">
+ <filter string='External Mapping' icon="terp-stock_symbol-selection" domain="[]" context="{'group_by' : 'mapping_id'}" />
+ </group>
+ </search>
+ </field>
+ </record>
+<!-- External mapping line tree views -->
+ <record id="external_mapping_line_tree_view" model="ir.ui.view">
+ <field name="name">external_mapping_line_tree_view</field>
+ <field name="model">external.mapping.line</field>
+ <field name="type">tree</field>
+ <field name="arch" type="xml">
+ <tree>
+ <field name="selected" />
+ <field name="sequence" />
+ <field name="field_id" />
+ <field name="internal_field" />
+ <field name="external_field" />
+ <field name="external_type" />
+ <field name="type" />
+ <field name="alternative_key" />
+ <field name="name" />
+ <field name="mapping_id" />
+ </tree>
+ </field>
+ </record>
+
+<!-- External mapping line form views -->
+ <record model="ir.ui.view" id="external_mapping_line_form_view">
+ <field name="name">external_mapping_line_form_view</field>
+ <field name="model">external.mapping.line</field>
+ <field name="type">form</field>
+ <field name="arch" type="xml">
+ <form>
+ <group name="main" colspan="4">
+ <field name="selected" />
+ <field name="sequence" />
+ <field name="type" />
+ <field name="evaluation_type" />
+ </group>
+ <group attrs="{'invisible':[('evaluation_type','=','function')]}" colspan="4">
+ <group name="external_field" colspan="2" col="2">
+ <separator string="External fields" colspan="2"/>
+ <field name="external_field" select="1"/>
+ <field name="external_type" attrs="{'required':[('evaluation_type','=','direct')]}"/>
+ <field name="datetime_format" attrs="{'invisible':[('external_type','!=','datetime')]}"/>
+ </group>
+ <group name="internal_field" colspan="2" col="2">
+ <separator string="Internal fields" colspan="2"/>
+ <field name="field_id" domain="[('model_id','in',parent.related_model_ids[0][2])]"
+ attrs="{'required':[('evaluation_type','in',['direct', 'sub-mapping'])],
+ 'invisible':[('evaluation_type', '=', 'function')]}"/>
+ <field name="internal_type" readonly="True"/>
+ <field name="child_mapping_id" colspan="2"
+ attrs="{'invisible':[('evaluation_type','!=','sub-mapping')],
+ 'required':[('evaluation_type','=','sub-mapping')]}"/>
+ </group>
+ </group>
+ <group attrs="{'invisible':[('evaluation_type','!=','function')]}" colspan="4">
+ <group name="import_function_field" colspan="2" col="2">
+ <separator string="Import in OpenERP Mapping Python Function" colspan="2"/>
+ <field name="in_function" colspan="2" nolabel="1"/>
+ </group>
+ <group name="export_function_field" colspan="2" col="2">
+ <separator string="Export from OpenERP Mapping Python Function" colspan="2"/>
+ <field name="out_function" colspan="2" nolabel="1"/>
+ </group>
+ </group>
+ <group name="other_information" colspan="4">
+ <separator string="Other Information" colspan="4"/>
+ <field name="alternative_key" />
+ <group name='full_name'>
+ <field name="function_name" string="Full Name"
+ attrs="{'invisible':[('evaluation_type','!=','function')],
+ 'required':[('evaluation_type','=','function')]}"/>
+ <field name="name" attrs="{'invisible':[('evaluation_type','=','function')]}"/>
+ </group>
+ </group>
+ </form>
+ </field>
+ </record>
+
+
+ <record id="external_referential_tree_view" model="ir.ui.view">
+ <field name="name">external_referential_tree_view</field>
+ <field name="model">external.referential</field>
+ <field name="type">tree</field>
+ <field name="arch" type="xml">
+ <tree>
+ <field name="name" select="1" />
+ <field name="location" select="1" />
+ </tree>
+ </field>
+ </record>
+
+ <record id="external_referential_version_form_view" model="ir.ui.view">
+ <field name="name">external_referential_version_form_view</field>
+ <field name="model">external.referential.version</field>
+ <field name="type">form</field>
+ <field name="arch" type="xml">
+ <form>
+ <field name="name" />
+ <field name="code"/>
+ <field name="full_name" />
+ <field name="type_id"/>
+ </form>
+ </field>
+ </record>
+
+ <!-- External Mappings -->
+
+ <record id="external_mapping_tree_view" model="ir.ui.view">
+ <field name="name">external_mapping_tree_view</field>
+ <field name="model">external.mapping</field>
+ <field name="type">tree</field>
+ <field name="arch" type="xml">
+ <tree>
+ <field name="model_id" select="1" />
+ <field name="referential_id" select="1" />
+ <field name="extra_name" select="1" />
+ </tree>
+ </field>
+ </record>
+
+ <record id="external_mapping_form_view" model="ir.ui.view">
+ <field name="name">external_mapping_form_view</field>
+ <field name="model">external.mapping</field>
+ <field name="type">form</field>
+ <field name="arch" type="xml">
+ <form string="Object Mappings">
+ <field name="model_id" on_change="model_id_change(model_id)" />
+ <field name="extra_name" />
+ <field name="related_model_ids" invisible="1" />
+ <group col="4" colspan="4">
+ <field name="external_list_method" />
+ <field name="external_search_method" />
+ <field name="external_get_method" />
+ <field name="external_update_method" />
+ <field name="external_create_method" />
+ <field name="external_delete_method" />
+ <field name="external_done_method" />
+ <field name="key_for_external_id" />
+ <field name="external_resource_name" />
+ </group>
+ <button name="add_all_fields" string="Add all object fields" colspan="2" type="object" />
+ <button name="create_mapping_file" string="Export mapping file" colspan="2" type="object" groups="base_external_referentials.group_export_mapping"/>
+ <field colspan="4" name="mapping_ids" widget="one2many_list" nolabel="1" context="{'model_id':model_id}" />
+ </form>
+ </field>
+ </record>
+
+
+ <record model="ir.ui.view" id="external_mapping_search_view">
+ <field name="name">external_mapping_search_view</field>
+ <field name="model">external.mapping</field>
+ <field name="type">search</field>
+ <field name="arch" type="xml">
+ <search string="External Mapping">
+ <field name="model_id"/>
+ <field name="referential_id"/>
+ <field name="extra_name"/>
+ <newline/>
+ <group expand='0' string='Group by...' groups="base.group_extended">
+ <filter string='Referential' icon="terp-stock_symbol-selection" domain="[]" context="{'group_by' : 'referential_id'}" />
+ </group>
+ </search>
+ </field>
+ </record>
+
+ <!-- External Referentials Types -->
+
+ <record id="external_referential_type_form_view" model="ir.ui.view">
+ <field name="name">external_referential_type_form_view</field>
+ <field name="model">external.referential.type</field>
+ <field name="type">form</field>
+ <field name="arch" type="xml">
+ <form>
+ <field name="name" />
+ <field name="code"/>
+ <field name="categ_id" />
+ <field name="version_ids" colspan="4"/>
+ </form>
+ </field>
+ </record>
+
+ <record id="external_referential_type_tree_view" model="ir.ui.view">
+ <field name="name">external_referential_type_tree_view</field>
+ <field name="model">external.referential.type</field>
+ <field name="type">tree</field>
+ <field name="arch" type="xml">
+ <tree string="External Referential Types">
+ <field name="name" />
+ <field name="categ_id" />
+ <field name="version_ids" colspan="4"/>
+ </tree>
+ </field>
+ </record>
+
+ <record id="external_referential_type_search_form_view" model="ir.ui.view">
+ <field name="name">external_referential_type_search_form_view</field>
+ <field name="model">external.referential.type</field>
+ <field name="type">search</field>
+ <field name="arch" type="xml">
+ <search string="External Referential Types">
+ <field name="name" />
+ <field name="categ_id" />
+ <field name="version_ids" colspan="4"/>
+ <newline/>
+ <group expand='0' string='Group by...' groups="base.group_extended">
+ <filter string='External Referential' icon="terp-stock_symbol-selection" domain="[]" context="{'group_by' : 'referential_id'}" />
+ </group>
+ </search>
+ </field>
+ </record>
+
+ </data>
+</openerp>
=== added file 'base_external_referentials/group_fields.py'
--- base_external_referentials/group_fields.py 1970-01-01 00:00:00 +0000
+++ base_external_referentials/group_fields.py 2012-09-13 01:56:18 +0000
@@ -0,0 +1,85 @@
+ # -*- encoding: utf-8 -*-
+###############################################################################
+# #
+# base_external_referentials for OpenERP #
+# Copyright (C) 2011 Akretion 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 #
+# 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/>. #
+# #
+###############################################################################
+
+
+from osv import osv, fields
+
+
+class group_fields(osv.osv):
+ _name = 'group.fields'
+ _description = 'trigger last write date by group of field'
+
+ _columns = {
+ 'name': fields.char('Name', size=64, required=True),
+ 'column_name': fields.char('Column Name', size=64),
+ 'field_ids': fields.one2many('ir.model.fields', 'group_fields_id', 'Fields'),
+ 'model_id': fields.many2one('ir.model', 'Model'),
+ }
+
+ def create(self, cr, uid, vals, context=None):
+ if not vals.get('column_name'):
+ vals['column_name'] = 'x_trigger_%s' %vals['name'].lower().replace(' ', '_')
+ field_obj = self.pool.get('ir.model.fields')
+
+ #Create the generic date trigger
+ if not field_obj.search(cr, uid, [('name', '=', 'x_last_update'), ('model_id', '=', vals['model_id'])], context=context):
+ field_vals = {
+ 'name': 'x_trigger_update',
+ 'model_id': vals['model_id'],
+# 'model': model_name,
+ 'field_description': 'trigger date field for %s'%(self._name),
+ 'ttype': 'datetime',
+ }
+ field_obj.create(cr, uid, field_vals, context=context)
+
+ #Create specific date trigger
+ if not field_obj.search(cr, uid, [('name', '=', vals['column_name']), ('model_id', '=', vals['model_id'])], context=context):
+ field_vals = {
+ 'name': vals['column_name'],
+ 'model_id': vals['model_id'],
+# 'model': model_name,
+ 'field_description': 'trigger date field for %s'%(vals['name']),
+ 'ttype': 'datetime',
+ }
+ field_obj.create(cr, uid, field_vals, context=context)
+ return super(group_fields, self).create(cr, uid, vals, context=context)
+
+ 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"))
+ return super(group_fields, self).write(cr, uid, ids, vals, context=context)
+
+class ir_model_fields(osv.osv):
+ _inherit = "ir.model.fields"
+
+ _columns = {
+ 'group_fields_id': fields.many2one('group.fields', 'Trigger Group', domain="[('model_id', '=', model_id)]"),
+ }
+
+ def write(self, cr, uid, ids, vals, context=None):
+ if vals.get('group_fields_id'):
+ cr.execute("UPDATE ir_model_fields set group_fields_id = %s where id in %s", (vals['group_fields_id'], tuple(ids)))
+ del vals['group_fields_id']
+ if vals:
+ return super(ir_model_fields, self).write(cr, uid, ids, vals, context=context)
+ return True
+
+
=== added file 'base_external_referentials/group_fields_view.xml'
--- base_external_referentials/group_fields_view.xml 1970-01-01 00:00:00 +0000
+++ base_external_referentials/group_fields_view.xml 2012-09-13 01:56:18 +0000
@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="utf-8"?>
+<openerp>
+ <data>
+
+ <record model="ir.ui.view" id="group_fields_search_view">
+ <field name="name">group.fields.search.view</field>
+ <field name="model">group.fields</field>
+ <field name="type">search</field>
+ <field name="arch" type="xml">
+ <search string="Group fields">
+ <field name="name"/>
+ <field name="model_id"/>
+ <newline/>
+ <group expand='0' string='Group by...' groups="base.group_extended">
+ <filter string='Model' icon="terp-stock_symbol-selection" domain="[]" context="{'group_by' : 'model_id'}" />
+ </group>
+ </search>
+ </field>
+ </record>
+
+ <record model="ir.ui.view" id="group_fields_form_view">
+ <field name="name">group_fields_form_view</field>
+ <field name="model">group.fields</field>
+ <field name="type">form</field>
+ <field name="arch" type="xml">
+ <form>
+ <field name="name" colspan="2"/>
+ <field name="model_id" colspan="2"/>
+ <field name="field_ids" colspan="4"/>
+ </form>
+ </field>
+ </record>
+
+
+ <record model="ir.ui.view" id="group_fields_tree_view">
+ <field name="name">group_fields_tree_view</field>
+ <field name="model">group.fields</field>
+ <field name="type">tree</field>
+ <field name="arch" type="xml">
+ <tree>
+ <field name="name" colspan="2"/>
+ <field name="model_id" colspan="2"/>
+ </tree>
+ </field>
+ </record>
+
+
+ <record id="group_field_action_open_form" model="ir.actions.act_window">
+ <field name="name">Group fields</field>
+ <field name="type">ir.actions.act_window</field>
+ <field name="res_model">group.fields</field>
+ <field name="view_type">form</field>
+ <field name="view_id" ref="group_fields_tree_view"/>
+ <field name="search_view_id" ref="group_fields_search_view"/>
+ </record>
+
+ <menuitem id="ir_ui_menu_group_fields" name="Group Fields" parent="base.next_id_9" groups="base.group_extended" action="group_field_action_open_form" />
+
+ <record id="view_model_fields_form" model="ir.ui.view">
+ <field name="name">base.external.referentials.ir.model.fields.form</field>
+ <field name="model">ir.model.fields</field>
+ <field name="type">form</field>
+ <field name="inherit_id" ref="base.view_model_fields_form"/>
+ <field name="arch" type="xml">
+ <field name="state" position="after">
+ <field name="group_fields_id" />
+ </field>
+ </field>
+ </record>
+
+ </data>
+</openerp>
=== added directory 'base_external_referentials/i18n'
=== added file 'base_external_referentials/i18n/base_external_referentials.pot'
--- base_external_referentials/i18n/base_external_referentials.pot 1970-01-01 00:00:00 +0000
+++ base_external_referentials/i18n/base_external_referentials.pot 2012-09-13 01:56:18 +0000
@@ -0,0 +1,337 @@
+# Translation of OpenERP Server.
+# This file contains the translation of the following modules:
+# * base_external_referentials
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: OpenERP Server 5.0.6\n"
+"Report-Msgid-Bugs-To: support@xxxxxxxxxxx\n"
+"POT-Creation-Date: 2009-12-20 17:21:26+0000\n"
+"PO-Revision-Date: 2009-12-20 17:21:26+0000\n"
+"Last-Translator: <>\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
+#: constraint:ir.model:0
+msgid "The Object name must start with x_ and not contain any special character !"
+msgstr ""
+
+#. module: base_external_referentials
+#: field:external.referential,mapping_ids:0
+msgid "Mappings"
+msgstr ""
+
+#. module: base_external_referentials
+#: view:external.referential:0
+msgid "Object Mappings"
+msgstr ""
+
+#. module: base_external_referentials
+#: view:external.referential:0
+msgid "Synchronize Referential Settings"
+msgstr ""
+
+#. module: base_external_referentials
+#: view:external.referential:0
+msgid "Authentication"
+msgstr ""
+
+#. module: base_external_referentials
+#: field:external.referential,location:0
+msgid "Location"
+msgstr ""
+
+#. module: base_external_referentials
+#: constraint:ir.actions.act_window:0
+msgid "Invalid model name in the action definition."
+msgstr ""
+
+#. module: base_external_referentials
+#: selection:external.mapping.line,type:0
+#: selection:external.mappinglines.template,type:0
+msgid "External <- OpenERP"
+msgstr ""
+
+#. module: base_external_referentials
+#: field:external.mapping.line,type:0
+#: field:external.mappinglines.template,type:0
+msgid "Type"
+msgstr ""
+
+#. module: base_external_referentials
+#: view:external.referential:0
+msgid "Reload Referential Mapping Templates"
+msgstr ""
+
+#. module: base_external_referentials
+#: model:ir.module.module,shortdesc:base_external_referentials.module_meta_information
+msgid "Base External Referentials"
+msgstr ""
+
+#. module: base_external_referentials
+#: field:external.mapping,related_model_ids:0
+msgid "Related Inherited Models"
+msgstr ""
+
+#. module: base_external_referentials
+#: field:external.mapping.line,external_type:0
+#: field:external.mappinglines.template,external_type:0
+msgid "External Type"
+msgstr ""
+
+#. module: base_external_referentials
+#: selection:external.mapping.line,external_type:0
+#: selection:external.mappinglines.template,external_type:0
+msgid "String"
+msgstr ""
+
+#. module: base_external_referentials
+#: field:external.mapping,external_list_method:0
+#: field:external.mapping.template,external_list_method:0
+msgid "List Method"
+msgstr ""
+
+#. module: base_external_referentials
+#: model:ir.ui.menu,name:base_external_referentials.ir_ui_menu_extref0
+msgid "External Referentials"
+msgstr ""
+
+#. module: base_external_referentials
+#: model:ir.model,name:base_external_referentials.model_external_referential_type
+msgid "External Referential Type (Ex.Magento,Spree)"
+msgstr ""
+
+#. module: base_external_referentials
+#: field:external.mapping.line,related_model_id:0
+msgid "Related Model"
+msgstr ""
+
+#. module: base_external_referentials
+#: field:ir.model.data,create_date:0
+msgid "Created date"
+msgstr ""
+
+#. module: base_external_referentials
+#: field:external.referential,apiusername:0
+msgid "User Name"
+msgstr ""
+
+#. module: base_external_referentials
+#: help:external.mapping,related_model_ids:0
+msgid "potentially inherited through '_inherits' model, used for mapping field selection"
+msgstr ""
+
+#. module: base_external_referentials
+#: field:external.mapping,external_get_method:0
+#: field:external.mapping.template,external_get_method:0
+msgid "Get Method"
+msgstr ""
+
+#. module: base_external_referentials
+#: field:external.mapping,model:0
+#: field:external.mapping.template,model:0
+#: field:external.mappinglines.template,model:0
+msgid "Model Name"
+msgstr ""
+
+#. module: base_external_referentials
+#: selection:external.mapping.line,external_type:0
+#: selection:external.mappinglines.template,external_type:0
+msgid "Integer"
+msgstr ""
+
+#. module: base_external_referentials
+#: view:external.referential:0
+#: model:ir.model,name:base_external_referentials.model_external_mapping_line
+msgid "Field Mapping"
+msgstr ""
+
+#. module: base_external_referentials
+#: model:ir.model,name:base_external_referentials.model_external_mapping_template
+msgid "The source mapping records"
+msgstr ""
+
+#. module: base_external_referentials
+#: model:ir.actions.act_window,name:base_external_referentials.ir_actions_act_window_externalreferential0
+msgid "external_referential"
+msgstr ""
+
+#. module: base_external_referentials
+#: constraint:ir.ui.view:0
+msgid "Invalid XML for View Architecture!"
+msgstr ""
+
+#. module: base_external_referentials
+#: field:external.mapping.line,external_field:0
+#: field:external.mappinglines.template,external_field:0
+msgid "External Field"
+msgstr ""
+
+#. module: base_external_referentials
+#: field:external.referential,name:0
+#: field:external.referential.type,name:0
+msgid "Name"
+msgstr ""
+
+#. module: base_external_referentials
+#: field:external.mapping.line,in_function:0
+#: field:external.mappinglines.template,in_function:0
+msgid "Import in OpenERP Mapping Python Function"
+msgstr ""
+
+#. module: base_external_referentials
+#: field:external.mapping,mapping_ids:0
+msgid "Mappings Lines"
+msgstr ""
+
+#. module: base_external_referentials
+#: selection:external.mapping.line,type:0
+#: selection:external.mappinglines.template,type:0
+msgid "External -> OpenERP"
+msgstr ""
+
+#. module: base_external_referentials
+#: model:ir.model,name:base_external_referentials.model_external_mappinglines_template
+msgid "The source mapping line records"
+msgstr ""
+
+#. module: base_external_referentials
+#: field:external.mapping,referential_id:0
+#: model:ir.model,name:base_external_referentials.model_external_referential
+msgid "External Referential"
+msgstr ""
+
+#. module: base_external_referentials
+#: field:external.referential,type_id:0
+msgid "Referential Type"
+msgstr ""
+
+#. module: base_external_referentials
+#: view:external.referential:0
+msgid "General"
+msgstr ""
+
+#. module: base_external_referentials
+#: field:external.mapping,external_update_method:0
+#: field:external.mapping.template,external_update_method:0
+msgid "Update Method"
+msgstr ""
+
+#. module: base_external_referentials
+#: field:external.mapping.line,name_function:0
+msgid "Full Name"
+msgstr ""
+
+#. module: base_external_referentials
+#: view:external.referential:0
+msgid "Field Mappings"
+msgstr ""
+
+#. module: base_external_referentials
+#: field:external.mapping,model_id:0
+#: field:external.mapping.template,model_id:0
+#: field:external.mappinglines.template,model_id:0
+msgid "OpenERP Model"
+msgstr ""
+
+#. module: base_external_referentials
+#: field:external.mapping.line,out_function:0
+#: field:external.mappinglines.template,out_function:0
+msgid "Export from OpenERP Mapping Python Function"
+msgstr ""
+
+#. module: base_external_referentials
+#: field:external.referential,apipass:0
+msgid "Password"
+msgstr ""
+
+#. module: base_external_referentials
+#: field:external.mapping.line,mapping_id:0
+#: model:ir.model,name:base_external_referentials.model_external_mapping
+msgid "External Mapping"
+msgstr ""
+
+#. module: base_external_referentials
+#: field:external.mapping.line,field_id:0
+msgid "OpenERP Field"
+msgstr ""
+
+#. module: base_external_referentials
+#: field:external.mapping,external_create_method:0
+#: field:external.mapping.template,external_create_method:0
+msgid "Create Method"
+msgstr ""
+
+#. module: base_external_referentials
+#: selection:external.mapping.line,external_type:0
+#: selection:external.mappinglines.template,external_type:0
+msgid "Float"
+msgstr ""
+
+#. module: base_external_referentials
+#: field:external.mapping,external_key_name:0
+#: field:external.mapping.template,external_key_name:0
+msgid "External field used as key"
+msgstr ""
+
+#. module: base_external_referentials
+#: field:external.mapping,external_delete_method:0
+#: field:external.mapping.template,external_delete_method:0
+msgid "Delete Method"
+msgstr ""
+
+#. module: base_external_referentials
+#: selection:external.mapping.line,external_type:0
+#: selection:external.mappinglines.template,external_type:0
+msgid "Boolean"
+msgstr ""
+
+#. module: base_external_referentials
+#: field:ir.model.data,external_referential_id:0
+msgid "Ext. Referential"
+msgstr ""
+
+#. module: base_external_referentials
+#: field:ir.model.data,write_date:0
+msgid "Updated date"
+msgstr ""
+
+#. module: base_external_referentials
+#: model:ir.module.module,description:base_external_referentials.module_meta_information
+msgid "\n"
+"This module provide an abstract common minimal base to add any additional external id columns\n"
+"to some OpenObject table, pointing to some external referential.\n"
+"A referential is abstract and minimal at this stage, it's only identified\n"
+"by:\n"
+"* a name\n"
+"* a location (possibly webservice URL, database connection URL...); the connection method will tell it...\n"
+"* referential credentials (user name + password)\n"
+"\n"
+"OpenERP already has limited supported to external ids using the ir_model_data and the id\n"
+"fields in the loaded data such as XML or CSV.\n"
+"The issue is that teh current system, while very useful to deal with internal OpenERP data has some\n"
+"limitations:\n"
+"* it doesn't scale well to whole production data because everything ends up into the ir_model_data\n"
+"* all the system is built with a using reference id in mind. But in fact you might want SEVERAL external ids.\n"
+"Say you sale your products over several websites (using the new Magento multi-instance connector for\n"
+"instance), then you want that each product have SEVERAL external id columns. This is exactly what\n"
+"this module enables!\n"
+" "
+msgstr ""
+
+#. module: base_external_referentials
+#: field:external.mapping.template,type_id:0
+#: field:external.mappinglines.template,type_id:0
+msgid "External Referential Type"
+msgstr ""
+
+#. module: base_external_referentials
+#: selection:external.mapping.line,type:0
+#: selection:external.mappinglines.template,type:0
+msgid "External <-> OpenERP"
+msgstr ""
+
=== added file 'base_external_referentials/i18n/ca.po'
--- base_external_referentials/i18n/ca.po 1970-01-01 00:00:00 +0000
+++ base_external_referentials/i18n/ca.po 2012-09-13 01:56:18 +0000
@@ -0,0 +1,379 @@
+# Translation of OpenERP Server.
+# This file contains the translation of the following modules:
+# * base_external_referentials
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: OpenERP Server 5.0.6\n"
+"Report-Msgid-Bugs-To: support@xxxxxxxxxxx\n"
+"POT-Creation-Date: 2009-12-20 17:21+0000\n"
+"PO-Revision-Date: 2011-02-14 10:04+0000\n"
+"Last-Translator: Jordi Esteve (www.zikzakmedia.com) "
+"<jesteve@xxxxxxxxxxxxxxx>\n"
+"Language-Team: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Launchpad-Export-Date: 2012-01-17 05:05+0000\n"
+"X-Generator: Launchpad (build 14676)\n"
+"X-Poedit-Language: Catalan\n"
+
+#. module: base_external_referentials
+#: constraint:ir.model:0
+msgid ""
+"The Object name must start with x_ and not contain any special character !"
+msgstr ""
+"El nom de l'objecte ha de començar amb x_ i no contenir cap caràcter "
+"especial!"
+
+#. module: base_external_referentials
+#: field:external.referential,mapping_ids:0
+msgid "Mappings"
+msgstr "Mapatges"
+
+#. module: base_external_referentials
+#: view:external.referential:0
+msgid "Object Mappings"
+msgstr "Mapatges d'objectes"
+
+#. module: base_external_referentials
+#: view:external.referential:0
+msgid "Synchronize Referential Settings"
+msgstr "Sincronitza configuracions de referències"
+
+#. module: base_external_referentials
+#: view:external.referential:0
+msgid "Authentication"
+msgstr "Autenticació"
+
+#. module: base_external_referentials
+#: field:external.referential,location:0
+msgid "Location"
+msgstr "URL Localització"
+
+#. module: base_external_referentials
+#: constraint:ir.actions.act_window:0
+msgid "Invalid model name in the action definition."
+msgstr "Nom de model no vàlid a la definició de l'acció."
+
+#. module: base_external_referentials
+#: selection:external.mapping.line,type:0
+#: selection:external.mappinglines.template,type:0
+msgid "External <- OpenERP"
+msgstr "Exterior <- OpenERP"
+
+#. module: base_external_referentials
+#: field:external.mapping.line,type:0
+#: field:external.mappinglines.template,type:0
+msgid "Type"
+msgstr "Tipus"
+
+#. module: base_external_referentials
+#: view:external.referential:0
+msgid "Reload Referential Mapping Templates"
+msgstr "Recarrega plantilles de mapatges de referències"
+
+#. module: base_external_referentials
+#: model:ir.module.module,shortdesc:base_external_referentials.module_meta_information
+msgid "Base External Referentials"
+msgstr "Base Referències externes"
+
+#. module: base_external_referentials
+#: field:external.mapping,related_model_ids:0
+msgid "Related Inherited Models"
+msgstr "Models heretats relacionats"
+
+#. module: base_external_referentials
+#: field:external.mapping.line,external_type:0
+#: field:external.mappinglines.template,external_type:0
+msgid "External Type"
+msgstr "Tipus extern"
+
+#. 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.mapping,external_list_method:0
+#: field:external.mapping.template,external_list_method:0
+msgid "List Method"
+msgstr "Mètode llista"
+
+#. module: base_external_referentials
+#: model:ir.ui.menu,name:base_external_referentials.ir_ui_menu_extref0
+msgid "External Referentials"
+msgstr "Referències externes"
+
+#. module: base_external_referentials
+#: model:ir.model,name:base_external_referentials.model_external_referential_type
+msgid "External Referential Type (Ex.Magento,Spree)"
+msgstr "Tipus referència externa (Ej. Magento, Spree, Moodle)"
+
+#. module: base_external_referentials
+#: field:external.mapping.line,related_model_id:0
+msgid "Related Model"
+msgstr "Model relacionat"
+
+#. module: base_external_referentials
+#: field:ir.model.data,create_date:0
+msgid "Created date"
+msgstr "Data creació"
+
+#. module: base_external_referentials
+#: field:external.referential,apiusername:0
+msgid "User Name"
+msgstr "Nom usuari"
+
+#. module: base_external_referentials
+#: help:external.mapping,related_model_ids:0
+msgid ""
+"potentially inherited through '_inherits' model, used for mapping field "
+"selection"
+msgstr ""
+"Potencialment heretat mitjançant models '_inherits', utilitzat pel mapatge "
+"de camps selecció."
+
+#. module: base_external_referentials
+#: field:external.mapping,external_get_method:0
+#: field:external.mapping.template,external_get_method:0
+msgid "Get Method"
+msgstr "Mètode obtenir (Get)"
+
+#. module: base_external_referentials
+#: field:external.mapping,model:0
+#: field:external.mapping.template,model:0
+#: field:external.mappinglines.template,model:0
+msgid "Model Name"
+msgstr "Nom model"
+
+#. 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
+#: view:external.referential:0
+#: model:ir.model,name:base_external_referentials.model_external_mapping_line
+msgid "Field Mapping"
+msgstr "Mapatge del camp"
+
+#. module: base_external_referentials
+#: model:ir.model,name:base_external_referentials.model_external_mapping_template
+msgid "The source mapping records"
+msgstr "Els mapatges originals"
+
+#. module: base_external_referentials
+#: model:ir.actions.act_window,name:base_external_referentials.ir_actions_act_window_externalreferential0
+msgid "external_referential"
+msgstr "Referències externes"
+
+#. module: base_external_referentials
+#: constraint:ir.ui.view:0
+msgid "Invalid XML for View Architecture!"
+msgstr "XML invàlid per a la definició de la vista!"
+
+#. module: base_external_referentials
+#: field:external.mapping.line,external_field:0
+#: field:external.mappinglines.template,external_field:0
+msgid "External Field"
+msgstr "Camp extern"
+
+#. module: base_external_referentials
+#: field:external.referential,name:0
+#: field:external.referential.type,name:0
+msgid "Name"
+msgstr "Nom"
+
+#. module: base_external_referentials
+#: field:external.mapping.line,in_function:0
+#: field:external.mappinglines.template,in_function:0
+msgid "Import in OpenERP Mapping Python Function"
+msgstr "Funció Python de mapatge, importació a OpenERP"
+
+#. module: base_external_referentials
+#: field:external.mapping,mapping_ids:0
+msgid "Mappings Lines"
+msgstr "Línies de mapatge"
+
+#. module: base_external_referentials
+#: selection:external.mapping.line,type:0
+#: selection:external.mappinglines.template,type:0
+msgid "External -> OpenERP"
+msgstr "Exterior -> OpenERP"
+
+#. module: base_external_referentials
+#: model:ir.model,name:base_external_referentials.model_external_mappinglines_template
+msgid "The source mapping line records"
+msgstr "Les línies de mapatge originals"
+
+#. module: base_external_referentials
+#: field:external.mapping,referential_id:0
+#: model:ir.model,name:base_external_referentials.model_external_referential
+msgid "External Referential"
+msgstr "Referència externa"
+
+#. module: base_external_referentials
+#: field:external.referential,type_id:0
+msgid "Referential Type"
+msgstr "Tipus referència"
+
+#. module: base_external_referentials
+#: view:external.referential:0
+msgid "General"
+msgstr "General"
+
+#. module: base_external_referentials
+#: field:external.mapping,external_update_method:0
+#: field:external.mapping.template,external_update_method:0
+msgid "Update Method"
+msgstr "Mètode actualització"
+
+#. module: base_external_referentials
+#: field:external.mapping.line,name_function:0
+msgid "Full Name"
+msgstr "Nom complet"
+
+#. module: base_external_referentials
+#: view:external.referential:0
+msgid "Field Mappings"
+msgstr "Mapatges de camps"
+
+#. module: base_external_referentials
+#: field:external.mapping,model_id:0
+#: field:external.mapping.template,model_id:0
+#: field:external.mappinglines.template,model_id:0
+msgid "OpenERP Model"
+msgstr "Model OpenERP"
+
+#. module: base_external_referentials
+#: field:external.mapping.line,out_function:0
+#: field:external.mappinglines.template,out_function:0
+msgid "Export from OpenERP Mapping Python Function"
+msgstr "Funció Python de mapatge, exportació des d'OpenERP"
+
+#. module: base_external_referentials
+#: field:external.referential,apipass:0
+msgid "Password"
+msgstr "Contrasenya"
+
+#. module: base_external_referentials
+#: field:external.mapping.line,mapping_id:0
+#: model:ir.model,name:base_external_referentials.model_external_mapping
+msgid "External Mapping"
+msgstr "Mapatge extern"
+
+#. module: base_external_referentials
+#: field:external.mapping.line,field_id:0
+msgid "OpenERP Field"
+msgstr "Camp OpenERP"
+
+#. module: base_external_referentials
+#: field:external.mapping,external_create_method:0
+#: field:external.mapping.template,external_create_method:0
+msgid "Create Method"
+msgstr "Mètode creació"
+
+#. 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.mapping,external_key_name:0
+#: field:external.mapping.template,external_key_name:0
+msgid "External field used as key"
+msgstr "Camp extern utilitzat com clau"
+
+#. module: base_external_referentials
+#: field:external.mapping,external_delete_method:0
+#: field:external.mapping.template,external_delete_method:0
+msgid "Delete Method"
+msgstr "Mètode esborrat"
+
+#. 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:ir.model.data,external_referential_id:0
+msgid "Ext. Referential"
+msgstr "Referència ext."
+
+#. module: base_external_referentials
+#: field:ir.model.data,write_date:0
+msgid "Updated date"
+msgstr "Data actualització"
+
+#. module: base_external_referentials
+#: model:ir.module.module,description:base_external_referentials.module_meta_information
+msgid ""
+"\n"
+"This module provide an abstract common minimal base to add any additional "
+"external id columns\n"
+"to some OpenObject table, pointing to some external referential.\n"
+"A referential is abstract and minimal at this stage, it's only identified\n"
+"by:\n"
+"* a name\n"
+"* a location (possibly webservice URL, database connection URL...); the "
+"connection method will tell it...\n"
+"* referential credentials (user name + password)\n"
+"\n"
+"OpenERP already has limited supported to external ids using the "
+"ir_model_data and the id\n"
+"fields in the loaded data such as XML or CSV.\n"
+"The issue is that teh current system, while very useful to deal with "
+"internal OpenERP data has some\n"
+"limitations:\n"
+"* it doesn't scale well to whole production data because everything ends up "
+"into the ir_model_data\n"
+"* all the system is built with a using reference id in mind. But in fact you "
+"might want SEVERAL external ids.\n"
+"Say you sale your products over several websites (using the new Magento "
+"multi-instance connector for\n"
+"instance), then you want that each product have SEVERAL external id columns. "
+"This is exactly what\n"
+"this module enables!\n"
+" "
+msgstr ""
+"\n"
+"Aquest mòdul proporciona una mínima base d'abstracció comuna per a afegir "
+"qualsevol id de columnes externes a algunes taules OpenObject per a que "
+"apuntin a algunes referències externes.\n"
+"Una referència és un concepte abstracte mínim a aquest nivell, s'identifica "
+"només per:\n"
+"* Un nom\n"
+"* URL d'una localització (possiblement URL del webservice, URL de la "
+"connexió a la base de dades...); el mètode de connexió el proporcionarà.\n"
+"* Credencials de connexió (nom d'usuari + contrasenya)\n"
+"\n"
+"OpenERP ja té un suport limitat a ids externes utilitzant la taula "
+"ir_model_data i els camps id en les dades carregades des de XML o CSV.\n"
+"La qüestió és que el sistema actual, encara que molt útil per a fer front a "
+"dades internes d'OpenERP, té algunes limitacions:\n"
+"* No escala bé amb totes les dades de producció, perquè tot acaba guardat en "
+"la taula ir_model_data\n"
+"* Tot el sistema està construït tenint en compte la id de referència. Però "
+"és possible que voleu tenir diverses identificacions externes.\n"
+"Per exemple, si veneu els vostres productes en diversos llocs web "
+"(utilitzant, per exemple, el nou connector Magento multi botiga), i voleu "
+"que cada producte tingui diverses columnes exteriors d'identificació. Això "
+"és exactament el que permet aquest mòdul.\n"
+" "
+
+#. module: base_external_referentials
+#: field:external.mapping.template,type_id:0
+#: field:external.mappinglines.template,type_id:0
+msgid "External Referential Type"
+msgstr "Tipus referència externa"
+
+#. module: base_external_referentials
+#: selection:external.mapping.line,type:0
+#: selection:external.mappinglines.template,type:0
+msgid "External <-> OpenERP"
+msgstr "Exterior <-> OpenERP"
=== added file 'base_external_referentials/i18n/ca_ES.po'
--- base_external_referentials/i18n/ca_ES.po 1970-01-01 00:00:00 +0000
+++ base_external_referentials/i18n/ca_ES.po 2012-09-13 01:56:18 +0000
@@ -0,0 +1,350 @@
+# Translation of OpenERP Server.
+# This file contains the translation of the following modules:
+# * base_external_referentials
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: OpenERP Server 5.0.6\n"
+"Report-Msgid-Bugs-To: support@xxxxxxxxxxx\n"
+"POT-Creation-Date: 2009-12-20 17:21:26+0000\n"
+"PO-Revision-Date: 2009-12-28 01:09+0100\n"
+"Last-Translator: Jordi Esteve <jesteve@xxxxxxxxxxxxxxx>\n"
+"Language-Team: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Poedit-Language: Catalan\n"
+
+#. module: base_external_referentials
+#: constraint:ir.model:0
+msgid "The Object name must start with x_ and not contain any special character !"
+msgstr "El nom de l'objecte ha de començar amb x_ i no contenir cap caràcter especial!"
+
+#. module: base_external_referentials
+#: field:external.referential,mapping_ids:0
+msgid "Mappings"
+msgstr "Mapatges"
+
+#. module: base_external_referentials
+#: view:external.referential:0
+msgid "Object Mappings"
+msgstr "Mapatges d'objectes"
+
+#. module: base_external_referentials
+#: view:external.referential:0
+msgid "Synchronize Referential Settings"
+msgstr "Sincronitza configuracions de referències"
+
+#. module: base_external_referentials
+#: view:external.referential:0
+msgid "Authentication"
+msgstr "Autenticació "
+
+#. module: base_external_referentials
+#: field:external.referential,location:0
+msgid "Location"
+msgstr "URL Localització"
+
+#. module: base_external_referentials
+#: constraint:ir.actions.act_window:0
+msgid "Invalid model name in the action definition."
+msgstr "Nom de model no vàlid a la definició de l'acció."
+
+#. module: base_external_referentials
+#: selection:external.mapping.line,type:0
+#: selection:external.mappinglines.template,type:0
+msgid "External <- OpenERP"
+msgstr "Exterior <- OpenERP"
+
+#. module: base_external_referentials
+#: field:external.mapping.line,type:0
+#: field:external.mappinglines.template,type:0
+msgid "Type"
+msgstr "Tipus"
+
+#. module: base_external_referentials
+#: view:external.referential:0
+msgid "Reload Referential Mapping Templates"
+msgstr "Recarrega plantilles de mapatges de referències"
+
+#. module: base_external_referentials
+#: model:ir.module.module,shortdesc:base_external_referentials.module_meta_information
+msgid "Base External Referentials"
+msgstr "Base Referències externes"
+
+#. module: base_external_referentials
+#: field:external.mapping,related_model_ids:0
+msgid "Related Inherited Models"
+msgstr "Models heretats relacionats"
+
+#. module: base_external_referentials
+#: field:external.mapping.line,external_type:0
+#: field:external.mappinglines.template,external_type:0
+msgid "External Type"
+msgstr "Tipus extern"
+
+#. 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.mapping,external_list_method:0
+#: field:external.mapping.template,external_list_method:0
+msgid "List Method"
+msgstr "Mètode llista"
+
+#. module: base_external_referentials
+#: model:ir.ui.menu,name:base_external_referentials.ir_ui_menu_extref0
+msgid "External Referentials"
+msgstr "Referències externes"
+
+#. module: base_external_referentials
+#: model:ir.model,name:base_external_referentials.model_external_referential_type
+msgid "External Referential Type (Ex.Magento,Spree)"
+msgstr "Tipus referència externa (Ej. Magento, Spree, Moodle)"
+
+#. module: base_external_referentials
+#: field:external.mapping.line,related_model_id:0
+msgid "Related Model"
+msgstr "Model relacionat"
+
+#. module: base_external_referentials
+#: field:ir.model.data,create_date:0
+msgid "Created date"
+msgstr "Data creació"
+
+#. module: base_external_referentials
+#: field:external.referential,apiusername:0
+msgid "User Name"
+msgstr "Nom usuari"
+
+#. module: base_external_referentials
+#: help:external.mapping,related_model_ids:0
+msgid "potentially inherited through '_inherits' model, used for mapping field selection"
+msgstr "Potencialment heretat mitjançant models '_inherits', utilitzat pel mapatge de camps selecció."
+
+#. module: base_external_referentials
+#: field:external.mapping,external_get_method:0
+#: field:external.mapping.template,external_get_method:0
+msgid "Get Method"
+msgstr "Mètode obtenir (Get)"
+
+#. module: base_external_referentials
+#: field:external.mapping,model:0
+#: field:external.mapping.template,model:0
+#: field:external.mappinglines.template,model:0
+msgid "Model Name"
+msgstr "Nom model"
+
+#. 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
+#: view:external.referential:0
+#: model:ir.model,name:base_external_referentials.model_external_mapping_line
+msgid "Field Mapping"
+msgstr "Mapatge del camp"
+
+#. module: base_external_referentials
+#: model:ir.model,name:base_external_referentials.model_external_mapping_template
+msgid "The source mapping records"
+msgstr "Els mapatges originals"
+
+#. module: base_external_referentials
+#: model:ir.actions.act_window,name:base_external_referentials.ir_actions_act_window_externalreferential0
+msgid "external_referential"
+msgstr "Referències externes"
+
+#. module: base_external_referentials
+#: constraint:ir.ui.view:0
+msgid "Invalid XML for View Architecture!"
+msgstr "XML invàlid per a la definició de la vista!"
+
+#. module: base_external_referentials
+#: field:external.mapping.line,external_field:0
+#: field:external.mappinglines.template,external_field:0
+msgid "External Field"
+msgstr "Camp extern"
+
+#. module: base_external_referentials
+#: field:external.referential,name:0
+#: field:external.referential.type,name:0
+msgid "Name"
+msgstr "Nom"
+
+#. module: base_external_referentials
+#: field:external.mapping.line,in_function:0
+#: field:external.mappinglines.template,in_function:0
+msgid "Import in OpenERP Mapping Python Function"
+msgstr "Funció Python de mapatge, importació a OpenERP"
+
+#. module: base_external_referentials
+#: field:external.mapping,mapping_ids:0
+msgid "Mappings Lines"
+msgstr "Línies de mapatge"
+
+#. module: base_external_referentials
+#: selection:external.mapping.line,type:0
+#: selection:external.mappinglines.template,type:0
+msgid "External -> OpenERP"
+msgstr "Exterior -> OpenERP"
+
+#. module: base_external_referentials
+#: model:ir.model,name:base_external_referentials.model_external_mappinglines_template
+msgid "The source mapping line records"
+msgstr "Les línies de mapatge originals"
+
+#. module: base_external_referentials
+#: field:external.mapping,referential_id:0
+#: model:ir.model,name:base_external_referentials.model_external_referential
+msgid "External Referential"
+msgstr "Referència externa"
+
+#. module: base_external_referentials
+#: field:external.referential,type_id:0
+msgid "Referential Type"
+msgstr "Tipus referència"
+
+#. module: base_external_referentials
+#: view:external.referential:0
+msgid "General"
+msgstr "General"
+
+#. module: base_external_referentials
+#: field:external.mapping,external_update_method:0
+#: field:external.mapping.template,external_update_method:0
+msgid "Update Method"
+msgstr "Mètode actualització"
+
+#. module: base_external_referentials
+#: field:external.mapping.line,name_function:0
+msgid "Full Name"
+msgstr "Nom complet"
+
+#. module: base_external_referentials
+#: view:external.referential:0
+msgid "Field Mappings"
+msgstr "Mapatges de camps"
+
+#. module: base_external_referentials
+#: field:external.mapping,model_id:0
+#: field:external.mapping.template,model_id:0
+#: field:external.mappinglines.template,model_id:0
+msgid "OpenERP Model"
+msgstr "Model OpenERP"
+
+#. module: base_external_referentials
+#: field:external.mapping.line,out_function:0
+#: field:external.mappinglines.template,out_function:0
+msgid "Export from OpenERP Mapping Python Function"
+msgstr "Funció Python de mapatge, exportació des d'OpenERP"
+
+#. module: base_external_referentials
+#: field:external.referential,apipass:0
+msgid "Password"
+msgstr "Contrasenya"
+
+#. module: base_external_referentials
+#: field:external.mapping.line,mapping_id:0
+#: model:ir.model,name:base_external_referentials.model_external_mapping
+msgid "External Mapping"
+msgstr "Mapatge extern"
+
+#. module: base_external_referentials
+#: field:external.mapping.line,field_id:0
+msgid "OpenERP Field"
+msgstr "Camp OpenERP"
+
+#. module: base_external_referentials
+#: field:external.mapping,external_create_method:0
+#: field:external.mapping.template,external_create_method:0
+msgid "Create Method"
+msgstr "Mètode creació"
+
+#. 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.mapping,external_key_name:0
+#: field:external.mapping.template,external_key_name:0
+msgid "External field used as key"
+msgstr "Camp extern utilitzat com clau"
+
+#. module: base_external_referentials
+#: field:external.mapping,external_delete_method:0
+#: field:external.mapping.template,external_delete_method:0
+msgid "Delete Method"
+msgstr "Mètode esborrat"
+
+#. 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:ir.model.data,external_referential_id:0
+msgid "Ext. Referential"
+msgstr "Referència ext."
+
+#. module: base_external_referentials
+#: field:ir.model.data,write_date:0
+msgid "Updated date"
+msgstr "Data actualització"
+
+#. module: base_external_referentials
+#: model:ir.module.module,description:base_external_referentials.module_meta_information
+msgid ""
+"\n"
+"This module provide an abstract common minimal base to add any additional external id columns\n"
+"to some OpenObject table, pointing to some external referential.\n"
+"A referential is abstract and minimal at this stage, it's only identified\n"
+"by:\n"
+"* a name\n"
+"* a location (possibly webservice URL, database connection URL...); the connection method will tell it...\n"
+"* referential credentials (user name + password)\n"
+"\n"
+"OpenERP already has limited supported to external ids using the ir_model_data and the id\n"
+"fields in the loaded data such as XML or CSV.\n"
+"The issue is that teh current system, while very useful to deal with internal OpenERP data has some\n"
+"limitations:\n"
+"* it doesn't scale well to whole production data because everything ends up into the ir_model_data\n"
+"* all the system is built with a using reference id in mind. But in fact you might want SEVERAL external ids.\n"
+"Say you sale your products over several websites (using the new Magento multi-instance connector for\n"
+"instance), then you want that each product have SEVERAL external id columns. This is exactly what\n"
+"this module enables!\n"
+" "
+msgstr ""
+"\n"
+"Aquest mòdul proporciona una mínima base d'abstracció comuna per a afegir qualsevol id de columnes externes a algunes taules OpenObject per a que apuntin a algunes referències externes.\n"
+"Una referència és un concepte abstracte mínim a aquest nivell, s'identifica només per:\n"
+"* Un nom\n"
+"* URL d'una localització (possiblement URL del webservice, URL de la connexió a la base de dades...); el mètode de connexió el proporcionarà.\n"
+"* Credencials de connexió (nom d'usuari + contrasenya)\n"
+"\n"
+"OpenERP ja té un suport limitat a ids externes utilitzant la taula ir_model_data i els camps id en les dades carregades des de XML o CSV.\n"
+"La qüestió és que el sistema actual, encara que molt útil per a fer front a dades internes d'OpenERP, té algunes limitacions:\n"
+"* No escala bé amb totes les dades de producció, perquè tot acaba guardat en la taula ir_model_data\n"
+"* Tot el sistema està construït tenint en compte la id de referència. Però és possible que voleu tenir diverses identificacions externes.\n"
+"Per exemple, si veneu els vostres productes en diversos llocs web (utilitzant, per exemple, el nou connector Magento multi botiga), i voleu que cada producte tingui diverses columnes exteriors d'identificació. Això és exactament el que permet aquest mòdul.\n"
+
+#. module: base_external_referentials
+#: field:external.mapping.template,type_id:0
+#: field:external.mappinglines.template,type_id:0
+msgid "External Referential Type"
+msgstr "Tipus referència externa"
+
+#. module: base_external_referentials
+#: selection:external.mapping.line,type:0
+#: selection:external.mappinglines.template,type:0
+msgid "External <-> OpenERP"
+msgstr "Exterior <-> OpenERP"
+
=== added file 'base_external_referentials/i18n/es.po'
--- base_external_referentials/i18n/es.po 1970-01-01 00:00:00 +0000
+++ base_external_referentials/i18n/es.po 2012-09-13 01:56:18 +0000
@@ -0,0 +1,378 @@
+# Translation of OpenERP Server.
+# This file contains the translation of the following modules:
+# * base_external_referentials
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: OpenERP Server 5.0.6\n"
+"Report-Msgid-Bugs-To: support@xxxxxxxxxxx\n"
+"POT-Creation-Date: 2009-12-20 17:21+0000\n"
+"PO-Revision-Date: 2011-02-14 11:36+0000\n"
+"Last-Translator: Jordi Esteve (www.zikzakmedia.com) "
+"<jesteve@xxxxxxxxxxxxxxx>\n"
+"Language-Team: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Launchpad-Export-Date: 2012-01-17 05:05+0000\n"
+"X-Generator: Launchpad (build 14676)\n"
+
+#. module: base_external_referentials
+#: constraint:ir.model:0
+msgid ""
+"The Object name must start with x_ and not contain any special character !"
+msgstr ""
+"¡El nombre del objeto debe empezar con x_ y no contener ningún carácter "
+"especial!"
+
+#. module: base_external_referentials
+#: field:external.referential,mapping_ids:0
+msgid "Mappings"
+msgstr "Mapeos"
+
+#. module: base_external_referentials
+#: view:external.referential:0
+msgid "Object Mappings"
+msgstr "Mapeos de objetos"
+
+#. module: base_external_referentials
+#: view:external.referential:0
+msgid "Synchronize Referential Settings"
+msgstr "Sincronizar configuraciones de referencias"
+
+#. module: base_external_referentials
+#: view:external.referential:0
+msgid "Authentication"
+msgstr "Autenticación"
+
+#. module: base_external_referentials
+#: field:external.referential,location:0
+msgid "Location"
+msgstr "URL Localización"
+
+#. module: base_external_referentials
+#: constraint:ir.actions.act_window:0
+msgid "Invalid model name in the action definition."
+msgstr "Nombre de modelo no válido en la definición de la acción."
+
+#. module: base_external_referentials
+#: selection:external.mapping.line,type:0
+#: selection:external.mappinglines.template,type:0
+msgid "External <- OpenERP"
+msgstr "Exterior <- OpenERP"
+
+#. module: base_external_referentials
+#: field:external.mapping.line,type:0
+#: field:external.mappinglines.template,type:0
+msgid "Type"
+msgstr "Tipo"
+
+#. module: base_external_referentials
+#: view:external.referential:0
+msgid "Reload Referential Mapping Templates"
+msgstr "Recargar plantillas de mapeo de referencias"
+
+#. module: base_external_referentials
+#: model:ir.module.module,shortdesc:base_external_referentials.module_meta_information
+msgid "Base External Referentials"
+msgstr "Base Referencias externas"
+
+#. module: base_external_referentials
+#: field:external.mapping,related_model_ids:0
+msgid "Related Inherited Models"
+msgstr "Modelos heredados relacionados"
+
+#. module: base_external_referentials
+#: field:external.mapping.line,external_type:0
+#: field:external.mappinglines.template,external_type:0
+msgid "External Type"
+msgstr "Tipo externo"
+
+#. 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.mapping,external_list_method:0
+#: field:external.mapping.template,external_list_method:0
+msgid "List Method"
+msgstr "Método lista"
+
+#. module: base_external_referentials
+#: model:ir.ui.menu,name:base_external_referentials.ir_ui_menu_extref0
+msgid "External Referentials"
+msgstr "Referencias externas"
+
+#. module: base_external_referentials
+#: model:ir.model,name:base_external_referentials.model_external_referential_type
+msgid "External Referential Type (Ex.Magento,Spree)"
+msgstr "Tipo referencia externa (Ej. Magento, Spree, Moodle)"
+
+#. module: base_external_referentials
+#: field:external.mapping.line,related_model_id:0
+msgid "Related Model"
+msgstr "Modelo relacionado"
+
+#. module: base_external_referentials
+#: field:ir.model.data,create_date:0
+msgid "Created date"
+msgstr "Fecha creación"
+
+#. module: base_external_referentials
+#: field:external.referential,apiusername:0
+msgid "User Name"
+msgstr "Nombre usuario"
+
+#. module: base_external_referentials
+#: help:external.mapping,related_model_ids:0
+msgid ""
+"potentially inherited through '_inherits' model, used for mapping field "
+"selection"
+msgstr ""
+"Potencialmente heredado mediante modelos '_inherits', usado para el mapeo de "
+"campos selección."
+
+#. module: base_external_referentials
+#: field:external.mapping,external_get_method:0
+#: field:external.mapping.template,external_get_method:0
+msgid "Get Method"
+msgstr "Método obtener (Get)"
+
+#. module: base_external_referentials
+#: field:external.mapping,model:0
+#: field:external.mapping.template,model:0
+#: field:external.mappinglines.template,model:0
+msgid "Model Name"
+msgstr "Nombre modelo"
+
+#. 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
+#: view:external.referential:0
+#: model:ir.model,name:base_external_referentials.model_external_mapping_line
+msgid "Field Mapping"
+msgstr "Mapeo de campo"
+
+#. module: base_external_referentials
+#: model:ir.model,name:base_external_referentials.model_external_mapping_template
+msgid "The source mapping records"
+msgstr "Los mapeos originales"
+
+#. module: base_external_referentials
+#: model:ir.actions.act_window,name:base_external_referentials.ir_actions_act_window_externalreferential0
+msgid "external_referential"
+msgstr "Referencias externas"
+
+#. module: base_external_referentials
+#: constraint:ir.ui.view:0
+msgid "Invalid XML for View Architecture!"
+msgstr "¡XML inválido para la definición de la vista!"
+
+#. module: base_external_referentials
+#: field:external.mapping.line,external_field:0
+#: field:external.mappinglines.template,external_field:0
+msgid "External Field"
+msgstr "Campo externo"
+
+#. module: base_external_referentials
+#: field:external.referential,name:0
+#: field:external.referential.type,name:0
+msgid "Name"
+msgstr "Nombre"
+
+#. module: base_external_referentials
+#: field:external.mapping.line,in_function:0
+#: field:external.mappinglines.template,in_function:0
+msgid "Import in OpenERP Mapping Python Function"
+msgstr "Función Python de mapeo, importación en OpenERP"
+
+#. module: base_external_referentials
+#: field:external.mapping,mapping_ids:0
+msgid "Mappings Lines"
+msgstr "Líneas de mapeo"
+
+#. module: base_external_referentials
+#: selection:external.mapping.line,type:0
+#: selection:external.mappinglines.template,type:0
+msgid "External -> OpenERP"
+msgstr "Exterior -> OpenERP"
+
+#. module: base_external_referentials
+#: model:ir.model,name:base_external_referentials.model_external_mappinglines_template
+msgid "The source mapping line records"
+msgstr "Las líneas de mapeo originales"
+
+#. module: base_external_referentials
+#: field:external.mapping,referential_id:0
+#: model:ir.model,name:base_external_referentials.model_external_referential
+msgid "External Referential"
+msgstr "Referencia externa"
+
+#. module: base_external_referentials
+#: field:external.referential,type_id:0
+msgid "Referential Type"
+msgstr "Tipo referencia"
+
+#. module: base_external_referentials
+#: view:external.referential:0
+msgid "General"
+msgstr "General"
+
+#. module: base_external_referentials
+#: field:external.mapping,external_update_method:0
+#: field:external.mapping.template,external_update_method:0
+msgid "Update Method"
+msgstr "Método actualización"
+
+#. module: base_external_referentials
+#: field:external.mapping.line,name_function:0
+msgid "Full Name"
+msgstr "Nombre completo"
+
+#. module: base_external_referentials
+#: view:external.referential:0
+msgid "Field Mappings"
+msgstr "Mapeos de campos"
+
+#. module: base_external_referentials
+#: field:external.mapping,model_id:0
+#: field:external.mapping.template,model_id:0
+#: field:external.mappinglines.template,model_id:0
+msgid "OpenERP Model"
+msgstr "Modelo OpenERP"
+
+#. module: base_external_referentials
+#: field:external.mapping.line,out_function:0
+#: field:external.mappinglines.template,out_function:0
+msgid "Export from OpenERP Mapping Python Function"
+msgstr "Función Python de mapeo, exportación desde OpenERP"
+
+#. module: base_external_referentials
+#: field:external.referential,apipass:0
+msgid "Password"
+msgstr "Contraseña"
+
+#. module: base_external_referentials
+#: field:external.mapping.line,mapping_id:0
+#: model:ir.model,name:base_external_referentials.model_external_mapping
+msgid "External Mapping"
+msgstr "Mapeo externo"
+
+#. module: base_external_referentials
+#: field:external.mapping.line,field_id:0
+msgid "OpenERP Field"
+msgstr "Campo OpenERP"
+
+#. module: base_external_referentials
+#: field:external.mapping,external_create_method:0
+#: field:external.mapping.template,external_create_method:0
+msgid "Create Method"
+msgstr "Método creación"
+
+#. 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.mapping,external_key_name:0
+#: field:external.mapping.template,external_key_name:0
+msgid "External field used as key"
+msgstr "Campo externo usado como clave"
+
+#. module: base_external_referentials
+#: field:external.mapping,external_delete_method:0
+#: field:external.mapping.template,external_delete_method:0
+msgid "Delete Method"
+msgstr "Método borrado"
+
+#. 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:ir.model.data,external_referential_id:0
+msgid "Ext. Referential"
+msgstr "Referencia ext."
+
+#. module: base_external_referentials
+#: field:ir.model.data,write_date:0
+msgid "Updated date"
+msgstr "Fecha actualización"
+
+#. module: base_external_referentials
+#: model:ir.module.module,description:base_external_referentials.module_meta_information
+msgid ""
+"\n"
+"This module provide an abstract common minimal base to add any additional "
+"external id columns\n"
+"to some OpenObject table, pointing to some external referential.\n"
+"A referential is abstract and minimal at this stage, it's only identified\n"
+"by:\n"
+"* a name\n"
+"* a location (possibly webservice URL, database connection URL...); the "
+"connection method will tell it...\n"
+"* referential credentials (user name + password)\n"
+"\n"
+"OpenERP already has limited supported to external ids using the "
+"ir_model_data and the id\n"
+"fields in the loaded data such as XML or CSV.\n"
+"The issue is that teh current system, while very useful to deal with "
+"internal OpenERP data has some\n"
+"limitations:\n"
+"* it doesn't scale well to whole production data because everything ends up "
+"into the ir_model_data\n"
+"* all the system is built with a using reference id in mind. But in fact you "
+"might want SEVERAL external ids.\n"
+"Say you sale your products over several websites (using the new Magento "
+"multi-instance connector for\n"
+"instance), then you want that each product have SEVERAL external id columns. "
+"This is exactly what\n"
+"this module enables!\n"
+" "
+msgstr ""
+"\n"
+"Este módulo proporciona una mínima base de abstracción común para añadir "
+"cualquier id de columnas externas a algunas tablas OpenObject para que "
+"apunten a algunas referencias externas.\n"
+"Una referencia es un concepto abstracto y mínimo a este nivel, se identifica "
+"sólo por:\n"
+"* Un nombre\n"
+"* URL de una localización (posiblemente URL del webservice, URL de la "
+"conexión a la base de datos...); el método de conexión lo proporcionará.\n"
+"* Credenciales de conexión (nombre de usuario + contraseña)\n"
+"\n"
+"OpenERP ya tiene un soporte limitado a ids externas utilizando la tabla "
+"ir_model_data y los campos id en los datos cargados como XML o CSV.\n"
+"La cuestión es que el sistema actual, aunque muy útil para hacer frente a "
+"datos internos de OpenERP, tiene algunas limitaciones:\n"
+"* No escala bien con todos los datos de producción, porque todo termina "
+"guardado en la tabla ir_model_data\n"
+"* Todo el sistema está construido teniendo en cuenta la id de referencia. "
+"Pero es posible que desee tener varias identificaciones externas.\n"
+"Por ejemplo, si vende sus productos en varios sitios web (utilizando, por "
+"ejemplo, el nuevo conector Magento multi tienda), y desea que cada producto "
+"tenga varias columnas exteriores de identificación. Esto es exactamente lo "
+"que permite este módulo.\n"
+" "
+
+#. module: base_external_referentials
+#: field:external.mapping.template,type_id:0
+#: field:external.mappinglines.template,type_id:0
+msgid "External Referential Type"
+msgstr "Tipo referencia externa"
+
+#. module: base_external_referentials
+#: selection:external.mapping.line,type:0
+#: selection:external.mappinglines.template,type:0
+msgid "External <-> OpenERP"
+msgstr "Exterior <-> OpenERP"
=== added file 'base_external_referentials/i18n/es_ES.po'
--- base_external_referentials/i18n/es_ES.po 1970-01-01 00:00:00 +0000
+++ base_external_referentials/i18n/es_ES.po 2012-09-13 01:56:18 +0000
@@ -0,0 +1,350 @@
+# Translation of OpenERP Server.
+# This file contains the translation of the following modules:
+# * base_external_referentials
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: OpenERP Server 5.0.6\n"
+"Report-Msgid-Bugs-To: support@xxxxxxxxxxx\n"
+"POT-Creation-Date: 2009-12-20 17:21:26+0000\n"
+"PO-Revision-Date: 2009-12-28 00:59+0100\n"
+"Last-Translator: Jordi Esteve <jesteve@xxxxxxxxxxxxxxx>\n"
+"Language-Team: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: \n"
+
+#. module: base_external_referentials
+#: constraint:ir.model:0
+msgid "The Object name must start with x_ and not contain any special character !"
+msgstr "¡El nombre del objeto debe empezar con x_ y no contener ningún carácter especial!"
+
+#. module: base_external_referentials
+#: field:external.referential,mapping_ids:0
+msgid "Mappings"
+msgstr "Mapeos"
+
+#. module: base_external_referentials
+#: view:external.referential:0
+msgid "Object Mappings"
+msgstr "Mapeos de objetos"
+
+#. module: base_external_referentials
+#: view:external.referential:0
+msgid "Synchronize Referential Settings"
+msgstr "Sincronizar configuraciones de referencias"
+
+#. module: base_external_referentials
+#: view:external.referential:0
+msgid "Authentication"
+msgstr "Autenticación "
+
+#. module: base_external_referentials
+#: field:external.referential,location:0
+msgid "Location"
+msgstr "URL Localización"
+
+#. module: base_external_referentials
+#: constraint:ir.actions.act_window:0
+msgid "Invalid model name in the action definition."
+msgstr "Nombre de modelo no válido en la definición de la acción."
+
+#. module: base_external_referentials
+#: selection:external.mapping.line,type:0
+#: selection:external.mappinglines.template,type:0
+msgid "External <- OpenERP"
+msgstr "Exterior <- OpenERP"
+
+#. module: base_external_referentials
+#: field:external.mapping.line,type:0
+#: field:external.mappinglines.template,type:0
+msgid "Type"
+msgstr "Tipo"
+
+#. module: base_external_referentials
+#: view:external.referential:0
+msgid "Reload Referential Mapping Templates"
+msgstr "Recargar plantillas de mapeo de referencias"
+
+#. module: base_external_referentials
+#: model:ir.module.module,shortdesc:base_external_referentials.module_meta_information
+msgid "Base External Referentials"
+msgstr "Base Referencias externas"
+
+#. module: base_external_referentials
+#: field:external.mapping,related_model_ids:0
+msgid "Related Inherited Models"
+msgstr "Modelos heredados relacionados"
+
+#. module: base_external_referentials
+#: field:external.mapping.line,external_type:0
+#: field:external.mappinglines.template,external_type:0
+msgid "External Type"
+msgstr "Tipo externo"
+
+#. 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.mapping,external_list_method:0
+#: field:external.mapping.template,external_list_method:0
+msgid "List Method"
+msgstr "Método lista"
+
+#. module: base_external_referentials
+#: model:ir.ui.menu,name:base_external_referentials.ir_ui_menu_extref0
+msgid "External Referentials"
+msgstr "Referencias externas"
+
+#. module: base_external_referentials
+#: model:ir.model,name:base_external_referentials.model_external_referential_type
+msgid "External Referential Type (Ex.Magento,Spree)"
+msgstr "Tipo referencia externa (Ej. Magento, Spree, Moodle)"
+
+#. module: base_external_referentials
+#: field:external.mapping.line,related_model_id:0
+msgid "Related Model"
+msgstr "Modelo relacionado"
+
+#. module: base_external_referentials
+#: field:ir.model.data,create_date:0
+msgid "Created date"
+msgstr "Fecha creación"
+
+#. module: base_external_referentials
+#: field:external.referential,apiusername:0
+msgid "User Name"
+msgstr "Nombre usuario"
+
+#. module: base_external_referentials
+#: help:external.mapping,related_model_ids:0
+msgid "potentially inherited through '_inherits' model, used for mapping field selection"
+msgstr "Potencialmente heredado mediante modelos '_inherits', usado para el mapeo de campos selección."
+
+#. module: base_external_referentials
+#: field:external.mapping,external_get_method:0
+#: field:external.mapping.template,external_get_method:0
+msgid "Get Method"
+msgstr "Método obtener (Get)"
+
+#. module: base_external_referentials
+#: field:external.mapping,model:0
+#: field:external.mapping.template,model:0
+#: field:external.mappinglines.template,model:0
+msgid "Model Name"
+msgstr "Nombre modelo"
+
+#. 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
+#: view:external.referential:0
+#: model:ir.model,name:base_external_referentials.model_external_mapping_line
+msgid "Field Mapping"
+msgstr "Mapeo de campo"
+
+#. module: base_external_referentials
+#: model:ir.model,name:base_external_referentials.model_external_mapping_template
+msgid "The source mapping records"
+msgstr "Los mapeos originales"
+
+#. module: base_external_referentials
+#: model:ir.actions.act_window,name:base_external_referentials.ir_actions_act_window_externalreferential0
+msgid "external_referential"
+msgstr "Referencias externas"
+
+#. module: base_external_referentials
+#: constraint:ir.ui.view:0
+msgid "Invalid XML for View Architecture!"
+msgstr "¡XML inválido para la definición de la vista!"
+
+#. module: base_external_referentials
+#: field:external.mapping.line,external_field:0
+#: field:external.mappinglines.template,external_field:0
+msgid "External Field"
+msgstr "Campo externo"
+
+#. module: base_external_referentials
+#: field:external.referential,name:0
+#: field:external.referential.type,name:0
+msgid "Name"
+msgstr "Nombre"
+
+#. module: base_external_referentials
+#: field:external.mapping.line,in_function:0
+#: field:external.mappinglines.template,in_function:0
+msgid "Import in OpenERP Mapping Python Function"
+msgstr "Función Python de mapeo, importación en OpenERP"
+
+#. module: base_external_referentials
+#: field:external.mapping,mapping_ids:0
+msgid "Mappings Lines"
+msgstr "Líneas de mapeo"
+
+#. module: base_external_referentials
+#: selection:external.mapping.line,type:0
+#: selection:external.mappinglines.template,type:0
+msgid "External -> OpenERP"
+msgstr "Exterior -> OpenERP"
+
+#. module: base_external_referentials
+#: model:ir.model,name:base_external_referentials.model_external_mappinglines_template
+msgid "The source mapping line records"
+msgstr "Las líneas de mapeo originales"
+
+#. module: base_external_referentials
+#: field:external.mapping,referential_id:0
+#: model:ir.model,name:base_external_referentials.model_external_referential
+msgid "External Referential"
+msgstr "Referencia externa"
+
+#. module: base_external_referentials
+#: field:external.referential,type_id:0
+msgid "Referential Type"
+msgstr "Tipo referencia"
+
+#. module: base_external_referentials
+#: view:external.referential:0
+msgid "General"
+msgstr "General"
+
+#. module: base_external_referentials
+#: field:external.mapping,external_update_method:0
+#: field:external.mapping.template,external_update_method:0
+msgid "Update Method"
+msgstr "Método actualización"
+
+#. module: base_external_referentials
+#: field:external.mapping.line,name_function:0
+msgid "Full Name"
+msgstr "Nombre completo"
+
+#. module: base_external_referentials
+#: view:external.referential:0
+msgid "Field Mappings"
+msgstr "Mapeos de campos"
+
+#. module: base_external_referentials
+#: field:external.mapping,model_id:0
+#: field:external.mapping.template,model_id:0
+#: field:external.mappinglines.template,model_id:0
+msgid "OpenERP Model"
+msgstr "Modelo OpenERP"
+
+#. module: base_external_referentials
+#: field:external.mapping.line,out_function:0
+#: field:external.mappinglines.template,out_function:0
+msgid "Export from OpenERP Mapping Python Function"
+msgstr "Función Python de mapeo, exportación desde OpenERP"
+
+#. module: base_external_referentials
+#: field:external.referential,apipass:0
+msgid "Password"
+msgstr "Contraseña"
+
+#. module: base_external_referentials
+#: field:external.mapping.line,mapping_id:0
+#: model:ir.model,name:base_external_referentials.model_external_mapping
+msgid "External Mapping"
+msgstr "Mapeo externo"
+
+#. module: base_external_referentials
+#: field:external.mapping.line,field_id:0
+msgid "OpenERP Field"
+msgstr "Campo OpenERP"
+
+#. module: base_external_referentials
+#: field:external.mapping,external_create_method:0
+#: field:external.mapping.template,external_create_method:0
+msgid "Create Method"
+msgstr "Método creación"
+
+#. 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.mapping,external_key_name:0
+#: field:external.mapping.template,external_key_name:0
+msgid "External field used as key"
+msgstr "Campo externo usado como clave"
+
+#. module: base_external_referentials
+#: field:external.mapping,external_delete_method:0
+#: field:external.mapping.template,external_delete_method:0
+msgid "Delete Method"
+msgstr "Método borrado"
+
+#. 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:ir.model.data,external_referential_id:0
+msgid "Ext. Referential"
+msgstr "Referencia ext."
+
+#. module: base_external_referentials
+#: field:ir.model.data,write_date:0
+msgid "Updated date"
+msgstr "Fecha actualización"
+
+#. module: base_external_referentials
+#: model:ir.module.module,description:base_external_referentials.module_meta_information
+msgid ""
+"\n"
+"This module provide an abstract common minimal base to add any additional external id columns\n"
+"to some OpenObject table, pointing to some external referential.\n"
+"A referential is abstract and minimal at this stage, it's only identified\n"
+"by:\n"
+"* a name\n"
+"* a location (possibly webservice URL, database connection URL...); the connection method will tell it...\n"
+"* referential credentials (user name + password)\n"
+"\n"
+"OpenERP already has limited supported to external ids using the ir_model_data and the id\n"
+"fields in the loaded data such as XML or CSV.\n"
+"The issue is that teh current system, while very useful to deal with internal OpenERP data has some\n"
+"limitations:\n"
+"* it doesn't scale well to whole production data because everything ends up into the ir_model_data\n"
+"* all the system is built with a using reference id in mind. But in fact you might want SEVERAL external ids.\n"
+"Say you sale your products over several websites (using the new Magento multi-instance connector for\n"
+"instance), then you want that each product have SEVERAL external id columns. This is exactly what\n"
+"this module enables!\n"
+" "
+msgstr ""
+"\n"
+"Este módulo proporciona una mínima base de abstracción común para añadir cualquier id de columnas externas a algunas tablas OpenObject para que apunten a algunas referencias externas.\n"
+"Una referencia es un concepto abstracto y mínimo a este nivel, se identifica sólo por:\n"
+"* Un nombre\n"
+"* URL de una localización (posiblemente URL del webservice, URL de la conexión a la base de datos...); el método de conexión lo proporcionará.\n"
+"* Credenciales de conexión (nombre de usuario + contraseña)\n"
+"\n"
+"OpenERP ya tiene un soporte limitado a ids externas utilizando la tabla ir_model_data y los campos id en los datos cargados como XML o CSV.\n"
+"La cuestión es que el sistema actual, aunque muy útil para hacer frente a datos internos de OpenERP, tiene algunas limitaciones:\n"
+"* No escala bien con todos los datos de producción, porque todo termina guardado en la tabla ir_model_data\n"
+"* Todo el sistema está construido teniendo en cuenta la id de referencia. Pero es posible que desee tener varias identificaciones externas.\n"
+"Por ejemplo, si vende sus productos en varios sitios web (utilizando, por ejemplo, el nuevo conector Magento multi tienda), y desea que cada producto tenga varias columnas exteriores de identificación. Esto es exactamente lo que permite este módulo.\n"
+
+#. module: base_external_referentials
+#: field:external.mapping.template,type_id:0
+#: field:external.mappinglines.template,type_id:0
+msgid "External Referential Type"
+msgstr "Tipo referencia externa"
+
+#. module: base_external_referentials
+#: selection:external.mapping.line,type:0
+#: selection:external.mappinglines.template,type:0
+msgid "External <-> OpenERP"
+msgstr "Exterior <-> OpenERP"
+
=== added file 'base_external_referentials/i18n/fi.po'
--- base_external_referentials/i18n/fi.po 1970-01-01 00:00:00 +0000
+++ base_external_referentials/i18n/fi.po 2012-09-13 01:56:18 +0000
@@ -0,0 +1,353 @@
+# Finnish translation for openobject-addons
+# Copyright (c) 2011 Rosetta Contributors and Canonical Ltd 2011
+# This file is distributed under the same license as the openobject-addons package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, 2011.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: openobject-addons\n"
+"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
+"POT-Creation-Date: 2009-12-20 17:21+0000\n"
+"PO-Revision-Date: 2011-07-05 07:49+0000\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: Finnish <fi@xxxxxx>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Launchpad-Export-Date: 2012-01-17 05:05+0000\n"
+"X-Generator: Launchpad (build 14676)\n"
+
+#. module: base_external_referentials
+#: constraint:ir.model:0
+msgid ""
+"The Object name must start with x_ and not contain any special character !"
+msgstr ""
+"Objektin nimi täytyy alkaa X_ eikä se saa sisältää mitää erikoismerkkejä!"
+
+#. module: base_external_referentials
+#: field:external.referential,mapping_ids:0
+msgid "Mappings"
+msgstr "Mäppäykset"
+
+#. module: base_external_referentials
+#: view:external.referential:0
+msgid "Object Mappings"
+msgstr "Objektien mäppäykset"
+
+#. module: base_external_referentials
+#: view:external.referential:0
+msgid "Synchronize Referential Settings"
+msgstr "Synkronoi viiteasetukset"
+
+#. module: base_external_referentials
+#: view:external.referential:0
+msgid "Authentication"
+msgstr "Tunnistus"
+
+#. module: base_external_referentials
+#: field:external.referential,location:0
+msgid "Location"
+msgstr "Sijainti"
+
+#. module: base_external_referentials
+#: constraint:ir.actions.act_window:0
+msgid "Invalid model name in the action definition."
+msgstr "Virheellinen mallin nimi toiminnon määrittelyssä."
+
+#. module: base_external_referentials
+#: selection:external.mapping.line,type:0
+#: selection:external.mappinglines.template,type:0
+msgid "External <- OpenERP"
+msgstr "Ulkoinen <- OpenERP"
+
+#. module: base_external_referentials
+#: field:external.mapping.line,type:0
+#: field:external.mappinglines.template,type:0
+msgid "Type"
+msgstr "Tyyppi"
+
+#. module: base_external_referentials
+#: view:external.referential:0
+msgid "Reload Referential Mapping Templates"
+msgstr "Lataa uudelleen viiteamäppäysten pohjat"
+
+#. module: base_external_referentials
+#: model:ir.module.module,shortdesc:base_external_referentials.module_meta_information
+msgid "Base External Referentials"
+msgstr "Ulkoisten viittausten pohjatiedot"
+
+#. module: base_external_referentials
+#: field:external.mapping,related_model_ids:0
+msgid "Related Inherited Models"
+msgstr "Liittyvät periytyvät mallit"
+
+#. module: base_external_referentials
+#: field:external.mapping.line,external_type:0
+#: field:external.mappinglines.template,external_type:0
+msgid "External Type"
+msgstr "Ulkoinen tyyppi"
+
+#. module: base_external_referentials
+#: selection:external.mapping.line,external_type:0
+#: selection:external.mappinglines.template,external_type:0
+msgid "String"
+msgstr "merkkijono"
+
+#. module: base_external_referentials
+#: field:external.mapping,external_list_method:0
+#: field:external.mapping.template,external_list_method:0
+msgid "List Method"
+msgstr "Listaus metodi"
+
+#. module: base_external_referentials
+#: model:ir.ui.menu,name:base_external_referentials.ir_ui_menu_extref0
+msgid "External Referentials"
+msgstr "Ulkoiset viittaukset"
+
+#. module: base_external_referentials
+#: model:ir.model,name:base_external_referentials.model_external_referential_type
+msgid "External Referential Type (Ex.Magento,Spree)"
+msgstr "Ulkoisten viittausten tyyppi (esim. Magneto.Spree)"
+
+#. module: base_external_referentials
+#: field:external.mapping.line,related_model_id:0
+msgid "Related Model"
+msgstr "Liittyvä malli"
+
+#. module: base_external_referentials
+#: field:ir.model.data,create_date:0
+msgid "Created date"
+msgstr "Luontipäivä"
+
+#. module: base_external_referentials
+#: field:external.referential,apiusername:0
+msgid "User Name"
+msgstr "Käyttäjätunnus"
+
+#. module: base_external_referentials
+#: help:external.mapping,related_model_ids:0
+msgid ""
+"potentially inherited through '_inherits' model, used for mapping field "
+"selection"
+msgstr ""
+"mahdollisesti peritty '_inherits' mallin kautta, käytetty kenttävalintojen "
+"mäppäykseen"
+
+#. module: base_external_referentials
+#: field:external.mapping,external_get_method:0
+#: field:external.mapping.template,external_get_method:0
+msgid "Get Method"
+msgstr "Hae metodi"
+
+#. module: base_external_referentials
+#: field:external.mapping,model:0
+#: field:external.mapping.template,model:0
+#: field:external.mappinglines.template,model:0
+msgid "Model Name"
+msgstr "Mallin nimi"
+
+#. module: base_external_referentials
+#: selection:external.mapping.line,external_type:0
+#: selection:external.mappinglines.template,external_type:0
+msgid "Integer"
+msgstr "kokonaisluku"
+
+#. module: base_external_referentials
+#: view:external.referential:0
+#: model:ir.model,name:base_external_referentials.model_external_mapping_line
+msgid "Field Mapping"
+msgstr "Kentän mäppäys"
+
+#. module: base_external_referentials
+#: model:ir.model,name:base_external_referentials.model_external_mapping_template
+msgid "The source mapping records"
+msgstr "Alkuperäiset mäppäykset"
+
+#. module: base_external_referentials
+#: model:ir.actions.act_window,name:base_external_referentials.ir_actions_act_window_externalreferential0
+msgid "external_referential"
+msgstr ""
+
+#. module: base_external_referentials
+#: constraint:ir.ui.view:0
+msgid "Invalid XML for View Architecture!"
+msgstr "Virheellinen XML näkymä-arkkitehtuurille!"
+
+#. module: base_external_referentials
+#: field:external.mapping.line,external_field:0
+#: field:external.mappinglines.template,external_field:0
+msgid "External Field"
+msgstr "Ulkoinen kenttä"
+
+#. module: base_external_referentials
+#: field:external.referential,name:0
+#: field:external.referential.type,name:0
+msgid "Name"
+msgstr "Nimi"
+
+#. module: base_external_referentials
+#: field:external.mapping.line,in_function:0
+#: field:external.mappinglines.template,in_function:0
+msgid "Import in OpenERP Mapping Python Function"
+msgstr "Tuo OpenERP python lauseke mäppäystä varten"
+
+#. module: base_external_referentials
+#: field:external.mapping,mapping_ids:0
+msgid "Mappings Lines"
+msgstr "Mäppäysrivit"
+
+#. module: base_external_referentials
+#: selection:external.mapping.line,type:0
+#: selection:external.mappinglines.template,type:0
+msgid "External -> OpenERP"
+msgstr "Ulkoisesta -> OpenERP"
+
+#. module: base_external_referentials
+#: model:ir.model,name:base_external_referentials.model_external_mappinglines_template
+msgid "The source mapping line records"
+msgstr "Alkuperäiset mäppäysrivit"
+
+#. module: base_external_referentials
+#: field:external.mapping,referential_id:0
+#: model:ir.model,name:base_external_referentials.model_external_referential
+msgid "External Referential"
+msgstr "Ulkoinen viittaus"
+
+#. module: base_external_referentials
+#: field:external.referential,type_id:0
+msgid "Referential Type"
+msgstr "Viittauksen tyyppi"
+
+#. module: base_external_referentials
+#: view:external.referential:0
+msgid "General"
+msgstr "Yleinen"
+
+#. module: base_external_referentials
+#: field:external.mapping,external_update_method:0
+#: field:external.mapping.template,external_update_method:0
+msgid "Update Method"
+msgstr "Päivitys menetelmä"
+
+#. module: base_external_referentials
+#: field:external.mapping.line,name_function:0
+msgid "Full Name"
+msgstr "Kokonimi"
+
+#. module: base_external_referentials
+#: view:external.referential:0
+msgid "Field Mappings"
+msgstr "Kenttien mäppäykset"
+
+#. module: base_external_referentials
+#: field:external.mapping,model_id:0
+#: field:external.mapping.template,model_id:0
+#: field:external.mappinglines.template,model_id:0
+msgid "OpenERP Model"
+msgstr "OpenERP malli"
+
+#. module: base_external_referentials
+#: field:external.mapping.line,out_function:0
+#: field:external.mappinglines.template,out_function:0
+msgid "Export from OpenERP Mapping Python Function"
+msgstr "Vie OpenERP python lauseke mäppäystä varten"
+
+#. module: base_external_referentials
+#: field:external.referential,apipass:0
+msgid "Password"
+msgstr "Salasana"
+
+#. module: base_external_referentials
+#: field:external.mapping.line,mapping_id:0
+#: model:ir.model,name:base_external_referentials.model_external_mapping
+msgid "External Mapping"
+msgstr "Ulkoinen mäppäys"
+
+#. module: base_external_referentials
+#: field:external.mapping.line,field_id:0
+msgid "OpenERP Field"
+msgstr "OpenERP kenttä"
+
+#. module: base_external_referentials
+#: field:external.mapping,external_create_method:0
+#: field:external.mapping.template,external_create_method:0
+msgid "Create Method"
+msgstr "Luo metodi"
+
+#. module: base_external_referentials
+#: selection:external.mapping.line,external_type:0
+#: selection:external.mappinglines.template,external_type:0
+msgid "Float"
+msgstr "Liukuluku"
+
+#. module: base_external_referentials
+#: field:external.mapping,external_key_name:0
+#: field:external.mapping.template,external_key_name:0
+msgid "External field used as key"
+msgstr "Ulkoinen kenttä jota käytetään avaimena"
+
+#. module: base_external_referentials
+#: field:external.mapping,external_delete_method:0
+#: field:external.mapping.template,external_delete_method:0
+msgid "Delete Method"
+msgstr "Poista metodi"
+
+#. module: base_external_referentials
+#: selection:external.mapping.line,external_type:0
+#: selection:external.mappinglines.template,external_type:0
+msgid "Boolean"
+msgstr "Totuusarvo"
+
+#. module: base_external_referentials
+#: field:ir.model.data,external_referential_id:0
+msgid "Ext. Referential"
+msgstr "Ulkoinen viittaus"
+
+#. module: base_external_referentials
+#: field:ir.model.data,write_date:0
+msgid "Updated date"
+msgstr "Päivityspäivä"
+
+#. module: base_external_referentials
+#: model:ir.module.module,description:base_external_referentials.module_meta_information
+msgid ""
+"\n"
+"This module provide an abstract common minimal base to add any additional "
+"external id columns\n"
+"to some OpenObject table, pointing to some external referential.\n"
+"A referential is abstract and minimal at this stage, it's only identified\n"
+"by:\n"
+"* a name\n"
+"* a location (possibly webservice URL, database connection URL...); the "
+"connection method will tell it...\n"
+"* referential credentials (user name + password)\n"
+"\n"
+"OpenERP already has limited supported to external ids using the "
+"ir_model_data and the id\n"
+"fields in the loaded data such as XML or CSV.\n"
+"The issue is that teh current system, while very useful to deal with "
+"internal OpenERP data has some\n"
+"limitations:\n"
+"* it doesn't scale well to whole production data because everything ends up "
+"into the ir_model_data\n"
+"* all the system is built with a using reference id in mind. But in fact you "
+"might want SEVERAL external ids.\n"
+"Say you sale your products over several websites (using the new Magento "
+"multi-instance connector for\n"
+"instance), then you want that each product have SEVERAL external id columns. "
+"This is exactly what\n"
+"this module enables!\n"
+" "
+msgstr ""
+
+#. module: base_external_referentials
+#: field:external.mapping.template,type_id:0
+#: field:external.mappinglines.template,type_id:0
+msgid "External Referential Type"
+msgstr "Ulkoisen viittauksen tyyppi"
+
+#. module: base_external_referentials
+#: selection:external.mapping.line,type:0
+#: selection:external.mappinglines.template,type:0
+msgid "External <-> OpenERP"
+msgstr "Ulkoinen <-> OpenERP"
=== added file 'base_external_referentials/i18n/pt.po'
--- base_external_referentials/i18n/pt.po 1970-01-01 00:00:00 +0000
+++ base_external_referentials/i18n/pt.po 2012-09-13 01:56:18 +0000
@@ -0,0 +1,382 @@
+# Portuguese translation for openobject-addons
+# Copyright (c) 2011 Rosetta Contributors and Canonical Ltd 2011
+# This file is distributed under the same license as the openobject-addons package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, 2011.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: openobject-addons\n"
+"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
+"POT-Creation-Date: 2009-12-20 17:21+0000\n"
+"PO-Revision-Date: 2011-02-14 10:04+0000\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: Portuguese <pt@xxxxxx>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Launchpad-Export-Date: 2012-01-17 05:05+0000\n"
+"X-Generator: Launchpad (build 14676)\n"
+
+#. module: base_external_referentials
+#: constraint:ir.model:0
+msgid ""
+"The Object name must start with x_ and not contain any special character !"
+msgstr ""
+"O nome do Objecto deve começar com x_ e não pode conter nenhum caracter "
+"especial !"
+
+#. module: base_external_referentials
+#: field:external.referential,mapping_ids:0
+msgid "Mappings"
+msgstr "Mapeamentos"
+
+#. module: base_external_referentials
+#: view:external.referential:0
+msgid "Object Mappings"
+msgstr "Mapeamento de Objectos"
+
+#. module: base_external_referentials
+#: view:external.referential:0
+msgid "Synchronize Referential Settings"
+msgstr "Sincronizar configurações Referênciais"
+
+#. module: base_external_referentials
+#: view:external.referential:0
+msgid "Authentication"
+msgstr "Autenticação"
+
+#. module: base_external_referentials
+#: field:external.referential,location:0
+msgid "Location"
+msgstr "Localização"
+
+#. module: base_external_referentials
+#: constraint:ir.actions.act_window:0
+msgid "Invalid model name in the action definition."
+msgstr "Nome do modelo inválido na definição da acção."
+
+#. module: base_external_referentials
+#: selection:external.mapping.line,type:0
+#: selection:external.mappinglines.template,type:0
+msgid "External <- OpenERP"
+msgstr "Externas <- OpenERP"
+
+#. module: base_external_referentials
+#: field:external.mapping.line,type:0
+#: field:external.mappinglines.template,type:0
+msgid "Type"
+msgstr "Tipo"
+
+#. module: base_external_referentials
+#: view:external.referential:0
+msgid "Reload Referential Mapping Templates"
+msgstr "Recarregar Modelos de Mapeamento Referenciais"
+
+#. module: base_external_referentials
+#: model:ir.module.module,shortdesc:base_external_referentials.module_meta_information
+msgid "Base External Referentials"
+msgstr "Base Referenciais Externas"
+
+#. module: base_external_referentials
+#: field:external.mapping,related_model_ids:0
+msgid "Related Inherited Models"
+msgstr "Modelo Herdado Relacionado"
+
+#. module: base_external_referentials
+#: field:external.mapping.line,external_type:0
+#: field:external.mappinglines.template,external_type:0
+msgid "External Type"
+msgstr "Tipo Externo"
+
+#. 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.mapping,external_list_method:0
+#: field:external.mapping.template,external_list_method:0
+msgid "List Method"
+msgstr "Método Lista"
+
+#. module: base_external_referentials
+#: model:ir.ui.menu,name:base_external_referentials.ir_ui_menu_extref0
+msgid "External Referentials"
+msgstr "Referenciais Externas"
+
+#. module: base_external_referentials
+#: model:ir.model,name:base_external_referentials.model_external_referential_type
+msgid "External Referential Type (Ex.Magento,Spree)"
+msgstr "Tipo Referencial Externo (Ex.Magento,Spree)"
+
+#. module: base_external_referentials
+#: field:external.mapping.line,related_model_id:0
+msgid "Related Model"
+msgstr "Modelo Relacionado"
+
+#. module: base_external_referentials
+#: field:ir.model.data,create_date:0
+msgid "Created date"
+msgstr "Data criada"
+
+#. module: base_external_referentials
+#: field:external.referential,apiusername:0
+msgid "User Name"
+msgstr "Nome de Utilizador"
+
+#. module: base_external_referentials
+#: help:external.mapping,related_model_ids:0
+msgid ""
+"potentially inherited through '_inherits' model, used for mapping field "
+"selection"
+msgstr ""
+"potencialmente herdado mediante modelos '_inherits', utilizado para "
+"mapeamentos de campo de selecção"
+
+#. module: base_external_referentials
+#: field:external.mapping,external_get_method:0
+#: field:external.mapping.template,external_get_method:0
+msgid "Get Method"
+msgstr "Obter Método"
+
+#. module: base_external_referentials
+#: field:external.mapping,model:0
+#: field:external.mapping.template,model:0
+#: field:external.mappinglines.template,model:0
+msgid "Model Name"
+msgstr "Nome do Modelo"
+
+#. module: base_external_referentials
+#: selection:external.mapping.line,external_type:0
+#: selection:external.mappinglines.template,external_type:0
+msgid "Integer"
+msgstr "Inteiro"
+
+#. module: base_external_referentials
+#: view:external.referential:0
+#: model:ir.model,name:base_external_referentials.model_external_mapping_line
+msgid "Field Mapping"
+msgstr "Mapeamento de Campo"
+
+#. module: base_external_referentials
+#: model:ir.model,name:base_external_referentials.model_external_mapping_template
+msgid "The source mapping records"
+msgstr "A origem das gravações de mapeamento"
+
+#. module: base_external_referentials
+#: model:ir.actions.act_window,name:base_external_referentials.ir_actions_act_window_externalreferential0
+msgid "external_referential"
+msgstr "Referencial_externas"
+
+#. module: base_external_referentials
+#: constraint:ir.ui.view:0
+msgid "Invalid XML for View Architecture!"
+msgstr "XML Inválido para a Arquitectura de Vista!"
+
+#. module: base_external_referentials
+#: field:external.mapping.line,external_field:0
+#: field:external.mappinglines.template,external_field:0
+msgid "External Field"
+msgstr "Campo Externo"
+
+#. module: base_external_referentials
+#: field:external.referential,name:0
+#: field:external.referential.type,name:0
+msgid "Name"
+msgstr "Nome"
+
+#. module: base_external_referentials
+#: field:external.mapping.line,in_function:0
+#: field:external.mappinglines.template,in_function:0
+msgid "Import in OpenERP Mapping Python Function"
+msgstr "Importar em OpenERP Função Python de Mapeamento"
+
+#. module: base_external_referentials
+#: field:external.mapping,mapping_ids:0
+msgid "Mappings Lines"
+msgstr "Linhas de Mapeamento"
+
+#. module: base_external_referentials
+#: selection:external.mapping.line,type:0
+#: selection:external.mappinglines.template,type:0
+msgid "External -> OpenERP"
+msgstr "Externo -> OpenERP"
+
+#. module: base_external_referentials
+#: model:ir.model,name:base_external_referentials.model_external_mappinglines_template
+msgid "The source mapping line records"
+msgstr "A origem da linha de gravações de mapeamento"
+
+#. module: base_external_referentials
+#: field:external.mapping,referential_id:0
+#: model:ir.model,name:base_external_referentials.model_external_referential
+msgid "External Referential"
+msgstr "Referencial Externo"
+
+#. module: base_external_referentials
+#: field:external.referential,type_id:0
+msgid "Referential Type"
+msgstr "Tipo Referencial"
+
+#. module: base_external_referentials
+#: view:external.referential:0
+msgid "General"
+msgstr "Geral"
+
+#. module: base_external_referentials
+#: field:external.mapping,external_update_method:0
+#: field:external.mapping.template,external_update_method:0
+msgid "Update Method"
+msgstr "Método Actualizado"
+
+#. module: base_external_referentials
+#: field:external.mapping.line,name_function:0
+msgid "Full Name"
+msgstr "Nome Completo"
+
+#. module: base_external_referentials
+#: view:external.referential:0
+msgid "Field Mappings"
+msgstr "Mapeamento de Campos"
+
+#. module: base_external_referentials
+#: field:external.mapping,model_id:0
+#: field:external.mapping.template,model_id:0
+#: field:external.mappinglines.template,model_id:0
+msgid "OpenERP Model"
+msgstr "Modelo OpenERP"
+
+#. module: base_external_referentials
+#: field:external.mapping.line,out_function:0
+#: field:external.mappinglines.template,out_function:0
+msgid "Export from OpenERP Mapping Python Function"
+msgstr "Exportar a partir do OpenERP Função Python de Mapeamento"
+
+#. module: base_external_referentials
+#: field:external.referential,apipass:0
+msgid "Password"
+msgstr "Palavra Passe"
+
+#. module: base_external_referentials
+#: field:external.mapping.line,mapping_id:0
+#: model:ir.model,name:base_external_referentials.model_external_mapping
+msgid "External Mapping"
+msgstr "Mapeamento Externo"
+
+#. module: base_external_referentials
+#: field:external.mapping.line,field_id:0
+msgid "OpenERP Field"
+msgstr "Campo OpenERP"
+
+#. module: base_external_referentials
+#: field:external.mapping,external_create_method:0
+#: field:external.mapping.template,external_create_method:0
+msgid "Create Method"
+msgstr "Criar Método"
+
+#. 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.mapping,external_key_name:0
+#: field:external.mapping.template,external_key_name:0
+msgid "External field used as key"
+msgstr "Campo Externas usado como chave"
+
+#. module: base_external_referentials
+#: field:external.mapping,external_delete_method:0
+#: field:external.mapping.template,external_delete_method:0
+msgid "Delete Method"
+msgstr "Método Apagado"
+
+#. module: base_external_referentials
+#: selection:external.mapping.line,external_type:0
+#: selection:external.mappinglines.template,external_type:0
+msgid "Boolean"
+msgstr "Boleano"
+
+#. module: base_external_referentials
+#: field:ir.model.data,external_referential_id:0
+msgid "Ext. Referential"
+msgstr "Ext. Referencial"
+
+#. module: base_external_referentials
+#: field:ir.model.data,write_date:0
+msgid "Updated date"
+msgstr "Data actualizado"
+
+#. module: base_external_referentials
+#: model:ir.module.module,description:base_external_referentials.module_meta_information
+msgid ""
+"\n"
+"This module provide an abstract common minimal base to add any additional "
+"external id columns\n"
+"to some OpenObject table, pointing to some external referential.\n"
+"A referential is abstract and minimal at this stage, it's only identified\n"
+"by:\n"
+"* a name\n"
+"* a location (possibly webservice URL, database connection URL...); the "
+"connection method will tell it...\n"
+"* referential credentials (user name + password)\n"
+"\n"
+"OpenERP already has limited supported to external ids using the "
+"ir_model_data and the id\n"
+"fields in the loaded data such as XML or CSV.\n"
+"The issue is that teh current system, while very useful to deal with "
+"internal OpenERP data has some\n"
+"limitations:\n"
+"* it doesn't scale well to whole production data because everything ends up "
+"into the ir_model_data\n"
+"* all the system is built with a using reference id in mind. But in fact you "
+"might want SEVERAL external ids.\n"
+"Say you sale your products over several websites (using the new Magento "
+"multi-instance connector for\n"
+"instance), then you want that each product have SEVERAL external id columns. "
+"This is exactly what\n"
+"this module enables!\n"
+" "
+msgstr ""
+"\n"
+"Este módulo fornecem uma mínina base de abstração comum para adicionar "
+"alguma identificação de colunas externas\n"
+"a algumas tabelas OpenObject, para que apontem algumas referências "
+"externas.\n"
+"Um referencial é abstrata e mínima nesta fase, só é identificado\n"
+"por:\n"
+"* um nome\n"
+"* uma localização (possibilidade de URL webservice,URL da conecção á base de "
+"dados...); o método de conexão vai contá-la...\n"
+"* credenciais referenciais (nome de utilizador + palavra passe)\n"
+"\n"
+"OpenERP já tem suporte limitado para identificação externa utilizando a "
+"identificação ir_model_data\n"
+"e campos de dados carregados, como XML ou CSV.\n"
+"A questão é que o sistema actual, e muito útil para lidar com dados internos "
+"e OpenERP tem algumas\n"
+"limitações:\n"
+"*não escala bem aos dados de produção inteira, porque tudo termina na "
+"ir_model_data\n"
+"* Todo o sistema é construído com uma identificação de referência em mente. "
+"Mas na verdade pode querer várias identificações externas.\n"
+"Digamos que venda o seu produto ao longo de vários sites (utilizando o novo "
+"conector Magento multi-instância por\n"
+"exemplo), então quer que cada produto tem várias colunas de identificações "
+"externas. Isto é exatamente o que \n"
+"este módulo permite!\n"
+" "
+
+#. module: base_external_referentials
+#: field:external.mapping.template,type_id:0
+#: field:external.mappinglines.template,type_id:0
+msgid "External Referential Type"
+msgstr "Tipo Referencial Externo"
+
+#. module: base_external_referentials
+#: selection:external.mapping.line,type:0
+#: selection:external.mappinglines.template,type:0
+msgid "External <-> OpenERP"
+msgstr "Externo <-> OpenERP"
=== added file 'base_external_referentials/i18n/sv.po'
--- base_external_referentials/i18n/sv.po 1970-01-01 00:00:00 +0000
+++ base_external_referentials/i18n/sv.po 2012-09-13 01:56:18 +0000
@@ -0,0 +1,349 @@
+# Translation of OpenERP Server.
+# This file contains the translation of the following modules:
+# * base_external_referentials
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: OpenERP Server 5.0.14\n"
+"Report-Msgid-Bugs-To: support@xxxxxxxxxxx\n"
+"POT-Creation-Date: 2009-12-20 17:21+0000\n"
+"PO-Revision-Date: 2011-02-14 11:51+0000\n"
+"Last-Translator: Olivier Dony (OpenERP) <Unknown>\n"
+"Language-Team: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Launchpad-Export-Date: 2012-01-17 05:05+0000\n"
+"X-Generator: Launchpad (build 14676)\n"
+
+#. module: base_external_referentials
+#: constraint:ir.model:0
+msgid ""
+"The Object name must start with x_ and not contain any special character !"
+msgstr ""
+
+#. module: base_external_referentials
+#: field:external.referential,mapping_ids:0
+msgid "Mappings"
+msgstr ""
+
+#. module: base_external_referentials
+#: view:external.referential:0
+msgid "Object Mappings"
+msgstr ""
+
+#. module: base_external_referentials
+#: view:external.referential:0
+msgid "Synchronize Referential Settings"
+msgstr ""
+
+#. module: base_external_referentials
+#: view:external.referential:0
+msgid "Authentication"
+msgstr ""
+
+#. module: base_external_referentials
+#: field:external.referential,location:0
+msgid "Location"
+msgstr ""
+
+#. module: base_external_referentials
+#: constraint:ir.actions.act_window:0
+msgid "Invalid model name in the action definition."
+msgstr ""
+
+#. module: base_external_referentials
+#: selection:external.mapping.line,type:0
+#: selection:external.mappinglines.template,type:0
+msgid "External <- OpenERP"
+msgstr ""
+
+#. module: base_external_referentials
+#: field:external.mapping.line,type:0
+#: field:external.mappinglines.template,type:0
+msgid "Type"
+msgstr ""
+
+#. module: base_external_referentials
+#: view:external.referential:0
+msgid "Reload Referential Mapping Templates"
+msgstr ""
+
+#. module: base_external_referentials
+#: model:ir.module.module,shortdesc:base_external_referentials.module_meta_information
+msgid "Base External Referentials"
+msgstr "Base External Referentials"
+
+#. module: base_external_referentials
+#: field:external.mapping,related_model_ids:0
+msgid "Related Inherited Models"
+msgstr ""
+
+#. module: base_external_referentials
+#: field:external.mapping.line,external_type:0
+#: field:external.mappinglines.template,external_type:0
+msgid "External Type"
+msgstr ""
+
+#. module: base_external_referentials
+#: selection:external.mapping.line,external_type:0
+#: selection:external.mappinglines.template,external_type:0
+msgid "String"
+msgstr ""
+
+#. module: base_external_referentials
+#: field:external.mapping,external_list_method:0
+#: field:external.mapping.template,external_list_method:0
+msgid "List Method"
+msgstr ""
+
+#. module: base_external_referentials
+#: model:ir.ui.menu,name:base_external_referentials.ir_ui_menu_extref0
+msgid "External Referentials"
+msgstr ""
+
+#. module: base_external_referentials
+#: model:ir.model,name:base_external_referentials.model_external_referential_type
+msgid "External Referential Type (Ex.Magento,Spree)"
+msgstr ""
+
+#. module: base_external_referentials
+#: field:external.mapping.line,related_model_id:0
+msgid "Related Model"
+msgstr ""
+
+#. module: base_external_referentials
+#: field:ir.model.data,create_date:0
+msgid "Created date"
+msgstr ""
+
+#. module: base_external_referentials
+#: field:external.referential,apiusername:0
+msgid "User Name"
+msgstr ""
+
+#. module: base_external_referentials
+#: help:external.mapping,related_model_ids:0
+msgid ""
+"potentially inherited through '_inherits' model, used for mapping field "
+"selection"
+msgstr ""
+
+#. module: base_external_referentials
+#: field:external.mapping,external_get_method:0
+#: field:external.mapping.template,external_get_method:0
+msgid "Get Method"
+msgstr ""
+
+#. module: base_external_referentials
+#: field:external.mapping,model:0
+#: field:external.mapping.template,model:0
+#: field:external.mappinglines.template,model:0
+msgid "Model Name"
+msgstr ""
+
+#. module: base_external_referentials
+#: selection:external.mapping.line,external_type:0
+#: selection:external.mappinglines.template,external_type:0
+msgid "Integer"
+msgstr ""
+
+#. module: base_external_referentials
+#: view:external.referential:0
+#: model:ir.model,name:base_external_referentials.model_external_mapping_line
+msgid "Field Mapping"
+msgstr ""
+
+#. module: base_external_referentials
+#: model:ir.model,name:base_external_referentials.model_external_mapping_template
+msgid "The source mapping records"
+msgstr ""
+
+#. module: base_external_referentials
+#: model:ir.actions.act_window,name:base_external_referentials.ir_actions_act_window_externalreferential0
+msgid "external_referential"
+msgstr ""
+
+#. module: base_external_referentials
+#: constraint:ir.ui.view:0
+msgid "Invalid XML for View Architecture!"
+msgstr ""
+
+#. module: base_external_referentials
+#: field:external.mapping.line,external_field:0
+#: field:external.mappinglines.template,external_field:0
+msgid "External Field"
+msgstr ""
+
+#. module: base_external_referentials
+#: field:external.referential,name:0
+#: field:external.referential.type,name:0
+msgid "Name"
+msgstr ""
+
+#. module: base_external_referentials
+#: field:external.mapping.line,in_function:0
+#: field:external.mappinglines.template,in_function:0
+msgid "Import in OpenERP Mapping Python Function"
+msgstr ""
+
+#. module: base_external_referentials
+#: field:external.mapping,mapping_ids:0
+msgid "Mappings Lines"
+msgstr ""
+
+#. module: base_external_referentials
+#: selection:external.mapping.line,type:0
+#: selection:external.mappinglines.template,type:0
+msgid "External -> OpenERP"
+msgstr ""
+
+#. module: base_external_referentials
+#: model:ir.model,name:base_external_referentials.model_external_mappinglines_template
+msgid "The source mapping line records"
+msgstr ""
+
+#. module: base_external_referentials
+#: field:external.mapping,referential_id:0
+#: model:ir.model,name:base_external_referentials.model_external_referential
+msgid "External Referential"
+msgstr ""
+
+#. module: base_external_referentials
+#: field:external.referential,type_id:0
+msgid "Referential Type"
+msgstr ""
+
+#. module: base_external_referentials
+#: view:external.referential:0
+msgid "General"
+msgstr ""
+
+#. module: base_external_referentials
+#: field:external.mapping,external_update_method:0
+#: field:external.mapping.template,external_update_method:0
+msgid "Update Method"
+msgstr ""
+
+#. module: base_external_referentials
+#: field:external.mapping.line,name_function:0
+msgid "Full Name"
+msgstr ""
+
+#. module: base_external_referentials
+#: view:external.referential:0
+msgid "Field Mappings"
+msgstr ""
+
+#. module: base_external_referentials
+#: field:external.mapping,model_id:0
+#: field:external.mapping.template,model_id:0
+#: field:external.mappinglines.template,model_id:0
+msgid "OpenERP Model"
+msgstr ""
+
+#. module: base_external_referentials
+#: field:external.mapping.line,out_function:0
+#: field:external.mappinglines.template,out_function:0
+msgid "Export from OpenERP Mapping Python Function"
+msgstr ""
+
+#. module: base_external_referentials
+#: field:external.referential,apipass:0
+msgid "Password"
+msgstr ""
+
+#. module: base_external_referentials
+#: field:external.mapping.line,mapping_id:0
+#: model:ir.model,name:base_external_referentials.model_external_mapping
+msgid "External Mapping"
+msgstr ""
+
+#. module: base_external_referentials
+#: field:external.mapping.line,field_id:0
+msgid "OpenERP Field"
+msgstr ""
+
+#. module: base_external_referentials
+#: field:external.mapping,external_create_method:0
+#: field:external.mapping.template,external_create_method:0
+msgid "Create Method"
+msgstr ""
+
+#. module: base_external_referentials
+#: selection:external.mapping.line,external_type:0
+#: selection:external.mappinglines.template,external_type:0
+msgid "Float"
+msgstr ""
+
+#. module: base_external_referentials
+#: field:external.mapping,external_key_name:0
+#: field:external.mapping.template,external_key_name:0
+msgid "External field used as key"
+msgstr ""
+
+#. module: base_external_referentials
+#: field:external.mapping,external_delete_method:0
+#: field:external.mapping.template,external_delete_method:0
+msgid "Delete Method"
+msgstr ""
+
+#. module: base_external_referentials
+#: selection:external.mapping.line,external_type:0
+#: selection:external.mappinglines.template,external_type:0
+msgid "Boolean"
+msgstr ""
+
+#. module: base_external_referentials
+#: field:ir.model.data,external_referential_id:0
+msgid "Ext. Referential"
+msgstr ""
+
+#. module: base_external_referentials
+#: field:ir.model.data,write_date:0
+msgid "Updated date"
+msgstr ""
+
+#. module: base_external_referentials
+#: model:ir.module.module,description:base_external_referentials.module_meta_information
+msgid ""
+"\n"
+"This module provide an abstract common minimal base to add any additional "
+"external id columns\n"
+"to some OpenObject table, pointing to some external referential.\n"
+"A referential is abstract and minimal at this stage, it's only identified\n"
+"by:\n"
+"* a name\n"
+"* a location (possibly webservice URL, database connection URL...); the "
+"connection method will tell it...\n"
+"* referential credentials (user name + password)\n"
+"\n"
+"OpenERP already has limited supported to external ids using the "
+"ir_model_data and the id\n"
+"fields in the loaded data such as XML or CSV.\n"
+"The issue is that teh current system, while very useful to deal with "
+"internal OpenERP data has some\n"
+"limitations:\n"
+"* it doesn't scale well to whole production data because everything ends up "
+"into the ir_model_data\n"
+"* all the system is built with a using reference id in mind. But in fact you "
+"might want SEVERAL external ids.\n"
+"Say you sale your products over several websites (using the new Magento "
+"multi-instance connector for\n"
+"instance), then you want that each product have SEVERAL external id columns. "
+"This is exactly what\n"
+"this module enables!\n"
+" "
+msgstr ""
+
+#. module: base_external_referentials
+#: field:external.mapping.template,type_id:0
+#: field:external.mappinglines.template,type_id:0
+msgid "External Referential Type"
+msgstr ""
+
+#. module: base_external_referentials
+#: selection:external.mapping.line,type:0
+#: selection:external.mappinglines.template,type:0
+msgid "External <-> OpenERP"
+msgstr ""
=== added file 'base_external_referentials/i18n/zh_CN.po'
--- base_external_referentials/i18n/zh_CN.po 1970-01-01 00:00:00 +0000
+++ base_external_referentials/i18n/zh_CN.po 2012-09-13 01:56:18 +0000
@@ -0,0 +1,1013 @@
+# 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-20120809-233316\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2012-09-07 08:17+0000\n"
+"PO-Revision-Date: 2012-09-07 08:17+0000\n"
+"Last-Translator: Jeff Wang(ShineIT)<jeff@xxxxxxxxxx>\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
+#: sql_constraint:ir.model.data:0
+msgid "You cannot have on record with multiple external id for a sae referential"
+msgstr "不能为一条记录指定多个外部系统ID"
+
+#. module: base_external_referentials
+#: view:external.mapping.line:0
+msgid "Mapping line"
+msgstr "映射行"
+
+#. module: base_external_referentials
+#: field:external.mapping.line,selected:0
+msgid "Selected"
+msgstr "已选"
+
+#. module: base_external_referentials
+#: view:external.referential:0
+msgid "Authentication"
+msgstr "验证"
+
+#. module: base_external_referentials
+#: model:ir.ui.menu,name:base_external_referentials.menu_all_external_referential
+msgid "All Referentials"
+msgstr "所有外部系统"
+
+#. 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 "当导入csv文件的时候,可以把此字段留空,因为这个字段不在你的csv文件里"
+
+#. module: base_external_referentials
+#: model:ir.model,name:base_external_referentials.model_external_referential_type
+msgid "External Referential Type (Ex.Magento,Spree)"
+msgstr "外部系统类型 (例如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 "组字段"
+
+#. module: base_external_referentials
+#: view:external.referential:0
+msgid "CSV file generation"
+msgstr "生成CSV文件"
+
+#. module: base_external_referentials
+#: model:ir.actions.act_window,name:base_external_referentials.ext_external_shop_group
+msgid "External External Referential Shop Group"
+msgstr "外部系统商店组"
+
+#. module: base_external_referentials
+#: view:external.report.line:0
+msgid "Action On Model"
+msgstr "模型上的动作"
+
+#. module: base_external_referentials
+#: field:external.report.line,args:0
+msgid "Args"
+msgstr "参数"
+
+#. 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 "同一个模块中不能有两个xml ID相同的记录"
+
+#. module: base_external_referentials
+#: field:external.mapping.line,related_model_id:0
+msgid "Related Model"
+msgstr "相关模型"
+
+#. module: base_external_referentials
+#: help:external.mapping,related_model_ids:0
+msgid "potentially inherited through '_inherits' model, used for mapping field selection"
+msgstr "用 '_inherits' 关键字来集成的模型,用于选择映射字段"
+
+#. module: base_external_referentials
+#: field:external.mapping,model:0
+#: field:external.mapping.template,model:0
+msgid "Model Name"
+msgstr "模型名称"
+
+#. module: base_external_referentials
+#: field:external.report,history_ids:0
+msgid "History"
+msgstr "历史"
+
+#. module: base_external_referentials
+#: model:ir.actions.act_window,name:base_external_referentials.ext_product_category
+msgid "External Product Category"
+msgstr "外部系统产品类别"
+
+#. module: base_external_referentials
+#: view:external.report:0
+msgid "Retry All Failed"
+msgstr "重试已失败的"
+
+#. module: base_external_referentials
+#: model:ir.model,name:base_external_referentials.model_external_mapping_template
+msgid "The source mapping records"
+msgstr "映射的源模型"
+
+#. module: base_external_referentials
+#: view:external.referential.type:0
+msgid "External Referential Types"
+msgstr "外部系统类型"
+
+#. module: base_external_referentials
+#: field:external.referential.type,code:0
+#: field:external.referential.version,code:0
+msgid "code"
+msgstr "编码"
+
+#. 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 "外部系统映射行"
+
+#. module: base_external_referentials
+#: field:external.referential,categ_id:0
+msgid "External Category"
+msgstr "外部系统类别"
+
+#. module: base_external_referentials
+#: model:ir.model,name:base_external_referentials.model_ir_model
+msgid "Models"
+msgstr "模型"
+
+#. 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 "外部系统类别(例如: 电子商务, CRM, 库存管理)"
+
+#. module: base_external_referentials
+#: view:external.mapping.line:0
+msgid "Other Information"
+msgstr "其他信息"
+
+#. module: base_external_referentials
+#: field:external.referential,debug:0
+msgid "Debug"
+msgstr "排错"
+
+#. module: base_external_referentials
+#: view:external.report.history:0
+#: view:external.report.line:0
+msgid "Failures"
+msgstr "失败信息"
+
+#. module: base_external_referentials
+#: model:ir.model,name:base_external_referentials.model_external_mappinglines_template
+msgid "The source mapping line records"
+msgstr "源映射行记录"
+
+#. module: base_external_referentials
+#: view:external.referential:0
+msgid "2- Export type"
+msgstr "2- 导出分类"
+
+#. module: base_external_referentials
+#: field:external.mapping,external_done_method:0
+#: field:external.mapping.template,external_done_method:0
+msgid "Done Method"
+msgstr "已完成的方法"
+
+#. module: base_external_referentials
+#: field:external.referential.version,name:0
+msgid "name"
+msgstr "名称"
+
+#. module: base_external_referentials
+#: constraint:external.referential:0
+msgid "The name cannot contain a dot!"
+msgstr "名称不能包含小数点!"
+
+#. 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 "外部系统类型"
+
+#. module: base_external_referentials
+#: field:external.mapping,related_model_ids:0
+msgid "Related Inherited Models"
+msgstr "相关继承模型"
+
+#. module: base_external_referentials
+#: view:external.report:0
+msgid "External Referential Reports"
+msgstr "外部系统报告"
+
+#. module: base_external_referentials
+#: field:external.mapping,external_create_method:0
+#: field:external.mapping.template,external_create_method:0
+msgid "Create Method"
+msgstr "创建方法"
+
+#. module: base_external_referentials
+#: selection:external.mapping.line,external_type:0
+#: selection:external.mappinglines.template,external_type:0
+msgid "Datetime"
+msgstr "日期时间"
+
+#. module: base_external_referentials
+#: field:ir.model.data,referential_id:0
+msgid "Ext. Referential"
+msgstr "外部系统"
+
+#. module: base_external_referentials
+#: help:external.mapping.line,selected:0
+msgid "to select for mapping"
+msgstr "选定映射"
+
+#. module: base_external_referentials
+#: field:external.referential,version_id:0
+msgid "Referential Version"
+msgstr "外部系统版本"
+
+#. module: base_external_referentials
+#: field:external.report,sync_from_object_model:0
+msgid "Sync From Object"
+msgstr "从此对象同步"
+
+#. module: base_external_referentials
+#: view:external.report.line:0
+msgid "Retry"
+msgstr "重试"
+
+#. module: base_external_referentials
+#: selection:external.report.line,state:0
+msgid "Failed"
+msgstr "已失败的"
+
+#. module: base_external_referentials
+#: view:external.mapping:0
+#: field:external.mapping.line,referential_id:0
+msgid "Referential"
+msgstr "外部系统"
+
+#. module: base_external_referentials
+#: view:external.referential:0
+msgid "Referential Actions"
+msgstr "外部系统动作"
+
+#. module: base_external_referentials
+#: field:external.referential,location:0
+msgid "Location"
+msgstr "网址"
+
+#. module: base_external_referentials
+#: selection:external.mapping.line,evaluation_type:0
+#: selection:external.mappinglines.template,evaluation_type:0
+msgid "Sub Mapping Line"
+msgstr "子映射行"
+
+#. module: base_external_referentials
+#: field:external.report,failed_line_ids:0
+msgid "Failed Report Lines"
+msgstr "已失败的报告行"
+
+#. module: base_external_referentials
+#: selection:external.mapping.line,external_type:0
+#: selection:external.mappinglines.template,external_type:0
+msgid "Dictionnary"
+msgstr "字典"
+
+#. module: base_external_referentials
+#: view:external.referential:0
+msgid "2 - Synchronize Referential Settings"
+msgstr "2 - 同步外部系统设置"
+
+#. 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 "类型"
+
+#. module: base_external_referentials
+#: field:external.mapping.line,field_id:0
+#: field:external.mappinglines.template,field_id:0
+msgid "OpenERP Field"
+msgstr "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 "名称"
+
+#. module: base_external_referentials
+#: selection:external.mapping.line,type:0
+#: selection:external.mappinglines.template,type:0
+msgid "External -> OpenERP"
+msgstr "外部系统到OpenERP"
+
+#. module: base_external_referentials
+#: selection:external.mapping.line,external_type:0
+#: selection:external.mappinglines.template,external_type:0
+msgid "String"
+msgstr "字符串"
+
+#. module: base_external_referentials
+#: field:external.referential,create_date:0
+msgid "Creation Date"
+msgstr "创建日期"
+
+#. module: base_external_referentials
+#: view:external.report.line:0
+#: field:external.report.line,error_message:0
+msgid "Error Message"
+msgstr "错误信息"
+
+#. module: base_external_referentials
+#: field:ir.model.fields,group_fields_id:0
+msgid "Trigger Group"
+msgstr "触发组"
+
+#. module: base_external_referentials
+#: model:ir.actions.act_window,name:base_external_referentials.ext_magerp_storeviews
+msgid "External The magento store views information"
+msgstr "外部系统Magento店铺信息"
+
+#. module: base_external_referentials
+#: field:external.mapping,external_get_method:0
+#: field:external.mapping.template,external_get_method:0
+msgid "Get Method"
+msgstr "Get方法"
+
+#. module: base_external_referentials
+#: view:external.report.history:0
+#: view:external.report.line:0
+msgid "Report"
+msgstr "报告"
+
+#. module: base_external_referentials
+#: field:external.mapping,extra_name:0
+#: field:external.mapping.template,extra_name:0
+msgid "Extra Name"
+msgstr "别名"
+
+#. module: base_external_referentials
+#: view:external.mapping.line:0
+msgid "Internal fields"
+msgstr "内部字段"
+
+#. module: base_external_referentials
+#: model:ir.model,name:base_external_referentials.model_external_mapping_line
+msgid "Field Mapping"
+msgstr "字段映射"
+
+#. module: base_external_referentials
+#: model:ir.ui.menu,name:base_external_referentials.ir_ui_menu_group_fields
+msgid "Group Fields"
+msgstr "Group Fields"
+
+#. module: base_external_referentials
+#: model:ir.actions.act_window,name:base_external_referentials.ext_sale_shop
+msgid "External Sales Shop"
+msgstr "外部系统门店"
+
+#. module: base_external_referentials
+#: field:external.mapping,template_id:0
+msgid "External Mapping Template"
+msgstr "外部系统映射模版"
+
+#. module: base_external_referentials
+#: field:external.referential.type,version_ids:0
+msgid "Versions"
+msgstr "版本"
+
+#. 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 "外部系统报告"
+
+#. module: base_external_referentials
+#: field:external.mapping,mapping_ids:0
+msgid "Mappings Lines"
+msgstr "外部系统行"
+
+#. 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 "External <- 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 "External Referential"
+
+#. module: base_external_referentials
+#: field:external.mapping.line,child_mapping_id:0
+#: field:external.mappinglines.template,child_mapping_id:0
+msgid "Child Mapping"
+msgstr "Child Mapping"
+
+#. module: base_external_referentials
+#: view:external.referential:0
+msgid "General"
+msgstr "General"
+
+#. 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 "External Data"
+
+#. module: base_external_referentials
+#: view:external.mapping.line:0
+#: field:external.referential.version,full_name:0
+msgid "Full Name"
+msgstr "Full Name"
+
+#. module: base_external_referentials
+#: field:external.referential,categ_name:0
+msgid "External Category Name"
+msgstr "External Category Name"
+
+#. 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 "Core Components"
+
+#. 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 "A referential can not have various mapping line imported from the same template mapping line"
+
+#. module: base_external_referentials
+#: view:external.referential:0
+msgid "6- Export mapping lines"
+msgstr "6- Export mapping lines"
+
+#. module: base_external_referentials
+#: model:ir.actions.act_window,name:base_external_referentials.ext_magerp_product_attributes
+msgid "External Attributes of products"
+msgstr "External Attributes of products"
+
+#. 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 "Group by..."
+
+#. module: base_external_referentials
+#: field:external.mapping,external_resource_name:0
+#: field:external.mapping.template,external_resource_name:0
+msgid "External Resource Name"
+msgstr "External Resource Name"
+
+#. module: base_external_referentials
+#: sql_constraint:external.mapping:0
+msgid "A referential can not have various mapping imported from the same template"
+msgstr "A referential can not have various mapping imported from the same template"
+
+#. module: base_external_referentials
+#: field:external.report.history,start_date:0
+msgid "Start Date"
+msgstr "Start Date"
+
+#. module: base_external_referentials
+#: model:ir.actions.act_window,name:base_external_referentials.ext_res_partner_address
+msgid "External Partner Addresses"
+msgstr "External Partner Addresses"
+
+#. module: base_external_referentials
+#: selection:external.mapping.line,type:0
+#: selection:external.mappinglines.template,type:0
+msgid "External <-> OpenERP"
+msgstr "External <-> OpenERP"
+
+#. module: base_external_referentials
+#: view:external.referential:0
+#: field:external.referential.type,categ_id:0
+msgid "Category"
+msgstr "Category"
+
+#. module: base_external_referentials
+#: field:external.referential,mapping_ids:0
+msgid "Mappings"
+msgstr "Mappings"
+
+#. module: base_external_referentials
+#: view:external.mapping:0
+#: view:external.referential:0
+msgid "Object Mappings"
+msgstr "Object Mappings"
+
+#. 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
+#: model:ir.actions.act_window,name:base_external_referentials.ext_product_link
+msgid "External product.link"
+msgstr "External product.link"
+
+#. module: base_external_referentials
+#: field:external.mapping,external_search_method:0
+#: field:external.mapping.template,external_search_method:0
+msgid "Search Method"
+msgstr "Search Method"
+
+#. module: base_external_referentials
+#: model:ir.actions.act_window,name:base_external_referentials.ext_res_partner
+msgid "External Partner"
+msgstr "External Partner"
+
+#. 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 "External Report History"
+
+#. 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 "External Product"
+
+#. 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 "每个模型都必须唯一!"
+
+#. module: base_external_referentials
+#: field:external.mapping.template,version_id:0
+#: field:external.mappinglines.template,version_id:0
+msgid "External Referential Version"
+msgstr "External Referential Version"
+
+#. module: base_external_referentials
+#: sql_constraint:external.referential:0
+msgid "Referential names must be unique !"
+msgstr "外部系统名称必须唯一 !"
+
+#. module: base_external_referentials
+#: field:external.mapping,external_list_method:0
+#: field:external.mapping.template,external_list_method:0
+msgid "List Method"
+msgstr "List Method"
+
+#. 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 "外部系统"
+
+#. 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 "作为关键字的外部字段"
+
+#. module: base_external_referentials
+#: view:external.referential:0
+msgid "1 - Reload Referential Mapping Templates"
+msgstr "1 - 重新载入外部系统映射模版"
+
+#. module: base_external_referentials
+#: field:external.referential,apiusername:0
+msgid "User Name"
+msgstr "用户名"
+
+#. module: base_external_referentials
+#: view:external.referential:0
+msgid "1- Export category"
+msgstr "1- 导出类别"
+
+#. module: base_external_referentials
+#: model:res.groups,name:base_external_referentials.group_export_mapping
+msgid "Export Mapping Manager"
+msgstr "导出映射管理器"
+
+#. module: base_external_referentials
+#: view:external.report.history:0
+#: view:external.report.line:0
+#: field:external.report.line,date:0
+msgid "Date"
+msgstr "日期"
+
+#. module: base_external_referentials
+#: selection:external.mapping.line,external_type:0
+#: selection:external.mappinglines.template,external_type:0
+msgid "Integer"
+msgstr "整数"
+
+#. module: base_external_referentials
+#: field:external.report,sync_from_object_id:0
+msgid "Sync From Object ID"
+msgstr "从对象ID同步"
+
+#. module: base_external_referentials
+#: field:external.report.history,user_id:0
+msgid "User"
+msgstr "用户"
+
+#. module: base_external_referentials
+#: field:external.mapping.line,external_field:0
+#: field:external.mappinglines.template,external_field:0
+msgid "External Field"
+msgstr "外部字段"
+
+#. module: base_external_referentials
+#: view:external.report.history:0
+#: view:external.report.line:0
+#: selection:external.report.line,state:0
+msgid "Success"
+msgstr "成功"
+
+#. module: base_external_referentials
+#: model:ir.actions.act_window,name:base_external_referentials.ext_magerp_product_attribute_set
+msgid "External Attribute sets in products"
+msgstr "产品的外部属性集"
+
+#. module: base_external_referentials
+#: field:external.mapping.line,alternative_key:0
+#: field:external.mappinglines.template,alternative_key:0
+msgid "Alternative Key"
+msgstr "可选关键字"
+
+#. module: base_external_referentials
+#: model:ir.actions.act_window,name:base_external_referentials.ext_res_partner_category
+msgid "External Partner Categories"
+msgstr "外部业务伙伴类别"
+
+#. module: base_external_referentials
+#: field:external.report,action:0
+#: view:external.report.line:0
+#: field:external.report.line,action:0
+msgid "Action"
+msgstr "动作"
+
+#. module: base_external_referentials
+#: field:external.report,line_ids:0
+msgid "Report Lines"
+msgstr "报告行"
+
+#. module: base_external_referentials
+#: view:external.report:0
+msgid "Delete All Failed"
+msgstr "删除所有失败的"
+
+#. module: base_external_referentials
+#: view:external.referential:0
+msgid "3- Export version"
+msgstr "3- 导出版本"
+
+#. 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 "从OpenERP映射Python函数导出"
+
+#. 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 "外部系统映射"
+
+#. module: base_external_referentials
+#: view:external.referential:0
+msgid "Compulsory"
+msgstr "必输的"
+
+#. module: base_external_referentials
+#: field:external.mapping,external_delete_method:0
+#: field:external.mapping.template,external_delete_method:0
+msgid "Delete Method"
+msgstr "删除方法"
+
+#. 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 "外部报告"
+
+#. 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 "外部系统版本 (如: 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 "浮点数"
+
+#. module: base_external_referentials
+#: field:external.report,action_on:0
+#: field:external.report.line,action_on:0
+msgid "Action On"
+msgstr "动作"
+
+#. module: base_external_referentials
+#: view:external.report.line:0
+#: field:external.report.line,kwargs_text:0
+msgid "Kwargs Data"
+msgstr "参数数据"
+
+#. module: base_external_referentials
+#: model:ir.actions.act_window,name:base_external_referentials.ext_magerp_product_attribute_groups
+msgid "External Attribute groups in Magento"
+msgstr "Magento中的外部属性组"
+
+#. module: base_external_referentials
+#: view:external.report.line:0
+#: field:external.report.line,args_text:0
+msgid "Args Data"
+msgstr "参数数据"
+
+#. module: base_external_referentials
+#: model:ir.model,name:base_external_referentials.model_group_fields
+msgid "trigger last write date by group of field"
+msgstr "按字段组的触发器最后更新日期"
+
+#. module: base_external_referentials
+#: field:external.report.line,kwargs:0
+msgid "Kwargs"
+msgstr "参数"
+
+#. module: base_external_referentials
+#: model:ir.actions.act_window,name:base_external_referentials.ext_sale_order
+msgid "External Sales Order"
+msgstr "外部销售订单"
+
+#. module: base_external_referentials
+#: help:external.mapping,extra_name:0
+msgid "In case you need to make many mappings on the same object"
+msgstr "如果你要在同一个对象上做多个映射"
+
+#. module: base_external_referentials
+#: selection:external.mapping.line,evaluation_type:0
+#: selection:external.mappinglines.template,evaluation_type:0
+msgid "Function"
+msgstr "函数"
+
+#. module: base_external_referentials
+#: field:external.report.line,res_id:0
+msgid "Resource Id"
+msgstr "资源Id"
+
+#. 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 "这样就可以导入有父子关系的数据。例如导入销售订单时,订单是订单行的父记录,这样你选择了子映射就可以转换这些数据了"
+
+#. module: base_external_referentials
+#: field:external.mapping.line,sequence:0
+#: field:external.mappinglines.template,sequence:0
+msgid "Sequence"
+msgstr "序号"
+
+#. module: base_external_referentials
+#: help:external.referential,create_date:0
+msgid "Date on which external referential is created."
+msgstr "外部系统创建的日期"
+
+#. module: base_external_referentials
+#: field:external.mapping.line,internal_field:0
+msgid "Field name"
+msgstr "字段名"
+
+#. module: base_external_referentials
+#: view:external.mapping:0
+#: view:external.referential:0
+msgid "Add all object fields"
+msgstr "添加所有对象字段"
+
+#. module: base_external_referentials
+#: field:external.mapping.line,internal_type:0
+msgid "Internal Type"
+msgstr "内部类型"
+
+#. 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 "只有一个字段可以被选为可选关键字,如果没有外部id,这个可选关键字会作为这条记录的唯一标识"
+
+#. module: base_external_referentials
+#: field:external.referential,apipass:0
+msgid "Password"
+msgstr "密码"
+
+#. module: base_external_referentials
+#: view:external.mapping:0
+#: view:external.referential:0
+msgid "Export mapping file"
+msgstr "导出映射文件"
+
+#. module: base_external_referentials
+#: field:external.referential.category,type_ids:0
+msgid "Types"
+msgstr "类型"
+
+#. module: base_external_referentials
+#: model:ir.actions.act_window,name:base_external_referentials.ext_account_invoice
+msgid "External Invoice"
+msgstr "外部发票"
+
+#. module: base_external_referentials
+#: field:external.report.history,end_date:0
+msgid "End Date"
+msgstr "结束日期"
+
+#. module: base_external_referentials
+#: field:external.mapping.line,function_name:0
+#: field:external.mappinglines.template,function_name:0
+msgid "Function Name"
+msgstr "函数名"
+
+#. module: base_external_referentials
+#: field:external.report.history,count_success:0
+msgid "Count Success"
+msgstr "成功计数"
+
+#. 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 "外部系统映射"
+
+#. module: base_external_referentials
+#: field:external.report.history,count_failed:0
+msgid "Count Failed"
+msgstr "失败计数"
+
+#. module: base_external_referentials
+#: field:group.fields,field_ids:0
+#: model:ir.model,name:base_external_referentials.model_ir_model_fields
+msgid "Fields"
+msgstr "字段"
+
+#. module: base_external_referentials
+#: selection:external.mapping.line,external_type:0
+#: selection:external.mappinglines.template,external_type:0
+msgid "List"
+msgstr "列表"
+
+#. 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 "外部系统类型"
+
+#. module: base_external_referentials
+#: view:group.fields:0
+#: field:group.fields,model_id:0
+msgid "Model"
+msgstr "模型"
+
+#. module: base_external_referentials
+#: field:external.mapping,external_update_method:0
+#: field:external.mapping.template,external_update_method:0
+msgid "Update Method"
+msgstr "更新方法"
+
+#. module: base_external_referentials
+#: view:external.report.line:0
+msgid "External Report Line"
+msgstr "外部系统报告行"
+
+#. module: base_external_referentials
+#: field:external.mapping,model_id:0
+#: field:external.mapping.template,model_id:0
+msgid "OpenERP Model"
+msgstr "OpenERP模型"
+
+#. module: base_external_referentials
+#: model:ir.actions.act_window,name:base_external_referentials.ext_sale_order_line
+msgid "External Sales Order Line"
+msgstr "外部销售订单行"
+
+#. module: base_external_referentials
+#: field:external.report.line,exception_type:0
+msgid "Exception Type"
+msgstr "异常类型"
+
+#. module: base_external_referentials
+#: field:external.report.line,external_id:0
+msgid "External ID"
+msgstr "外部系统ID"
+
+#. module: base_external_referentials
+#: view:external.referential:0
+msgid "5- Export mapping template"
+msgstr "5- 导出映射模版"
+
+#. module: base_external_referentials
+#: field:external.mapping.line,template_id:0
+msgid "External Mapping Lines Template"
+msgstr "导出映射行模版"
+
+#. 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 "如果激活了排错模式,所有外部系统与OpenERP的同步请求都会记录下来"
+
+#. module: base_external_referentials
+#: selection:external.mapping.line,external_type:0
+#: selection:external.mappinglines.template,external_type:0
+msgid "Boolean"
+msgstr "布尔型"
+
+#. module: base_external_referentials
+#: field:group.fields,column_name:0
+msgid "Column Name"
+msgstr "列名"
+
+#. module: base_external_referentials
+#: field:external.mapping.line,evaluation_type:0
+#: field:external.mappinglines.template,evaluation_type:0
+msgid "Evalution Type"
+msgstr "评估类型"
+
+#. module: base_external_referentials
+#: view:external.referential:0
+msgid "4- Export referential"
+msgstr "4- 导出外部系统"
+
+#. module: base_external_referentials
+#: view:external.mapping.line:0
+msgid "External fields"
+msgstr "外部字段"
+
+#. 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 "外部系统报告行"
+
=== added file 'base_external_referentials/ir_model.py'
--- base_external_referentials/ir_model.py 1970-01-01 00:00:00 +0000
+++ base_external_referentials/ir_model.py 2012-09-13 01:56:18 +0000
@@ -0,0 +1,35 @@
+# -*- encoding: utf-8 -*-
+###############################################################################
+# #
+# base_external_referentials for OpenERP #
+# Copyright (C) 2011 Akretion 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 #
+# 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/>. #
+# #
+###############################################################################
+
+from osv import osv
+
+
+class ir_model(osv.osv):
+ _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'}
+ 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')
+ 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)
+
=== added file 'base_external_referentials/message_error.py'
--- base_external_referentials/message_error.py 1970-01-01 00:00:00 +0000
+++ base_external_referentials/message_error.py 2012-09-13 01:56:18 +0000
@@ -0,0 +1,37 @@
+# -*- encoding: utf-8 -*-
+###############################################################################
+# #
+# base_external_referentials for OpenERP #
+# Copyright (C) 2011 Akretion 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 #
+# 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/>. #
+# #
+###############################################################################
+
+
+class MappingError(Exception):
+ def __init__(self, value, mapping_name, mapping_object):
+ self.value = value
+ 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))
+
+
+class ExtConnError(Exception):
+ def __init__(self, value):
+ self.value = value
+ def __str__(self):
+ return repr(self.value)
+
=== added file 'base_external_referentials/report.py'
--- base_external_referentials/report.py 1970-01-01 00:00:00 +0000
+++ base_external_referentials/report.py 2012-09-13 01:56:18 +0000
@@ -0,0 +1,364 @@
+# -*- encoding: utf-8 -*-
+##############################################################################
+#
+# Author Guewen Baconnier. Copyright Camptocamp SA
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+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 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):
+ _name = 'external.report'
+ _description = 'External Report'
+ _order = 'name desc'
+
+
+ def _get_full_name(self, cr, uid, ids, name, arg, context=None):
+ res = {}
+ model_obj = self.pool.get('ir.model')
+ for report in self.browse(cr, uid, ids, context=context):
+ obj = self.pool.get(report.sync_from_object_model.model)
+ object_name = obj.browse(cr, uid, report.sync_from_object_id, context=context)
+ name = "%s %s from %s"%(report.action, report.action_on.name, object_name.name)
+ name = name.replace('_', ' ').lower().strip()
+ res[report.id] = name
+ return res
+
+ _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_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),
+ 'sync_from_object_id': fields.integer('Sync From Object ID', required=True, readonly=True),
+ 'referential_id': fields.many2one('external.referential','External Referential',
+ required=True,readonly=True),
+ 'line_ids': fields.one2many('external.report.line','report_id', 'Report Lines'),
+ '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'),
+ }
+
+ def _get_report(self, cr, uid, action, action_on, sync_from_object, context=None):
+ report_id = self.search(cr, uid,
+ [
+ ('action', '=', action),
+ ('action_on', '=', action_on),
+ ('sync_from_object_model', '=', sync_from_object._name),
+ ('sync_from_object_id', '=', sync_from_object.id),
+ ], context=context)
+ return report_id and report_id[0] or False
+
+ def _clean_successful_lines(self, cr, uid, report_id, context=None):
+ lines_obj = self.pool.get('external.report.line')
+ line_ids = lines_obj.search(cr, uid,
+ [('report_id', '=', report_id),
+ ('state', '=', 'success')],
+ context=context)
+ lines_obj.unlink(cr, uid, line_ids, context=context)
+ return True
+
+ def retry_failed_lines(self, cr, uid, ids, context=None):
+ logging.getLogger('external_synchro').info("retry the failed lines of the reports ids %s" % (ids,))
+ if isinstance(ids, int):
+ ids = [ids]
+ if context is None:
+ context={}
+ context['origin'] = 'retry'
+ for report in self.read(cr, uid, ids, ['failed_line_ids'], context=context):
+ failed_line_ids = report['failed_line_ids']
+ if failed_line_ids:
+ context['report_id'] = report['id']
+ self.pool.get('external.report.line').retry(cr, uid, failed_line_ids, context=context)
+ return True
+
+ def _prepare_start_report(self, cr, uid, action, action_on, sync_from_object, context=None):
+ model_obj = self.pool.get('ir.model')
+ model_id = model_obj.search(cr, uid, [['model', '=', sync_from_object._name]])[0]
+ action_on_model_id = model_obj.search(cr, uid, [['model', '=', action_on]])[0]
+ return {
+ 'action': action,
+ '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,
+ }
+
+ @commit_now
+ def start_report(self, cr, uid, external_session, id=None, action=None,
+ action_on=None, context=None):
+ """ Start a report, use the report with the id in the parameter
+ if given. Otherwise, try to find the report which have the same method
+ and object (we use the same report to avoid a
+ multiplication of reports) If nothing is found, it create a new report
+ """
+
+ if not id and not (action and action_on):
+ raise Exception('No reference to create the report!')
+ if id:
+ report_id = id
+ else:
+ report_id = self._get_report(cr, uid, action, action_on, external_session.sync_from_object, context)
+
+ if report_id:
+ self._clean_successful_lines(cr, uid, report_id, context)
+ else:
+ report_id = self.create(
+ cr, uid,
+ self._prepare_start_report(
+ cr, uid, action, action_on, external_session.sync_from_object, context=context),
+ context=context)
+ history_id = self.pool.get('external.report.history').create(
+ cr, uid,
+ {'report_id': report_id,
+ 'user_id': uid,
+ 'start_date': time.strftime(DEFAULT_SERVER_DATETIME_FORMAT)},
+ context=context)
+ external_session.tmp['history_id'] = history_id
+ return report_id
+
+ @commit_now
+ def end_report(self, cr, uid, external_session, id, context=None):
+ """ Create history lines based on lines
+ Successful lines are cleaned at each start of a report
+ so we historize their aggregation.
+ """
+ history_obj = self.pool.get('external.report.history')
+ history_obj.write(cr, uid, external_session.tmp['history_id'],
+ {'end_date': time.strftime(DEFAULT_SERVER_DATETIME_FORMAT)},
+ context=context)
+ return id
+
+ def delete_failed_lines(self, cr, uid, ids, context=None):
+ if isinstance(ids, int):
+ ids = [ids]
+ for report in self.read(cr, uid, ids, ['failed_line_ids'], context=context):
+ failed_line_ids = report['failed_line_ids']
+ if failed_line_ids:
+ self.pool.get('external.report.line').unlink(cr, uid, failed_line_ids, context=context)
+ return True
+
+external_report()
+
+
+class external_report_history(osv.osv):
+ _name = 'external.report.history'
+ _description = 'External Report History'
+ _rec_name = 'report_id'
+ _order = 'start_date desc'
+
+ _columns = {
+ 'report_id': fields.many2one('external.report',
+ 'External Report',
+ required=True,
+ readonly=True,
+ ondelete='cascade'),
+ 'start_date': fields.datetime('Start Date', required=True, readonly=True),
+ 'end_date': fields.datetime('End Date', readonly=True),
+ 'count_success': fields.integer('Count Success', readonly=True),
+ 'count_failed': fields.integer('Count Failed', readonly=True),
+ 'user_id': fields.many2one('res.users', 'User', required=True, readonly=True),
+ }
+
+ _defaults = {
+ "start_date": lambda *a: time.strftime(DEFAULT_SERVER_DATETIME_FORMAT)
+ }
+
+ def add_one_fail(self, cr, uid, history_id, context=None):
+ return self._add_one(cr, uid, history_id, 'fail', context=context)
+
+ def add_one_success(self, cr, uid, history_id, context=None):
+ return self._add_one(cr, uid, history_id, 'success', context=context)
+
+ @commit_now
+ def _add_one(self, cr, uid, history_id, state, context=None):
+ history = self.browse(cr, uid, history_id, context=context)
+ if state == 'fail':
+ vals = {'count_failed': history.count_failed + 1}
+ else:
+ vals = {'count_success': history.count_success + 1}
+ self.write(cr, uid, history_id, vals, context=context)
+ return True
+
+external_report_history()
+
+
+class external_report_lines(osv.osv):
+ _name = 'external.report.line'
+ _description = 'External Report Lines'
+ _rec_name = 'res_id'
+ _order = 'date desc'
+
+ def _get_resource(self, cr, uid, ids, field_name, arg, context=None):
+ res = {}
+ for report_line in self.browse(cr, uid, ids, context=context):
+ res[report_line.id] = {
+ 'resource_text': simplejson.dumps(report_line.resource),
+ 'args_text': simplejson.dumps(report_line.args),
+ 'kwargs_text': simplejson.dumps(report_line.kwargs),
+ }
+ return res
+
+ def _set_resource(self, cr, uid, ids, field_name, field_value, arg, context=None):
+ res = {}
+ if isinstance(ids, int) or isinstance(ids, long):
+ ids = [ids]
+ for report_line in self.browse(cr, uid, ids, context=context):
+ self.write(cr, uid, report_line.id, {field_name.replace('_text', ''): simplejson.loads(field_value)})
+ return True
+
+ _columns = {
+ 'report_id': fields.many2one('external.report',
+ 'External Report',
+ readonly=True,
+ ondelete='restrict'),
+ 'state': fields.selection((('success', 'Success'),
+ ('fail', 'Failed')),
+ 'Status', required=True, readonly=True),
+ 'action': fields.char('Action', size=32, 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),
+ 'external_id': fields.char('External ID', size=64, readonly=True),
+ 'error_message': fields.text('Error Message', readonly=True),
+ 'traceback': fields.text('Traceback', readonly=True),
+ 'exception_type': fields.char('Exception Type', size=128, readonly=True),
+ 'resource': fields.serialized('External Data', readonly=True),
+ 'resource_text':fields.function(_get_resource, fnct_inv=_set_resource, type="text", string='External Data', multi='into_text'),
+ 'args': fields.serialized('Args', readonly=True),
+ 'args_text':fields.function(_get_resource, fnct_inv=_set_resource, type="text", string='Args Data', multi='into_text'),
+ 'kwargs': fields.serialized('Kwargs', readonly=True),
+ 'kwargs_text':fields.function(_get_resource, fnct_inv=_set_resource, type="text", string='Kwargs Data', multi='into_text'),
+ }
+
+ _defaults = {
+ "date": lambda *a: time.strftime(DEFAULT_SERVER_DATETIME_FORMAT)
+ }
+
+
+ #TODO
+ #1 - Did it usefull to log sucessfull entry?
+ #2 - We should not recreate a new entry for an existing line created from a previous report
+ #3 - Move the existing line id in the external_session.tmp ;)
+ @commit_now
+ 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)
+ report_id = context.get('report_id')
+
+ if existing_line_id:
+ self.write(cr, uid,
+ existing_line_id,
+ {'state': 'fail',
+ 'date': time.strftime(DEFAULT_SERVER_DATETIME_FORMAT),
+ 'res_id': res_id,
+ 'external_id': external_id,
+ 'args': args,
+ 'kwargs': kwargs,
+ })
+ else:
+ action_on_model_id = self.pool.get('ir.model').search(cr, uid, [['model', '=', action_on]])[0]
+ existing_line_id = self.create(cr, uid, {
+ 'report_id': report_id,
+ 'state': 'fail',
+ 'action_on': action_on_model_id,
+ 'action': action,
+ 'date': time.strftime(DEFAULT_SERVER_DATETIME_FORMAT),
+ 'res_id': res_id,
+ 'external_id': external_id,
+ 'resource': resource,
+ 'args': args,
+ 'kwargs': kwargs,
+ })
+ return existing_line_id
+
+ @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)
+ self.write(cr, uid, report_line_id, {
+ 'error_message': error_message,
+ 'exception_type': exc_type,
+ 'traceback': ''.join(traceback.format_exception(
+ exc_type, exc_value, exc_traceback)),
+ 'state': 'fail',
+ }, context=context)
+ if external_session and external_session.tmp.get('history_id'):
+ self.pool.get('external.report.history').add_one_fail(cr, uid, \
+ external_session.tmp['history_id'], 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'):
+ self.pool.get('external.report.history').add_one_success(cr, uid, \
+ external_session.tmp['history_id'], context=context)
+ return True
+
+ def retry(self, cr, uid, ids, context=None):
+ if isinstance(ids, int) or isinstance(ids, long):
+ ids = [ids]
+
+ for log in self.browse(cr, uid, ids, context=context):
+ method = getattr(self.pool.get(log.action_on.model), log.action)
+ args = log.args
+ kwargs = log.kwargs
+ if log.report_id:
+ sync_from_object = self.pool.get(log.report_id.sync_from_object_model.model).\
+ browse(cr, uid, log.report_id.sync_from_object_id, context=context)
+ external_session = ExternalSession(log.report_id.referential_id, sync_from_object)
+ resource = log.resource
+ if not kwargs.get('context', False):
+ kwargs['context']={}
+
+ # keep the id of the line to update it with the result
+ kwargs['context']['retry_report_line_id'] = log.id
+
+ method(cr, uid, external_session, resource, *args, **kwargs)
+ else:
+ if not kwargs.get('context', False):
+ kwargs['context']={}
+ kwargs['context']['retry_report_line_id'] = log.id
+ method(cr, uid, *args, **kwargs)
+ return True
+
+ def aggregate_actions(self, cr, uid, ids, context=None):
+ res = {}
+ for line in self.browse(cr, uid, ids, context=context):
+ state = line.state
+ model = line.res_model
+ action = line.action
+
+ if not res.get((state, model, action), False):
+ res[(state, model, action)] = 0
+ res[(state, model, action)] += 1
+
+ return res
+
+external_report_lines()
=== added file 'base_external_referentials/report_view.xml'
--- base_external_referentials/report_view.xml 1970-01-01 00:00:00 +0000
+++ base_external_referentials/report_view.xml 2012-09-13 01:56:18 +0000
@@ -0,0 +1,191 @@
+<?xml version="1.0" encoding="utf-8"?>
+<openerp>
+ <data>
+
+ <!-- External Report -->
+ <record id="external_report_form_view" model="ir.ui.view">
+ <field name="name">external_report_form_view</field>
+ <field name="model">external.report</field>
+ <field name="type">form</field>
+ <field name="arch" type="xml">
+ <form string="External Referential Reports">
+ <field name="name"/>
+ <newline/>
+ <field name="action"/>
+ <field name="action_on"/>
+ <field name="sync_from_object_model"/>
+ <field name="sync_from_object_id"/>
+ <field name="referential_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"/>
+ <button name="delete_failed_lines" string="Delete All Failed" icon="gtk-cancel" type="object" colspan="2"/>
+ <newline/>
+ <field name="history_ids" nolabel="1" colspan="4"/>
+ </form>
+ </field>
+ </record>
+
+ <record id="external_report_tree_view" model="ir.ui.view">
+ <field name="name">external_report_tree_view</field>
+ <field name="model">external.report</field>
+ <field name="type">tree</field>
+ <field name="arch" type="xml">
+ <tree string="External Reports" colors="red:failed_line_ids">
+ <field name="referential_id"/>
+ <field name="name"/>
+ <field name="sync_from_object_model"/>
+ <field name="sync_from_object_id"/>
+ <field name="failed_line_ids" invisible="1"/>
+ </tree>
+ </field>
+ </record>
+
+ <record id="external_report_search_form_view" model="ir.ui.view">
+ <field name="name">external_report_search_view</field>
+ <field name="model">external.report</field>
+ <field name="type">search</field>
+ <field name="arch" type="xml">
+ <search string="External Referential Reports">
+ <field name="name"/>
+ <field name="referential_id"/>
+ <newline/>
+ <group expand='0' string='Group by...' groups="base.group_extended">
+ <filter string='External Referential' icon="terp-stock_symbol-selection" domain="[]" context="{'group_by' : 'referential_id'}" />
+ <!--<filter string='Object Related' icon="terp-stock_symbol-selection" domain="[]" context="{'group_by' : 'sync_from_object_id'}" />-->
+ </group>
+ </search>
+ </field>
+ </record>
+
+ <!-- External Report History -->
+ <record id="external_report_history_form_view" model="ir.ui.view">
+ <field name="name">external_report_history_view</field>
+ <field name="model">external.report.history</field>
+ <field name="type">form</field>
+ <field name="arch" type="xml">
+ <form string="External Report History">
+ <field name="report_id" invisible="not context.get('main_view')"/>
+ <field name="start_date"/>
+ <field name="end_date"/>
+ <field name="count_failed"/>
+ <field name="count_success"/>
+ <field name="user_id"/>
+ </form>
+ </field>
+ </record>
+
+ <record id="external_report_history_tree_view" model="ir.ui.view">
+ <field name="name">external_report_history_tree_view</field>
+ <field name="model">external.report.history</field>
+ <field name="type">tree</field>
+ <field name="arch" type="xml">
+ <tree string="External Report History">
+ <field name="report_id" invisible="not context.get('main_view')"/>
+ <field name="start_date"/>
+ <field name="end_date"/>
+ <field name="count_failed"/>
+ <field name="count_success"/>
+ <field name="user_id"/>
+ </tree>
+ </field>
+ </record>
+
+ <record id="external_report_history_search_view" model="ir.ui.view">
+ <field name="name">external_report_history_search_view</field>
+ <field name="model">external.report.history</field>
+ <field name="type">search</field>
+ <field name="arch" type="xml">
+ <search string="External Report History">
+ <filter string="Success" icon="terp-accessories-archiver" domain="[('state','=','success')]"/>
+ <filter string="Failures" icon="terp-accessories-archiver" domain="[('state','=','fail')]"/>
+ <separator orientation="vertical"/>
+ <field name="report_id"/>
+ <field name="start_date"/>
+ <field name="end_date"/>
+ <field name="user_id"/>
+ <newline/>
+ <group expand='0' string='Group by...' groups="base.group_extended">
+ <filter string='Report' icon="terp-stock_symbol-selection" domain="[]" context="{'group_by' : 'report_id'}" />
+ <filter string='Date' icon="terp-stock_symbol-selection" domain="[]" context="{'group_by' : 'start_date'}" />
+ </group>
+ </search>
+ </field>
+ </record>
+
+ <record id="external_report_line_search_view" model="ir.ui.view">
+ <field name="name">external_report_line_search_view</field>
+ <field name="model">external.report.line</field>
+ <field name="type">search</field>
+ <field name="arch" type="xml">
+ <search string="External Report History">
+ <filter string="Success" icon="terp-accessories-archiver" domain="[('state','=','success')]"/>
+ <filter string="Failures" icon="terp-accessories-archiver" domain="[('state','=','fail')]"/>
+ <separator orientation="vertical"/>
+ <field name="report_id"/>
+ <field name="date"/>
+ <field name="action_on"/>
+ <field name="action"/>
+ <field name="state"/>
+ <newline/>
+ <group expand='0' string='Group by...' groups="base.group_extended">
+ <filter string='Report' icon="terp-stock_symbol-selection" domain="[]" context="{'group_by' : 'report_id'}" />
+ <filter string='Date' icon="terp-stock_symbol-selection" domain="[]" context="{'group_by' : 'date'}" />
+ <filter string='Action On Model' icon="terp-stock_symbol-selection" domain="[]" context="{'group_by' : 'action_on'}" />
+ <filter string='Action' icon="terp-stock_symbol-selection" domain="[]" context="{'group_by' : 'action'}" />
+ </group>
+ </search>
+ </field>
+ </record>
+
+ <!-- External Report Line -->
+ <record id="external_report_line_form_view" model="ir.ui.view">
+ <field name="name">external_report_line_form_view</field>
+ <field name="model">external.report.line</field>
+ <field name="type">form</field>
+ <field name="arch" type="xml">
+ <form string="External Report Line">
+ <field name="report_id" invisible="not context.get('main_view')"/>
+ <field name="action_on"/>
+ <field name="res_id"/>
+ <field name="external_id"/>
+ <field name="action"/>
+ <field name="date"/>
+ <field name="state"/>
+ <separator string="Error Message" colspan="4"/>
+ <field name="error_message" colspan="4" nolabel="1"/>
+ <field name="exception_type" colspan="4" nolabel="1"/>
+ <field name="traceback" colspan="4" nolabel="1"/>
+ <separator string="External Data" colspan="4"/>
+ <field name="resource_text" colspan="4" nolabel="1"/>
+ <separator string="Args Data" colspan="4"/>
+ <field name="args_text" colspan="4" nolabel="1"/>
+ <separator string="Kwargs Data" colspan="4"/>
+ <field name="kwargs_text" colspan="4" nolabel="1"/>
+ <separator colspan="4"/>
+ <button name="retry" string="Retry" icon="gtk-go-forward" type="object" colspan="2"/>
+ </form>
+ </field>
+ </record>
+
+ <record id="external_report_line_tree_view" model="ir.ui.view">
+ <field name="name">external_report_line_tree_view</field>
+ <field name="model">external.report.line</field>
+ <field name="type">tree</field>
+ <field name="arch" type="xml">
+ <tree colors="red:state=='fail'" string="External Report Lines">
+ <field name="report_id" invisible="not context.get('main_view')"/>
+ <field name="state"/>
+ <field name="action_on"/>
+ <field name="action"/>
+ <field name="date"/>
+ <field name="res_id"/>
+ <field name="external_id"/>
+ <field name="error_message"/>
+ <button name="retry" string="Retry" icon="gtk-go-forward" type="object" colspan="2"/>
+ </tree>
+ </field>
+ </record>
+
+ </data>
+</openerp>
=== added directory 'base_external_referentials/security'
=== added file 'base_external_referentials/security/base_external_referentials_security.xml'
--- base_external_referentials/security/base_external_referentials_security.xml 1970-01-01 00:00:00 +0000
+++ base_external_referentials/security/base_external_referentials_security.xml 2012-09-13 01:56:18 +0000
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ base_external_referentials for OpenERP
+ Copyright (C) 2011 Akretion Benoît Guillot <benoit.guillot@xxxxxxxxxxxx>
+ The licence is in the file __openerp__.py
+-->
+
+<openerp>
+ <data>
+
+ <record id="base_external_referentials.group_export_mapping" model="res.groups">
+ <field name="name">Export Mapping Manager</field>
+ </record>
+
+ </data>
+</openerp>
=== added file 'base_external_referentials/security/ir.model.access.csv'
--- base_external_referentials/security/ir.model.access.csv 1970-01-01 00:00:00 +0000
+++ base_external_referentials/security/ir.model.access.csv 2012-09-13 01:56:18 +0000
@@ -0,0 +1,7 @@
+id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
+access_external_referential_category,Configuration group has full access to external.referential.category,model_external_referential_category,base.group_system,1,1,1,1
+access_base_external_referentials_external_referential_categ,base_external_referentials_external_referential,model_external_referential_category,base.group_user,1,0,0,0
+access_base_external_referentials_external_referential,base_external_referentials_external_referential,base_external_referentials.model_external_referential,base.group_user,1,0,0,0
+access_base_external_referentials_external_referential_type,base_external_referentials_external_referential_type,base_external_referentials.model_external_referential_type,base.group_user,1,0,0,0
+access_base_external_referentials_group_fields_manager,base_external_referentials_group_fields,base_external_referentials.model_group_fields,base.group_system,1,1,1,1
+access_base_external_referentials_group_fields_user,base_external_referentials_group_fields,base_external_referentials.model_group_fields,base.group_user,1,0,0,0
=== added directory 'base_file_protocole'
=== added file 'base_file_protocole/__init__.py'
--- base_file_protocole/__init__.py 1970-01-01 00:00:00 +0000
+++ base_file_protocole/__init__.py 2012-09-13 01:56:18 +0000
@@ -0,0 +1,26 @@
+# -*- encoding: utf-8 -*-
+###############################################################################
+# #
+# base_file_protocole for OpenERP #
+# Copyright (C) 2011 Akretion 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 #
+# 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 base_file_protocole
+
+
+
+
=== added file 'base_file_protocole/__openerp__.py'
--- base_file_protocole/__openerp__.py 1970-01-01 00:00:00 +0000
+++ base_file_protocole/__openerp__.py 2012-09-13 01:56:18 +0000
@@ -0,0 +1,38 @@
+# -*- encoding: utf-8 -*-
+###############################################################################
+# #
+# base_file_protocole for OpenERP #
+# Copyright (C) 2011 Akretion 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 #
+# 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': 'base_file_protocole',
+ 'version': '0.1',
+ 'category': 'Generic Modules/Others',
+ 'license': 'AGPL-3',
+ 'description': """empty""",
+ 'author': 'Akretion',
+ 'website': 'http://www.akretion.com/',
+ 'depends': ['base'],
+ 'init_xml': [],
+ 'update_xml': [
+ ],
+ 'demo_xml': [],
+ 'installable': True,
+ 'active': False,
+}
+
=== added file 'base_file_protocole/base_file_protocole.py'
--- base_file_protocole/base_file_protocole.py 1970-01-01 00:00:00 +0000
+++ base_file_protocole/base_file_protocole.py 2012-09-13 01:56:18 +0000
@@ -0,0 +1,238 @@
+# -*- encoding: utf-8 -*-
+###############################################################################
+# #
+# base_file_protocole for OpenERP #
+# Copyright (C) 2011 Akretion 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 #
+# 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/>. #
+# #
+###############################################################################
+
+from osv import osv, fields
+import netsvc
+from tempfile import TemporaryFile
+from ftplib import FTP
+import sys
+import os
+import shutil
+import csv
+import paramiko
+import errno
+import functools
+
+def open_and_close_connection(func):
+ """
+ Open And Close Decorator will automatically launch the connection
+ to the external storage system.
+ Then the function is excecuted and the connection is closed
+ """
+ @functools.wraps(func)
+ def wrapper(self, *args, **kwargs):
+ self.connect()
+ try:
+ response = func(self, *args, **kwargs)
+ except:
+ raise
+ finally:
+ self.close()
+ return response
+ return wrapper
+
+# Extend paramiko lib with the method mkdirs
+def mkdirs(self, path, mode=511):
+ try:
+ self.stat(path)
+ except IOError, e:
+ if e.errno == errno.ENOENT:
+ try:
+ self.mkdir(path, mode)
+ except IOError, e:
+ if e.errno == errno.ENOENT:
+ self.mkdirs(os.path.dirname(path), mode)
+ self.mkdir(path, mode)
+ else:
+ raise
+paramiko.SFTPClient.mkdirs = mkdirs
+
+
+class FileConnection(object):
+
+ def is_(self, protocole):
+ return self.protocole.lower() == protocole
+
+ def __init__(self, protocole, location, user, pwd, port=None, allow_dir_creation=None, home_folder='/'):
+ self.protocole = protocole
+ self.allow_dir_creation = allow_dir_creation
+ self.location = location
+ self.home_folder = home_folder
+ self.port = port
+ self.user = user
+ self.pwd = pwd
+
+
+ def connect(self):
+ if self.is_('ftp'):
+ self.connection = FTP(self.location)
+ self.connection.login(self.user, self.pwd)
+ elif self.is_('sftp'):
+ transport = paramiko.Transport((self.location, self.port or 22))
+ transport.connect(username = self.user, password = self.pwd)
+ self.connection = paramiko.SFTPClient.from_transport(transport)
+
+ def close(self):
+ if self.is_('ftp') or self.is_('sftp'):
+ self.connection.close()
+
+ @open_and_close_connection
+ def send(self, filepath, filename, output_file, create_patch=None):
+ if self.is_('ftp'):
+ self.connection.cwd(filepath)
+ self.connection.storbinary('STOR ' + filename, output_file)
+ output_file.close()
+ return True
+ elif self.is_('filestore'):
+ if not os.path.isabs(filepath):
+ filepath = os.path.join(self.location, filepath)
+ if self.allow_dir_creation and not os.path.exists(filepath):
+ os.makedirs(filepath)
+ output = open(os.path.join(filepath, filename), 'w+b')
+ for line in output_file.readlines():
+ output.write(line)
+ output.close()
+ output_file.close()
+ return True
+ elif self.is_('sftp'):
+ if not os.path.isabs(filepath):
+ filepath = os.path.join(self.home_folder, filepath)
+ if self.allow_dir_creation:
+ self.connection.mkdirs(filepath)
+ output = self.connection.open(os.path.join(filepath, filename), 'w+b')
+ for line in output_file.readlines():
+ output.write(line)
+ output.close()
+ output_file.close()
+ return True
+
+ @open_and_close_connection
+ def get(self, filepath, filename):
+ if self.is_('ftp'):
+ outfile = TemporaryFile('w+b')
+ self.connection.cwd(filepath)
+ self.connection.retrbinary("RETR " + filename, outfile.write)
+ outfile.seek(0)
+ return outfile
+ elif self.is_('filestore'):
+ return open(os.path.join(filepath, filename), 'r+b')
+
+ @open_and_close_connection
+ def search(self, filepath, filename):
+ if self.is_('ftp'):
+ self.connection.cwd(filepath)
+ #Take care that ftp lib use utf-8 and not unicode
+ return [x for x in self.connection.nlst() if filename.encode('utf-8') in x]
+ elif self.is_('filestore'):
+ return [x for x in os.listdir(filepath) if filename in x]
+
+ @open_and_close_connection
+ def move(self, oldfilepath, newfilepath, filename):
+ if self.is_('ftp'):
+ self.connection.rename(os.path.join(oldfilepath, filename), os.path.join(newfilepath, filename))
+ elif self.is_('filestore'):
+ os.rename(os.path.join(oldfilepath, filename), os.path.join(newfilepath, filename))
+
+class FileCsvReader(object):
+ """
+ A CSV reader which will iterate over lines in the CSV file "f",
+ which is encoded in the given encoding.
+ """
+
+ def __init__(self, f, encoding="utf-8", **kwds):
+ self.encoding = encoding
+ self.reader = csv.DictReader(f, **kwds)
+
+ def next(self):
+ row = self.reader.next()
+ res = {}
+ for key, value in row.items():
+ if not isinstance(key, unicode) and key:
+ key = unicode(key, self.encoding)
+ if not isinstance(value, unicode) and value:
+ value = unicode(value, self.encoding)
+ res[key] = value
+ return res
+
+ def __iter__(self):
+ return self
+
+ 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)
+ 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)
+ """
+ result_merge = {}
+ result = []
+ for line in self:
+ line_tmp = line.copy()
+ for child, parent in field_structure:
+ if not parent in line:
+ line[parent] = {}
+ if line.get(child) or line_tmp.get(child):
+ line[parent][child] = line.get(child) or line_tmp.get(child)
+ if line.get(child):
+ del line[child]
+ if ref_field:
+ if line[ref_field] in result_merge:
+ for key in merge_keys:
+ result_merge[line[ref_field]][key].append(line[key])
+ else:
+ result_merge[line[ref_field]] = line
+ for key in merge_keys:
+ result_merge[line[ref_field]][key] = [result_merge[line[ref_field]][key]]
+ else:
+ result.append(line)
+ if ref_field:
+ return [result_merge[key] for key in result_merge]
+ else:
+ return result
+
+class FileCsvWriter(object):
+ """
+ A CSV writer which will write rows to CSV file "f",
+ which is encoded in the given encoding.
+ """
+
+ def __init__(self, f, fieldnames, encoding="utf-8", writeheader=False, **kwds):
+ self.encoding = encoding
+ if not kwds.get('dialect'):
+ kwds['dialect'] = 'UNIX'
+ self.writer = csv.DictWriter(f, fieldnames, **kwds)
+ if writeheader:
+ row = {}
+ for field in fieldnames:
+ row[field] = field.encode(self.encoding)
+ self.writer.writerow(row)
+
+ def writerow(self, row):
+ write_row = {}
+ for k,v in row.items():
+ if isinstance(v, unicode) and v!=False:
+ write_row[k] = v.encode(self.encoding)
+ else:
+ write_row[k] = v
+ self.writer.writerow(write_row)
+
+ def writerows(self, rows):
+ for row in rows:
+ self.writerow(row)
=== added directory 'base_onchange_player'
=== added file 'base_onchange_player/__init__.py'
--- base_onchange_player/__init__.py 1970-01-01 00:00:00 +0000
+++ base_onchange_player/__init__.py 2012-09-13 01:56:18 +0000
@@ -0,0 +1,27 @@
+# -*- encoding: utf-8 -*-
+#################################################################################
+# #
+# base_onchange_player for OpenERP #
+# Copyright (C) 2011 Akretion 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 #
+# 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 onchange_osv
+
+
+
+
=== added file 'base_onchange_player/__openerp__.py'
--- base_onchange_player/__openerp__.py 1970-01-01 00:00:00 +0000
+++ base_onchange_player/__openerp__.py 2012-09-13 01:56:18 +0000
@@ -0,0 +1,41 @@
+# -*- encoding: utf-8 -*-
+#################################################################################
+# #
+# base_onchange_player for OpenERP #
+# Copyright (C) 2011 Akretion 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 #
+# 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': 'base_onchange_player',
+ '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
+ """,
+ 'author': 'Akretion',
+ 'website': 'http://www.akretion.com/',
+ 'depends': ['base'],
+ 'init_xml': [],
+ 'update_xml': [
+ ],
+ 'demo_xml': [],
+ 'installable': True,
+ 'active': False,
+}
+
=== added file 'base_onchange_player/onchange_osv.py'
--- base_onchange_player/onchange_osv.py 1970-01-01 00:00:00 +0000
+++ base_onchange_player/onchange_osv.py 2012-09-13 01:56:18 +0000
@@ -0,0 +1,63 @@
+# -*- encoding: utf-8 -*-
+################################################################################
+# #
+# base_onchange_player for OpenERP #
+# Copyright (C) 2011 Akretion 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 #
+# 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/>. #
+# #
+################################################################################
+
+from osv import osv
+import netsvc
+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
+
+ @param onchange_name: string that contain the onchange method to call
+ @param vals: dictionnary of value that have 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
+ """
+ if not defaults:
+ 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)
+ 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)))
+ try :
+ res = eval("self.%s"%onchange_name)(cr, uid, **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 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)))
+ return vals
+
+osv.osv.call_onchange = call_onchange
=== added directory 'base_pop_up'
=== added file 'base_pop_up/__init__.py'
--- base_pop_up/__init__.py 1970-01-01 00:00:00 +0000
+++ base_pop_up/__init__.py 2012-09-13 01:56:18 +0000
@@ -0,0 +1,27 @@
+# -*- encoding: utf-8 -*-
+#################################################################################
+# #
+# base_pop_up 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 pop_up_file
+
+
+
+
=== added file 'base_pop_up/__openerp__.py'
--- base_pop_up/__openerp__.py 1970-01-01 00:00:00 +0000
+++ base_pop_up/__openerp__.py 2012-09-13 01:56:18 +0000
@@ -0,0 +1,40 @@
+# -*- encoding: utf-8 -*-
+#################################################################################
+# #
+# base_pop_up 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/>. #
+# #
+#################################################################################
+
+
+{
+ 'name': 'base_pop_up',
+ 'version': '0.1',
+ 'category': 'Generic Modules/Others',
+ 'license': 'AGPL-3',
+ 'description': """empty""",
+ 'author': 'Akretion',
+ 'website': 'http://www.akretion.com/',
+ 'depends': ['base'],
+ 'init_xml': [],
+ 'update_xml': [
+ 'pop_up_file_view.xml',
+ ],
+ 'demo_xml': [],
+ 'installable': True,
+ 'active': False,
+}
+
=== added file 'base_pop_up/pop_up_file.py'
--- base_pop_up/pop_up_file.py 1970-01-01 00:00:00 +0000
+++ base_pop_up/pop_up_file.py 2012-09-13 01:56:18 +0000
@@ -0,0 +1,99 @@
+# -*- encoding: utf-8 -*-
+#################################################################################
+# #
+# base_pop_up for OpenERP #
+# Copyright (C) 2011 Akretion Benoît Guillot <benoit.guillot@xxxxxxxxxxxx> #
+# Copyright (C) 2011 Akretion 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 #
+# 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/>. #
+# #
+#################################################################################
+
+from osv import osv, fields
+import netsvc
+import base64
+from tempfile import TemporaryFile
+
+class pop_up_file(osv.osv_memory):
+ _name = "pop.up.file"
+ _description = "Output File"
+
+ _columns = {
+ 'name': fields.char('Name', size=64),
+ 'file': fields.binary('File'),
+ }
+
+ def open_output_file(self, cr, uid, file_name, output_file, title, context=None):
+ mod_obj = self.pool.get('ir.model.data')
+ output_file.seek(0)
+ file_data = base64.encodestring(output_file.read())
+ output_object_id = self.pool.get('pop.up.file').create(cr, uid, {'name' : file_name, 'file' : file_data}, context=context)
+ res = mod_obj.get_object_reference(cr, uid, 'base_pop_up', 'output_file_form_view')
+ res_id = res and res[1] or False
+ action = {
+ 'name': title,
+ 'view_type': 'form',
+ 'view_mode': 'form',
+ 'view_id': [res_id],
+ 'res_model': 'pop.up.file',
+ 'type': 'ir.actions.act_window',
+ 'nodestroy': True,
+ 'target': 'new',
+ 'res_id': output_object_id,
+ }
+ return action
+
+ def close(self, cr, uid, ids, context=None):
+ self.unlink(cr, uid, ids, context=context)
+ return {'type': 'ir.actions.act_window_close'}
+
+
+ def open_input_file(self, cr, uid, title, callback, args, context=None):
+ mod_obj = self.pool.get('ir.model.data')
+ context['pop_up_callback'] = {
+ 'func_name': callback.func_name,
+ 'self': callback.__self__._name,
+ 'args': args,
+ }
+ input_object_id = self.pool.get('pop.up.file').create(cr, uid, {}, context=context)
+ res = mod_obj.get_object_reference(cr, uid, 'base_pop_up', 'input_file_form_view')
+ res_id = res and res[1] or False
+ action = {
+ 'name': title,
+ 'view_type': 'form',
+ 'view_mode': 'form',
+ 'view_id': [res_id],
+ 'res_model': 'pop.up.file',
+ 'type': 'ir.actions.act_window',
+ 'nodestroy': True,
+ 'target': 'new',
+ 'res_id': input_object_id,
+ 'context': context,
+ }
+ print 'open action', action
+ return action
+
+ def send(self, cr, uid, ids, context=None):
+ callback_object = self.pool.get(context['pop_up_callback']['self'])
+ callback_func_name = context['pop_up_callback']['func_name']
+ callback_args = context['pop_up_callback']['args']
+ wizard = self.browse(cr, uid, ids[0], context=context)
+ input_file =TemporaryFile('w+b')
+ input_file.write(base64.decodestring(wizard.file))
+ input_file.seek(0)
+ callback_args += [input_file, wizard.name]
+ getattr(callback_object, callback_func_name)(*([cr, uid] + callback_args), context=context)
+ return {'type': 'ir.actions.act_window_close'}
+
+
=== added file 'base_pop_up/pop_up_file_view.xml'
--- base_pop_up/pop_up_file_view.xml 1970-01-01 00:00:00 +0000
+++ base_pop_up/pop_up_file_view.xml 2012-09-13 01:56:18 +0000
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ base_pop_up for OpenERP
+ Copyright (C) 2012 Akretion Benoît Guillot <benoit.guillot@xxxxxxxxxxxx>
+ Copyright (C) 2012 Akretion Sébastien BEAU <sebastien.beau@xxxxxxxxxxxx>
+ The licence is in the file __openerp__.py
+-->
+
+<openerp>
+ <data>
+
+ <!-- VIEW FOR THE OBJECT : pop_up_file -->
+
+ <record model="ir.ui.view" id="output_file_form_view">
+ <field name="name">output_file_form_view</field>
+ <field name="model">pop.up.file</field>
+ <field name="type">form</field>
+ <field name="arch" type="xml">
+ <form>
+ <group name="output file" colspan="4" col="2">
+ <field name="name" invisible="1"/>
+ <field name="file" filename="name" readonly="1"/>
+ </group>
+ <button name="close" colspan="1" string="Close" type="object" icon="gtk-go-forward"/>
+ </form>
+ </field>
+ </record>
+
+ <record model="ir.ui.view" id="input_file_form_view">
+ <field name="name">input_file_form_view</field>
+ <field name="model">pop.up.file</field>
+ <field name="type">form</field>
+ <field name="arch" type="xml">
+ <form>
+ <group name="input file" colspan="4" col="2">
+ <field name="name" invisible="1"/>
+ <field name="file" filename="name"/>
+ </group>
+ <button icon="gtk-cancel" special="cancel" string="Cancel"/>
+ <button name="send" colspan="1" string="Send" type="object" icon="gtk-go-forward"/>
+ </form>
+ </field>
+ </record>
+
+ </data>
+</openerp>
+
=== added directory 'base_scheduler_creator'
=== added file 'base_scheduler_creator/__init__.py'
--- base_scheduler_creator/__init__.py 1970-01-01 00:00:00 +0000
+++ base_scheduler_creator/__init__.py 2012-09-13 01:56:18 +0000
@@ -0,0 +1,22 @@
+# -*- encoding: utf-8 -*-
+#########################################################################
+#
+# Base scheduler creator module for OpenERP
+# Copyright (C) 2010 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
+# 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 schedulder_creator
=== added file 'base_scheduler_creator/__openerp__.py'
--- base_scheduler_creator/__openerp__.py 1970-01-01 00:00:00 +0000
+++ base_scheduler_creator/__openerp__.py 2012-09-13 01:56:18 +0000
@@ -0,0 +1,36 @@
+# -*- encoding: utf-8 -*-
+#########################################################################
+#
+# Base scheduler creator module for OpenERP
+# Copyright (C) 2010 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
+# 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" : "base_scheduler_creator",
+ "version" : "1.0",
+ "license": "AGPL-3",
+ "depends" : ["base"],
+ "author" : "Akretion",
+ "description": """Allows the automatic creation of a scheduler.""",
+ "website" : "http://www.akretion.com/",
+ "category" : "Generic Modules/Other",
+ "init_xml" : [],
+ "demo_xml" : [],
+ "update_xml" : ["schedulder_creator.xml"],
+ "active": False,
+ "installable": True,
+}
=== added file 'base_scheduler_creator/schedulder_creator.py'
--- base_scheduler_creator/schedulder_creator.py 1970-01-01 00:00:00 +0000
+++ base_scheduler_creator/schedulder_creator.py 2012-09-13 01:56:18 +0000
@@ -0,0 +1,50 @@
+# -*- encoding: utf-8 -*-
+#########################################################################
+#
+# Base scheduler creator module for OpenERP
+# Copyright (C) 2010 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
+# 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/>.
+#
+#########################################################################
+
+from osv import fields,osv
+from tools.translate import _
+
+class scheduler_creator_wizard(osv.osv_memory):
+ _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 !'))
+
+ vals = {'name':self.pool.get(context['object_link']).read(cr, uid, id, ['name'], context)['name'],
+ 'active':False,
+ 'user_id':uid,
+ 'interval_number':30,
+ 'interval_type':'minutes',
+ 'numbercall':-1,
+ 'doall':False,
+ 'model':context['wizard_object'],
+ 'function':context['function'],
+ 'args':'([' + str(id) +'],)',
+ }
+ cron_id = self.pool.get('ir.cron').create(cr, uid, vals, context)
+ 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()
=== added file 'base_scheduler_creator/schedulder_creator.xml'
--- base_scheduler_creator/schedulder_creator.xml 1970-01-01 00:00:00 +0000
+++ base_scheduler_creator/schedulder_creator.xml 2012-09-13 01:56:18 +0000
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<openerp>
+ <data>
+
+ <record id="scheduler_creator_wizard" model="ir.ui.view">
+ <field name="name">scheduler.creator.wizard.form</field>
+ <field name="model">scheduler.creator.wizard</field>
+ <field name="type">form</field>
+ <field name="arch" type="xml">
+ <form string="Scheduler Creator">
+ <group>
+ <separator colspan="4" string="Create Automaticaly Your Scheduler"/>
+ <button icon="gtk-cancel" special="cancel" string="Cancel"/>
+ <button icon="gtk-ok" name="action_create" string="Create" type="object"/>
+ <separator colspan="4"/>
+ </group>
+ </form>
+ </field>
+ </record>
+
+ <record id="action_scheduler_creator_wizard" model="ir.actions.act_window">
+ <field name="name">Create a scheduler</field>
+ <field name="type">ir.actions.act_window</field>
+ <field name="res_model">scheduler.creator.wizard</field>
+ <field name="view_type">form</field>
+ <field name="view_mode">form</field>
+ <field name="target">new</field>
+ <field name="context">{}</field>
+ </record>
+
+
+
+ </data>
+</openerp>
=== added directory 'file_exchange'
=== added file 'file_exchange/__init__.py'
--- file_exchange/__init__.py 1970-01-01 00:00:00 +0000
+++ file_exchange/__init__.py 2012-09-13 01:56:18 +0000
@@ -0,0 +1,23 @@
+# -*- encoding: utf-8 -*-
+#################################################################################
+# #
+# file_exchange for OpenERP #
+# Copyright (C) 2012 Akretion Emmanuel Samyn <emmanuel.samyn@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 file_exchange
+import file_exchange_osv
+
=== added file 'file_exchange/__openerp__.py'
--- file_exchange/__openerp__.py 1970-01-01 00:00:00 +0000
+++ file_exchange/__openerp__.py 2012-09-13 01:56:18 +0000
@@ -0,0 +1,47 @@
+# -*- encoding: utf-8 -*-
+###############################################################################
+# #
+# file_exchange for OpenERP #
+# Copyright (C) 2012 Akretion Emmanuel Samyn <emmanuel.samyn@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': 'file_exchange',
+ 'version': '0.1',
+ 'category': 'Generic Modules/Others',
+ 'license': 'AGPL-3',
+ 'description': """
+Definition : a file exchange is a file to be exchanged (in/out) between OpenERP and another system (referential)
+Goal : store file details and and file fields
+""",
+ 'author': 'Akretion',
+ 'website': 'http://www.akretion.com/',
+ 'depends': ['base_scheduler_creator', 'base_external_file_protocole'],
+ 'init_xml': [],
+ 'update_xml': [
+ 'file_exchange_view.xml',
+ 'file_exchange_menu.xml',
+ 'settings/external.referential.category.csv',
+ 'security/file_exchange_security.xml',
+ 'security/file_exchange_security.xml',
+ 'security/ir.model.access.csv',
+ ],
+ 'demo_xml': [],
+ 'installable': True,
+ 'active': False,
+}
+
=== added file 'file_exchange/file_exchange.py'
--- file_exchange/file_exchange.py 1970-01-01 00:00:00 +0000
+++ file_exchange/file_exchange.py 2012-09-13 01:56:18 +0000
@@ -0,0 +1,623 @@
+# -*- encoding: utf-8 -*-
+###############################################################################
+# #
+# file_exchange for OpenERP #
+# Copyright (C) 2012 Akretion Emmanuel Samyn <emmanuel.samyn@xxxxxxxxxxxx> #
+# Copyright (C) 2011 Akretion 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 #
+# 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/>. #
+# #
+###############################################################################
+from tools.safe_eval import safe_eval as eval
+from osv import osv, fields
+import netsvc
+from base_external_referentials.external_osv import ExternalSession
+from base_file_protocole.base_file_protocole import FileCsvReader, FileCsvWriter
+from base_external_referentials.decorator import open_report
+from tempfile import TemporaryFile
+from encodings.aliases import aliases
+from tools.translate import _
+
+
+#TODO implement the FileCsvWriter in base_file_protocole and remove import csv
+import csv
+
+class FileExchangeCsvReader(FileCsvReader):
+ def __init__(self, f, pre_processing=None, **kwds):
+ init = super(FileExchangeCsvReader, self).__init__(f, **kwds)
+ self.pre_processing = pre_processing
+ return init
+
+ def next(self):
+ row = super(FileExchangeCsvReader, self).next()
+ if self.pre_processing:
+ space = {'row': row,
+ }
+ 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'))
+ return row
+
+class file_exchange(osv.osv):
+ _name = "file.exchange"
+ _description = "file exchange"
+
+ def get_export_default_fields_values(self, cr, uid, id, context=None):
+ if isinstance(id, list):
+ id = id[0]
+ res = {}
+ method = self.browse(cr, uid, id, context=context)
+ for field in method.field_ids:
+ if field.advanced_default_value:
+ space = {'self': self,
+ 'cr': cr,
+ 'uid': uid,
+ 'id': id,
+ 'context': context,
+ }
+ 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)))
+ 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,
+ 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)
+ method = external_session.sync_from_object
+ 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),
+ ('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,
+ convertion_type='from_external_to_openerp',
+ mapping_id=method.mapping_id.id,
+ context=context)
+ mapping_tree, merge_keys = self._get_mapping_tree(cr, uid, mapping_id, context=context)
+ csv = FileExchangeCsvReader(external_file,
+ fieldnames= format=='csv_no_header' and fields_name or None,
+ delimiter=method.delimiter.encode('utf-8'),
+ encoding=method.encoding,
+ pre_processing=method.pre_processing)
+ res = csv.reorganize(field_structure=mapping_tree, merge_keys=merge_keys, ref_field=merge_key)
+ return res
+
+ def _get_mapping_tree(self, cr, uid, mapping_id, parent_name=None, grand_parent_name=None, context=None):
+ mapping_tree = []
+ result = []
+ merge_keys = []
+ mapping = self.pool.get('external.mapping').browse(cr, uid, mapping_id, context=context)
+ mapping_name = "%s_%s" %(mapping.model_id.model, mapping.id)
+ for mapping_line in mapping.mapping_ids:
+ if mapping_line.evaluation_type == 'sub-mapping':
+ res, sub_merge_keys = self._get_mapping_tree(cr, uid, mapping_line.child_mapping_id.id, mapping_name, context=context)
+ result = res + result
+ merge_keys = merge_keys + sub_merge_keys
+ if mapping_line.internal_type in ['one2many','many2many']:
+ merge_keys.append("%s_%s" %(mapping_line.child_mapping_id.model, mapping_line.child_mapping_id.id))
+ else:
+ if parent_name:
+ result.append((mapping_line.external_field , mapping_name))
+ if grand_parent_name:
+ result.append((mapping_name , parent_name))
+ if not parent_name:
+ result = list(set(result))
+ return result, merge_keys
+
+ #needed for cron task
+ def start_task(self, cr, uid, ids, context=None):
+ if context is None:
+ context={}
+ for method in self.browse(cr, uid, ids, context=context):
+ if method.type == 'in':
+ self.import_task(cr, uid, method.id, context=context)
+ elif method.type == 'out':
+ self.export_task(cr, uid, method.id, context=context)
+
+ def import_task(self, cr, uid, method_id, context=None):
+ if hasattr(method_id, '__iter__'):
+ method_id = method_id[0]
+ method = self.browse(cr, uid, method_id, context=context)
+ if method.synchronize_from == 'pop_up':
+ return self.import_file_form_pop_up(cr, uid, method.id, context=context)
+ else:
+ self._import_files(cr, uid, method.id, context=context)
+ return True
+
+ def export_task(self, cr, uid, method_id, context=None):
+ if hasattr(method_id, '__iter__'):
+ method_id = method_id[0]
+ method = self.browse(cr, uid, method_id, context=context)
+ return self._export_files(cr, uid, method.id, context=context)
+
+
+ def import_file_form_pop_up(self, cr, uid, method_id, context=None):
+ return self.pool.get('pop.up.file').open_input_file(cr, uid, 'import file', self._import_file_from_pop_up, [method_id], context=context)
+
+ def _import_file_from_pop_up(self, cr, uid, method_id, input_file, input_filename, context=None):
+ #TODO remove this duplicated code from import_file
+ context['pop_up_callback'] = False
+ context['file_exchange_id'] = method_id
+ method = self.browse(cr, uid, method_id, context=context)
+ external_session = ExternalSession(method.referential_id, method)
+ file_fields_obj = self.pool.get('file.fields')
+ model_obj = self.pool.get(method.mapping_id.model_id.model)
+ 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)
+ 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,
+ mapping_id, fields_name, external_file=input_file, context=context)
+ return True
+
+ def _import_files(self, cr, uid, method_id, context=None):
+ if context is None:
+ context={}
+ context['file_exchange_id'] = method_id
+ file_fields_obj = self.pool.get('file.fields')
+ method = self.browse(cr, uid, method_id, context=context)
+ context['report_line_based_on'] = method.mapping_id.model_id.model
+ external_session = ExternalSession(method.referential_id, method)
+ model_obj = self.pool.get(method.mapping_id.model_id.model)
+ 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)
+
+ 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)]
+
+ result = {"create_ids" : [], "write_ids" : []}
+ list_filename = external_session.connection.search(method.folder_path, method.filename)
+ if not list_filename:
+ external_session.logger.info("No file '%s' found on the server"%(method.filename,))
+ for filename in list_filename:
+ res = self._import_one_file(cr, uid, external_session, method_id, filename, defaults,
+ mapping, mapping_id, fields_name, context=context)
+ result["create_ids"] += res.get('create_ids',[])
+ result["write_ids"] += res.get('write_ids',[])
+ return result
+
+ @open_report
+ 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)
+ model_obj = self.pool.get(method.mapping_id.model_id.model)
+ external_session.logger.info("Start to import the file %s"%(filename,))
+ method.start_action('action_before_all', model_obj, context=context)
+ resources = self._get_external_file_resources(cr, uid, external_session, method.folder_path,
+ filename, method.format, fields_name,
+ mapping=mapping,
+ 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,
+ defaults=defaults,
+ mapping=mapping,
+ mapping_id=mapping_id,
+ context=context)
+ ids_imported += res['create_ids'] + res['write_ids']
+ method.start_action('action_after_all', model_obj, ids_imported, context=context)
+ if method.synchronize_from == 'referential' and method.archive_folder_path:
+ external_session.connection.move(method.folder_path, method.archive_folder_path, filename)
+ external_session.logger.info("Finish to import the file %s"%(filename,))
+ return res
+
+ 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)))
+ return False
+
+ def _export_files(self, cr, uid, method_id, context=None):
+ #TODO refactor this method toooooo long!!!!!
+ def flat_resources(resources):
+ result=[]
+ for resource in resources:
+ row_to_flat = False
+ for key, value in resource.items():
+ if key != False:
+ 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'))
+ row_to_flat = value
+ elif isinstance(value, dict):
+ for k,v in flat_resources([value])[0].items():
+ resource[k] = v
+ del resource[key]
+ if row_to_flat:
+ for elements in row_to_flat:
+ tmp_dict = resource.copy()
+ tmp_dict.update(flat_resources([elements])[0])
+ result.append(tmp_dict)
+ else:
+ result.append(resource)
+ return result
+
+ file_fields_obj = self.pool.get('file.fields')
+
+ method = self.browse(cr, uid, method_id, context=context)
+
+ #=== Get connection
+ external_session = ExternalSession(method.referential_id, method)
+ sequence_obj = self.pool.get('ir.sequence')
+ d = sequence_obj._interpolation_dict()
+ filename = sequence_obj._interpolate(method.filename, d)
+ #=== Check if file already exist in specified folder. If so, raise an alert
+ if method.synchronize_from != 'pop_up':
+ self._check_if_file_exist(cr, uid, external_session, method.folder_path, filename, context=context)
+ #=== Start export
+ external_session.logger.info("Start to export %s"%(method.name,))
+ model_obj = self.pool.get(method.mapping_id.model_id.model)
+ method.start_action('action_before_all', model_obj, context=context)
+ defaults = self.get_export_default_fields_values(cr, uid, method_id, context=context)
+ encoding = method.encoding
+
+ #=== Get external file ids and fields
+ fields_name_ids = file_fields_obj.search(cr, uid, [['file_id', '=', method.id]], context=context)
+ fields_info = file_fields_obj.read(cr, uid, fields_name_ids, ['name', 'mapping_line_id'], context=context)
+ #=== Get lines that need to be mapped
+ mapping_line_filter_ids = [x['mapping_line_id'][0] for x in fields_info if x['mapping_line_id']]
+ fields_name = [x['name'] for x in fields_info]
+ #=== Apply filter
+ #TODO add a filter
+ 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)
+ #=== Start mapping
+ mapping,mapping_id = model_obj._init_mapping(cr, uid, external_session.referential_id.id,
+ convertion_type='from_openerp_to_external',
+ mapping_line_filter_ids=mapping_line_filter_ids,
+ mapping_id=method.mapping_id.id,
+ context=context)
+ fields_to_read = [x['internal_field'] for x in mapping[mapping_id]['mapping_lines']]
+ # TODO : CASE fields_to_read is False !!!
+ resources = model_obj._get_oe_resources_into_external_format(cr, uid, external_session,
+ ids_to_export,
+ mapping=mapping,mapping_id=mapping_id,
+ mapping_line_filter_ids=mapping_line_filter_ids,
+ fields=fields_to_read,
+ defaults=defaults,
+ context=context)
+ #=== Check if content to export
+ if not resources:
+ external_session.logger.info("Not data to export for %s"%(method.name,))
+ return True
+ output_file =TemporaryFile('w+b')
+ fields_name = [x.encode(encoding) for x in fields_name]
+ dw = csv.DictWriter(output_file, fieldnames=fields_name, delimiter=';', quotechar='"')
+# dw.writeheader() TODO : only for python >= 2.7
+ row = {}
+ #=== Write CSV file
+ if method.format == 'csv':
+ #=== Write header
+ for name in fields_name:
+ row[name.encode(encoding)] = name.encode(encoding)
+ dw.writerow(row)
+ #=== Write content
+ resources = flat_resources(resources)
+ for resource in resources:
+ row = {}
+ for k,v in resource.items():
+ if k!=False:
+ try:
+ if isinstance(v, unicode) and v!=False:
+ row[k.encode(encoding)] = v.encode(encoding)
+ else:
+ row[k.encode(encoding)] = v
+ except:
+ row[k.encode(encoding)] = "ERROR"
+ #TODO raise an error correctly
+ dw.writerow(row)
+
+ 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):
+ if method.synchronize_from == 'pop_up':
+ return self.pool.get('pop.up.file').open_output_file(cr, uid, filename, output_file, 'File export', context=context)
+ else:
+ external_session.connection.send(method.folder_path, filename, output_file)
+ external_session.logger.info("File transfert have been done succesfully %s"%(method.name,))
+ return True
+
+ def start_action(self, cr, uid, id, action_name, self_object, object_ids=None, resource=None,
+ context=None,external_session=None):
+ if context is None:
+ context={}
+ if isinstance(id, list):
+ id = id[0]
+ method = self.browse(cr, uid, id, context=context)
+ action_code = getattr(method, action_name)
+ if action_code:
+ space = {'self': self_object,
+ 'cr': cr,
+ 'uid': uid,
+ 'ids': object_ids,
+ 'resource': resource,
+ 'context': context,
+ 'external_session':external_session,
+ }
+ 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 'result' in space:
+ return space['result']
+ return True
+
+ def _get_encoding(self, cr, user, context=None):
+ result = [(x, x.replace('_', '-')) for x in set(aliases.values())]
+ result.sort()
+ return result
+
+ def _get_related_mapping_ids(self, cr, uid, ids, field_name, arg, context=None):
+ res = {}
+ for parent in self.browse(cr, uid, ids, context=context):
+ if parent.mapping_id:
+ res[parent.id] = [parent.mapping_id.id] + parent.mapping_id._get_related_child_mapping_ids()
+ else:
+ res[parent.id] = []
+ return res
+
+ _columns = {
+ 'name': fields.char('Name', size=64, help="Exchange description like the name of the supplier, bank,...", require=True),
+ 'type': fields.selection([('in','IN'),('out','OUT'),('in-out', 'IN & OUT')], 'Type',help=("IN for files coming from the other system"
+ "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'),
+ '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),
+ 'filename': fields.char('Filename', size=128, help="Filename will be used to generate the output file name or to read the incoming file. It is possible to use variables (check in sequence for syntax)", require=True),
+ 'folder_path': fields.char('Folder Path', size=128, help="folder that containt the incomming or the outgoing file"),
+ 'archive_folder_path': fields.char('Archive Folder Path', size=128, help="if a path is set when a file is imported the file will be automatically moved to this folder"),
+ 'encoding': fields.selection(_get_encoding, 'Encoding', require=True),
+ '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_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"),
+ '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'),
+ 'do_not_update':fields.boolean('Do Not Update'),
+ 'pre_processing': fields.text('Pre-Processing', help="This python code will be executed before merge of elements of the import"),
+ 'mapping_template_id':fields.many2one('external.mapping.template', 'External Mapping Template', require="True"),
+ 'notes': fields.text('Notes'),
+ 'related_mapping_ids': fields.function(_get_related_mapping_ids, type="many2many", relation="external.mapping", string='Related Mappings'),
+ 'synchronize_from': fields.selection([('referential', 'Referential'), ('pop_up', 'Pop Up')], string='Synchronize From'),
+ 'linked_task': fields.many2one('file.exchange', 'Linked Task'),
+ }
+
+ def get_absolute_id(self, cr, uid, id, context=None):
+ if isinstance(id,list):
+ id = id[0]
+ file_exchange = self.browse(cr, uid, id, context=context)
+ file_exchange_id = file_exchange.get_external_id(context=context)[file_exchange.id]
+ if not file_exchange_id:
+ file_exchange_id = file_exchange.name.replace(' ','_').replace('.','_')
+ return file_exchange_id
+
+ # Method to export the exchange file
+ def create_exchange_file(self, cr, uid, id, context=None):
+ if isinstance(id,list):
+ id = id[0]
+ output_file = TemporaryFile('w+b')
+ fieldnames = ['id', 'name','referential_id:id', 'type','do_not_update', 'mapping_template_id:id', 'encoding', 'format', 'search_filter','delimiter', 'folder_path', 'archive_folder_path', 'filename', 'action_before_all', 'action_after_all', 'action_before_each', 'action_after_each', 'check_if_import', 'pre_processing']
+ csv = FileCsvWriter(output_file, fieldnames, encoding="utf-8", writeheader=True, delimiter=',', quotechar='"')
+ current_file = self.browse(cr, uid, id, context=context)
+ row = {
+ 'id': current_file.get_absolute_id(context=context),
+ 'name': current_file.name,
+ 'referential_id:id':current_file.referential_id.get_absolute_id(context=context),
+ 'type': current_file.type,
+ 'do_not_update': str(current_file.do_not_update),
+ 'mapping_template_id:id': current_file.mapping_id.get_absolute_id(context=context),
+ 'encoding': current_file.encoding,
+ 'format': current_file.format,
+ 'search_filter': current_file.search_filter or '',
+# 'lang'
+ 'delimiter': current_file.delimiter,
+ 'folder_path': current_file.folder_path or '',
+ 'archive_folder_path': current_file.archive_folder_path or '',
+ 'filename': current_file.filename,
+ 'action_before_all': current_file.action_before_all or '',
+ 'action_after_all': current_file.action_after_all or '',
+ 'action_before_each': current_file.action_before_each or '',
+ 'action_after_each': current_file.action_after_each or '',
+ 'check_if_import': current_file.check_if_import or '',
+ 'pre_processing': current_file.pre_processing or '',
+ }
+ 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):
+ id = id[0]
+ output_file = TemporaryFile('w+b')
+ fieldnames = ['id', 'is_required', 'name', 'custom_name', 'sequence', 'mappinglines_template_id:id', 'file_id:id', 'default_value', 'advanced_default_value', 'merge_key']
+ csv = FileCsvWriter(output_file, fieldnames, encoding="utf-8", writeheader=True, delimiter=',', quotechar='"')
+ current_file = self.browse(cr, uid, id, context=context)
+ for field in current_file.field_ids:
+ row = {
+ 'file_id:id': field.file_id.get_absolute_id(context=context),
+ 'name': field.name,
+ 'id': field.get_absolute_id(context=context),
+ 'sequence': str(field.sequence),
+ 'mappinglines_template_id:id': field.mapping_line_id and field.mapping_line_id.get_absolute_id(context=context) or '',
+ 'custom_name': field.custom_name or '',
+ 'default_value': field.default_value or '',
+ 'is_required': str(field.is_required),
+ 'advanced_default_value': field.advanced_default_value or '',
+ 'merge_key': str(field.merge_key),
+ }
+ csv.writerow(row)
+ return self.pool.get('pop.up.file').open_output_file(cr, uid, 'file.fields.csv', output_file, 'File Exchange Fields Export', context=context)
+
+ # Method to export the default fields file
+ def create_file_default_fields(self, cr, uid, id, context=None):
+ if isinstance(id,list):
+ id = id[0]
+ output_file = TemporaryFile('w+b')
+ fieldnames = ['id', 'import_default_field:id', 'import_default_value', 'file_id:id', 'mapping_template_id:id', 'type']
+ csv = FileCsvWriter(output_file, fieldnames, encoding="utf-8", writeheader=True, delimiter=',', quotechar='"')
+ current_file = self.browse(cr, uid, id, context=context)
+ for field in current_file.import_default_fields:
+ row = {
+ 'id': field.get_absolute_id(context=context),
+ 'import_default_field:id': field.import_default_field.get_external_id(context=context)[field.import_default_field.id],
+ 'import_default_value': field.import_default_value,
+ 'file_id:id': current_file.get_absolute_id(context=context),
+ 'mapping_template_id:id': field.mapping_id.get_absolute_id(context=context),
+ 'type': field.type,
+ }
+ csv.writerow(row)
+ return self.pool.get('pop.up.file').open_output_file(cr, uid, 'file.default.import.values.csv', output_file, 'File Exchange Fields Export', context=context)
+
+ def load_mapping(self, cr, uid, ids, context=None):
+ for method in self.browse(cr, uid, ids, context=context):
+ mapping_id = self.pool.get('external.mapping').search(cr, uid, [('referential_id', '=', method.referential_id.id),('template_id', '=', method.mapping_template_id.id)], context=context)[0]
+ self.write(cr, uid, method.id, {'mapping_id': mapping_id}, context=context)
+ for default_field in method.import_default_fields:
+ default_mapping_id = self.pool.get('external.mapping').search(cr, uid, [('referential_id', '=', method.referential_id.id),('template_id', '=', default_field.mapping_template_id.id)], context=context)[0]
+ default_field.write({'mapping_id': default_mapping_id}, context=context)
+ for field in method.field_ids:
+ if field.mappinglines_template_id:
+ field_mapping_line_id = self.pool.get('external.mapping.line').search(cr, uid, [('referential_id', '=', method.referential_id.id),('template_id', '=', field.mappinglines_template_id.id)], context=context)[0]
+ field.write({'mapping_line_id': field_mapping_line_id}, context=context)
+ return True
+
+file_exchange()
+
+class file_fields(osv.osv):
+ _name = "file.fields"
+ _description = "file fields"
+ _order='sequence'
+
+ def _clean_vals(self, vals):
+ if vals.get('custom_name'):
+ vals['mapping_line_id'] = False
+ elif vals.get('mapping_line_id'):
+ vals['custom_name'] = False
+ return vals
+
+ def create(self, cr, uid, vals, context=None):
+ vals = self._clean_vals(vals)
+ return super(file_fields, self).create(cr, uid, vals, context=context)
+
+ def write(self, cr, uid, ids, vals, context=None):
+ vals = self._clean_vals(vals)
+ return super(file_fields, self).write(cr, uid, ids, vals, context=context)
+
+ def _name_get_fnc(self, cr, uid, ids, name, arg, context=None):
+ res = {}
+ for file_field in self.browse(cr, uid, ids, context):
+ res[file_field.id] = file_field.mapping_line_id and file_field.mapping_line_id.external_field or file_field.custom_name
+ return res
+
+ _columns = {
+ #TODO the field name should be autocompleted bey the external field when selecting a mapping
+ 'name': fields.function(_name_get_fnc, type="char", string='Name', method=True),
+ 'custom_name': fields.char('Custom Name', size=128),
+ 'sequence': fields.integer('Sequence', required=True, help="The sequence field is used to define the order of the fields"),
+ #TODO add a filter only fields that belong to the main object or to sub-object should be available
+ 'mapping_line_id': fields.many2one('external.mapping.line', 'OpenERP Mapping', domain = "[('referential_id', '=', parent.referential_id),('mapping_id', 'in', parent.related_mapping_ids[0][2])]"),
+ 'file_id': fields.many2one('file.exchange', 'File Exchange', require="True"),
+ 'default_value': fields.char('Default Value', size=64),
+ 'advanced_default_value': fields.text('Advanced Default Value', help=("This python code will be evaluate and the value"
+ "in the varaible result will be used as defaut value")),
+ 'alternative_key': fields.related('mapping_line_id', 'alternative_key', type='boolean', string='Alternative Key'),
+ 'is_required' : fields.boolean('Is required', help="Is this field required in the exchange ?"),
+ 'mappinglines_template_id':fields.many2one('external.mappinglines.template', 'External Mappinglines Template'),
+ 'merge_key': fields.boolean('Merge Key', help="Used to merge each line with the same value of this field")
+ }
+
+ def get_absolute_id(self, cr, uid, id, context=None):
+ if isinstance(id,list):
+ id = id[0]
+ field = self.browse(cr, uid, id, context=context)
+ field_id = field.get_external_id(context=context)[field.id]
+ if not field_id:
+ file_name = field.file_id.name.replace(' ','_')
+ field_name = field.name
+ sequence = str(field.sequence)
+ field_id = (file_name + '_' + field_name + '_' + sequence).replace('.','_')
+ return field_id
+
+file_fields()
+
+class file_default_import_values(osv.osv):
+ _name = "file.default.import.values"
+ _description = "file default import values"
+
+ _columns = {
+ 'import_default_field':fields.many2one('ir.model.fields', 'Default Field'),
+ 'import_default_value':fields.char('Default Value', size=128),
+ 'file_id': fields.many2one('file.exchange', 'File Exchange'),
+ 'mapping_id':fields.many2one('external.mapping', 'External Mapping'),
+ 'mapping_template_id':fields.many2one('external.mapping.template', 'External Mapping Template'),
+ 'type':fields.selection([('integer', 'Integer'), ('float', 'Float'),('char','String'),('dict','Dict'),('list','List')], 'Field Type'),
+ }
+
+ def get_absolute_id(self, cr, uid, id, context=None):
+ if isinstance(id,list):
+ id = id[0]
+ field = self.browse(cr, uid, id, context=context)
+ field_id = field.get_external_id(context=context)[field.id]
+ if not field_id:
+ file_name = field.file_id.name.replace(' ','_')
+ field_name = field.import_default_field.name
+ field_id = (file_name + '_' + field_name).replace('.','_')
+ return field_id
+
+ def on_change_models(self, cr, uid, ids, mapping_id=False, context=None):
+ res = {}
+ if mapping_id:
+ mapping = self.pool.get('external.mapping').browse(cr, uid, mapping_id, context=context)
+ models = [x for x in self.pool.get(mapping.model_id.model)._inherits]
+ models.append(mapping.model_id.model)
+ res['import_default_field'] = [('model', 'in', models)]
+ return {'domain': res}
=== added file 'file_exchange/file_exchange_menu.xml'
--- file_exchange/file_exchange_menu.xml 1970-01-01 00:00:00 +0000
+++ file_exchange/file_exchange_menu.xml 2012-09-13 01:56:18 +0000
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<openerp>
+ <data>
+
+ <menuitem id="menu_file_exchange" name="File exchange" parent="base.menu_administration" sequence="10"/>
+
+ <!-- File exchange -->
+ <record id="actions_open_file_exchange" model="ir.actions.act_window">
+ <field name="name">File exchange</field>
+ <field name="res_model">file.exchange</field>
+ <field name="view_type">form</field>
+ <field name="view_mode">tree,form</field>
+ <field name="context">{'wizard_object' : 'file.exchange', 'function' : 'start_task', 'object_link' : 'file.exchange' }</field>
+ </record>
+
+ <menuitem id="menu_files_exchange_list" name="Files exchange" parent="menu_file_exchange" action="actions_open_file_exchange" />
+
+
+
+ </data>
+</openerp>
=== added file 'file_exchange/file_exchange_osv.py'
--- file_exchange/file_exchange_osv.py 1970-01-01 00:00:00 +0000
+++ file_exchange/file_exchange_osv.py 2012-09-13 01:56:18 +0000
@@ -0,0 +1,73 @@
+# -*- encoding: utf-8 -*-
+###############################################################################
+# #
+# ftp_external_referential for OpenERP #
+# Copyright (C) 2011 Akretion 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 #
+# 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/>. #
+# #
+###############################################################################
+
+from osv import osv, fields
+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)
+@catch_error_in_report
+def _record_one_external_resource(self, cr, uid, external_session, resource, **kwargs):
+ context=kwargs.get('context')
+ method = self.pool.get('file.exchange').browse(cr, uid, context['file_exchange_id'], context=context)
+ check = method.start_action('check_if_import', self, None, resource, context=context)
+ res = {}
+ if check:
+ method.start_action('action_before_each', self, None, resource, context=context)
+ res = self._feo_record_one_external_resource(cr, uid, external_session, resource, **kwargs)
+ res_id = res.get('create_id', False) or res.get('write_id', False)
+ if res_id:
+ 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)
+def _get_default_import_values(self, cr, uid, external_session, mapping_id=None, defaults=None, context=None):
+ if not defaults:
+ defaults = {}
+ method = external_session.sync_from_object
+ mapping = self.pool.get('external.mapping').browse(cr, uid, mapping_id, context=context)
+ for field in method.import_default_fields:
+ if field.mapping_id.id == mapping.id:
+ if field.type == 'integer':
+ defaults[field.import_default_field.name] = int(field.import_default_value)
+ elif field.type == 'float':
+ defaults[field.import_default_field.name] = float(field.import_default_value.replace(',','.'))
+ elif field.type in ['list','dict']:
+ defaults[field.import_default_field.name] = eval(field.import_default_value)
+ else:
+ defaults[field.import_default_field.name] = str(field.import_default_value)
+ return defaults
+
+osv.osv._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
+
=== added file 'file_exchange/file_exchange_view.xml'
--- file_exchange/file_exchange_view.xml 1970-01-01 00:00:00 +0000
+++ file_exchange/file_exchange_view.xml 2012-09-13 01:56:18 +0000
@@ -0,0 +1,188 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ file_exchange for OpenERP
+ Copyright (C) 2012 Akretion Emmanuel Samyn <emmanuel.samyn@xxxxxxxxxxxx>
+ The licence is in the file __openerp__.py
+-->
+
+<openerp>
+ <data>
+ <!-- VIEW FOR THE OBJECT : file_exchange -->
+ <record id="file_exchange_view_form" model="ir.ui.view">
+ <field name="name">file_exchange.file_exchange.view_form</field>
+ <field name="model">file.exchange</field>
+ <field eval="16" name="priority"/>
+ <field name="type">form</field>
+ <field name="arch" type="xml">
+ <form string="file_exchange">
+ <notebook colspan="4">
+ <page string="Main information" >
+ <field name="name" />
+ <field name="referential_id" />
+ <field name="scheduler" />
+ <field name="linked_task" />
+ <field name="type" />
+ <field name="do_not_update" />
+ <field name="mapping_id" />
+ <field name="encoding"/>
+ <field name="format" />
+ <field name="search_filter" attrs="{'invisible':[('type','!=','out')]}"/>
+ <field name="lang" />
+ <field name="delimiter" />
+ <field name="synchronize_from" />
+ <field name="filename" attrs="{'invisible':[('synchronize_from','=','pop_up'), ('type','=','out')]}"/>
+ <group name="file_folder" colspan="2" col="4" attrs="{'invisible':[('synchronize_from','=','pop_up')]}">
+ <field name="folder_path" />
+ <field name="archive_folder_path" attrs="{'invisible':[('type','=','out')]}"/>
+ </group>
+ <group name="Start Task" colspan="2" col="4">
+ <button name="import_task" string="Import files" type="object" attrs="{'invisible':[('type','=','out')]}"/>
+ <button name="export_task" string="Export files" type="object" attrs="{'invisible':[('type','=','in')]}"/>
+ <button name="load_mapping" string="Load Mapping" type="object" attrs="{'invisible':[('referential_id', '=', False)]}"/>
+ </group>
+ <field name="related_mapping_ids" invisible="1" />
+
+ </page>
+ <page string="Fields">
+ <field name="field_ids" colspan="4" nolabel="1"/>
+ </page>
+ <page string="Pre-Processing" >
+ <separator string="Pre-Processing" colspan="4"/>
+ <field name="pre_processing" colspan="4" nolabel="1"/>
+ </page>
+ <page string="Action Before/After All" >
+ <separator string="Action Before All" colspan="4"/>
+ <field name="action_before_all" colspan="4" nolabel="1"/>
+ <separator string="Action After All" colspan="4"/>
+ <field name="action_after_all" colspan="4" nolabel="1"/>
+ </page>
+ <page string="Action Before/After Each" >
+ <group name="Check If Import" colspan="4" attrs="{'invisible':[('type','!=','in')]}" >
+ <separator string="Check If Import" colspan="4" />
+ <field name="check_if_import" colspan="4" nolabel="1" />
+ </group>
+ <separator string="Action Before Each" colspan="4"/>
+ <field name="action_before_each" colspan="4" nolabel="1"/>
+ <separator string="Action After Each" colspan="4"/>
+ <field name="action_after_each" colspan="4" nolabel="1"/>
+ </page>
+ <page string="CSV file generation" groups="base_external_referentials.group_export_mapping" >
+ <button name="create_exchange_file" string="Export exchange file" colspan="2" type="object" />
+ <button name="create_file_fields" string="Export fields file" colspan="2" type="object" />
+ <button name="create_file_default_fields" string="Export default fields file" colspan="2" type="object" />
+ </page>
+ <page string="Import Default Values">
+ <field name="import_default_fields" colspan="4" nolabel="1"/>
+ </page>
+ <page string="Notes">
+ <field name="notes" colspan="4" nolabel="1"/>
+ </page>
+ </notebook>
+ </form>
+ </field>
+ </record>
+
+ <record id="file_exchange_view_tree" model="ir.ui.view">
+ <field name="name">file_exchange_view_tree</field>
+ <field name="model">file.exchange</field>
+ <field eval="16" name="priority"/>
+ <field name="type">tree</field>
+ <field name="arch" type="xml">
+ <tree string="file_exchange">
+ <field name="referential_id" />
+ <field name="name" />
+ <field name="format" />
+ <field name="type" />
+ <field name="scheduler" />
+ </tree>
+ </field>
+ </record>
+
+ <!-- VIEW FOR THE OBJECT : file_fields -->
+ <record id="file_fields_view_form" model="ir.ui.view">
+ <field name="name">file_exchange.file_fields.view_form</field>
+ <field name="model">file.fields</field>
+ <field eval="16" name="priority"/>
+ <field name="type">form</field>
+ <field name="arch" type="xml">
+ <form string="file_fields">
+ <field name="sequence" />
+ <field name="mapping_line_id" attrs="{'readonly':[('custom_name','!=',False)]}">
+ <tree>
+ <field name="external_field"/>
+ <field name="mapping_id"/>
+ </tree>
+ </field>
+ <field name="custom_name" attrs="{'readonly':[('mapping_line_id','!=',False)]}"/>
+ <field name="default_value" attrs="{'readonly':[('advanced_default_value','!=',False)]}"/>
+ <field name="is_required"/>
+ <separator string="Advanced Default Value" colspan="4"/>
+ <field name='alternative_key'/>
+ <field name='merge_key'/>
+ <field name="advanced_default_value" nolabel="1" colspan="4"/>
+ </form>
+ </field>
+ </record>
+
+ <record id="file_fields_view_tree" model="ir.ui.view">
+ <field name="name">file_fields_view_tree</field>
+ <field name="model">file.fields</field>
+ <field eval="16" name="priority"/>
+ <field name="type">tree</field>
+ <field name="arch" type="xml">
+ <tree editable="top" string="file_fields">
+ <field name="sequence" />
+ <field name="is_required"/>
+ <field name="mapping_line_id" attrs="{'readonly':[('custom_name','!=',False)]}"/>
+ <field name="custom_name" attrs="{'readonly':[('mapping_line_id','!=',False)]}"/>
+ <field name="name"/>
+ <field name="default_value"/>
+ <field name='alternative_key'/>
+ <field name='merge_key'/>
+ </tree>
+ </field>
+ </record>
+
+ <!-- VIEW FOR THE OBJECT : default_fields -->
+ <record id="default_fields_view_form" model="ir.ui.view">
+ <field name="name">file_exchange.default_fields.view_form</field>
+ <field name="model">file.default.import.values</field>
+ <field eval="16" name="priority"/>
+ <field name="type">form</field>
+ <field name="arch" type="xml">
+ <form string="file default import values">
+ <field name="mapping_id" on_change="on_change_models(mapping_id)"/>
+ <field name="import_default_field" />
+ <field name="import_default_value" />
+ <field name="type" />
+ </form>
+ </field>
+ </record>
+
+ <record id="default_fields_view_tree" model="ir.ui.view">
+ <field name="name">file_exchange.default_fields_view_tree</field>
+ <field name="model">file.default.import.values</field>
+ <field eval="16" name="priority"/>
+ <field name="type">tree</field>
+ <field name="arch" type="xml">
+ <tree editable="top" string="file default import values">
+ <field name="mapping_id" on_change="on_change_models(mapping_id)"/>
+ <field name="import_default_field" />
+ <field name="import_default_value" />
+ <field name="type" />
+ </tree>
+ </field>
+ </record>
+
+<!--WIZARD TO ADD SCHEDULER -->
+
+ <record id="ir_action_create_scheduler_in_file_exchange" model="ir.values">
+ <field name="key2">client_action_multi</field>
+ <field name="model">file.exchange</field>
+ <field name="name">Create a scheduler</field>
+ <field eval="'ir.actions.act_window,%d'%ref('base_scheduler_creator.action_scheduler_creator_wizard')" name="value"/>
+ <field eval="True" name="object"/>
+ </record>
+
+ </data>
+</openerp>
=== added directory 'file_exchange/security'
=== added file 'file_exchange/security/file_exchange_security.xml'
--- file_exchange/security/file_exchange_security.xml 1970-01-01 00:00:00 +0000
+++ file_exchange/security/file_exchange_security.xml 2012-09-13 01:56:18 +0000
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ file_exchange for OpenERP
+ Copyright (C) 2011 Akretion Beau Sébastien <sebastien.beau@xxxxxxxxxxxx>
+ The licence is in the file __openerp__.py
+-->
+
+<openerp>
+ <data>
+
+ <record id="file_exchange.group_manager" model="res.groups">
+ <field name="name">File Exchange Manager</field>
+ </record>
+
+ </data>
+</openerp>
=== added file 'file_exchange/security/ir.model.access.csv'
--- file_exchange/security/ir.model.access.csv 1970-01-01 00:00:00 +0000
+++ file_exchange/security/ir.model.access.csv 2012-09-13 01:56:18 +0000
@@ -0,0 +1,7 @@
+id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
+access_file_exchange_user,file_exchange_file_exchange,model_file_exchange,base.group_user,1,0,0,0
+access_file_exchange_manager,file_exchange_file_exchange,model_file_exchange,file_exchange.group_manager,1,1,1,1
+access_file_fields_user,file_exchange_file_fields,model_file_fields,base.group_user,1,0,0,0
+access_file_fields_manager,file_exchange_file_fields,model_file_fields,file_exchange.group_manager,1,1,1,1
+access_file_default_import_values_user,file_exchange_file_default_import_values,model_file_default_import_values,base.group_user,1,0,0,0
+access_file_default_import_values_manager,file_exchange_file_default_import_values,model_file_default_import_values,file_exchange.group_manager,1,1,1,1
=== added directory 'file_exchange/settings'
=== added file 'file_exchange/settings/external.referential.category.csv'
--- file_exchange/settings/external.referential.category.csv 1970-01-01 00:00:00 +0000
+++ file_exchange/settings/external.referential.category.csv 2012-09-13 01:56:18 +0000
@@ -0,0 +1,2 @@
+"id","name"
+"file-exchange","File Exchange"
=== added directory 'report_synchronizer'
=== added file 'report_synchronizer/__init__.py'
--- report_synchronizer/__init__.py 1970-01-01 00:00:00 +0000
+++ report_synchronizer/__init__.py 2012-09-13 01:56:18 +0000
@@ -0,0 +1,28 @@
+# -*- encoding: utf-8 -*-
+###############################################################################
+# #
+# report_synchronizer for OpenERP #
+# Copyright (C) 2012 Akretion 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 #
+# 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 report_osv
+
+
+
+
=== added file 'report_synchronizer/__openerp__.py'
--- report_synchronizer/__openerp__.py 1970-01-01 00:00:00 +0000
+++ report_synchronizer/__openerp__.py 2012-09-13 01:56:18 +0000
@@ -0,0 +1,40 @@
+# -*- encoding: utf-8 -*-
+###############################################################################
+# #
+# report_synchronizer for OpenERP #
+# Copyright (C) 2012 Akretion 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 #
+# 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': 'report_synchronizer',
+ 'version': '0.1',
+ 'category': 'Generic Modules/Others',
+ 'license': 'AGPL-3',
+ 'description': """Abstract module to send report to external system""",
+ 'author': 'Akretion',
+ 'website': 'http://www.akretion.com/',
+ 'depends': ['base_external_file_protocole'],
+ 'init_xml': [],
+ 'update_xml': [
+ ],
+ 'demo_xml': [],
+ 'installable': True,
+ 'active': False,
+}
+
=== added file 'report_synchronizer/report_osv.py'
--- report_synchronizer/report_osv.py 1970-01-01 00:00:00 +0000
+++ report_synchronizer/report_osv.py 2012-09-13 01:56:18 +0000
@@ -0,0 +1,37 @@
+# -*- encoding: utf-8 -*-
+###############################################################################
+# #
+# report_synchronizer for OpenERP #
+# Copyright (C) 2012 Akretion 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 #
+# 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/>. #
+# #
+###############################################################################
+
+from osv import osv, fields
+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):
+ 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)
+ external_session.connection.send(path, file_name, output_file)
+ return file_name
+