Thibault Francois
8 years ago
13 changed files with 0 additions and 1187 deletions
-
22beesdoo_migration_asbl_to_coop/__init__.py
-
40beesdoo_migration_asbl_to_coop/__openerp__.py
-
220beesdoo_migration_asbl_to_coop/migration.py
-
31beesdoo_migration_asbl_to_coop/view/migration.xml
-
25import_base/__init__.py
-
42import_base/__openerp__.py
-
415import_base/import_framework.py
-
220import_base/mapper.py
-
23import_odoo/__init__.py
-
42import_odoo/__openerp__.py
-
38import_odoo/odoo_connector.py
-
2import_odoo/security/ir.model.access.csv
-
67import_odoo/view/connector.xml
@ -1,22 +0,0 @@ |
|||||
# -*- coding: utf-8 -*- |
|
||||
############################################################################## |
|
||||
# |
|
||||
# OpenERP, Open Source Management Solution |
|
||||
# Copyright (C) 2004-2010 Openerp sa (<http://openerp.com>). |
|
||||
# |
|
||||
# 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 migration |
|
@ -1,40 +0,0 @@ |
|||||
# -*- coding: utf-8 -*- |
|
||||
############################################################################## |
|
||||
# |
|
||||
# OpenERP, Open Source Management Solution |
|
||||
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>). |
|
||||
# |
|
||||
# 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': 'Import data from ASBL', |
|
||||
'version': '0.9', |
|
||||
'category': 'Import', |
|
||||
'description': """ |
|
||||
This module provide a tools to import data from ASBL |
|
||||
""", |
|
||||
'author': 'Thibault Francois', |
|
||||
'website': 'https://github.com/tfrancoi/', |
|
||||
'depends': ['base', 'import_base', 'import_odoo'], |
|
||||
'data': [ |
|
||||
'view/migration.xml' |
|
||||
], |
|
||||
'test': [], #TODO provide test |
|
||||
'installable': True, |
|
||||
'auto_install': False, |
|
||||
} |
|
||||
|
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: |
|
@ -1,220 +0,0 @@ |
|||||
# -*- coding: utf-8 -*- |
|
||||
|
|
||||
from openerp import models, fields, api |
|
||||
from openerp.exceptions import Warning |
|
||||
|
|
||||
from openerp.addons.import_base.import_framework import * |
|
||||
from openerp.addons.import_base.mapper import * |
|
||||
|
|
||||
|
|
||||
class odoo_connection_data(models.TransientModel): |
|
||||
|
|
||||
_name = 'beesdoo.import.asbl' |
|
||||
|
|
||||
@api.multi |
|
||||
def migrate(self): |
|
||||
imp = migration_framework(self, self.env.cr, self.env.uid, "Odoo", 'beesdoo.import.asbl', dict(self.env.context)) |
|
||||
imp.launch_import() |
|
||||
|
|
||||
|
|
||||
class migration_framework(import_framework): |
|
||||
black_list_field = { |
|
||||
|
|
||||
} |
|
||||
|
|
||||
tables = ['product.category', |
|
||||
'product.uom', |
|
||||
'product.uom.categ', |
|
||||
'pos.category', |
|
||||
'res.partner', |
|
||||
'product.template', |
|
||||
'product.supplierinfo', |
|
||||
] |
|
||||
|
|
||||
table_domain = { |
|
||||
'res.partner' : [('supplier', '=', True), '|', ('active', '=', True), ('active', '=', False)], |
|
||||
'product.template' : ['|', ('active', '=', True), ('active', '=', False)] |
|
||||
} |
|
||||
|
|
||||
|
|
||||
def initialize(self): |
|
||||
self.connection = self.obj.env['import.odoo.connection'].search([], limit=1) |
|
||||
self.set_table_list(self.tables) |
|
||||
print self.connection.name |
|
||||
|
|
||||
def _get_field(self, model): |
|
||||
fields = ['id'] |
|
||||
|
|
||||
for mapper_object in self.get_mapping()[model.model_name]['map'].values(): |
|
||||
if isinstance(mapper_object, basestring): |
|
||||
fields.append(mapper_object) |
|
||||
else: |
|
||||
fields.extend(mapper_object.get_fields()) |
|
||||
print "read field", fields |
|
||||
return fields |
|
||||
|
|
||||
def res_to_dict(self, fields, datas): |
|
||||
datas = datas['datas'] |
|
||||
res = [] |
|
||||
for data in datas: |
|
||||
data_dict = {} |
|
||||
for i, field in enumerate(fields): |
|
||||
data_dict[field] = data[i] |
|
||||
res.append(data_dict) |
|
||||
return res |
|
||||
|
|
||||
def get_data(self, table): |
|
||||
con = self.connection._get_connection() |
|
||||
obj = con.get_model(table) |
|
||||
fields = self._get_field(obj) |
|
||||
ids = obj.search(self.table_domain.get(table, [])) |
|
||||
datas = obj.export_data(ids, fields, context={'lang' : 'fr_BE'}) |
|
||||
return self.res_to_dict(fields, datas) |
|
||||
|
|
||||
def _generate_xml_id(self, name, table): |
|
||||
""" |
|
||||
@param name: name of the object, has to be unique in for a given table |
|
||||
@param table : table where the record we want generate come from |
|
||||
@return: a unique xml id for record, the xml_id will be the same given the same table and same name |
|
||||
To be used to avoid duplication of data that don't have ids |
|
||||
""" |
|
||||
return name |
|
||||
|
|
||||
def get_mapping(self): |
|
||||
return { |
|
||||
'product.category': { |
|
||||
'model' : 'product.category', |
|
||||
'dependencies' : [], |
|
||||
'map' : { |
|
||||
'name' : 'name', |
|
||||
'parent_id/id_parent' : 'parent_id/id', |
|
||||
'type' : 'type', |
|
||||
|
|
||||
} |
|
||||
}, |
|
||||
'product.uom.categ' : { |
|
||||
'model' : 'product.uom.categ', |
|
||||
'dependencies' : [], |
|
||||
'map' : { |
|
||||
'name' : 'name', |
|
||||
} |
|
||||
}, |
|
||||
'product.uom': { |
|
||||
'model' : 'product.uom', |
|
||||
'dependencies' : ['product.uom.categ'], |
|
||||
'map' : { |
|
||||
'name' : 'name', |
|
||||
'category_id/id' : 'category_id/id', |
|
||||
'rounding' : 'rounding', |
|
||||
'uom_type' : 'uom_type', |
|
||||
'factor' : 'factor', |
|
||||
'factor_inv' : 'factor_inv', |
|
||||
} |
|
||||
}, |
|
||||
'pos.category': { |
|
||||
'model' : 'pos.category', |
|
||||
'dependencies' : [], |
|
||||
'map' : { |
|
||||
'id' : 'id', |
|
||||
'name' : 'name', |
|
||||
'parent_id/id_parent' : 'parent_id/id', |
|
||||
} |
|
||||
}, |
|
||||
'res.partner': { |
|
||||
'model' : 'res.partner', |
|
||||
'dependencies' : [], |
|
||||
'map' : { |
|
||||
'active' : 'active', |
|
||||
'barcode' : 'barcode', |
|
||||
'birthdate' : 'birthdate', |
|
||||
'city' : 'city', |
|
||||
'comment' : 'comment', |
|
||||
'company_type' : 'company_type', |
|
||||
'contact_address' : 'contact_address', |
|
||||
'country_id/id' : 'country_id/id', |
|
||||
'email' : 'email', |
|
||||
'employee' : 'employee', |
|
||||
'fax' : 'fax', |
|
||||
'first_name' : 'first_name', |
|
||||
'function' : 'function', |
|
||||
'is_company' : 'is_company', |
|
||||
'lang' : 'lang', |
|
||||
'last_name' : 'last_name', |
|
||||
'mobile' : 'mobile', |
|
||||
'name' : 'name', |
|
||||
'parent_id/id_parent' : 'parent_id/id', |
|
||||
'phone' : 'phone', |
|
||||
'ref' : 'ref', |
|
||||
'street' : 'street', |
|
||||
'street2' : 'street2', |
|
||||
'supplier' : 'supplier', |
|
||||
'website' : 'website', |
|
||||
'zip' : 'zip', |
|
||||
'supplier' : 'supplier', |
|
||||
'customer' : 'customer', |
|
||||
'vat' : 'vat', |
|
||||
} |
|
||||
}, |
|
||||
'beesdoo.product.label' : { |
|
||||
'model' : 'beesdoo.product.label', |
|
||||
'dependencies' : [], |
|
||||
'map' : { |
|
||||
'color_code' : 'color_code', |
|
||||
'name' : 'name', |
|
||||
'type' : 'type', |
|
||||
} |
|
||||
}, |
|
||||
'product.template': { |
|
||||
'model' : 'product.template', |
|
||||
'dependencies' : ['pos.category', 'product.category', 'beesdoo.product.label'], |
|
||||
'map' : { |
|
||||
'active' : 'active', |
|
||||
'available_in_pos' : 'available_in_pos', |
|
||||
'barcode' : 'barcode', |
|
||||
'categ_id/id' : 'categ_id/id', |
|
||||
'default_code' : 'default_code', |
|
||||
'description' : 'description', |
|
||||
'description_picking' : 'description_picking', |
|
||||
'description_purchase' : 'description_purchase', |
|
||||
'description_sale' : 'description_sale', |
|
||||
'eco_label/id' : 'eco_label/id', |
|
||||
'fair_label/id' : 'fair_label/id', |
|
||||
'invoice_policy' : 'invoice_policy', |
|
||||
'local_label/id' : 'local_label/id', |
|
||||
'name' : 'name', |
|
||||
'origin_label/id' : 'origin_label/id', |
|
||||
'pos_categ_id/id' : 'pos_categ_id/id', |
|
||||
'purchase_ok' : 'purchase_ok', |
|
||||
'sale_delay' : 'sale_delay', |
|
||||
'sale_ok' : 'sale_ok', |
|
||||
'standard_price' : 'standard_price', |
|
||||
'supplier_taxes_id/id' : 'supplier_taxes_id/id', #Taxes problème |
|
||||
'taxes_id/id' : 'taxes_id/id', |
|
||||
'to_weight' : 'to_weight', |
|
||||
'type' : 'type', |
|
||||
'uom_id/id' : 'uom_id/id', |
|
||||
'uom_po_id/id' : 'uom_po_id/id', |
|
||||
'weight' : 'weight', |
|
||||
'list_price' : 'list_price', |
|
||||
} |
|
||||
}, |
|
||||
'product.supplierinfo': { |
|
||||
'model' : 'product.supplierinfo', |
|
||||
'dependencies' : ['product.template'], |
|
||||
'map' : { |
|
||||
'delay' : 'delay', |
|
||||
'min_qty' : 'min_qty', |
|
||||
'name/id' : 'name/id', |
|
||||
'price' : 'price', |
|
||||
'product_code' : 'product_code', |
|
||||
'product_name' : 'product_name', |
|
||||
'product_uom/id' : 'product_uom/id', |
|
||||
'date_start' : 'date_start', |
|
||||
'date_end' : 'date_end', |
|
||||
'product_tmpl_id/id': 'product_tmpl_id/id', |
|
||||
} |
|
||||
}, |
|
||||
} |
|
||||
|
|
||||
|
|
||||
|
|
@ -1,31 +0,0 @@ |
|||||
<?xml version="1.0" encoding="utf-8"?> |
|
||||
<openerp> |
|
||||
<data> |
|
||||
<record model="ir.ui.view" id="import_odoo_form"> |
|
||||
<field name="name">beesdoo.import.asbl.form</field> |
|
||||
<field name="model">beesdoo.import.asbl</field> |
|
||||
<field name="arch" type="xml"> |
|
||||
<form string="Migration" version="7.0"> |
|
||||
<footer> |
|
||||
<button type="object" name="migrate" string="Migrate" /> |
|
||||
or |
|
||||
<button special="cancel" name="cancel" string="Cancel" /> |
|
||||
</footer> |
|
||||
</form> |
|
||||
</field> |
|
||||
</record> |
|
||||
|
|
||||
<record model="ir.actions.act_window" id="odoo_import_form"> |
|
||||
<field name="name">Import From ASBL</field> |
|
||||
<field name="res_model">beesdoo.import.asbl</field> |
|
||||
<field name="view_type">form</field> |
|
||||
<field name="view_mode">form</field> |
|
||||
<field name="target">new</field> |
|
||||
</record> |
|
||||
|
|
||||
<menuitem id="perso_account_migration_menu" |
|
||||
parent="import_odoo.import_odoo" |
|
||||
name="Import data from ASBL" |
|
||||
action="odoo_import_form" /> |
|
||||
</data> |
|
||||
</openerp> |
|
@ -1,25 +0,0 @@ |
|||||
# -*- coding: utf-8 -*- |
|
||||
############################################################################## |
|
||||
# |
|
||||
# OpenERP, Open Source Management Solution |
|
||||
# Copyright (C) 2004-2010 Openerp sa (<http://openerp.com>). |
|
||||
# |
|
||||
# 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 import_framework |
|
||||
import mapper |
|
||||
|
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: |
|
@ -1,42 +0,0 @@ |
|||||
# -*- coding: utf-8 -*- |
|
||||
############################################################################## |
|
||||
# |
|
||||
# OpenERP, Open Source Management Solution |
|
||||
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>). |
|
||||
# |
|
||||
# This program is free software: you can redistribute it and/or modify |
|
||||
# it under the terms of the GNU Affero General Public License as |
|
||||
# published by the Free Software Foundation, either version 3 of the |
|
||||
# License, or (at your option) any later version. |
|
||||
# |
|
||||
# This program is distributed in the hope that it will be useful, |
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||
# GNU Affero General Public License for more details. |
|
||||
# |
|
||||
# You should have received a copy of the GNU Affero General Public License |
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
||||
# |
|
||||
############################################################################## |
|
||||
|
|
||||
{ |
|
||||
'name': 'Framework for complex import', |
|
||||
'version': '0.9', |
|
||||
'category': 'Hidden/Dependency', |
|
||||
'description': """ |
|
||||
This module provide a class import_framework to help importing |
|
||||
complex data from other software |
|
||||
""", |
|
||||
'author': 'OpenERP SA', |
|
||||
'website': 'http://www.openerp.com', |
|
||||
'depends': ['base'], |
|
||||
'init_xml': [], |
|
||||
'update_xml': [], |
|
||||
'demo_xml': [], |
|
||||
'test': [], #TODO provide test |
|
||||
'installable': True, |
|
||||
'auto_install': False, |
|
||||
'certificate': '00141537995453', |
|
||||
} |
|
||||
|
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: |
|
@ -1,415 +0,0 @@ |
|||||
# -*- coding: utf-8 -*- |
|
||||
############################################################################## |
|
||||
# |
|
||||
# OpenERP, Open Source Management Solution |
|
||||
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>). |
|
||||
# |
|
||||
# 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 pprint |
|
||||
import mapper |
|
||||
from openerp.tools.translate import _ |
|
||||
|
|
||||
import datetime |
|
||||
import logging |
|
||||
import StringIO |
|
||||
import traceback |
|
||||
pp = pprint.PrettyPrinter(indent=4) |
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
class import_framework(): |
|
||||
""" |
|
||||
This class should be extends, |
|
||||
get_data and get_mapping have to extends |
|
||||
get_state_map and initialize can be extended |
|
||||
for advanced purpose get_default_hook can also be extended |
|
||||
@see dummy import for a minimal exemple |
|
||||
""" |
|
||||
|
|
||||
""" |
|
||||
for import_object, this domain will avoid to find an already existing object |
|
||||
""" |
|
||||
DO_NOT_FIND_DOMAIN = [('id', '=', 0)] |
|
||||
|
|
||||
#TODO don't use context to pass credential parameters |
|
||||
def __init__(self, obj, cr, uid, instance_name, module_name, context=None): |
|
||||
self.external_id_field = 'id' |
|
||||
self.obj = obj |
|
||||
self.cr = cr |
|
||||
self.uid = uid |
|
||||
self.instance_name = instance_name |
|
||||
self.module_name = module_name |
|
||||
self.context = context or {} |
|
||||
self.table_list = [] |
|
||||
self.logger = logging.getLogger(module_name) |
|
||||
self.initialize() |
|
||||
|
|
||||
""" |
|
||||
Abstract Method to be implemented in |
|
||||
the real instance |
|
||||
""" |
|
||||
def initialize(self): |
|
||||
""" |
|
||||
init before import |
|
||||
usually for the login |
|
||||
""" |
|
||||
pass |
|
||||
|
|
||||
def init_run(self): |
|
||||
""" |
|
||||
call after intialize run in the thread, not in the main process |
|
||||
TO use for long initialization operation |
|
||||
""" |
|
||||
pass |
|
||||
|
|
||||
def get_data(self, table): |
|
||||
""" |
|
||||
@return: a list of dictionaries |
|
||||
each dictionnaries contains the list of pair external_field_name : value |
|
||||
""" |
|
||||
return [{}] |
|
||||
|
|
||||
def get_link(self, from_table, ids, to_table): |
|
||||
""" |
|
||||
@return: a dictionaries that contains the association between the id (from_table) |
|
||||
and the list (to table) of id linked |
|
||||
""" |
|
||||
return {} |
|
||||
|
|
||||
def get_external_id(self, data): |
|
||||
""" |
|
||||
@return the external id |
|
||||
the default implementation return self.external_id_field (that has 'id') by default |
|
||||
if the name of id field is different, you can overwrite this method or change the value |
|
||||
of self.external_id_field |
|
||||
""" |
|
||||
return data[self.external_id_field] |
|
||||
|
|
||||
def get_mapping(self): |
|
||||
""" |
|
||||
@return: { TABLE_NAME : { |
|
||||
'model' : 'openerp.model.name', |
|
||||
#if true import the table if not just resolve dependencies, use for meta package, by default => True |
|
||||
#Not required |
|
||||
'import' : True or False, |
|
||||
#Not required |
|
||||
'dependencies' : [TABLE_1, TABLE_2], |
|
||||
#Not required |
|
||||
'hook' : self.function_name, #get the val dict of the object, return the same val dict or False |
|
||||
'map' : { @see mapper |
|
||||
'openerp_field_name' : 'external_field_name', or val('external_field_name') |
|
||||
'openerp_field_id/id' : ref(TABLE_1, 'external_id_field'), #make the mapping between the external id and the xml on the right |
|
||||
'openerp_field2_id/id_parent' : ref(TABLE_1,'external_id_field') #indicate a self dependencies on openerp_field2_id |
|
||||
'state' : map_val('state_equivalent_field', mapping), # use get_state_map to make the mapping between the value of the field and the value of the state |
|
||||
'text_field' : concat('field_1', 'field_2', .., delimiter=':'), #concat the value of the list of field in one |
|
||||
'description_field' : ppconcat('field_1', 'field_2', .., delimiter='\n\t'), #same as above but with a prettier formatting |
|
||||
'field' : call(callable, arg1, arg2, ..), #call the function with all the value, the function should send the value : self.callable |
|
||||
'field' : callable |
|
||||
'field' : call(method, val('external_field') interface of method is self, val where val is the value of the field |
|
||||
'field' : const(value) #always set this field to value |
|
||||
+ any custom mapper that you will define |
|
||||
} |
|
||||
}, |
|
||||
|
|
||||
} |
|
||||
""" |
|
||||
return {} |
|
||||
|
|
||||
def default_hook(self, val): |
|
||||
""" |
|
||||
this hook will be apply on each table that don't have hook |
|
||||
here we define the identity hook |
|
||||
""" |
|
||||
return val |
|
||||
|
|
||||
def _import_table(self, table): |
|
||||
self.logger.info('Import table %s' % table) |
|
||||
data = self.get_data(table) |
|
||||
map = self.get_mapping()[table]['map'] |
|
||||
hook = self.get_mapping()[table].get('hook', self.default_hook) |
|
||||
model = self.get_mapping()[table]['model'] |
|
||||
|
|
||||
final_data = [] |
|
||||
for val in data: |
|
||||
res = hook(val) |
|
||||
if res: |
|
||||
final_data.append(res) |
|
||||
return self._save_data(model, dict(map), final_data, table) |
|
||||
|
|
||||
def _save_data(self, model, mapping, datas, table): |
|
||||
""" |
|
||||
@param model: the model of the object to import |
|
||||
@param table : the external table where the data come from |
|
||||
@param mapping : definition of the mapping |
|
||||
@see: get_mapping |
|
||||
@param datas : list of dictionnaries |
|
||||
datas = [data_1, data_2, ..] |
|
||||
data_i is a map external field_name => value |
|
||||
and each data_i have a external id => in data_id['id'] |
|
||||
""" |
|
||||
self.logger.info(' Importing %s into %s' % (table, model)) |
|
||||
if not datas: |
|
||||
return (0, 'No data found') |
|
||||
mapping['id'] = 'id_new' |
|
||||
res = [] |
|
||||
|
|
||||
|
|
||||
self_dependencies = [] |
|
||||
for k in mapping.keys(): |
|
||||
if '_parent' in k: |
|
||||
self_dependencies.append((k[:-7], mapping.pop(k))) |
|
||||
for data in datas: |
|
||||
for k, field_name in self_dependencies: |
|
||||
data[k] = data.get(field_name) and self._generate_xml_id(data.get(field_name), table) |
|
||||
|
|
||||
data['id_new'] = self._generate_xml_id(self.get_external_id(data), table) |
|
||||
fields, values = self._fields_mapp(data, mapping, table) |
|
||||
res.append(values) |
|
||||
|
|
||||
model_obj = self.obj.pool.get(model) |
|
||||
if not model_obj: |
|
||||
raise ValueError(_("%s is not a valid model name") % model) |
|
||||
self.logger.info(_("fields imported : ") + str(fields)) |
|
||||
(p, r, warning, s) = model_obj.import_data(self.cr, self.uid, fields, res, mode='update', current_module=self.module_name, noupdate=False, context=self.context) |
|
||||
self.logger.info('%s %s %s %s %s' % ("Done", p, r, warning, s)) |
|
||||
for (field, field_name) in self_dependencies: |
|
||||
self.logger.info('Import parent %s' % field) |
|
||||
self._import_self_dependencies(model_obj, field, datas) |
|
||||
return (len(res), warning) |
|
||||
|
|
||||
def _import_self_dependencies(self, obj, parent_field, datas): |
|
||||
""" |
|
||||
@param parent_field: the name of the field that generate a self_dependencies, we call the object referenced in this |
|
||||
field the parent of the object |
|
||||
@param datas: a list of dictionnaries |
|
||||
Dictionnaries need to contains |
|
||||
id_new : the xml_id of the object |
|
||||
field_new : the xml_id of the parent |
|
||||
""" |
|
||||
fields = ['id', parent_field] |
|
||||
for data in datas: |
|
||||
if data.get(parent_field): |
|
||||
values = [data['id_new'], data[parent_field]] |
|
||||
res = obj.import_data(self.cr, self.uid, fields, [values], mode='update', current_module=self.module_name, noupdate=False, context=self.context) |
|
||||
|
|
||||
def _preprocess_mapping(self, mapping): |
|
||||
""" |
|
||||
Preprocess the mapping : |
|
||||
after the preprocces, everything is |
|
||||
callable in the val of the dictionary |
|
||||
|
|
||||
use to allow syntaxical sugar like 'field': 'external_field' |
|
||||
instead of 'field' : value('external_field') |
|
||||
""" |
|
||||
map = dict(mapping) |
|
||||
for key, value in map.items(): |
|
||||
if isinstance(value, basestring): |
|
||||
map[key] = mapper.value(value) |
|
||||
#set parent for instance of dbmapper |
|
||||
elif isinstance(value, mapper.dbmapper): |
|
||||
value.set_parent(self) |
|
||||
return map |
|
||||
|
|
||||
|
|
||||
def _fields_mapp(self,dict_sugar, openerp_dict, table): |
|
||||
""" |
|
||||
call all the mapper and transform data |
|
||||
to be compatible with import_data |
|
||||
""" |
|
||||
fields=[] |
|
||||
data_lst = [] |
|
||||
mapping = self._preprocess_mapping(openerp_dict) |
|
||||
for key,val in mapping.items(): |
|
||||
if key not in fields and dict_sugar: |
|
||||
fields.append(key) |
|
||||
value = val(dict(dict_sugar)) |
|
||||
data_lst.append(value) |
|
||||
return fields, data_lst |
|
||||
|
|
||||
def _generate_xml_id(self, name, table): |
|
||||
""" |
|
||||
@param name: name of the object, has to be unique in for a given table |
|
||||
@param table : table where the record we want generate come from |
|
||||
@return: a unique xml id for record, the xml_id will be the same given the same table and same name |
|
||||
To be used to avoid duplication of data that don't have ids |
|
||||
""" |
|
||||
sugar_instance = self.instance_name |
|
||||
name = name.replace('.', '_').replace(',', '_') |
|
||||
return sugar_instance + "_" + table + "_" + name |
|
||||
|
|
||||
|
|
||||
""" |
|
||||
Public interface of the framework |
|
||||
those function can be use in the callable function defined in the mapping |
|
||||
""" |
|
||||
def xml_id_exist(self, table, external_id): |
|
||||
""" |
|
||||
Check if the external id exist in the openerp database |
|
||||
in order to check if the id exist the table where it come from |
|
||||
should be provide |
|
||||
@return the xml_id generated if the external_id exist in the database or false |
|
||||
""" |
|
||||
if not external_id: |
|
||||
return False |
|
||||
|
|
||||
xml_id = self._generate_xml_id(external_id, table) |
|
||||
id = self.obj.pool.get('ir.model.data').search(self.cr, self.uid, [('name', '=', xml_id), ('module', '=', self.module_name)]) |
|
||||
return id and xml_id or False |
|
||||
|
|
||||
def name_exist(self, table, name, model): |
|
||||
""" |
|
||||
Check if the object with the name exist in the openerp database |
|
||||
in order to check if the id exist the table where it come from |
|
||||
should be provide and the model of the object |
|
||||
""" |
|
||||
fields = ['name'] |
|
||||
data = [name] |
|
||||
return self.import_object(fields, data, model, table, name, [('name', '=', name)]) |
|
||||
|
|
||||
def get_mapped_id(self, table, external_id, context=None): |
|
||||
""" |
|
||||
@return return the databse id linked with the external_id |
|
||||
""" |
|
||||
if not external_id: |
|
||||
return False |
|
||||
|
|
||||
xml_id = self._generate_xml_id(external_id, table) |
|
||||
return self.obj.pool.get('ir.model.data').get_object_reference(self.cr, self.uid, self.module_name, xml_id)[1] |
|
||||
|
|
||||
def import_object_mapping(self, mapping, data, model, table, name, domain_search=False): |
|
||||
""" |
|
||||
same as import_objects but instead of two list fields and data, |
|
||||
this method take a dictionnaries : external_field : value |
|
||||
and the mapping similar to the one define in 'map' key |
|
||||
@see import_object, get_mapping |
|
||||
""" |
|
||||
fields, datas = self._fields_mapp(data, mapping, table) |
|
||||
return self.import_object(fields, datas, model, table, name, domain_search) |
|
||||
|
|
||||
def import_object(self, fields, data, model, table, name, domain_search=False): |
|
||||
""" |
|
||||
This method will import an object in the openerp, usefull for field that is only a char in sugar and is an object in openerp |
|
||||
use import_data that will take care to create/update or do nothing with the data |
|
||||
this method return the xml_id |
|
||||
|
|
||||
To be use, when you want to create an object or link if already exist |
|
||||
use DO_NOT_LINK_DOMAIN to create always a new object |
|
||||
@param fields: list of fields needed to create the object without id |
|
||||
@param data: the list of the data, in the same order as the field |
|
||||
ex : fields = ['firstname', 'lastname'] ; data = ['John', 'Mc donalds'] |
|
||||
@param model: the openerp's model of the create/update object |
|
||||
@param table: the table where data come from in sugarcrm, no need to fit the real name of openerp name, just need to be unique |
|
||||
@param unique_name: the name of the object that we want to create/update get the id |
|
||||
@param domain_search : the domain that should find the unique existing record |
|
||||
|
|
||||
@return: the xml_id of the ressources |
|
||||
""" |
|
||||
domain_search = not domain_search and [('name', 'ilike', name)] or domain_search |
|
||||
obj = self.obj.pool.get(model) |
|
||||
if not obj: #if the model doesn't exist |
|
||||
return False |
|
||||
|
|
||||
xml_id = self._generate_xml_id(name, table) |
|
||||
xml_ref = self.mapped_id_if_exist(model, domain_search, table, name) |
|
||||
fields.append('id') |
|
||||
data.append(xml_id) |
|
||||
obj.import_data(self.cr, self.uid, fields, [data], mode='update', current_module=self.module_name, noupdate=True, context=self.context) |
|
||||
return xml_ref or xml_id |
|
||||
|
|
||||
|
|
||||
def mapped_id_if_exist(self, model, domain, table, name): |
|
||||
""" |
|
||||
To be use when we want link with and existing object, if the object don't exist |
|
||||
just ignore. |
|
||||
@param domain : search domain to find existing record, should return a unique record |
|
||||
@param xml_id: xml_id give to the mapping |
|
||||
@param name: external_id or name of the object to create if there is no id |
|
||||
@param table: the name of the table of the object to map |
|
||||
@return : the xml_id if the record exist in the db, False otherwise |
|
||||
""" |
|
||||
obj = self.obj.pool.get(model) |
|
||||
ids = obj.search(self.cr, self.uid, domain, context=self.context) |
|
||||
if ids: |
|
||||
xml_id = self._generate_xml_id(name, table) |
|
||||
ir_model_data_obj = obj.pool.get('ir.model.data') |
|
||||
id = ir_model_data_obj._update(self.cr, self.uid, model, |
|
||||
self.module_name, {}, mode='update', xml_id=xml_id, |
|
||||
noupdate=True, res_id=ids[0], context=self.context) |
|
||||
return xml_id |
|
||||
return False |
|
||||
|
|
||||
|
|
||||
def set_table_list(self, table_list): |
|
||||
""" |
|
||||
Set the list of table to import, this method should be call before run |
|
||||
@param table_list: the list of external table to import |
|
||||
['Leads', 'Opportunity'] |
|
||||
""" |
|
||||
self.table_list = table_list |
|
||||
|
|
||||
def launch_import(self): |
|
||||
""" |
|
||||
Import all data into openerp, |
|
||||
this is the Entry point to launch the process of import |
|
||||
|
|
||||
|
|
||||
""" |
|
||||
self.data_started = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") |
|
||||
error = False |
|
||||
result = [] |
|
||||
try: |
|
||||
self.init_run() |
|
||||
imported = set() #to invoid importing 2 times the sames modules |
|
||||
for table in self.table_list: |
|
||||
to_import = self.get_mapping()[table].get('import', True) |
|
||||
if not table in imported: |
|
||||
res = self._resolve_dependencies(self.get_mapping()[table].get('dependencies', []), imported) |
|
||||
result.extend(res) |
|
||||
if to_import: |
|
||||
(position, warning) = self._import_table(table) |
|
||||
result.append((table, position, warning)) |
|
||||
imported.add(table) |
|
||||
self.cr.commit() |
|
||||
|
|
||||
except Exception, err: |
|
||||
sh = StringIO.StringIO() |
|
||||
traceback.print_exc(file=sh) |
|
||||
error = sh.getvalue() |
|
||||
self.logger.error(error) |
|
||||
|
|
||||
|
|
||||
self.date_ended = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") |
|
||||
|
|
||||
def _resolve_dependencies(self, dep, imported): |
|
||||
""" |
|
||||
import dependencies recursively |
|
||||
and avoid to import twice the same table |
|
||||
""" |
|
||||
result = [] |
|
||||
for dependency in dep: |
|
||||
if not dependency in imported: |
|
||||
to_import = self.get_mapping()[dependency].get('import', True) |
|
||||
res = self._resolve_dependencies(self.get_mapping()[dependency].get('dependencies', []), imported) |
|
||||
result.extend(res) |
|
||||
if to_import: |
|
||||
r = self._import_table(dependency) |
|
||||
(position, warning) = r |
|
||||
result.append((dependency, position, warning)) |
|
||||
imported.add(dependency) |
|
||||
return result |
|
||||
|
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: |
|
@ -1,220 +0,0 @@ |
|||||
# -*- coding: utf-8 -*- |
|
||||
############################################################################## |
|
||||
# |
|
||||
# OpenERP, Open Source Management Solution |
|
||||
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>). |
|
||||
# |
|
||||
# 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 openerp import tools |
|
||||
|
|
||||
class mapper(object): |
|
||||
""" |
|
||||
super class for all mapper class |
|
||||
They are call before import data |
|
||||
to transform the mapping into real value that we |
|
||||
will import |
|
||||
|
|
||||
the call function receive a dictionary with external data |
|
||||
'external_field' : value |
|
||||
""" |
|
||||
def __call__(self, external_values): |
|
||||
raise NotImplementedError() |
|
||||
|
|
||||
def get_fields(self): |
|
||||
return [] |
|
||||
|
|
||||
class dbmapper(mapper): |
|
||||
""" |
|
||||
Super class for mapper that need to access to |
|
||||
data base or any function of the import_framework |
|
||||
|
|
||||
self.parent contains a reference to the instance of |
|
||||
the import framework |
|
||||
""" |
|
||||
def set_parent(self, parent): |
|
||||
self.parent = parent |
|
||||
|
|
||||
|
|
||||
class concat(mapper): |
|
||||
""" |
|
||||
Use : contact('field_name1', 'field_name2', delimiter='_') |
|
||||
concat value of fields using the delimiter, delimiter is optional |
|
||||
and by default is a space |
|
||||
""" |
|
||||
def __init__(self, *arg, **delimiter): |
|
||||
self.arg = arg |
|
||||
self.delimiter = delimiter and delimiter.get('delimiter', ' ') or ' ' |
|
||||
|
|
||||
def __call__(self, external_values): |
|
||||
return self.delimiter.join(map(lambda x : tools.ustr(external_values.get(x,'')), self.arg)) |
|
||||
|
|
||||
def get_fields(self): |
|
||||
return self.arg |
|
||||
|
|
||||
class ppconcat(concat): |
|
||||
""" |
|
||||
Use : contact('field_name1', 'field_name2', delimiter='_') |
|
||||
concat external field name and value of fields using the delimiter, |
|
||||
delimiter is optional and by default is a two line feeds |
|
||||
|
|
||||
""" |
|
||||
def __init__(self, *arg, **delimiter): |
|
||||
self.arg = arg |
|
||||
self.delimiter = delimiter and delimiter.get('delimiter', ' ') or '\n\n' |
|
||||
|
|
||||
def __call__(self, external_values): |
|
||||
return self.delimiter.join(map(lambda x : x + ": " + tools.ustr(external_values.get(x,'')), self.arg)) |
|
||||
|
|
||||
class const(mapper): |
|
||||
""" |
|
||||
Use : const(arg) |
|
||||
return always arg |
|
||||
""" |
|
||||
def __init__(self, val): |
|
||||
self.val = val |
|
||||
|
|
||||
def __call__(self, external_values): |
|
||||
return self.val |
|
||||
|
|
||||
class value(mapper): |
|
||||
""" |
|
||||
Use : value(external_field_name) |
|
||||
Return the value of the external field name |
|
||||
this is equivalent to the a single string |
|
||||
|
|
||||
usefull for call if you want your call get the value |
|
||||
and don't care about the name of the field |
|
||||
call(self.method, value('field1')) |
|
||||
""" |
|
||||
def __init__(self, val, default='', fallback=False): |
|
||||
self.val = val |
|
||||
self.default = default |
|
||||
self.fallback = fallback |
|
||||
|
|
||||
def __call__(self, external_values): |
|
||||
val = external_values.get(self.val, self.default) |
|
||||
if self.fallback and (not val or val == self.default): |
|
||||
val = external_values.get(self.fallback, self.default) |
|
||||
return val |
|
||||
|
|
||||
def get_fields(self): |
|
||||
return [self.val] |
|
||||
|
|
||||
|
|
||||
class map_val(mapper): |
|
||||
""" |
|
||||
Use : map_val(external_field, val_mapping) |
|
||||
where val_mapping is a dictionary |
|
||||
with external_val : openerp_val |
|
||||
|
|
||||
usefull for selection field like state |
|
||||
to map value |
|
||||
""" |
|
||||
def __init__(self, val, map, default='draft'): |
|
||||
self.val = value(val) |
|
||||
self.map = map |
|
||||
self.default = default |
|
||||
|
|
||||
def __call__(self, external_values): |
|
||||
return self.map.get(self.val(external_values), self.default) |
|
||||
|
|
||||
def get_fields(self): |
|
||||
return self.val.get_fields() |
|
||||
|
|
||||
class map_val_default(mapper): |
|
||||
""" |
|
||||
Use : map_val(external_field, val_mapping) |
|
||||
where val_mapping is a dictionary |
|
||||
with external_val : openerp_val |
|
||||
|
|
||||
usefull for selection field like state |
|
||||
to map value |
|
||||
""" |
|
||||
def __init__(self, val, map): |
|
||||
self.val = value(val) |
|
||||
self.map = map |
|
||||
|
|
||||
def __call__(self, external_values): |
|
||||
value = self.map.get(self.val(external_values), self.val(external_values)) |
|
||||
return value |
|
||||
|
|
||||
def get_fields(self): |
|
||||
return self.val.get_fields() |
|
||||
|
|
||||
class ref(dbmapper): |
|
||||
""" |
|
||||
Use : ref(table_name, external_id) |
|
||||
return the xml_id of the ressource |
|
||||
|
|
||||
to associate an already imported object with the current object |
|
||||
""" |
|
||||
def __init__(self, table, field_name): |
|
||||
self.table = table |
|
||||
self.field_name = field_name |
|
||||
|
|
||||
def __call__(self, external_values): |
|
||||
return self.parent.xml_id_exist(self.table, external_values.get(self.field_name)) |
|
||||
|
|
||||
def get_fields(self): |
|
||||
return self.field_name |
|
||||
|
|
||||
class refbyname(dbmapper): |
|
||||
""" |
|
||||
Use : refbyname(table_name, external_name, res.model) |
|
||||
same as ref but use the name of the ressource to find it |
|
||||
""" |
|
||||
def __init__(self, table, field_name, model): |
|
||||
self.table = table |
|
||||
self.field_name = field_name |
|
||||
self.model = model |
|
||||
|
|
||||
def __call__(self, external_values): |
|
||||
v = external_values.get(self.field_name, '') |
|
||||
return self.parent.name_exist(self.table, v , self.model) |
|
||||
|
|
||||
def get_fields(self): |
|
||||
return self.field_name |
|
||||
|
|
||||
class call(mapper): |
|
||||
""" |
|
||||
Use : call(function, arg1, arg2) |
|
||||
to call the function with external val follow by the arg specified |
|
||||
""" |
|
||||
def __init__(self, fun, *arg): |
|
||||
self.fun = fun |
|
||||
self.arg = arg |
|
||||
|
|
||||
def __call__(self, external_values): |
|
||||
args = [] |
|
||||
for arg in self.arg: |
|
||||
if isinstance(arg, mapper): |
|
||||
args.append(arg(external_values)) |
|
||||
else: |
|
||||
args.append(arg) |
|
||||
return self.fun(external_values, *args) |
|
||||
|
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: |
|
||||
|
|
||||
|
|
||||
def val(field_name): |
|
||||
def val_fun(data_line): |
|
||||
return data_line[field_name] |
|
||||
|
|
||||
return val_fun |
|
||||
|
|
||||
def const(const): |
|
||||
def val_fun(data_line): |
|
||||
return const |
|
@ -1,23 +0,0 @@ |
|||||
# -*- coding: utf-8 -*- |
|
||||
############################################################################## |
|
||||
# |
|
||||
# OpenERP, Open Source Management Solution |
|
||||
# Copyright (C) 2004-2010 Openerp sa (<http://openerp.com>). |
|
||||
# |
|
||||
# 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 odoo_connector |
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: |
|
@ -1,42 +0,0 @@ |
|||||
# -*- coding: utf-8 -*- |
|
||||
############################################################################## |
|
||||
# |
|
||||
# OpenERP, Open Source Management Solution |
|
||||
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>). |
|
||||
# |
|
||||
# This program is free software: you can redistribute it and/or modify |
|
||||
# it under the terms of the GNU Affero General Public License as |
|
||||
# published by the Free Software Foundation, either version 3 of the |
|
||||
# License, or (at your option) any later version. |
|
||||
# |
|
||||
# This program is distributed in the hope that it will be useful, |
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||
# GNU Affero General Public License for more details. |
|
||||
# |
|
||||
# You should have received a copy of the GNU Affero General Public License |
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
||||
# |
|
||||
############################################################################## |
|
||||
|
|
||||
{ |
|
||||
'name': 'Framework to import from other odoo instance', |
|
||||
'version': '0.9', |
|
||||
'category': 'Import', |
|
||||
'description': """ |
|
||||
This module provide a class import_framework to help importing |
|
||||
data from odoo |
|
||||
""", |
|
||||
'author': 'Thibault Francois', |
|
||||
'website': 'https://github.com/tfrancoi/', |
|
||||
'depends': ['base', 'import_base'], |
|
||||
'data': [ |
|
||||
'view/connector.xml', |
|
||||
'security/ir.model.access.csv', |
|
||||
], |
|
||||
'test': [], #TODO provide test |
|
||||
'installable': True, |
|
||||
'auto_install': False, |
|
||||
} |
|
||||
|
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: |
|
@ -1,38 +0,0 @@ |
|||||
''' |
|
||||
Created on 25 nov. 2014 |
|
||||
|
|
||||
@author: openerp |
|
||||
''' |
|
||||
from openerp import models, fields, api |
|
||||
import openerplib |
|
||||
from openerp.exceptions import Warning |
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
class odoo_connection_data(models.Model): |
|
||||
|
|
||||
_name = 'import.odoo.connection' |
|
||||
|
|
||||
name = fields.Char("Name", required=True) |
|
||||
host = fields.Char("Host", required=True) |
|
||||
port = fields.Integer("Port", required=True, default=8069) |
|
||||
database = fields.Char("Database", required=True) |
|
||||
user = fields.Char("Login", required=True, default="admin") |
|
||||
password = fields.Char("Password", required=True) |
|
||||
protocol = fields.Selection([('xmlrpc', 'Xmlrpc'), ('jsonrpc', 'Jsonrpc'),('xmlrpcs', 'Xmlrpcs'), ('jsonrpcs', 'Jsonrpcs')], string="Protocol", default="xmlrpc") |
|
||||
active = fields.Boolean("Active", default=True) |
|
||||
|
|
||||
@api.multi |
|
||||
def test_connection(self): |
|
||||
connection = self._get_connection() |
|
||||
connection.check_login(force=True) |
|
||||
raise Warning("Connection Successful") |
|
||||
|
|
||||
def _get_connection(self): |
|
||||
return openerplib.get_connection(hostname=self.host, |
|
||||
port=self.port, |
|
||||
database=self.database, |
|
||||
login=self.user, |
|
||||
password=self.password, |
|
||||
protocol=self.protocol) |
|
@ -1,2 +0,0 @@ |
|||||
id,name,model_id/id,group_id/id,perm_read,perm_write,perm_create,perm_unlink |
|
||||
access_import_odoo_connection,access_import_odoo_connection,model_import_odoo_connection,,1,0,0,0 |
|
@ -1,67 +0,0 @@ |
|||||
<?xml version="1.0" encoding="utf-8"?> |
|
||||
<openerp> |
|
||||
<data> |
|
||||
<record model="ir.ui.view" id="import_odoo_tree"> |
|
||||
<field name="name">import.odoo.connection.tree</field> |
|
||||
<field name="model">import.odoo.connection</field> |
|
||||
<field name="arch" type="xml"> |
|
||||
<tree string="Odoo Connector"> |
|
||||
<field name="name"/> |
|
||||
<field name="host"/> |
|
||||
<field name="database" /> |
|
||||
</tree> |
|
||||
</field> |
|
||||
</record> |
|
||||
|
|
||||
<record model="ir.ui.view" id="import_odoo_form"> |
|
||||
<field name="name">import.odoo.connection.form</field> |
|
||||
<field name="model">import.odoo.connection</field> |
|
||||
<field name="arch" type="xml"> |
|
||||
<form string="Account" version="7.0"> |
|
||||
<header> |
|
||||
<button type="object" name="test_connection" string="Test Connection" /> |
|
||||
</header> |
|
||||
<sheet> |
|
||||
<div class="oe_title"> |
|
||||
<div class="oe_edit_only"> |
|
||||
<label for="name"/> |
|
||||
</div> |
|
||||
<h1> |
|
||||
<field name="name" default_focus="1" placeholder="Name" /> |
|
||||
</h1> |
|
||||
</div> |
|
||||
<group> |
|
||||
<group> |
|
||||
<field name="host" /> |
|
||||
<field name="port" /> |
|
||||
<field name="database" /> |
|
||||
<field name="protocol" /> |
|
||||
</group> |
|
||||
<group> |
|
||||
<field name="user" /> |
|
||||
<field name="password" /> |
|
||||
<field name="active" /> |
|
||||
</group> |
|
||||
</group> |
|
||||
</sheet> |
|
||||
</form> |
|
||||
</field> |
|
||||
</record> |
|
||||
|
|
||||
|
|
||||
|
|
||||
<record model="ir.actions.act_window" id="odoo_import_form"> |
|
||||
<field name="name">Odoo Connector</field> |
|
||||
<field name="res_model">import.odoo.connection</field> |
|
||||
<field name="view_type">form</field> |
|
||||
<field name="view_mode">tree,form</field> |
|
||||
</record> |
|
||||
|
|
||||
<menuitem id="import_odoo" name="Import from odoo" parent="base.menu_custom" /> |
|
||||
<menuitem id="odoo_import_form_menu" parent="import_odoo" name="Odoo Connector" action="odoo_import_form"/> |
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
</data> |
|
||||
</openerp> |
|
Write
Preview
Loading…
Cancel
Save
Reference in new issue