diff --git a/openerp/addons/base/__openerp__.py b/openerp/addons/base/__openerp__.py index 5233cdcbfdb..e436a0a6005 100644 --- a/openerp/addons/base/__openerp__.py +++ b/openerp/addons/base/__openerp__.py @@ -92,7 +92,6 @@ 'test/test_osv_expression.yml', 'test/test_ir_rule.yml', # <-- These tests modify/add/delete ir_rules. 'test/test_ir_values.yml', - 'test/test_edi_documents.yml', # Commented because this takes some time. # This must be (un)commented with the corresponding import statement # in test/__init__.py. diff --git a/openerp/addons/base/ir/__init__.py b/openerp/addons/base/ir/__init__.py index 850a3ae40de..4a6bd3c614c 100644 --- a/openerp/addons/base/ir/__init__.py +++ b/openerp/addons/base/ir/__init__.py @@ -36,7 +36,6 @@ import ir_rule import wizard import ir_config_parameter import osv_memory_autovacuum -import ir_edi import ir_mail_server # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/openerp/addons/base/ir/ir_edi.py b/openerp/addons/base/ir/ir_edi.py deleted file mode 100644 index b9ae11fd71b..00000000000 --- a/openerp/addons/base/ir/ir_edi.py +++ /dev/null @@ -1,589 +0,0 @@ -# -*- coding: utf-8 -*- -############################################################################## -# -# OpenERP, Open Source Business Applications -# Copyright (c) 2011 OpenERP S.A. -# -# 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 . -# -############################################################################## - -import base64 -import hashlib -import json -import logging -import re -import time -import urllib2 - -import openerp -import openerp.release as release -from osv import osv,fields -from tools.translate import _ -from tools.parse_version import parse_version - -EXTERNAL_ID_PATTERN = re.compile(r'^(\S+:)?(\S+?)\.(\S+)$') - -def split_external_id(ext_id): - match = EXTERNAL_ID_PATTERN.match(ext_id) - assert match, \ - _("'%s' is an invalid external ID") % (ext_id) - return {'module': match.group(1) and match.group(1)[:-1], - 'db_uuid': match.group(2), - 'id': match.group(3), - 'full': match.group(0)} - -def safe_unique_id(database_id, model, record_id): - """Generate a unique string to represent a (database_uuid,model,record_id) pair - without being too long, and with a very low probability of collisions. - """ - msg = "%s-%s-%s-%s" % (time.time(), database_id, model, record_id) - digest = hashlib.sha1(msg).digest() - # fold the sha1 20 bytes digest to 9 bytes - digest = ''.join(chr(ord(x) ^ ord(y)) for (x,y) in zip(digest[:9], digest[9:-2])) - # b64-encode the 9-bytes folded digest to a reasonable 12 chars ASCII ID - digest = base64.urlsafe_b64encode(digest) - return '%s-%s' % (model.replace('.','_'), digest) - -def version_tuple(): - return parse_version(release.version) - -def last_update_for(record): - """Returns the last update timestamp for the given record, - if available, otherwise False - """ - if record._model._log_access: - record_log = record.perm_read()[0] - return record_log.get('write_date') or record_log.get('create_date') or False - return False - -_logger = logging.getLogger('edi') - -class ir_edi_document(osv.osv): - _name = 'ir.edi.document' - _description = 'EDI Document' - _columns = { - 'name': fields.char("EDI token", size = 128, help="Unique identifier for retrieving an EDI document."), - 'document': fields.text("Document", help="EDI document content") - } - _sql_constraints = [ - ('name_uniq', 'unique (name)', 'EDI Tokens must be unique!') - ] - - def new_edi_token(self, cr, uid, record): - """Return a new, random unique token to identify this model record, - and to be used as token when exporting it as an EDI document. - - :param browse_record record: model record for which a token is needed - """ - db_uuid = self.pool.get('ir.config_parameter').get_param(cr, uid, 'database.uuid') - edi_token = hashlib.sha256('%s-%s-%s-%s' % (time.time(), db_uuid, record._name, record.id)).hexdigest() - return edi_token - - def serialize(self, edi_documents): - """Serialize the given EDI document structures (Python dicts holding EDI data), - using JSON serialization. - - :param [dict] edi_documents: list of EDI document structures to serialize - :return: UTF-8 encoded string containing the serialized document - """ - serialized_list = json.dumps(edi_documents) - return serialized_list - - def generate_edi(self, cr, uid, records, context=None): - """Generates a final EDI document containing the EDI serialization - of the given records, which should all be instances of a Model - that has the :meth:`~.edi` mixin. The document is not saved in the - database, this is done by :meth:`~.export_edi`. - - :param list(browse_record) records: records to export as EDI - :return: UTF-8 encoded string containing the serialized records - """ - edi_list = [] - for record in records: - record_model_obj = self.pool.get(record._name) - edi_list += record_model_obj.edi_export(cr, uid, [record], context=context) - return self.serialize(edi_list) - - def get_document(self, cr, uid, edi_token, context=None): - """Retrieve the EDI document corresponding to the given edi_token. - - :return: EDI document string - :raise: ValueError if requested EDI token does not match any know document - """ - _logger.debug("get_document(%s)", edi_token) - edi_ids = self.search(cr, uid, [('name','=', edi_token)], context=context) - if not edi_ids: - raise ValueError('Invalid EDI token: %s' % edi_token) - edi = self.browse(cr, uid, edi_ids[0], context=context) - return edi.document - - def load_edi(self, cr, uid, edi_documents, context=None): - """Import the given EDI document structures into the system, using - :meth:`~.import_edi`. - - :param edi_documents: list of Python dicts containing the deserialized - version of EDI documents - :return: list of (model, id) pairs containing the model and database ID - of all records that were imported in the system - """ - ir_module = self.pool.get('ir.module.module') - res = [] - for edi_document in edi_documents: - module = edi_document.get('__module') - if module != 'base' and not ir_module.search(cr, uid, [('name','=',module),('state','=','installed')]): - raise osv.except_osv(_('Missing Application'), - _("The document you are trying to import requires the OpenERP `%s` application. " - "The OpenERP configuration assistant will help with this if you are connected as an administrator.")%(module,)) - model = edi_document.get('__model') - assert model, '__model attribute is required in each EDI document' - model_obj = self.pool.get(model) - record_id = model_obj.edi_import(cr, uid, edi_document, context=context) - res.append((model, record_id)) - return res - - def deserialize(self, edi_documents_string): - """Return deserialized version of the given EDI Document string. - - :param str|unicode edi_documents_string: UTF-8 string (or unicode) containing - JSON-serialized EDI document(s) - :return: Python object representing the EDI document(s) (usually a list of dicts) - """ - return json.loads(edi_documents_string) - - def export_edi(self, cr, uid, records, context=None): - """Export the given database records as EDI documents, stores them - permanently with a new unique EDI token, for later retrieval via :meth:`~.get_document`, - and returns the list of the new corresponding ``ir.edi.document`` records. - - :param records: list of browse_record of any model - :return: list of IDs of the new ``ir.edi.document`` entries, in the same - order as the provided ``records``. - """ - exported_ids = [] - for record in records: - document = self.generate_edi(cr, uid, [record], context) - token = self.new_edi_token(cr, uid, record) - self.create(cr, uid, { - 'name': token, - 'document': document - }, context=context) - exported_ids.append(token) - return exported_ids - - def import_edi(self, cr, uid, edi_document=None, edi_url=None, context=None): - """Import a JSON serialized EDI Document string into the system, first retrieving it - from the given ``edi_url`` if provided. - - :param str|unicode edi_document: UTF-8 string or unicode containing JSON-serialized - EDI Document to import. Must not be provided if - ``edi_url`` is given. - :param str|unicode edi_url: URL where the EDI document (same format as ``edi_document``) - may be retrieved, without authentication. - """ - if edi_url: - assert not edi_document, 'edi_document must not be provided if edi_url is given' - edi_document = urllib2.urlopen(edi_url).read() - assert edi_document, 'EDI Document is empty!' - edi_documents = self.deserialize(edi_document) - return self.load_edi(cr, uid, edi_documents, context=context) - - -class edi(object): - """Mixin class for Model objects that want be exposed as EDI documents. - Classes that inherit from this mixin class should override the - ``edi_import()`` and ``edi_export()`` methods to implement their - specific behavior, based on the primitives provided by this mixin.""" - - # private method, not RPC-exposed as it creates ir.model.data entries as - # SUPERUSER based on its parameters - def _edi_external_id(self, cr, uid, record, existing_id=None, existing_module=None, - context=None): - """Generate/Retrieve unique external ID for ``record``. - Each EDI record and each relationship attribute in it is identified by a - unique external ID, which includes the database's UUID, as a way to - refer to any record within any OpenERP instance, without conflict. - - For OpenERP records that have an existing "External ID" (i.e. an entry in - ir.model.data), the EDI unique identifier for this record will be made of - "%s:%s:%s" % (module, database UUID, ir.model.data ID). The database's - UUID MUST NOT contain a colon characters (this is guaranteed by the - UUID algorithm). - - For records that have no existing ir.model.data entry, a new one will be - created during the EDI export. It is recommended that the generated external ID - contains a readable reference to the record model, plus a unique value that - hides the database ID. If ``existing_id`` is provided (because it came from - an import), it will be used instead of generating a new one. - If ``existing_module`` is provided (because it came from - an import), it will be used instead of using local values. - - :param browse_record record: any browse_record needing an EDI external ID - :param string existing_id: optional existing external ID value, usually coming - from a just-imported EDI record, to be used instead - of generating a new one - :param string existing_module: optional existing module name, usually in the - format ``module:db_uuid`` and coming from a - just-imported EDI record, to be used instead - of local values - :return: the full unique External ID to use for record - """ - ir_model_data = self.pool.get('ir.model.data') - db_uuid = self.pool.get('ir.config_parameter').get_param(cr, uid, 'database.uuid') - ext_id = self.get_external_id(cr, uid, [record.id])[record.id] - if not ext_id: - ext_id = existing_id or safe_unique_id(db_uuid, record._name, record.id) - # ID is unique cross-db thanks to db_uuid (already included in existing_module) - module = existing_module or "%s:%s" % (record._module, db_uuid) - _logger.debug("%s: Generating new external ID `%s.%s` for %r", self._name, - module, ext_id, record) - ir_model_data.create(cr, openerp.SUPERUSER_ID, - {'name': ext_id, - 'model': record._name, - 'module': module, - 'res_id': record.id}) - else: - module, ext_id = ext_id.split('.') - if not ':' in module: - # this record was not previously EDI-imported - assert module == record._module, 'Module mismatch between record and its current'\ - 'external ID' - # ID is unique cross-db thanks to db_uuid - module = "%s:%s" % (module, db_uuid) - - return '%s.%s' % (module, ext_id) - - def edi_metadata(self, cr, uid, records, context=None): - """Return a list containing the boilerplate EDI structures for - exporting ``records`` as EDI, including - the metadata fields - - The metadata fields always include:: - - { - '__model': 'some.model', # record model - '__module': 'module', # require module - '__id': 'module:db-uuid:model.id', # unique global external ID for the record - '__last_update': '2011-01-01 10:00:00', # last update date in UTC! - '__version' : [6,1,0], # server version, to check compatibility. - '__attachments_': - } - - :param list(browse_record) records: records to export - :return: list of dicts containing boilerplate EDI metadata for each record, - at the corresponding index from ``records``. - """ - data_ids = [] - ir_attachment = self.pool.get('ir.attachment') - results = [] - version = version_tuple() - for record in records: - attachment_ids = ir_attachment.search(cr, uid, [('res_model','=', record._name), ('res_id', '=', record.id)]) - attachments = [] - for attachment in ir_attachment.browse(cr, uid, attachment_ids, context=context): - attachments.append({ - 'name' : attachment.name, - 'content': attachment.datas, # already base64 encoded! - 'file_name': attachment.datas_fname, - }) - ext_id = self._edi_external_id(cr, uid, record, context=context) - edi_dict = { - '__id': ext_id, - '__last_update': last_update_for(record), - '__model' : record._name, - '__module' : record._module, - '__version': version, - '__attachments': attachments, - } - results.append(edi_dict) - return results - - def edi_m2o(self, cr, uid, record, context=None): - """Return a m2o EDI representation for the given record. - - The EDI format for a many2one is:: - - ['unique_external_id', 'Document Name'] - """ - edi_ext_id = self._edi_external_id(cr, uid, record, context=context) - relation_model = record._model - name = relation_model.name_get(cr, uid, [record.id], context=context) - name = name and name[0][1] or False - return [edi_ext_id, name] - - def edi_o2m(self, cr, uid, records, edi_struct=None, context=None): - """Return a list representing a O2M EDI relationship containing - all the given records, according to the given ``edi_struct``. - This is basically the same as exporting all the record using - :meth:`~.edi_export` with the given ``edi_struct``, and wrapping - the results in a list. - - Example:: - - [ # O2M fields would be a list of dicts, with their - { '__id': 'module:db-uuid.id', # own __id. - '__last_update': 'iso date', # update date - 'name': 'some name', - #... - }, - # ... - ], - """ - result = [] - for record in records: - result += record._model.edi_export(cr, uid, [record], edi_struct=edi_struct, context=context) - return result - - def edi_m2m(self, cr, uid, records, context=None): - """Return a list representing a M2M EDI relationship directed towards - all the given records. - This is basically the same as exporting all the record using - :meth:`~.edi_m2o` and wrapping the results in a list. - - Example:: - - # M2M fields are exported as a list of pairs, like a list of M2O values - [ - ['module:db-uuid.id1', 'Task 01: bla bla'], - ['module:db-uuid.id2', 'Task 02: bla bla'] - ] - """ - return [self.edi_m2o(cr, uid, r, context=context) for r in records] - - def edi_export(self, cr, uid, records, edi_struct=None, context=None): - """Returns a list of dicts representing an edi.document containing the - records, and matching the given ``edi_struct``, if provided. - - :param edi_struct: if provided, edi_struct should be a dictionary - with a skeleton of the fields to export. - Basic fields can have any key as value, but o2m - values should have a sample skeleton dict as value, - to act like a recursive export. - For example, for a res.partner record:: - - edi_struct: { - 'name': True, - 'company_id': True, - 'address': { - 'name': True, - 'street': True, - } - } - - Any field not specified in the edi_struct will not - be included in the exported data. Fields with no - value (False) will be omitted in the EDI struct. - If edi_struct is omitted, no fields will be exported - """ - if edi_struct is None: - edi_struct = {} - fields_to_export = edi_struct.keys() - results = [] - for record in records: - edi_dict = self.edi_metadata(cr, uid, [record], context=context)[0] - for field in fields_to_export: - column = self._all_columns[field].column - value = getattr(record, field) - if not value: - continue - #if _fields[field].has_key('function') or _fields[field].has_key('related_columns'): - # # Do not Export Function Fields and related fields - # continue - elif column._type == 'many2one': - value = self.edi_m2o(cr, uid, value, context=context) - elif column._type == 'many2many': - value = self.edi_m2m(cr, uid, value, context=context) - elif column._type == 'one2many': - value = self.edi_o2m(cr, uid, value, edi_struct=edi_struct.get(field, {}), context=context) - edi_dict[field] = value - results.append(edi_dict) - return results - - def _edi_get_object_by_name(self, cr, uid, name, model_name, context=None): - model = self.pool.get(model_name) - search_results = model.name_search(cr, uid, name, operator='=', context=context) - if len(search_results) == 1: - return model.browse(cr, uid, search_results[0][0], context=context) - return False - - def _edi_import_attachments(self, cr, uid, record_id, edi_document, context=None): - ir_attachment = self.pool.get('ir.attachment') - for attachment in edi_document.get('__attachments', []): - # check attachment data is non-empty and valid - file_data = None - try: - file_data = base64.b64decode(attachment.get('content')) - except TypeError: - pass - assert file_data, 'Incorrect/Missing attachment file content' - assert attachment.get('name'), 'Incorrect/Missing attachment name' - assert attachment.get('file_name'), 'Incorrect/Missing attachment file name' - assert attachment.get('file_name'), 'Incorrect/Missing attachment file name' - ir_attachment.create(cr, uid, {'name': attachment['name'], - 'datas_fname': attachment['file_name'], - 'res_model': self._name, - 'res_id': record_id, - # should be pure 7bit ASCII - 'datas': str(attachment['content']), - }, context=context) - - - def _edi_get_object_by_external_id(self, cr, uid, external_id, model, context=None): - """Returns browse_record representing object identified by the model and external_id, - or None if no record was found with this external id. - - :param external_id: fully qualified external id, in the EDI form - ``module:db_uuid:identifier``. - :param model: model name the record belongs to. - """ - ir_model_data = self.pool.get('ir.model.data') - # external_id is expected to have the form: ``module:db_uuid:model.random_name`` - ext_id_members = split_external_id(external_id) - db_uuid = self.pool.get('ir.config_parameter').get_param(cr, uid, 'database.uuid') - module = ext_id_members['module'] - ext_id = ext_id_members['id'] - ext_module = '%s:%s' % (module, ext_id_members['db_uuid']) - data_ids = ir_model_data.search(cr, uid, [('model','=',model), - ('name','=',ext_id), - ('module','in',[ext_module,module])]) - if data_ids: - model = self.pool.get(model) - data = ir_model_data.browse(cr, uid, data_ids[0], context=context) - result = model.browse(cr, uid, data.res_id, context=context) - return result - - def edi_import_relation(self, cr, uid, model, value, external_id, context=None): - """Imports a M2O/M2M relation EDI specification ``[external_id,value]`` for the - given model, returning the corresponding database ID: - - * First, checks if the ``external_id`` is already known, in which case the corresponding - database ID is directly returned, without doing anything else; - * If the ``external_id`` is unknown, attempts to locate an existing record - with the same ``value`` via name_search(). If found, the given external_id will - be assigned to this local record (in addition to any existing one) - * If previous steps gave no result, create a new record with the given - value in the target model, assign it the given external_id, and return - the new database ID - """ - _logger.debug("%s: Importing EDI relationship [%r,%r]", self._name, external_id, value) - target = self._edi_get_object_by_external_id(cr, uid, external_id, model, context=context) - need_new_ext_id = False - if not target: - _logger.debug("%s: Importing EDI relationship [%r,%r] - ID not found, trying name_get", - self._name, external_id, value) - target = self._edi_get_object_by_name(cr, uid, value, model, context=context) - need_new_ext_id = True - if not target: - _logger.debug("%s: Importing EDI relationship [%r,%r] - name not found, creating it!", - self._name, external_id, value) - # also need_new_ext_id here, but already been set above - res_id, name = self.name_create(cr, uid, value, context=context) - target = model.browse(cr, uid, res_id, context=context) - if need_new_ext_id: - ext_id_members = split_external_id(external_id) - # module name is never used bare when creating ir.model.data entries, in order - # to avoid being taken as part of the module's data, and cleanup up at next update - module = "%s:%s" % (ext_id_members['module'], ext_id_members['db_uuid']) - # create a new ir.model.data entry for this value - self._edi_external_id(cr, uid, target, existing_id=ext_id_members['id'], existing_module=module, context=context) - return target.id - - def edi_import(self, cr, uid, edi_document, context=None): - """Imports a dict representing an edi.document into the system, - applying the following rules. - - All relationship fields are exported in a special way, and provide their own - unique identifier, so that we can avoid duplication of records when importing. - - #. Many2One - See :meth:`~.edi_import_relation` - - #. One2Many - O2M fields are always exported as a list of dicts, where each dict corresponds - to a full EDI record. The import should not update existing records - if they already exist, it should only link them to the parent object, in this - fashion: - * First import the parent object, using the usual procedire - * Look for a record that matches the db_id provided in the __id field. If - found, keep the corresponding database id, and connect it to the parent. - * If not found via db_id, create a new entry using the same method that - imports a full EDI record, grab the resulting db id, and use it to - connect to the parent. - - #: Many2Many - M2M fields are always exported as a list of pairs similar to M2O. - For each pair in the M2M: - * Perform the same steps as for a Many2One (See :meth:`~.edi_import_relation`) - * After finding the database ID of the final record in the database, - connect it to the parent record. - """ - assert self._name == edi_document['__model'], "EDI Document Model and current model do not match: "\ - "'%s' (EDI) vs '%s' (current)" % (edi_document['__model'], - self._name) - - # First check the record is now already known in the database, in which case it is ignored - ext_id_members = split_external_id(edi_document['__id']) - existing_id = self._edi_get_object_by_external_id(cr, uid, ext_id_members['full'], self._name, context=context) - if existing_id: - _logger.info("'%s' EDI Document with ID '%s' is already known, skipping import!", self._name, ext_id_members['full']) - return - - record_values = {} - o2m_todo = {} # o2m values are processed after their parent already exists - for field_name, field_value in edi_document.iteritems(): - # skip metadata and empty fields - if field_name.startswith('__') or field_value is None or field_value is False: - continue - field = self._all_columns[field_name].column - # skip function/related fields - if isinstance(field, fields.function): - _logger.warning("Unexpected function field value found in '%s' EDI document: '%s'" % (self._name, field_name)) - continue - relation_model = field._obj - if field._type == 'many2one': - record_values[field_name] = self.edi_import_relation(cr, uid, relation_model, - field_value[1], field_value[0], - context=context) - elif field._type == 'many2many': - record_values[field_name] = [self.edi_import_relation(cr, uid, relation_model, m2m_value[1], - m2m_value[0], context=context) - for m2m_value in field_value] - elif field._type == 'one2many': - # must wait until parent report is imported, as the parent relationship - # is often required in o2m child records - o2m_todo[field_name] = field_value - else: - record_values[field_name] = field_value - - module_ref = "%s:%s" % (ext_id_members['module'], ext_id_members['db_uuid']) - record_id = self.pool.get('ir.model.data')._update(cr, uid, self._name, module_ref, record_values, - xml_id=ext_id_members['id'], context=context) - - record_display, = self.name_get(cr, uid, [record_id], context=context) - - # process o2m values, connecting them to their parent on-the-fly - for o2m_field, o2m_value in o2m_todo.iteritems(): - field = self._all_columns[o2m_field].column - dest_model = self.pool.get(field._obj) - for o2m_line in o2m_value: - # link to parent record: expects an (ext_id, name) pair - o2m_line[field._fields_id] = (ext_id_members['full'], record_display[1]) - dest_model.edi_import(cr, uid, o2m_line, context=context) - - # process the attachments, if any - self._edi_import_attachments(cr, uid, record_id, edi_document, context=context) - - return record_id - -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: \ No newline at end of file diff --git a/openerp/addons/base/res/__init__.py b/openerp/addons/base/res/__init__.py index cb4c68b2a72..ba3e906497e 100644 --- a/openerp/addons/base/res/__init__.py +++ b/openerp/addons/base/res/__init__.py @@ -35,8 +35,6 @@ import res_lang import res_log import res_widget import ir_property -import edi_partner -import edi_res_company import wizard import report diff --git a/openerp/addons/base/res/edi_partner.py b/openerp/addons/base/res/edi_partner.py deleted file mode 100644 index b8b64fad9e6..00000000000 --- a/openerp/addons/base/res/edi_partner.py +++ /dev/null @@ -1,65 +0,0 @@ -# -*- coding: utf-8 -*- -############################################################################## -# -# OpenERP, Open Source Management Solution -# Copyright (C) 2004-2009 Tiny SPRL (). -# -# 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 . -# -############################################################################## -from osv import fields,osv -from base.ir import ir_edi - -RES_PARTNER_ADDRESS_EDI_STRUCT = { - 'name': True, - 'email': True, - 'street': True, - 'street2': True, - 'zip': True, - 'city': True, - 'country_id': True, - 'state_id': True, - 'phone': True, - 'fax': True, - 'mobile': True, -} - -RES_PARTNER_EDI_STRUCT = { - 'name': True, - 'ref': True, - 'lang': True, - 'website': True, - 'address': RES_PARTNER_ADDRESS_EDI_STRUCT -} - - -class res_partner(osv.osv, ir_edi.edi): - _inherit = "res.partner" - - def edi_export(self, cr, uid, records, edi_struct=None, context=None): - return super(res_partner,self).edi_export(cr, uid, records, - dict(RES_PARTNER_EDI_STRUCT), - context=context) - -class res_partner_address(osv.osv, ir_edi.edi): - _inherit = "res.partner.address" - - def edi_export(self, cr, uid, records, edi_struct=None, context=None): - return super(res_partner_address,self).edi_export(cr, uid, records, - dict(RES_PARTNER_ADDRESS_EDI_STRUCT), - context=context) - -class res_partner_bank(osv.osv, ir_edi.edi): - _inherit = "res.partner.bank" - diff --git a/openerp/addons/base/res/edi_res_company.py b/openerp/addons/base/res/edi_res_company.py deleted file mode 100644 index 3cf236756a4..00000000000 --- a/openerp/addons/base/res/edi_res_company.py +++ /dev/null @@ -1,123 +0,0 @@ -# -*- coding: utf-8 -*- -############################################################################## -# -# OpenERP, Open Source Management Solution -# Copyright (C) 2004-2011 Tiny SPRL (). -# -# 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 . -# -############################################################################## - -#from osv import osv -#from osv import fields -#from tools.translate import _ - -# TODO: CHECK below, seems useless -# -#class res_company(osv.osv): -# """Helper subclass for res.company providing util methods for working with -# companies in the context of EDI import/export. The res.company object -# itself is not EDI-exportable""" -# _inherit = "res.company" -# -# def edi_import_as_partner(self, cr, uid, edi_document, values=None, context=None): -# """ -# import company as a new partner -# company_address data used to add address to new partner -# -# edi_document is a dict to have company datas -# edi_document = { -# 'company_address': { -# 'street': True, -# 'street2': True, -# 'zip': True, -# 'city': True, -# 'state_id': True, -# 'country_id': True, -# 'email': True, -# 'phone': True, -# -# }, -# 'company_id': True, -# } -# values is a dict to have other datas of partner which are need to import of partner record -# values = { -# 'customer': True, -# 'supplier': True, -# } -# """ -# if values is None: -# values = {} -# partner_model = 'res.partner' -# partner_pool = self.pool.get(partner_model) -# xml_id = edi_document['company_id'][0] -# company_address = edi_document.get('company_address', False) -# partner_name = edi_document['company_id'][1] -# partner = partner_pool.edi_get_object(cr, uid, xml_id, partner_model, context=context) -# if not partner: -# partner = partner_pool.edi_get_object_by_name(cr, uid, partner_name, partner_model, context=context) -# -# if partner: - #FIXME -# record_xml = partner_pool._get_external_id(cr, uid, [partner.id], context=context) -# if record_xml: -# module, xml_id = record_xml -# xml_id = '%s.%s' % (module, xml_id) -# -# edi_document_partner = { -# '__model': partner_model, -# '__id' : xml_id, -# 'name' : partner_name, -# } -# if company_address: -# edi_document_partner['address'] = [company_address] -# -# edi_document_partner.update(values) -# return partner_pool.edi_import(cr, uid, edi_document_partner, context=context) -# -# def edi_export_address(self, cr, uid, records, edi_address_struct=None, context=None): -# """Return a dict representation of the address of each company record, suitable for -# inclusion in an EDI document, and matching the given edi_address_struct if provided. -# -# :param list(browse_record) records: list of companies to export -# :rtype: list(dict) -# :return: list of dicts, where each dict contains the address representation for -# the company record as the same index in ``records``. -# """ -# if context is None: -# context = {} -# res_partner = self.pool.get('res.partner') -# res_partner_address = self.pool.get('res.partner.address') -# if edi_address_struct is None: -# edi_address_struct = { -# 'street': True, -# 'street2': True, -# 'zip': True, -# 'city': True, -# 'state_id': True, -# 'country_id': True, -# 'email': True, -# 'phone': True, -# } -# results = [] -# for company in records: -# res = res_partner.address_get(cr, uid, [company.partner_id.id], ['default', 'contact', 'invoice']) -# addr_id = res['invoice'] or res['contact'] or res['default'] -# result = {} -# if addr_id: -# address = res_partner_address.browse(cr, uid, addr_id, context=context) -# result = res_partner_address.edi_export(cr, uid, [address], edi_struct=edi_address_struct, context=ctx)[0] -# results.append(result) -# return results - diff --git a/openerp/addons/base/security/ir.model.access.csv b/openerp/addons/base/security/ir.model.access.csv index 56e6c1b2408..659938a73a3 100644 --- a/openerp/addons/base/security/ir.model.access.csv +++ b/openerp/addons/base/security/ir.model.access.csv @@ -127,5 +127,3 @@ "access_ir_mail_server_all","ir_mail_server","model_ir_mail_server",,1,0,0,0 "access_ir_actions_todo_category","ir_actions_todo_category","model_ir_actions_todo_category","group_system",1,1,1,1 "access_ir_actions_client","ir_actions_client all","model_ir_actions_client",,1,0,0,0 -"access_ir_edi_all_read","access_ir_edi_all_read","model_ir_edi_document",,1,0,0,0 -"access_ir_edi_employee_create","access_ir_edi_employee_create","model_ir_edi_document","group_user",1,0,1,0 diff --git a/openerp/addons/base/test/test_edi_documents.yml b/openerp/addons/base/test/test_edi_documents.yml deleted file mode 100644 index c9695af73e1..00000000000 --- a/openerp/addons/base/test/test_edi_documents.yml +++ /dev/null @@ -1,43 +0,0 @@ -- - In order to test the basic EDI system, I will export a partner, - modify the exported EDI document to add an attachment and change - the data, and then re-import it and re-export it. - - with an attached file, check the result, the alter the data - and reimport it. -- - !python {model: ir.edi.document}: | - import json - partner_obj = self.pool.get('res.partner') - tokens = self.export_edi(cr, uid, [partner_obj.browse(cr, uid, ref('base.res_partner_agrolait'))]) - doc = self.get_document(cr, uid, tokens[0], context=context) - edi_doc, = json.loads(doc) - - # check content of the document - assert edi_doc.get('__id').endswith('.res_partner_agrolait'), 'Incorrect external ID' - assert edi_doc.get('__model') == 'res.partner', 'Incorrect/Missing __model' - assert edi_doc.get('__module') == 'base', 'Incorrect/Missing __module' - assert edi_doc.get('__last_update'), 'Missing __last_update' - - # try to import the document after changing the name and id, and attaching a - # file, and check that a new partner is returned - edi_doc['__id'] = 'base:xxd37f8a-xx55-11e0-xxdd-xx81124c8b50.res_partner_xxx' - edi_doc['name'] = 'AgroMilk' - attachment = { - 'name': 'Test file', - 'file_name': 'test.png', - 'content': 'iVBORw0KGgoAAAANSUhEUgAAAA4AAAAKCAYAAACE2W/HAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9oIDQ84BkjLWAYAAACNSURBVCjPjZKxDUJBDEOf/wbUbEHDhkxAzRjUDECBhMQYjIApuPBNpK+PpUinOPYll5Nt1iCJXifbSPpJZtHgXLUdu0FWpMEt87a/xtsmqjjNetPFyhuWYFuj7RcgQBNwXNGdw2CqY85yXWi5z7YBnmRyEHvg0YSXrLE9P30nwugOHHr+s5va4x+fofAGm1+JjnJICm0AAAAASUVORK5CYII=', - } - edi_doc['__attachments'] = [attachment] - doc = json.dumps([edi_doc]) - result, = self.import_edi(cr, uid, edi_document=doc) - assert result[0] == 'res.partner' and result[1] > ref('base.res_partner_agrolait'),\ - "Expected (%r,> %r) after import 1, got %r" % ('res.partner', ref('base.res_partner_agrolait'), result) - - # export the same partner we just created, and see if the output matches the input - tokens = self.export_edi(cr, uid, [partner_obj.browse(cr, uid, result[1])]) - doc_output = self.get_document(cr, uid, tokens[0], context=context) - edi_doc_output, = json.loads(doc_output) - for attribute in ('__model', '__module', '__id', 'name', '__attachments'): - assert edi_doc_output.get(attribute) == edi_doc.get(attribute), \ - 'Incorrect value for %s, expected %r, got %r' % (attribute, edi_doc.get(attribute), edi_doc_output.get(attribute)) \ No newline at end of file diff --git a/openerp/service/web_services.py b/openerp/service/web_services.py index 09112f884fd..16bf50683c6 100644 --- a/openerp/service/web_services.py +++ b/openerp/service/web_services.py @@ -40,67 +40,6 @@ import openerp.tools as tools import openerp.modules import openerp.exceptions -class edi(netsvc.ExportService): - def exp_get_edi_document(self, edi_token, db_name): - res = None - if db_name: - cr = pooler.get_db(db_name).cursor() - else: - raise Exception("No database cursor found!") - pool = pooler.get_pool(db_name) - edi_pool = pool.get('ir.edi.document') - try: - res = edi_pool.get_document(cr, 1, edi_token) - finally: - cr.close() - return res - - def exp_import_edi_document(self, db, uid, passwd, edi_document, context=None): - res = None - cr = pooler.get_db(db).cursor() - pool = pooler.get_pool(db) - edi_pool = pool.get('ir.edi.document') - try: - res = edi_pool.import_edi(cr, uid, edi_document=edi_document, context=context) - cr.commit() - except: - print traceback.format_exc() - cr.rollback() - finally: - cr.close() - return res - - def exp_import_edi_url(self, db, uid, passwd, edi_url, context=None): - res = None - cr = pooler.get_db(db).cursor() - pool = pooler.get_pool(db) - edi_pool = pool.get('ir.edi.document') - try: - res = edi_pool.import_edi(cr, uid, edi_url=edi_url, context=context) - cr.commit() - except: - print traceback.format_exc() - cr.rollback() - finally: - cr.close() - return res - - def __init__(self, name="edi"): - netsvc.ExportService.__init__(self, name) - - def dispatch(self, method, auth, params): - if method in ['import_edi_document', 'import_edi_url']: - (db, uid, passwd ) = params[0:3] - security.check(db, uid, passwd) - elif method in ['get_edi_document']: - # params = params - # No security check for these methods - pass - else: - raise KeyError("Method not found: %s" % method) - fn = getattr(self, 'exp_'+method) - return fn(*params) - #.apidoc title: Exported Service methods #.apidoc module-mods: member-order: bysource @@ -836,8 +775,6 @@ def start_web_services(): objects_proxy() wizard() report_spool() - edi() - # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: