diff --git a/openerp/addons/base/ir/ir_edi.py b/openerp/addons/base/ir/ir_edi.py index bdc038b6236..9af5bb325f8 100644 --- a/openerp/addons/base/ir/ir_edi.py +++ b/openerp/addons/base/ir/ir_edi.py @@ -26,30 +26,17 @@ import time import base64 import urllib2 import openerp.release as release +from tools.translate import _ +import netsvc edi_module = 'edi_import' -def safe_unique_id(model, database_id): - """Generate a unique string to represent a (model,database id) pair +def safe_unique_id(database_id, model, record_id): + """Generate a unique string to represent a (database id,model,record_id) pair without being too long, without revealing the database id, and with a very low probability of collisions. - - Each EDI record and each relationship value are represented using a unique - database identifier. These database identifiers include the database unique - ID, as a way to uniquely refer to any record within any OpenERP instance, - without conflict. - - For OpenERP records that have an existing "XML ID" (i.e. an entry in - ir.model.data), the EDI unique identifier for this record will be made of - "%s:%s" % (the database's UUID, the XML ID). The database's UUID MUST - NOT contain a colon characters (this is guaranteed by the UUID algorithm). - - For OpenERP records that have no existing "XML ID", a new one should be - created during the EDI export. It is recommended that the generated XML ID - contains a readable reference to the record model, plus a unique value that - hides the database ID. """ - msg = "%s-%s-%s" % (model, time.time(), database_id) + msg = "%s-%s-%s-%s" % (time.time(), database_id, model, record_id) digest = hashlib.sha1(msg).digest() digest = ''.join(chr(ord(x) ^ ord(y)) for (x,y) in zip(digest[:9], digest[9:-2])) # finally, use the b64-encoded folded digest as ID part of the unique ID: @@ -70,14 +57,14 @@ class ir_edi_document(osv.osv): ] - def new_edi_token(self, record): + def new_edi_token(self, cr, uid, record): """ Return a new, random unique token to identify an edi.document :param record: It's a object of browse_record of any model """ db_uuid = self.pool.get('ir.config_parameter').get_param(cr, uid, 'database.uuid') - edi_token = hashlib.sha256('%s-%s-%s' % (time.time(), db_uuid, time.time())).hexdigest() + 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): @@ -123,8 +110,14 @@ class ir_edi_document(osv.osv): :param edi_dicts: list of edi_dict """ + module_obj =self.pool.get('ir.module.module') res = [] for edi_document in edi_documents: + module = edi_document.get('__module') + module_ids = module_obj.search(cr, uid, [('name','=',module),('state','not in',['uninstalled', 'uninstallable', 'to remove'])]) + if not module_ids: + raise osv.except_osv(_('Invalid action !'), + _('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 should be provided in EDI Dict') model_obj = self.pool.get(model) @@ -154,7 +147,7 @@ class ir_edi_document(osv.osv): exported_ids = [] for record in records: document = self.generate_edi(cr, uid, [record], context) - token = self.new_edi_token(record) + token = self.new_edi_token(cr, uid, record) self.create(cr, uid, { 'name': token, 'document': document @@ -193,6 +186,23 @@ class edi(object): specific behavior, based on the primitives provided by this superclass.""" def edi_xml_id(self, cr, uid, record, context=None): + """ + Generate a unique string to represent a pair of (the database's UUID, the XML ID). + Each EDI record and each relationship value are represented using a unique + database identifier. These database identifiers include the database unique + ID, as a way to uniquely refer to any record within any OpenERP instance, + without conflict. + + For OpenERP records that have an existing "XML ID" (i.e. an entry in + ir.model.data), the EDI unique identifier for this record will be made of + "%s:%s" % (the database's UUID, the XML ID). The database's UUID MUST + NOT contain a colon characters (this is guaranteed by the UUID algorithm). + + For OpenERP records that have no existing "XML ID", a new one should be + created during the EDI export. It is recommended that the generated XML ID + contains a readable reference to the record model, plus a unique value that + hides the database ID. + """ model_data_pool = self.pool.get('ir.model.data') db_uuid = self.pool.get('ir.config_parameter').get_param(cr, uid, 'database.uuid') @@ -202,14 +212,13 @@ class edi(object): xml_record = model_data_pool.browse(cr, uid, xml_record_id, context=context) uuid = '%s:%s' % (db_uuid, xml_record.name) else: - xml_id = safe_unique_id(model, db_uuid) + xml_id = safe_unique_id(db_uuid, record._name, record.id) uuid = '%s:%s' % (db_uuid, xml_id) xml_record_id = model_data_pool.create(cr, uid, { 'name': xml_id, 'model': record._name, 'module': uuid, 'res_id': record.id}, context=context) - return uuid def edi_metadata(self, cr, uid, records, context=None): @@ -250,9 +259,9 @@ class edi(object): }) - db_uuid = self.edi_xml_id(cr, uid, record, context=context) + uuid = self.edi_xml_id(cr, uid, record, context=context) edi_dict = { - '__id': db_uuid, + '__id': uuid, '__last_update': False, #record.write_date, #TODO: convert into UTC } if not context.get('o2m_export'): @@ -320,7 +329,7 @@ class edi(object): dict_list = [] for record in records: - dict_list.append(self.edi_o2m(cr, uid, [record], context=None)) + dict_list.append(self.edi_m2o(cr, uid, [record], context=None)) return dict_list diff --git a/openerp/addons/base/res/partner/partner.py b/openerp/addons/base/res/partner/partner.py index 132d1e61a5e..afd7d48996c 100644 --- a/openerp/addons/base/res/partner/partner.py +++ b/openerp/addons/base/res/partner/partner.py @@ -111,7 +111,8 @@ class res_partner(osv.osv): _order = "name" _columns = { 'name': fields.char('Name', size=128, required=True, select=True), - 'opt_out':fields.boolean('Opt-out'), + 'opt_out':fields.boolean('Opt-out', help="If checked, this partner will not receive any automated email \ +notifications, such as the availability of invoices."), 'date': fields.date('Date', select=1), 'title': fields.many2one('res.partner.title','Partner Firm'), 'parent_id': fields.many2one('res.partner','Parent Partner'), @@ -151,7 +152,7 @@ class res_partner(osv.osv): 'address': [{'type': 'default'}], 'category_id': _default_category, 'company_id': lambda s,cr,uid,c: s.pool.get('res.company')._company_default_get(cr, uid, 'res.partner', context=c), - 'opt_out' : False + 'opt_out' : False, } def copy(self, cr, uid, id, default={}, context={}): diff --git a/openerp/addons/base/res/partner/partner_demo.xml b/openerp/addons/base/res/partner/partner_demo.xml index e8d8d540422..8f2f661234d 100644 --- a/openerp/addons/base/res/partner/partner_demo.xml +++ b/openerp/addons/base/res/partner/partner_demo.xml @@ -94,57 +94,68 @@ 1 + Agrolait + Camptocamp 1 + http://www.syleam.fr Syleam + Thymbra + Axelor 1 + Tiny AT Work + Bank Wealthy and sons + China Export + Distrib PC 1 + Ecole de Commerce de Liege + Elec Import @@ -152,6 +163,7 @@ 1 + Maxtor @@ -160,6 +172,7 @@ 1 + Seagate @@ -168,6 +181,7 @@ 1 + http://mediapole.net @@ -175,6 +189,7 @@ + http://balmerinc.com @@ -184,12 +199,14 @@ + Tecsas 3020170000003 + Leclerc @@ -197,6 +214,7 @@ + Centrale d'achats BML @@ -205,6 +223,7 @@ + Magazin BML 1 @@ -214,11 +233,13 @@ + Université de Liège +