From eab2e225a223d0919ee4dde65f4dfe7e269fa01c Mon Sep 17 00:00:00 2001 From: "Nimesh (Open ERP)" Date: Fri, 6 Jul 2012 14:46:08 +0530 Subject: [PATCH 001/122] [FIX]: add date validation. bzr revid: nco@tinyerp.com-20120706091608-f5o08ke6z84oilui --- addons/membership/membership.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/addons/membership/membership.py b/addons/membership/membership.py index dc4eadbada9..f7007ac28e7 100644 --- a/addons/membership/membership.py +++ b/addons/membership/membership.py @@ -478,7 +478,14 @@ class Product(osv.osv): 'membership_date_from': fields.date('Date from', help='Date from which membership becomes active.'), 'membership_date_to': fields.date('Date to', help='Date until which membership remains active.'), } - + def _check_end_date(self, cr, uid, ids, context=None): + for membership in self.browse(cr, uid, ids, context=context): + if membership.membership_date_to < membership.membership_date_from: + return False + return True + _constraints = [ + (_check_end_date, 'Error ! Ending Date cannot be set before Beginning Date.', ['membership_date_to']), + ] _defaults = { 'membership': False, } From 5f2459422335c966567370eadce3281adff729f7 Mon Sep 17 00:00:00 2001 From: Olivier Dony Date: Thu, 11 Oct 2012 17:20:08 +0200 Subject: [PATCH 002/122] [IMP] edi: work-in-progress: remove permanent storage of edi.document The EDI documents will now be generated on demand and available from the Portal view of each document. Instead of getting a link to a statically generated EDI document, customers will receive a link to the portal access to the document. They will be able to signup on the portal the first time as well, provided they are using the secure token that was sent to them (i.e. the right link). The link to pay online will be available in the portal as well. Still much to do, this is a small first step, with edi.document renamed to edi.edi for consistency, as it will not persist any edi.document anymore. bzr revid: odo@openerp.com-20121011152008-bht7ub6woaex0a7u --- addons/account/edi/invoice.py | 12 +- addons/account/edi/invoice_action_data.xml | 26 +-- addons/account/test/test_edi_invoice.yml | 7 +- addons/edi/__init__.py | 8 +- addons/edi/__openerp__.py | 2 - addons/edi/controllers/main.py | 65 +------- addons/edi/edi_service.py | 12 +- addons/edi/models/edi.py | 153 ++++-------------- addons/edi/models/res_company.py | 4 +- addons/edi/models/res_currency.py | 4 +- addons/edi/models/res_partner.py | 6 +- addons/edi/security/ir.model.access.csv | 3 - addons/edi/test/edi_partner_test.yml | 10 +- .../wizard/mail_compose_message.py | 1 + addons/mail/static/src/xml/mail.xml | 4 +- addons/purchase/edi/purchase_order.py | 21 +-- .../edi/purchase_order_action_data.xml | 29 +--- .../test/process/edi_purchase_order.yml | 14 +- addons/sale/edi/sale_order.py | 23 +-- addons/sale/edi/sale_order_action_data.xml | 10 +- addons/sale/test/edi_sale_order.yml | 9 +- 21 files changed, 86 insertions(+), 337 deletions(-) delete mode 100644 addons/edi/security/ir.model.access.csv diff --git a/addons/account/edi/invoice.py b/addons/account/edi/invoice.py index 751eb8656f7..e84bec6614d 100644 --- a/addons/account/edi/invoice.py +++ b/addons/account/edi/invoice.py @@ -71,16 +71,6 @@ INVOICE_EDI_STRUCT = { class account_invoice(osv.osv, EDIMixin): _inherit = 'account.invoice' - def action_invoice_sent(self, cr, uid, ids, context=None): - """"Override this method to add a link to mail""" - if context is None: - context = {} - invoice_objs = self.browse(cr, uid, ids, context=context) - edi_token = self.pool.get('edi.document').export_edi(cr, uid, invoice_objs, context = context)[0] - web_root_url = self.pool.get('ir.config_parameter').get_param(cr, uid, 'web.base.url') - ctx = dict(context, edi_web_url_view=edi.EDI_VIEW_WEB_URL % (web_root_url, cr.dbname, edi_token)) - return super(account_invoice, self).action_invoice_sent(cr, uid, ids, context=ctx) - def edi_export(self, cr, uid, records, edi_struct=None, context=None): """Exports a supplier or customer invoice""" edi_struct = dict(edi_struct or INVOICE_EDI_STRUCT) @@ -136,7 +126,7 @@ class account_invoice(osv.osv, EDIMixin): self._edi_requires_attributes(('company_id','company_address','type'), edi_document) res_partner = self.pool.get('res.partner') - src_company_id, src_company_name = edi_document.pop('company_id') + _, src_company_name = edi_document.pop('company_id') invoice_type = edi_document['type'] partner_value = {} diff --git a/addons/account/edi/invoice_action_data.xml b/addons/account/edi/invoice_action_data.xml index 53fa03a6902..1ad023c3a60 100644 --- a/addons/account/edi/invoice_action_data.xml +++ b/addons/account/edi/invoice_action_data.xml @@ -1,17 +1,6 @@ - - - if (object.type in ('out_invoice', 'out_refund')) and not object.partner_id.opt_out: object.edi_export_and_email(template_ext_id='account.email_template_edi_invoice', context=context) - - code - ir.actions.server - - True - Auto-email confirmed invoices - - Email Templates @@ -27,17 +16,12 @@ - - - - - - - Automated Invoice Notification Mail + Invoice - Send by mail ${object.user_id.email or object.company_id.email or 'noreply@localhost'} ${object.company_id.name} Invoice (Ref ${object.number or 'n/a' }) ${object.partner_id.email or ''} @@ -61,12 +45,6 @@   Your contact: ${object.user_id.name}

-

- You can view the invoice document, download it and pay online using the following link: -

- View Invoice - % if object.company_id.paypal_account and object.type in ('out_invoice', 'in_refund'): <% comp_name = quote(object.company_id.name) diff --git a/addons/account/test/test_edi_invoice.yml b/addons/account/test/test_edi_invoice.yml index 80dc098e770..3d57f8dc608 100644 --- a/addons/account/test/test_edi_invoice.yml +++ b/addons/account/test/test_edi_invoice.yml @@ -38,11 +38,12 @@ - Then I export the customer invoice - - !python {model: edi.document}: | + !python {model: edi.edi}: | + import json invoice_pool = self.pool.get('account.invoice') invoice = invoice_pool.browse(cr, uid, ref("invoice_edi_1")) - token = self.export_edi(cr, uid, [invoice]) - assert token, 'Invalid EDI Token' + edi_doc = self.generate_edi(cr, uid, [invoice]) + assert isinstance(json.loads(edi_doc)[0], dict), 'EDI doc should be a JSON dict' - Then I import a sample EDI document of another customer invoice - diff --git a/addons/edi/__init__.py b/addons/edi/__init__.py index 46fabbc2fd0..71ee8aaa53d 100644 --- a/addons/edi/__init__.py +++ b/addons/edi/__init__.py @@ -20,14 +20,14 @@ ############################################################################## import logging -import models -import edi_service -from models.edi import EDIMixin, edi_document +from . import models +from . import edi_service +from models.edi import EDIMixin, edi _logger = logging.getLogger(__name__) # web try: - import controllers + import openerp.addons.web.controllers except ImportError: _logger.warn( """Could not load openerp-web section of EDI, EDI will not behave correctly diff --git a/addons/edi/__openerp__.py b/addons/edi/__openerp__.py index b06c01eb03b..72ccb32d701 100644 --- a/addons/edi/__openerp__.py +++ b/addons/edi/__openerp__.py @@ -36,12 +36,10 @@ documentation at http://doc.openerp.com. 'website': 'http://www.openerp.com', 'depends': ['base', 'email_template'], 'icon': '/edi/static/src/img/knowledge.png', - 'data': ['security/ir.model.access.csv'], 'test': ['test/edi_partner_test.yml'], 'js': ['static/src/js/edi.js'], 'css': ['static/src/css/edi.css'], 'qweb': ['static/src/xml/*.xml'], - 'installable': True, 'auto_install': False, } diff --git a/addons/edi/controllers/main.py b/addons/edi/controllers/main.py index c62fef19cba..0322099b6f3 100644 --- a/addons/edi/controllers/main.py +++ b/addons/edi/controllers/main.py @@ -1,31 +1,10 @@ -import json -import textwrap - -import simplejson -import werkzeug.wrappers - -import openerp.addons.web.http as openerpweb +import openerp.addons.web.common.http as openerpweb import openerp.addons.web.controllers.main as webmain class EDI(openerpweb.Controller): - # http://hostname:8069/edi/view?db=XXXX&token=XXXXXXXXXXX # http://hostname:8069/edi/import_url?url=URIEncodedURL _cp_path = "/edi" - def template(self, req, mods='web,edi'): - d = {} - d["js"] = "\n".join(''%i for i in webmain.manifest_list(req, mods, 'js')) - d["css"] = "\n".join(''%i for i in webmain.manifest_list(req, mods, 'css')) - d["modules"] = simplejson.dumps(mods.split(',')) - return d - - @openerpweb.httprequest - def view(self, req, db, token): - d = self.template(req) - d["init"] = 's.edi.edi_view("%s","%s");'%(db,token) - r = webmain.html_template % d - return r - @openerpweb.httprequest def import_url(self, req, url): d = self.template(req) @@ -33,46 +12,6 @@ class EDI(openerpweb.Controller): r = webmain.html_template % d return r - @openerpweb.httprequest - def download(self, req, db, token): - result = req.session.proxy('edi').get_edi_document(db, token) - response = werkzeug.wrappers.Response( result, headers=[('Content-Type', 'text/html; charset=utf-8'), ('Content-Length', len(result))]) - return response - - @openerpweb.httprequest - def download_attachment(self, req, db, token): - result = req.session.proxy('edi').get_edi_document(db, token) - doc = json.loads(result)[0] - attachment = doc['__attachments'] and doc['__attachments'][0] - if attachment: - result = attachment["content"].decode('base64') - import email.Utils as utils - - # Encode as per RFC 2231 - filename_utf8 = attachment['file_name'] - filename_encoded = "%s=%s" % ('filename*', - utils.encode_rfc2231(filename_utf8, 'utf-8')) - response = werkzeug.wrappers.Response(result, headers=[('Content-Type', 'application/pdf'), - ('Content-Disposition', 'inline; ' + filename_encoded), - ('Content-Length', len(result))]) - return response - - @openerpweb.httprequest - def binary(self, req, db, token, field_path="company_address.logo", content_type='image/png'): - result = req.session.proxy('edi').get_edi_document(db, token) - doc = json.loads(result)[0] - for name in field_path.split("."): - doc = doc[name] - result = doc.decode('base64') - response = werkzeug.wrappers.Response(result, headers=[('Content-Type', content_type), - ('Content-Length', len(result))]) - return response - - @openerpweb.jsonrequest - def get_edi_document(self, req, db, token): - result = req.session.proxy('edi').get_edi_document(db, token) - return json.loads(result) - @openerpweb.jsonrequest def import_edi_url(self, req, url): result = req.session.proxy('edi').import_edi_url(req.session._db, req.session._uid, req.session._password, url) @@ -80,6 +19,4 @@ class EDI(openerpweb.Controller): return {"action": webmain.clean_action(req, result[0][2])} return True -# - # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/edi/edi_service.py b/addons/edi/edi_service.py index 63fe38786e0..fd911139170 100644 --- a/addons/edi/edi_service.py +++ b/addons/edi/edi_service.py @@ -20,8 +20,8 @@ ############################################################################## import logging -import netsvc import openerp +import openerp.netsvc as netsvc _logger = logging.getLogger(__name__) @@ -34,10 +34,10 @@ class edi(netsvc.ExportService): try: registry = openerp.modules.registry.RegistryManager.get(db_name) assert registry, 'Unknown database %s' % db_name - edi_document = registry['edi.document'] + edi = registry['edi.edi'] cr = registry.db.cursor() res = None - res = getattr(edi_document, method_name)(cr, *method_args) + res = getattr(edi, method_name)(cr, *method_args) cr.commit() except Exception: _logger.exception('Failed to execute EDI method %s with args %r.', method_name, method_args) @@ -46,9 +46,6 @@ class edi(netsvc.ExportService): cr.close() return res - def exp_get_edi_document(self, db_name, edi_token): - return self._edi_dispatch(db_name, 'get_document', 1, edi_token) - def exp_import_edi_document(self, db_name, uid, passwd, edi_document, context=None): return self._edi_dispatch(db_name, 'import_edi', uid, edi_document, None) @@ -59,9 +56,6 @@ class edi(netsvc.ExportService): if method in ['import_edi_document', 'import_edi_url']: (db, uid, passwd ) = params[0:3] openerp.service.security.check(db, uid, passwd) - elif method in ['get_edi_document']: - # No security check for these methods - pass else: raise KeyError("Method not found: %s." % method) fn = getattr(self, 'exp_'+method) diff --git a/addons/edi/models/edi.py b/addons/edi/models/edi.py index 6d11db1c52c..29e19f2da3b 100644 --- a/addons/edi/models/edi.py +++ b/addons/edi/models/edi.py @@ -30,9 +30,9 @@ import urllib2 import openerp import openerp.release as release -import netsvc -import pooler -from osv import osv,fields,orm +import openerp.netsvc as netsvc +from openerp.modules.registry import RegistryManager +from openerp.osv import osv, fields from tools.translate import _ from tools.safe_eval import safe_eval as eval _logger = logging.getLogger(__name__) @@ -74,16 +74,9 @@ def last_update_for(record): return False -class edi_document(osv.osv): - _name = '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!') - ] +class edi(osv.AbstractModel): + _name = 'edi.edi' + _description = 'EDI Subsystem' def new_edi_token(self, cr, uid, record): """Return a new, random unique token to identify this model record, @@ -109,7 +102,7 @@ class edi_document(osv.osv): """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`. + database. :param list(browse_record) records: records to export as EDI :return: UTF-8 encoded string containing the serialized records @@ -120,19 +113,6 @@ class edi_document(osv.osv): 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`. @@ -171,38 +151,18 @@ class edi_document(osv.osv): """ 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 + :param str|unicode edi: 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``) + :param str|unicode edi_url: URL where the EDI document (same format as ``edi``) may be retrieved, without authentication. """ if edi_url: - assert not edi_document, 'edi_document must not be provided if edi_url is given.' + assert not edi_document, 'edi 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) @@ -215,10 +175,10 @@ class EDIMixin(object): ``edi_import()`` and ``edi_export()`` methods to implement their specific behavior, based on the primitives provided by this mixin.""" - def _edi_requires_attributes(self, attributes, edi_document): - model_name = edi_document.get('__imported_model') or edi_document.get('__model') or self._name + def _edi_requires_attributes(self, attributes, edi): + model_name = edi.get('__imported_model') or edi.get('__model') or self._name for attribute in attributes: - assert edi_document.get(attribute),\ + assert edi.get(attribute),\ 'Attribute `%s` is required in %s EDI documents.' % (attribute, model_name) # private method, not RPC-exposed as it creates ir.model.data entries as @@ -318,7 +278,6 @@ class EDIMixin(object): :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 = [] for record in records: @@ -398,7 +357,7 @@ class EDIMixin(object): 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 + """Returns a list of dicts representing EDI documents containing the records, and matching the given ``edi_struct``, if provided. :param edi_struct: if provided, edi_struct should be a dictionary @@ -443,50 +402,6 @@ class EDIMixin(object): results.append(edi_dict) return results - def edi_export_and_email(self, cr, uid, ids, template_ext_id, context=None): - """Export the given records just like :meth:`~.export_edi`, the render the - given email template, in order to trigger appropriate notifications. - This method is intended to be called as part of business documents' - lifecycle, so it silently ignores any error occurring during the process, - as this is usually non-critical. To avoid any delay, it is also asynchronous - and will spawn a short-lived thread to perform the action. - - :param str template_ext_id: external id of the email.template to use for - the mail notifications - :return: True - """ - def email_task(): - db = pooler.get_db(cr.dbname) - local_cr = None - try: - time.sleep(3) # lame workaround to wait for commit of parent transaction - # grab a fresh browse_record on local cursor - local_cr = db.cursor() - web_root_url = self.pool.get('ir.config_parameter').get_param(local_cr, uid, 'web.base.url') - if not web_root_url: - _logger.warning('Ignoring EDI mail notification, web.base.url is not defined in parameters.') - return - mail_tmpl = self._edi_get_object_by_external_id(local_cr, uid, template_ext_id, 'email.template', context=context) - if not mail_tmpl: - # skip EDI export if the template was not found - _logger.warning('Ignoring EDI mail notification, template %s cannot be located.', template_ext_id) - return - for edi_record in self.browse(local_cr, uid, ids, context=context): - edi_token = self.pool.get('edi.document').export_edi(local_cr, uid, [edi_record], context = context)[0] - edi_context = dict(context, edi_web_url_view=EDI_VIEW_WEB_URL % (web_root_url, local_cr.dbname, edi_token)) - self.pool.get('email.template').send_mail(local_cr, uid, mail_tmpl.id, edi_record.id, - force_send=False, context=edi_context) - _logger.info('EDI export successful for %s #%s, email notification sent.', self._name, edi_record.id) - except Exception: - _logger.warning('Ignoring EDI mail notification, failed to generate it.', exc_info=True) - finally: - if local_cr: - local_cr.commit() - local_cr.close() - - threading.Thread(target=email_task, name='EDI ExportAndEmail for %s %r' % (self._name, ids)).start() - return True - 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) @@ -515,18 +430,20 @@ class EDIMixin(object): file_name = record.name_get()[0][1] file_name = re.sub(r'[^a-zA-Z0-9_-]', '_', file_name) file_name += ".pdf" - ir_attachment = self.pool.get('ir.attachment').create(cr, uid, - {'name': file_name, - 'datas': result, - 'datas_fname': file_name, - 'res_model': self._name, - 'res_id': record.id, - 'type': 'binary'}, - context=context) + self.pool.get('ir.attachment').create(cr, uid, + { + 'name': file_name, + 'datas': result, + 'datas_fname': file_name, + 'res_model': self._name, + 'res_id': record.id, + 'type': 'binary' + }, + context=context) - def _edi_import_attachments(self, cr, uid, record_id, edi_document, context=None): + def _edi_import_attachments(self, cr, uid, record_id, edi, context=None): ir_attachment = self.pool.get('ir.attachment') - for attachment in edi_document.get('__attachments', []): + for attachment in edi.get('__attachments', []): # check attachment data is non-empty and valid file_data = None try: @@ -614,19 +531,19 @@ class EDIMixin(object): 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. + def edi_import(self, cr, uid, edi, context=None): + """Imports a dict representing an EDI document into the system. - :param dict edi_document: EDI document to import + :param dict edi: EDI document to import :return: the database ID of the imported record """ - assert self._name == edi_document.get('__import_model') or \ - ('__import_model' not in edi_document and self._name == edi_document.get('__model')), \ + assert self._name == edi.get('__import_model') or \ + ('__import_model' not in edi and self._name == edi.get('__model')), \ "EDI Document Model and current model do not match: '%s' (EDI) vs '%s' (current)." % \ - (edi_document['__model'], self._name) + (edi['__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']) + ext_id_members = split_external_id(edi['__id']) existing = self._edi_get_object_by_external_id(cr, uid, ext_id_members['full'], self._name, context=context) if existing: _logger.info("'%s' EDI Document with ID '%s' is already known, skipping import!", self._name, ext_id_members['full']) @@ -634,7 +551,7 @@ class EDIMixin(object): record_values = {} o2m_todo = {} # o2m values are processed after their parent already exists - for field_name, field_value in edi_document.iteritems(): + for field_name, field_value in edi.iteritems(): # skip metadata and empty fields if field_name.startswith('__') or field_value is None or field_value is False: continue @@ -679,7 +596,7 @@ class EDIMixin(object): 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) + self._edi_import_attachments(cr, uid, record_id, edi, context=context) return record_id diff --git a/addons/edi/models/res_company.py b/addons/edi/models/res_company.py index 0ab6607cdad..d87827df99d 100644 --- a/addons/edi/models/res_company.py +++ b/addons/edi/models/res_company.py @@ -2,7 +2,7 @@ ############################################################################## # # OpenERP, Open Source Business Applications -# Copyright (c) 2011 OpenERP S.A. +# Copyright (c) 2011-2012 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 @@ -19,7 +19,7 @@ # ############################################################################## -from osv import fields,osv +from openerp.osv import osv class res_company(osv.osv): """Helper subclass for res.company providing util methods for working with diff --git a/addons/edi/models/res_currency.py b/addons/edi/models/res_currency.py index 0f56bc83f45..474e386a248 100644 --- a/addons/edi/models/res_currency.py +++ b/addons/edi/models/res_currency.py @@ -2,7 +2,7 @@ ############################################################################## # # OpenERP, Open Source Business Applications -# Copyright (c) 2011 OpenERP S.A. +# Copyright (c) 2011-2012 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 @@ -19,7 +19,7 @@ # ############################################################################## -from osv import fields,osv +from openerp.osv import osv from edi import EDIMixin from openerp import SUPERUSER_ID diff --git a/addons/edi/models/res_partner.py b/addons/edi/models/res_partner.py index 86d8c81b790..37483c1d38d 100644 --- a/addons/edi/models/res_partner.py +++ b/addons/edi/models/res_partner.py @@ -2,7 +2,7 @@ ############################################################################## # # OpenERP, Open Source Business Applications -# Copyright (c) 2011 OpenERP S.A. +# Copyright (c) 2011-2012 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 @@ -20,10 +20,10 @@ ############################################################################## import logging -from osv import fields,osv +from openerp.osv import osv from edi import EDIMixin from openerp import SUPERUSER_ID -from tools.translate import _ +from openerp.tools.translate import _ _logger = logging.getLogger(__name__) RES_PARTNER_EDI_STRUCT = { diff --git a/addons/edi/security/ir.model.access.csv b/addons/edi/security/ir.model.access.csv deleted file mode 100644 index b1f470d80ae..00000000000 --- a/addons/edi/security/ir.model.access.csv +++ /dev/null @@ -1,3 +0,0 @@ -id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink -access_ir_edi_all_read,access_ir_edi_all_read,model_edi_document,,1,0,0,0 -access_ir_edi_employee_create,access_ir_edi_employee_create,model_edi_document,base.group_user,1,0,1,0 diff --git a/addons/edi/test/edi_partner_test.yml b/addons/edi/test/edi_partner_test.yml index 9fc523bf84f..97ae669e52e 100644 --- a/addons/edi/test/edi_partner_test.yml +++ b/addons/edi/test/edi_partner_test.yml @@ -6,11 +6,10 @@ with an attached file, check the result, the alter the data and reimport it. - - !python {model: edi.document}: | + !python {model: edi.edi}: | import json - partner_obj = self.pool.get('res.partner') - tokens = self.export_edi(cr, uid, [partner_obj.browse(cr, uid, ref('base.res_partner_2'))]) - doc = self.get_document(cr, uid, tokens[0], context=context) + res_partner = self.pool.get('res.partner') + doc = self.generate_edi(cr, uid, [res_partner.browse(cr, uid, ref('base.res_partner_2'))]) edi_doc, = json.loads(doc) # check content of the document @@ -36,8 +35,7 @@ "Expected (%r,> %r) after import 1, got %r" % ('res.partner', ref('base.res_partner_2'), 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) + doc_output = self.generate_edi(cr, uid, [res_partner.browse(cr, uid, result[1])]) 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), \ diff --git a/addons/email_template/wizard/mail_compose_message.py b/addons/email_template/wizard/mail_compose_message.py index c0cb7fc92e5..3e434c4d65e 100644 --- a/addons/email_template/wizard/mail_compose_message.py +++ b/addons/email_template/wizard/mail_compose_message.py @@ -83,6 +83,7 @@ class mail_compose_message(osv.osv_memory): 'datas_fname': attach_fname, 'res_model': model, 'res_id': res_id, + 'type': 'binary', # override default_type from context, possibly meant for another model! } values['attachment_ids'].append(ir_attach_obj.create(cr, uid, data_attach, context=context)) else: diff --git a/addons/mail/static/src/xml/mail.xml b/addons/mail/static/src/xml/mail.xml index 2fc97154e33..66556a30c24 100644 --- a/addons/mail/static/src/xml/mail.xml +++ b/addons/mail/static/src/xml/mail.xml @@ -60,7 +60,7 @@
  • - ...wait upload... + Upload in progress...
    @@ -73,7 +73,7 @@ - x + x
  • diff --git a/addons/purchase/edi/purchase_order.py b/addons/purchase/edi/purchase_order.py index d1c00a3e60d..f44c16eb0d9 100644 --- a/addons/purchase/edi/purchase_order.py +++ b/addons/purchase/edi/purchase_order.py @@ -2,7 +2,7 @@ ############################################################################## # # OpenERP, Open Source Business Applications -# Copyright (c) 2011 OpenERP S.A. +# Copyright (c) 2011-2012 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 @@ -19,13 +19,8 @@ # ############################################################################## -from datetime import datetime, timedelta -from dateutil.relativedelta import relativedelta - -from osv import fields, osv, orm +from openerp.osv import osv from edi import EDIMixin -from edi.models import edi -from tools import DEFAULT_SERVER_DATE_FORMAT from tools.translate import _ PURCHASE_ORDER_LINE_EDI_STRUCT = { @@ -62,16 +57,6 @@ PURCHASE_ORDER_EDI_STRUCT = { class purchase_order(osv.osv, EDIMixin): _inherit = 'purchase.order' - def wkf_send_rfq(self, cr, uid, ids, context=None): - """"Override this method to add a link to mail""" - if context is None: - context = {} - purchase_objs = self.browse(cr, uid, ids, context=context) - edi_token = self.pool.get('edi.document').export_edi(cr, uid, purchase_objs, context = context)[0] - web_root_url = self.pool.get('ir.config_parameter').get_param(cr, uid, 'web.base.url') - ctx = dict(context, edi_web_url_view=edi.EDI_VIEW_WEB_URL % (web_root_url, cr.dbname, edi_token)) - return super(purchase_order, self).wkf_send_rfq(cr, uid, ids, context=ctx) - def edi_export(self, cr, uid, records, edi_struct=None, context=None): """Exports a purchase order""" edi_struct = dict(edi_struct or PURCHASE_ORDER_EDI_STRUCT) @@ -109,7 +94,7 @@ class purchase_order(osv.osv, EDIMixin): res_partner_obj = self.pool.get('res.partner') # imported company_address = new partner address - src_company_id, src_company_name = edi_document.pop('company_id') + _, src_company_name = edi_document.pop('company_id') address_info = edi_document.pop('company_address') address_info['customer'] = True if 'name' not in address_info: diff --git a/addons/purchase/edi/purchase_order_action_data.xml b/addons/purchase/edi/purchase_order_action_data.xml index daad4467929..02e7a1c1ae1 100644 --- a/addons/purchase/edi/purchase_order_action_data.xml +++ b/addons/purchase/edi/purchase_order_action_data.xml @@ -1,18 +1,6 @@ - - - Email Templates @@ -25,19 +13,12 @@ - - - - - Automated Purchase Order Notification Mail + Purchase Order - Send by mail ${object.validator.email or ''} ${object.company_id.name} Order (Ref ${object.name or 'n/a' }) ${object.partner_id.email} @@ -64,12 +45,6 @@   Your contact: ${object.validator.name}

    -

    - You can view the ${object.state in ('draft', 'sent') and 'request for quotation' or 'order confirmation'} document and download it using the following link: -

    - View Order -

    If you have any question, do not hesitate to contact us.

    Thank you!

    diff --git a/addons/purchase/test/process/edi_purchase_order.yml b/addons/purchase/test/process/edi_purchase_order.yml index d0e90f3788d..79f244a283d 100644 --- a/addons/purchase/test/process/edi_purchase_order.yml +++ b/addons/purchase/test/process/edi_purchase_order.yml @@ -27,16 +27,16 @@ - Then I export the purchase order via EDI - - !python {model: edi.document}: | - order_pool = self.pool.get('purchase.order') - order = order_pool.browse(cr, uid, ref("purchase_order_edi_1")) - token = self.export_edi(cr, uid, [order]) - assert token, 'Invalid EDI Token' - + !python {model: edi.edi}: | + import json + order_pool = self.pool.get('purchase.order') + order = order_pool.browse(cr, uid, ref("purchase_order_edi_1")) + edi_doc = self.generate_edi(cr, uid, [order]) + assert isinstance(json.loads(edi_doc)[0], dict), 'EDI doc should be a JSON dict' - Then I import a sample EDI document of a sale order - - !python {model: edi.document}: | + !python {model: edi.edi}: | purchase_order_pool = self.pool.get('purchase.order') edi_document = { "__id": "sale:724f93ec-ddd0-11e0-88ec-701a04e25543.sale_order_test", diff --git a/addons/sale/edi/sale_order.py b/addons/sale/edi/sale_order.py index edec15a86ae..0ca1b55898c 100644 --- a/addons/sale/edi/sale_order.py +++ b/addons/sale/edi/sale_order.py @@ -2,7 +2,7 @@ ############################################################################## # # OpenERP, Open Source Business Applications -# Copyright (c) 2011 OpenERP S.A. +# Copyright (c) 2011-2012 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 @@ -19,13 +19,8 @@ # ############################################################################## -from datetime import datetime, timedelta -from dateutil.relativedelta import relativedelta - -from osv import fields, osv, orm +from openerp.osv import osv from edi import EDIMixin -from edi.models import edi -from tools import DEFAULT_SERVER_DATE_FORMAT SALE_ORDER_LINE_EDI_STRUCT = { 'sequence': True, @@ -65,15 +60,6 @@ SALE_ORDER_EDI_STRUCT = { class sale_order(osv.osv, EDIMixin): _inherit = 'sale.order' - def action_quotation_send(self, cr, uid, ids, context=None): - if context is None: - context = {} - sale_objs = self.browse(cr, uid, ids, context=context) - edi_token = self.pool.get('edi.document').export_edi(cr, uid, sale_objs, context = context)[0] - web_root_url = self.pool.get('ir.config_parameter').get_param(cr, uid, 'web.base.url') - ctx = dict(context, edi_web_url_view=edi.EDI_VIEW_WEB_URL % (web_root_url, cr.dbname, edi_token)) - return super(sale_order, self).action_quotation_send(cr, uid, ids, context=ctx) - def edi_export(self, cr, uid, records, edi_struct=None, context=None): """Exports a Sale order""" edi_struct = dict(edi_struct or SALE_ORDER_EDI_STRUCT) @@ -112,7 +98,7 @@ class sale_order(osv.osv, EDIMixin): res_partner_obj = self.pool.get('res.partner') # imported company_address = new partner address - src_company_id, src_company_name = edi_document.pop('company_id') + _, src_company_name = edi_document.pop('company_id') address_info = edi_document.pop('company_address') address_info['supplier'] = True @@ -171,7 +157,6 @@ class sale_order(osv.osv, EDIMixin): currency_id = res_currency.edi_import(cr, uid, currency_info, context=context) order_currency = res_currency.browse(cr, uid, currency_id) - date_order = edi_document['date_order'] partner_ref = edi_document.pop('partner_ref', False) edi_document['client_order_ref'] = edi_document['name'] edi_document['name'] = partner_ref or edi_document['name'] @@ -185,7 +170,7 @@ class sale_order(osv.osv, EDIMixin): order_lines = edi_document['order_line'] for order_line in order_lines: - self._edi_requires_attributes(( 'product_id', 'product_uom', 'product_qty', 'price_unit'), order_line) + self._edi_requires_attributes(('product_id', 'product_uom', 'product_qty', 'price_unit'), order_line) order_line['product_uom_qty'] = order_line['product_qty'] del order_line['product_qty'] diff --git a/addons/sale/edi/sale_order_action_data.xml b/addons/sale/edi/sale_order_action_data.xml index 9796d0bda16..5ce35bf497d 100644 --- a/addons/sale/edi/sale_order_action_data.xml +++ b/addons/sale/edi/sale_order_action_data.xml @@ -1,7 +1,6 @@ - Email Templates @@ -15,14 +14,13 @@ - - Automated Sale Order Notification Mail + Sale Order - Send by mail ${object.user_id.email or ''} ${object.company_id.name} Order (Ref ${object.name or 'n/a' }) ${object.partner_invoice_id.email} @@ -49,12 +47,6 @@   Your contact: ${object.user_id.name}

    -

    - You can view the ${object.state in ('draft', 'sent') and 'quotation' or 'order confirmation'} document, download it and pay online using the following link: -

    - View Order - % if object.order_policy in ('prepaid','manual') and object.company_id.paypal_account and object.state not in ('draft', 'sent'): <% comp_name = quote(object.company_id.name) diff --git a/addons/sale/test/edi_sale_order.yml b/addons/sale/test/edi_sale_order.yml index 967aaa1337c..65a5887fe40 100644 --- a/addons/sale/test/edi_sale_order.yml +++ b/addons/sale/test/edi_sale_order.yml @@ -25,15 +25,16 @@ - Then I export the sale order via EDI - - !python {model: edi.document}: | + !python {model: edi.edi}: | + import json sale_order = self.pool.get('sale.order') so = sale_order.browse(cr, uid, ref("sale_order_edi_1")) - token = self.export_edi(cr, uid, [so]) - assert token, 'Invalid EDI Token' + edi_doc = self.generate_edi(cr, uid, [so]) + assert isinstance(json.loads(edi_doc)[0], dict), 'EDI doc should be a JSON dict' - Then I import a sample EDI document of a purchase order - - !python {model: edi.document}: | + !python {model: edi.edi}: | sale_order_pool = self.pool.get('sale.order') edi_document = { "__id": "purchase:5af1272e-dd26-11e0-b65e-701a04e25543.purchase_order_test", From c7757baf7768dee5699824f0ed9110c73c917288 Mon Sep 17 00:00:00 2001 From: Olivier Dony Date: Tue, 16 Oct 2012 14:29:13 +0200 Subject: [PATCH 003/122] [IMP] edi: ported web part to 7.0 + removed the EDI preview- and export-related parts As started in previous commits, in 7.0 there is no more static storage of exported EDI documents, and they are instead replaced by the improved portal - which will provide the preview as well as export capabilities. (The export might be added in a second phase) bzr revid: odo@openerp.com-20121016122913-ndl0l36buhku3kxy --- addons/account/edi/invoice.py | 10 +- addons/account/test/test_edi_invoice.yml | 145 ++++++++++-- addons/auth_signup/controllers/main.py | 1 - addons/edi/__init__.py | 13 +- addons/edi/controllers/main.py | 19 +- addons/edi/models/edi.py | 4 +- addons/edi/models/res_partner.py | 1 - addons/edi/static/src/css/edi.css | 210 ------------------ addons/edi/static/src/img/pdf.png | Bin 6960 -> 0 bytes addons/edi/static/src/js/edi.js | 137 ++---------- addons/edi/static/src/xml/edi.xml | 93 -------- addons/edi/static/src/xml/edi_account.xml | 163 -------------- .../edi/static/src/xml/edi_sale_purchase.xml | 169 -------------- 13 files changed, 163 insertions(+), 802 deletions(-) delete mode 100644 addons/edi/static/src/css/edi.css delete mode 100644 addons/edi/static/src/img/pdf.png delete mode 100644 addons/edi/static/src/xml/edi.xml delete mode 100644 addons/edi/static/src/xml/edi_account.xml delete mode 100644 addons/edi/static/src/xml/edi_sale_purchase.xml diff --git a/addons/account/edi/invoice.py b/addons/account/edi/invoice.py index e84bec6614d..91747de4ea1 100644 --- a/addons/account/edi/invoice.py +++ b/addons/account/edi/invoice.py @@ -19,9 +19,8 @@ # ############################################################################## -from osv import fields, osv, orm +from openerp.osv import osv from edi import EDIMixin -from edi.models import edi INVOICE_LINE_EDI_STRUCT = { 'name': True, @@ -137,9 +136,14 @@ class account_invoice(osv.osv, EDIMixin): # imported company_address = new partner address address_info = edi_document.pop('company_address') + if '__import_model' not in address_info and '__model' not in address_info: + # for pre-7.0 EDI format - address used to be a record of res.partner.address + address_info['__import_model'] = 'res.partner' if 'name' not in address_info: + # for pre-7.0 EDI format - address name was not required address_info['name'] = src_company_name address_info['type'] = 'invoice' + address_info['is_company'] = True address_info.update(partner_value) address_id = res_partner.edi_import(cr, uid, address_info, context=context) @@ -190,7 +194,7 @@ class account_invoice(osv.osv, EDIMixin): invoice_type = invoice_type.startswith('in_') and invoice_type.replace('in_','out_') or invoice_type.replace('out_','in_') edi_document['type'] = invoice_type - #import company as a new partner + # import company as a new partner partner_id = self._edi_import_company(cr, uid, edi_document, context=context) # Set Account diff --git a/addons/account/test/test_edi_invoice.yml b/addons/account/test/test_edi_invoice.yml index 3d57f8dc608..fea829e4ba3 100644 --- a/addons/account/test/test_edi_invoice.yml +++ b/addons/account/test/test_edi_invoice.yml @@ -45,39 +45,39 @@ edi_doc = self.generate_edi(cr, uid, [invoice]) assert isinstance(json.loads(edi_doc)[0], dict), 'EDI doc should be a JSON dict' - - Then I import a sample EDI document of another customer invoice + Then I import a sample EDI document of another customer invoice from OpenERP 7.0 - !python {model: account.invoice}: | import time edi_document = { - "__id": "account:b22acf7a-ddcd-11e0-a4db-701a04e25543.random_invoice_763jsms", + "__id": "account:b33adf8a-decd-11f0-a4de-702a04e25700.random_invoice_763jsms", "__module": "account", "__model": "account.invoice", - "__version": [6,1,0], - "internal_number": time.strftime("SAJ/%Y/002"), + "__version": [7,0,0], + "internal_number": time.strftime("SAJ/%Y/070"), "company_address": { - "__id": "base:b22acf7a-ddcd-11e0-a4db-701a04e25543.main_address", + "__id": "base:b33adf8a-decd-11f0-a4de-702a04e25700.main_address", "__module": "base", "__model": "res.partner", "city": "Gerompont", "name": "Company main address", "zip": "1367", - "country_id": ["base:b22acf7a-ddcd-11e0-a4db-701a04e25543.be", "Belgium"], + "country_id": ["base:b33adf8a-decd-11f0-a4de-702a04e25700.be", "Belgium"], "phone": "(+32).81.81.37.00", "street": "Chaussee de Namur 40", "bank_ids": [ - ["base:b22acf7a-ddcd-11e0-a4db-701a04e25543.res_partner_bank-ZrTWzesfsdDJzGbp","Sample bank: 123465789-156113"] + ["base:b33adf8a-decd-11f0-a4de-702a04e25700.res_partner_bank-ZrTWzesfsdDJzGbp","Sample bank: 70-123465789-156113"] ], }, - "company_id": ["account:b22acf7a-ddcd-11e0-a4db-701a04e25543.res_company_test11", "Thomson pvt. ltd."], + "company_id": ["account:b33adf8a-decd-11f0-a4de-702a04e25700.res_company_test11", "Thomson pvt. ltd."], "currency": { - "__id": "base:b22acf7a-ddcd-11e0-a4db-701a04e25543.EUR", + "__id": "base:b33adf8a-decd-11f0-a4de-702a04e25700.EUR", "__module": "base", "__model": "res.currency", "code": "EUR", "symbol": "€", }, - "partner_id": ["account:b22acf7a-ddcd-11e0-a4db-701a04e25543.res_partner_test20", "Junjun wala"], + "partner_id": ["account:b33adf8a-decd-11f0-a4de-702a04e25700.res_partner_test20", "Junjun wala"], "partner_address": { "__id": "base:5af1272e-dd26-11e0-b65e-701a04e25543.res_partner_address_7wdsjasdjh", "__module": "base", @@ -92,7 +92,7 @@ "date_invoice": time.strftime('%Y-%m-%d'), "name": "sample invoice", "tax_line": [{ - "__id": "account:b22acf7a-ddcd-11e0-a4db-701a04e25543.account_invoice_tax-4g4EutbiEMVl", + "__id": "account:b33adf8a-decd-11f0-a4de-702a04e25700.account_invoice_tax-4g4EutbiEMVl", "__module": "account", "__model": "account.invoice.tax", "amount": 1000.0, @@ -103,21 +103,21 @@ "invoice_line": [{ "__module": "account", "__model": "account.invoice.line", - "__id": "account:b22acf7a-ddcd-11e0-a4db-701a04e25543.account_invoice_line-1RP3so", - "uos_id": ["product:b22acf7a-ddcd-11e0-a4db-701a04e25543.product_uom_unit", "Unit"], + "__id": "account:b33adf8a-decd-11f0-a4de-702a04e25700.account_invoice_line-1RP3so", + "uos_id": ["product:b33adf8a-decd-11f0-a4de-702a04e25700.product_uom_unit", "Unit"], "name": "PC Assemble SC234", "price_unit": 10.0, - "product_id": ["product:b22acf7a-ddcd-11e0-a4db-701a04e25543.product_product_3", "[PCSC234] PC Assemble SC234"], + "product_id": ["product:b33adf8a-decd-11f0-a4de-702a04e25700.product_product_3", "[PCSC234] PC Assemble SC234"], "quantity": 1.0 }, { "__module": "account", "__model": "account.invoice.line", - "__id": "account:b22acf7a-ddcd-11e0-a4db-701a04e25543.account_invoice_line-u2XV5", - "uos_id": ["product:b22acf7a-ddcd-11e0-a4db-701a04e25543.product_uom_unit", "Unit"], + "__id": "account:b33adf8a-decd-11f0-a4de-702a04e25700.account_invoice_line-u2XV5", + "uos_id": ["product:b33adf8a-decd-11f0-a4de-702a04e25700.product_uom_unit", "Unit"], "name": "PC on Demand", "price_unit": 100.0, - "product_id": ["product:b22acf7a-ddcd-11e0-a4db-701a04e25543.product_product_5", "[PC-DEM] PC on Demand"], + "product_id": ["product:b33adf8a-decd-11f0-a4de-702a04e25700.product_product_5", "[PC-DEM] PC on Demand"], "quantity": 5.0 }] } @@ -128,10 +128,10 @@ # check bank info on partner assert len(invoice_new.partner_id.bank_ids) == 1, "Expected 1 bank entry related to partner" bank_info = invoice_new.partner_id.bank_ids[0] - assert bank_info.acc_number == "Sample bank: 123465789-156113", 'Expected "Sample bank: 123465789-156113", got %s' % bank_info.acc_number + assert bank_info.acc_number == "Sample bank: 70-123465789-156113", 'Expected "Sample bank: 70-123465789-156113", got %s' % bank_info.acc_number assert invoice_new.partner_id.supplier, 'Imported Partner is not marked as supplier' - assert invoice_new.reference == time.strftime("SAJ/%Y/002"), "internal number is not stored in reference" + assert invoice_new.reference == time.strftime("SAJ/%Y/070"), "internal number is not stored in reference" assert invoice_new.reference_type == 'none', "reference type is not set to 'none'" assert invoice_new.internal_number == False, "internal number is not reset" assert invoice_new.journal_id.id, "journal id is not selected" @@ -153,3 +153,110 @@ for inv_tax in invoice_new.tax_line: assert inv_tax.manual, "tax line not set to manual" assert inv_tax.account_id, "missing tax line account" +- + Then I import a sample EDI document of another customer invoice from OpenERP 6.1 (to test backwards compatibility) +- + !python {model: account.invoice}: | + import time + edi_document = { + "__id": "account:b22acf7a-ddcd-11e0-a4db-701a04e25543.random_invoice_763jsms", + "__module": "account", + "__model": "account.invoice", + "__version": [6,1,0], + "internal_number": time.strftime("SAJ/%Y/061"), + "company_address": { + "__id": "base:b22acf7a-ddcd-11e0-a4db-701a04e25543.main_address", + "__module": "base", + "__model": "res.partner.address", + "city": "Gerompont", + "zip": "1367", + "country_id": ["base:b22acf7a-ddcd-11e0-a4db-701a04e25543.be", "Belgium"], + "phone": "(+32).81.81.37.00", + "street": "Chaussee de Namur 40", + "bank_ids": [ + ["base:b22acf7a-ddcd-11e0-a4db-701a04e25543.res_partner_bank-ZrTWzesfsdDJzGbp","Sample bank: 123465789-156113"] + ], + }, + "company_id": ["account:b22acf7a-ddcd-11e0-a4db-701a04e25543.res_company_test11", "Thomson pvt. ltd."], + "currency": { + "__id": "base:b22acf7a-ddcd-11e0-a4db-701a04e25543.EUR", + "__module": "base", + "__model": "res.currency", + "code": "EUR", + "symbol": "€", + }, + "partner_id": ["account:b22acf7a-ddcd-11e0-a4db-701a04e25543.res_partner_test20", "Junjun wala"], + "partner_address": { + "__id": "base:5af1272e-dd26-11e0-b65e-701a04e25543.res_partner_address_7wdsjasdjh", + "__module": "base", + "__model": "res.partner.address", + "phone": "(+32).81.81.37.00", + "street": "Chaussee de Namur 40", + "city": "Gerompont", + "zip": "1367", + "country_id": ["base:5af1272e-dd26-11e0-b65e-701a04e25543.be", "Belgium"], + }, + "date_invoice": time.strftime('%Y-%m-%d'), + "name": "sample invoice", + "tax_line": [{ + "__id": "account:b22acf7a-ddcd-11e0-a4db-701a04e25543.account_invoice_tax-4g4EutbiEMVl", + "__module": "account", + "__model": "account.invoice.tax", + "amount": 1000.0, + "manual": True, + "name": "sale tax", + }], + "type": "out_invoice", + "invoice_line": [{ + "__module": "account", + "__model": "account.invoice.line", + "__id": "account:b22acf7a-ddcd-11e0-a4db-701a04e25543.account_invoice_line-1RP3so", + "uos_id": ["product:b22acf7a-ddcd-11e0-a4db-701a04e25543.product_uom_unit", "PCE"], + "name": "Basic PC", + "price_unit": 10.0, + "product_id": ["product:b22acf7a-ddcd-11e0-a4db-701a04e25543.product_product_pc1", "[PC1] Basic PC"], + "quantity": 1.0 + }, + { + "__module": "account", + "__model": "account.invoice.line", + "__id": "account:b22acf7a-ddcd-11e0-a4db-701a04e25543.account_invoice_line-u2XV5", + "uos_id": ["product:b22acf7a-ddcd-11e0-a4db-701a04e25543.product_uom_unit", "PCE"], + "name": "Medium PC", + "price_unit": 100.0, + "product_id": ["product:b22acf7a-ddcd-11e0-a4db-701a04e25543.product_product_pc3", "[PC3] Medium PC"], + "quantity": 5.0 + }] + } + invoice_id = self.edi_import(cr, uid, edi_document, context=context) + assert invoice_id, 'EDI import failed' + invoice_new = self.browse(cr, uid, invoice_id) + + # check bank info on partner + assert len(invoice_new.partner_id.bank_ids) == 1, "Expected 1 bank entry related to partner" + bank_info = invoice_new.partner_id.bank_ids[0] + assert bank_info.acc_number == "Sample bank: 123465789-156113", 'Expected "Sample bank: 123465789-156113", got %s' % bank_info.acc_number + + assert invoice_new.partner_id.supplier, 'Imported Partner is not marked as supplier' + assert invoice_new.reference == time.strftime("SAJ/%Y/061"), "internal number is not stored in reference" + assert invoice_new.reference_type == 'none', "reference type is not set to 'none'" + assert invoice_new.internal_number == False, "internal number is not reset" + assert invoice_new.journal_id.id, "journal id is not selected" + assert invoice_new.type == 'in_invoice', "Invoice type was not set properly" + assert len(invoice_new.invoice_line) == 2, "invoice lines are not same" + for inv_line in invoice_new.invoice_line: + if inv_line.name == 'Basic PC': + assert inv_line.uos_id.name == "Unit" , "uom is not same" + assert inv_line.price_unit == 10 , "price unit is not same" + assert inv_line.quantity == 1 , "product qty is not same" + assert inv_line.price_subtotal == 10, "price sub total is not same" + elif inv_line.name == 'Medium PC': + assert inv_line.uos_id.name == "Unit" , "uom is not same" + assert inv_line.price_unit == 100 , "price unit is not same" + assert inv_line.quantity == 5 , "product qty is not same" + assert inv_line.price_subtotal == 500, "price sub total is not same" + else: + raise AssertionError('unknown invoice line: %s' % inv_line) + for inv_tax in invoice_new.tax_line: + assert inv_tax.manual, "tax line not set to manual" + assert inv_tax.account_id, "missing tax line account" diff --git a/addons/auth_signup/controllers/main.py b/addons/auth_signup/controllers/main.py index 54dcc5b4362..65a05255f97 100644 --- a/addons/auth_signup/controllers/main.py +++ b/addons/auth_signup/controllers/main.py @@ -35,7 +35,6 @@ class Controller(openerp.addons.web.http.Controller): def retrieve(self, req, dbname, token): """ retrieve the user info (name, login or email) corresponding to a signup token """ registry = RegistryManager.get(dbname) - user_info = None with registry.cursor() as cr: res_partner = registry.get('res.partner') user_info = res_partner.signup_retrieve_info(cr, openerp.SUPERUSER_ID, token) diff --git a/addons/edi/__init__.py b/addons/edi/__init__.py index 71ee8aaa53d..b1563ed72cd 100644 --- a/addons/edi/__init__.py +++ b/addons/edi/__init__.py @@ -20,18 +20,9 @@ ############################################################################## import logging +from . import controllers from . import models from . import edi_service -from models.edi import EDIMixin, edi -_logger = logging.getLogger(__name__) - -# web -try: - import openerp.addons.web.controllers -except ImportError: - _logger.warn( - """Could not load openerp-web section of EDI, EDI will not behave correctly - -To fix, launch openerp-web in embedded mode""") +from .models.edi import EDIMixin, edi # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/edi/controllers/main.py b/addons/edi/controllers/main.py index 0322099b6f3..14cd97b3e62 100644 --- a/addons/edi/controllers/main.py +++ b/addons/edi/controllers/main.py @@ -1,4 +1,6 @@ -import openerp.addons.web.common.http as openerpweb +import simplejson + +import openerp.addons.web.http as openerpweb import openerp.addons.web.controllers.main as webmain class EDI(openerpweb.Controller): @@ -7,10 +9,17 @@ class EDI(openerpweb.Controller): @openerpweb.httprequest def import_url(self, req, url): - d = self.template(req) - d["init"] = 's.edi.edi_import("%s");'%(url) - r = webmain.html_template % d - return r + modules = webmain.module_boot(req) + ['edi'] + modules_str = ','.join(modules) + modules_json = simplejson.dumps(modules) + js = "\n ".join('' % i for i in webmain.manifest_list(req, modules_str, 'js')) + css = "\n ".join('' % i for i in webmain.manifest_list(req, modules_str, 'css')) + return webmain.html_template % { + 'js': js, + 'css': css, + 'modules': modules_json, + 'init': 's.edi.edi_import("%s");' % url, + } @openerpweb.jsonrequest def import_edi_url(self, req, url): diff --git a/addons/edi/models/edi.py b/addons/edi/models/edi.py index 29e19f2da3b..7c6fcc3ddfe 100644 --- a/addons/edi/models/edi.py +++ b/addons/edi/models/edi.py @@ -24,14 +24,12 @@ import hashlib import json import logging import re -import threading import time import urllib2 import openerp import openerp.release as release import openerp.netsvc as netsvc -from openerp.modules.registry import RegistryManager from openerp.osv import osv, fields from tools.translate import _ from tools.safe_eval import safe_eval as eval @@ -540,7 +538,7 @@ class EDIMixin(object): assert self._name == edi.get('__import_model') or \ ('__import_model' not in edi and self._name == edi.get('__model')), \ "EDI Document Model and current model do not match: '%s' (EDI) vs '%s' (current)." % \ - (edi['__model'], self._name) + (edi.get('__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['__id']) diff --git a/addons/edi/models/res_partner.py b/addons/edi/models/res_partner.py index 37483c1d38d..057e84b5541 100644 --- a/addons/edi/models/res_partner.py +++ b/addons/edi/models/res_partner.py @@ -23,7 +23,6 @@ import logging from openerp.osv import osv from edi import EDIMixin from openerp import SUPERUSER_ID -from openerp.tools.translate import _ _logger = logging.getLogger(__name__) RES_PARTNER_EDI_STRUCT = { diff --git a/addons/edi/static/src/css/edi.css b/addons/edi/static/src/css/edi.css deleted file mode 100644 index 6385959c036..00000000000 --- a/addons/edi/static/src/css/edi.css +++ /dev/null @@ -1,210 +0,0 @@ -/** EDI content **/ -.openerp .company_logo { - background-size: 180px 46px; -} -.oe_edi_view { - width: 65%; - vertical-align: top; - padding: 0px 25px; - border-right: 1px solid #D2CFCF; -} -.oe_edi_sidebar_container { - width: 35%; - padding: 0px 10px; - vertical-align: top; -} -button.oe_edi_action_print { - font-size: 1.5em; - margin-left: 35%; - margin-bottom: 20px; -} -button.oe_edi_action_print img { - vertical-align: bottom; - width: 32px; - height: 32px; -} - -/** EDI Sidebar **/ -.oe_edi_sidebar_title { - border-bottom: 1px solid #D2CFCF; - font-weight: bold; - font-size: 1.3em; - min-width: 10em; -} -.oe_edi_nested_block, .oe_edi_nested_block_import, .oe_edi_nested_block_pay { - margin: 0px 40px; - min-width: 10em; - display: none; /* made visible by click on parent input/label */ -} -.oe_edi_right_top .oe_edi_nested_block label { - float: left; - text-align: right; - margin-right: 0.5em; - line-height: 180%; - font-weight: bold; - min-width: 5em; -} -.oe_edi_option { - padding-left: 5px; - line-height: 2em; -} -.oe_edi_option:hover { - background: #e8e8e8; -} -.oe_edi_import_button { - margin: 2px 10px; - white-space: nowrap; -} -.oe_edi_small, .oe_edi_small input { - font-size: 90%; -} - -/** Sidebar bottom **/ -.oe_edi_paypal_button { - margin: 6px; -} - - -/** Paperbox, from http://www.sitepoint.com/pure-css3-paper-curl/ **/ -.oe_edi_paperbox { - position: relative; - width: 700px; - padding: 30px; - padding-bottom: 50px; - margin: 20px auto; - background-color: #fff; - -webkit-box-shadow: 0 0 4px rgba(0, 0, 0, 0.2), inset 0 0 50px rgba(0, 0, 0, 0.1); - -moz-box-shadow: 0 0 4px rgba(0, 0, 0, 0.2), inset 0 0 50px rgba(0, 0, 0, 0.1); - box-shadow: 0 0 5px rgba(0, 0, 0, 0.2), inset 0 0 50px rgba(0, 0, 0, 0.1); -} -.oe_edi_paperbox:before, .oe_edi_paperbox:after { - position: absolute; - width: 40%; - height: 10px; - content: ' '; - left: 12px; - bottom: 15px; - background: transparent; - -webkit-transform: skew(-5deg) rotate(-5deg); - -moz-transform: skew(-5deg) rotate(-5deg); - -ms-transform: skew(-5deg) rotate(-5deg); - -o-transform: skew(-5deg) rotate(-5deg); - transform: skew(-5deg) rotate(-5deg); - -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, 0.3); - -moz-box-shadow: 0 6px 12px rgba(0, 0, 0, 0.3); - box-shadow: 0 6px 12px rgba(0, 0, 0, 0.3); - z-index: -1; -} -.oe_edi_paperbox:after { - left: auto; right: 12px; - -webkit-transform: skew(5deg) rotate(5deg); - -moz-transform: skew(5deg) rotate(5deg); - -ms-transform: skew(5deg) rotate(5deg); - -o-transform: skew(5deg) rotate(5deg); - transform: skew(5deg) rotate(5deg); -} - -/** Sale Order / Purchase Order Preview **/ -table.oe_edi_data, .oe_edi_doc_title { - border-collapse: collapse; - clear: both; -} -.oe_edi_data th { - white-space: nowrap; -} -.oe_edi_data .oe_edi_floor { - border-bottom: 1px solid black; -} -.oe_edi_data .oe_edi_ceiling { - border-top: 1px solid black; -} -.oe_edi_data .oe_edi_data_row { - border-bottom: 1px solid #D2CFCF; -} -.oe_edi_data_row td { - vertical-align: top; -} -.oe_edi_inner_note { - font-style: italic; - font-size: 95%; - padding-left: 10px; - - /* prevent wide notes from disrupting layout due to
     styling */
    -    white-space: pre-line;
    -    width: 90%;
    -}
    -.oe_edi_data_row .oe_edi_inner_note {
    -    /* prevent wide notes from disrupting layout due to 
     styling */
    -    width: 25em;
    -}
    -.oe_edi_shade {
    -    background: #e8e8e8;
    -}
    -.oe_edi_company_name {
    -    text-transform: uppercase;
    -    font-weight: bold;
    -}
    -.oe_edi_address_from {
    -    float: left;
    -}
    -.oe_edi_address_to {
    -    float: right;
    -    margin-top: 25px;
    -    margin-bottom: 30px;
    -}
    -.oe_edi_company_block_title {
    -    width: 375px;
    -    margin: 0px;
    -    padding: 2px 14px;
    -    background-color: #252525;
    -    border-top-left-radius: 5px 5px;
    -    border-top-right-radius: 5px 5px;
    -    background-repeat: repeat no-repeat; 
    -}
    -.oe_edi_company_block_title .oe_edi_company_name {
    -    margin: 0px;
    -    font-size: 1em;
    -    color: #FFF;
    -}
    -.oe_edi_company_block_body {
    -    width: 375px;
    -    margin: 0px;
    -    padding: 5px 14px;
    -    line-height: 16px;
    -    background-color: rgb(242, 242, 242);
    -}
    -.oe_edi_company_block_body p {
    -    color: #222;
    -    margin: 5px 0px;
    -}
    -.oe_edi_summary_label {
    -    float: left;
    -}
    -.oe_edi_summary_value {
    -    float: right;
    -}
    -
    -
    -/** Python code highlighting **/
    -/*  GeSHi (C) 2004 - 2007 Nigel McNie, 2007 - 2008 Benny Baumann
    -    (http://qbnz.com/highlighter/ and http://geshi.org/) */
    -.python .de1, .python .de2 {font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;}
    -.python  {font-family:monospace;}
    -.python .imp {font-weight: bold; color: red;}
    -.python li, .python .li1 {background: #ffffff; list-style: none;}
    -.python .ln {width:1px;text-align:right;margin:0;padding:0 2px;vertical-align:top;}
    -.python .li2 {background: #f8f8f8;}
    -.python .kw1 {color: #ff7700;font-weight:bold;}
    -.python .kw2 {color: #008000;}
    -.python .kw3 {color: #dc143c;}
    -.python .kw4 {color: #0000cd;}
    -.python .co1 {color: #808080; font-style: italic;}
    -.python .coMULTI {color: #808080; font-style: italic;}
    -.python .es0 {color: #000099; font-weight: bold;}
    -.python .br0 {color: black;}
    -.python .sy0 {color: #66cc66;}
    -.python .st0 {color: #483d8b;}
    -.python .nu0 {color: #ff4500;}
    -.python .me1 {color: black;}
    -.python span.xtra { display:block; }
    -.python ol { padding: 0px; }
    diff --git a/addons/edi/static/src/img/pdf.png b/addons/edi/static/src/img/pdf.png
    deleted file mode 100644
    index d35dfd20c2db2622560c7f04dc174b52f223a753..0000000000000000000000000000000000000000
    GIT binary patch
    literal 0
    HcmV?d00001
    
    literal 6960
    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
    -
    -    
    -
    - - - - - - - - - - - - - - -
    -
    - -
    - - - - - -
    -

    - -
    -

    - Import this document -

    -
    - - -
    -

    - -
    -
    - -

    - -
    - - -
    -

    - -

    - -
    - - -
    -

    - OpenERP's Electronic Data Interchange documents are based on a generic and language - independent JSON serialization of the document's attribute. - It is usually very quick and straightforward to create a small plug-in for your preferred - application that will be capable of importing any OpenERP EDI document. - You can find out more details about how to do this and what the content of OpenERP EDI documents - is like in the OpenERP documentation. -
    - To get started immediately, see is all it takes to use this EDI document in Python. -

    -
    -
    1. import urllib2, simplejson
    2. -
    3. edi_document = urllib2.urlopen('').read()
    4. -
    5. document_data = simplejson.loads(edi_document)[0]
    6. -
    7. print "Amount: ", document_data['amount_total']
    8. -
    -

    - You can download the raw EDI document here:
    - - -

    - -
    - -
    -
    -
    - -
    -
    - diff --git a/addons/edi/static/src/xml/edi_account.xml b/addons/edi/static/src/xml/edi_account.xml deleted file mode 100644 index 3ce1daebf93..00000000000 --- a/addons/edi/static/src/xml/edi_account.xml +++ /dev/null @@ -1,163 +0,0 @@ - diff --git a/addons/edi/static/src/xml/edi_sale_purchase.xml b/addons/edi/static/src/xml/edi_sale_purchase.xml deleted file mode 100644 index 8d6bab67761..00000000000 --- a/addons/edi/static/src/xml/edi_sale_purchase.xml +++ /dev/null @@ -1,169 +0,0 @@ - From b42801595e48ab266a60ae6b9e77d73a1adb98fe Mon Sep 17 00:00:00 2001 From: Olivier Dony Date: Wed, 17 Oct 2012 18:28:55 +0200 Subject: [PATCH 004/122] [IMP] product.uom: support name_create, allows EDI import to work silently bzr revid: odo@openerp.com-20121017162855-dkrr07bldsnc6f5s --- addons/product/product.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/addons/product/product.py b/addons/product/product.py index 6c6c5f2650c..9623a5f1248 100644 --- a/addons/product/product.py +++ b/addons/product/product.py @@ -100,6 +100,23 @@ class product_uom(osv.osv): def _factor_inv_write(self, cursor, user, id, name, value, arg, context=None): return self.write(cursor, user, id, {'factor': self._compute_factor_inv(value)}, context=context) + def name_create(self, cr, uid, name, context=None): + """ The UoM category and factor are required, so we'll have to add temporary values + for imported UoMs """ + uom_categ = self.pool.get('product.uom.categ') + # look for the category based on the english name, i.e. no context on purpose! + # TODO: should find a way to have it translated but not created until actually used + categ_misc = 'Unsorted/Imported Units' + categ_id = uom_categ.search(cr, uid, [('name', '=', categ_misc)]) + if categ_id: + categ_id = categ_id[0] + else: + categ_id, _ = uom_categ.name_create(cr, uid, categ_misc) + uom_id = self.create(cr, uid, {self._rec_name: name, + 'category_id': categ_id, + 'factor': 1}) + return self.name_get(cr, uid, [uom_id], context=context)[0] + def create(self, cr, uid, data, context=None): if 'factor_inv' in data: if data['factor_inv'] <> 1: From 48cfc1bb029407fce29d2ac31f7be474444da775 Mon Sep 17 00:00:00 2001 From: Olivier Dony Date: Wed, 17 Oct 2012 18:29:37 +0200 Subject: [PATCH 005/122] [IMP] edi,account: fix EDI import of invoices, now compatible again with 6.1, and correct wrt. partners import (vs old addresses) bzr revid: odo@openerp.com-20121017162937-fprd53n4ljo5bdim --- addons/account/edi/invoice.py | 49 +++++++++++------------- addons/account/test/test_edi_invoice.yml | 4 +- addons/edi/models/edi.py | 13 +++++-- 3 files changed, 33 insertions(+), 33 deletions(-) diff --git a/addons/account/edi/invoice.py b/addons/account/edi/invoice.py index 91747de4ea1..80a4b145054 100644 --- a/addons/account/edi/invoice.py +++ b/addons/account/edi/invoice.py @@ -2,7 +2,7 @@ ############################################################################## # # OpenERP, Open Source Business Applications -# Copyright (c) 2011 OpenERP S.A. +# Copyright (c) 2011-2012 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 @@ -100,8 +100,8 @@ class account_invoice(osv.osv, EDIMixin): return tax_account def _edi_invoice_account(self, cr, uid, partner_id, invoice_type, context=None): - partner_pool = self.pool.get('res.partner') - partner = partner_pool.browse(cr, uid, partner_id, context=context) + res_partner = self.pool.get('res.partner') + partner = res_partner.browse(cr, uid, partner_id, context=context) if invoice_type in ('out_invoice', 'out_refund'): invoice_account = partner.property_account_receivable else: @@ -125,36 +125,31 @@ class account_invoice(osv.osv, EDIMixin): self._edi_requires_attributes(('company_id','company_address','type'), edi_document) res_partner = self.pool.get('res.partner') - _, src_company_name = edi_document.pop('company_id') + xid, company_name = edi_document.pop('company_id') + # Retrofit address info into a unified partner info (changed in v7 - used to keep them separate) + company_address_edi = edi_document.pop('company_address') + company_address_edi['name'] = company_name + company_address_edi['is_company'] = True + company_address_edi['__import_model'] = 'res.partner' + company_address_edi['__id'] = xid # override address ID, as of v7 they should be the same anyway + if company_address_edi.get('logo'): + company_address_edi['image'] = company_address_edi.pop('logo') invoice_type = edi_document['type'] - partner_value = {} - if invoice_type in ('out_invoice', 'out_refund'): - partner_value.update({'customer': True}) - if invoice_type in ('in_invoice', 'in_refund'): - partner_value.update({'supplier': True}) - - # imported company_address = new partner address - address_info = edi_document.pop('company_address') - if '__import_model' not in address_info and '__model' not in address_info: - # for pre-7.0 EDI format - address used to be a record of res.partner.address - address_info['__import_model'] = 'res.partner' - if 'name' not in address_info: - # for pre-7.0 EDI format - address name was not required - address_info['name'] = src_company_name - address_info['type'] = 'invoice' - address_info['is_company'] = True - address_info.update(partner_value) - address_id = res_partner.edi_import(cr, uid, address_info, context=context) + if invoice_type.startswith('out_'): + company_address_edi['customer'] = True + else: + company_address_edi['supplier'] = True + partner_id = res_partner.edi_import(cr, uid, company_address_edi, context=context) # modify edi_document to refer to new partner - partner_address = res_partner.browse(cr, uid, address_id, context=context) - address_edi_m2o = self.edi_m2o(cr, uid, partner_address, context=context) - edi_document['partner_id'] = address_edi_m2o - edi_document.pop('partner_address', False) # ignored + partner = res_partner.browse(cr, uid, partner_id, context=context) + partner_edi_m2o = self.edi_m2o(cr, uid, partner, context=context) + edi_document['partner_id'] = partner_edi_m2o + edi_document.pop('partner_address', None) # ignored, that's supposed to be our own address! - return address_id + return partner_id def edi_import(self, cr, uid, edi_document, context=None): """ During import, invoices will import the company that is provided in the invoice as diff --git a/addons/account/test/test_edi_invoice.yml b/addons/account/test/test_edi_invoice.yml index fea829e4ba3..5ca3b979f28 100644 --- a/addons/account/test/test_edi_invoice.yml +++ b/addons/account/test/test_edi_invoice.yml @@ -246,12 +246,12 @@ assert len(invoice_new.invoice_line) == 2, "invoice lines are not same" for inv_line in invoice_new.invoice_line: if inv_line.name == 'Basic PC': - assert inv_line.uos_id.name == "Unit" , "uom is not same" + assert inv_line.uos_id.name == "PCE" , "uom is not same" assert inv_line.price_unit == 10 , "price unit is not same" assert inv_line.quantity == 1 , "product qty is not same" assert inv_line.price_subtotal == 10, "price sub total is not same" elif inv_line.name == 'Medium PC': - assert inv_line.uos_id.name == "Unit" , "uom is not same" + assert inv_line.uos_id.name == "PCE" , "uom is not same" assert inv_line.price_unit == 100 , "price unit is not same" assert inv_line.quantity == 5 , "product qty is not same" assert inv_line.price_subtotal == 500, "price sub total is not same" diff --git a/addons/edi/models/edi.py b/addons/edi/models/edi.py index 7c6fcc3ddfe..5edbca11d13 100644 --- a/addons/edi/models/edi.py +++ b/addons/edi/models/edi.py @@ -488,8 +488,10 @@ class EDIMixin(object): 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 + if model.exists(cr, uid, [data.res_id]): + return model.browse(cr, uid, data.res_id, context=context) + # stale external-id, cleanup to allow re-import, as the corresponding record is gone + ir_model_data.unlink(cr, 1, [data_ids[0]]) 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 @@ -503,6 +505,10 @@ class EDIMixin(object): * 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 + + :param str value: display name of the record to import + :param str external_id: fully-qualified external ID of the record + :return: database id of newly-imported or pre-existing record """ _logger.debug("%s: Importing EDI relationship [%r,%r]", model, external_id, value) target = self._edi_get_object_by_external_id(cr, uid, external_id, model, context=context) @@ -517,8 +523,7 @@ class EDIMixin(object): self._name, external_id, value) # also need_new_ext_id here, but already been set above model = self.pool.get(model) - # should use name_create() but e.g. res.partner won't allow it at the moment - res_id = model.create(cr, uid, {model._rec_name: value}, context=context) + res_id, _ = model.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) From e0fcab1f620affb1a69308cdf215c9a90ab864a6 Mon Sep 17 00:00:00 2001 From: Olivier Dony Date: Thu, 18 Oct 2012 17:21:29 +0200 Subject: [PATCH 006/122] [FIX] edi,sale,purchase: fix EDI import of SO/PO, now compatible again with 6.1, and correct wrt. partners import (vs old addresses) bzr revid: odo@openerp.com-20121018152129-s22uozt77s37urp1 --- addons/account/test/test_edi_invoice.yml | 2 + addons/purchase/edi/purchase_order.py | 32 +++-- .../test/process/edi_purchase_order.yml | 134 +++++++++++++++--- addons/sale/edi/sale_order.py | 38 ++--- addons/sale/test/edi_sale_order.yml | 131 +++++++++++++++-- 5 files changed, 274 insertions(+), 63 deletions(-) diff --git a/addons/account/test/test_edi_invoice.yml b/addons/account/test/test_edi_invoice.yml index 5ca3b979f28..2225ae5ba9b 100644 --- a/addons/account/test/test_edi_invoice.yml +++ b/addons/account/test/test_edi_invoice.yml @@ -126,6 +126,7 @@ invoice_new = self.browse(cr, uid, invoice_id) # check bank info on partner + assert invoice_new.partner_id.supplier, "Imported partner should be a supplier, as we just imported the document as a supplier invoice" assert len(invoice_new.partner_id.bank_ids) == 1, "Expected 1 bank entry related to partner" bank_info = invoice_new.partner_id.bank_ids[0] assert bank_info.acc_number == "Sample bank: 70-123465789-156113", 'Expected "Sample bank: 70-123465789-156113", got %s' % bank_info.acc_number @@ -233,6 +234,7 @@ invoice_new = self.browse(cr, uid, invoice_id) # check bank info on partner + assert invoice_new.partner_id.supplier, "Imported partner should be a supplier, as we just imported the document as a supplier invoice" assert len(invoice_new.partner_id.bank_ids) == 1, "Expected 1 bank entry related to partner" bank_info = invoice_new.partner_id.bank_ids[0] assert bank_info.acc_number == "Sample bank: 123465789-156113", 'Expected "Sample bank: 123465789-156113", got %s' % bank_info.acc_number diff --git a/addons/purchase/edi/purchase_order.py b/addons/purchase/edi/purchase_order.py index f44c16eb0d9..cdb4c0ca73d 100644 --- a/addons/purchase/edi/purchase_order.py +++ b/addons/purchase/edi/purchase_order.py @@ -91,22 +91,26 @@ class purchase_order(osv.osv, EDIMixin): # the desired company among the user's allowed companies self._edi_requires_attributes(('company_id','company_address'), edi_document) - res_partner_obj = self.pool.get('res.partner') + res_partner = self.pool.get('res.partner') - # imported company_address = new partner address - _, src_company_name = edi_document.pop('company_id') - address_info = edi_document.pop('company_address') - address_info['customer'] = True - if 'name' not in address_info: - address_info['name'] = src_company_name - address_id = res_partner_obj.edi_import(cr, uid, address_info, context=context) + xid, company_name = edi_document.pop('company_id') + # Retrofit address info into a unified partner info (changed in v7 - used to keep them separate) + company_address_edi = edi_document.pop('company_address') + company_address_edi['name'] = company_name + company_address_edi['is_company'] = True + company_address_edi['__import_model'] = 'res.partner' + company_address_edi['__id'] = xid # override address ID, as of v7 they should be the same anyway + if company_address_edi.get('logo'): + company_address_edi['image'] = company_address_edi.pop('logo') + company_address_edi['supplier'] = True + partner_id = res_partner.edi_import(cr, uid, company_address_edi, context=context) - # modify edi_document to refer to new partner/address - partner_address = res_partner_obj.browse(cr, uid, address_id, context=context) - edi_document.pop('partner_address', False) # ignored - edi_document['partner_id'] = self.edi_m2o(cr, uid, partner_address, context=context) - - return address_id + # modify edi_document to refer to new partner + partner = res_partner.browse(cr, uid, partner_id, context=context) + partner_edi_m2o = self.edi_m2o(cr, uid, partner, context=context) + edi_document['partner_id'] = partner_edi_m2o + edi_document.pop('partner_address', None) # ignored, that's supposed to be our own address! + return partner_id def _edi_get_pricelist(self, cr, uid, partner_id, currency, context=None): # TODO: refactor into common place for purchase/sale, e.g. into product module diff --git a/addons/purchase/test/process/edi_purchase_order.yml b/addons/purchase/test/process/edi_purchase_order.yml index 79f244a283d..8e34606afb4 100644 --- a/addons/purchase/test/process/edi_purchase_order.yml +++ b/addons/purchase/test/process/edi_purchase_order.yml @@ -34,29 +34,29 @@ edi_doc = self.generate_edi(cr, uid, [order]) assert isinstance(json.loads(edi_doc)[0], dict), 'EDI doc should be a JSON dict' - - Then I import a sample EDI document of a sale order + Then I import a sample EDI document of a sale order (v7.0) - !python {model: edi.edi}: | purchase_order_pool = self.pool.get('purchase.order') edi_document = { - "__id": "sale:724f93ec-ddd0-11e0-88ec-701a04e25543.sale_order_test", + "__id": "sale:724f9v70-dv70-1v70-8v70-701a04e25v70.sale_order_test", "__module": "sale", "__model": "sale.order", "__import_module": "purchase", "__import_model": "purchase.order", - "__version": [6,1,0], + "__version": [7,0,0], "name": "SO008", "currency": { - "__id": "base:724f93ec-ddd0-11e0-88ec-701a04e25543.EUR", + "__id": "base:724f9v70-dv70-1v70-8v70-701a04e25v70.EUR", "__module": "base", "__model": "res.currency", "code": "EUR", "symbol": "€", }, "date_order": "2011-09-13", - "partner_id": ["sale:724f93ec-ddd0-11e0-88ec-701a04e25543.res_partner_test22", "Junjun wala"], + "partner_id": ["sale:724f9v70-dv70-1v70-8v70-701a04e25v70.res_partner_test22", "Junjun wala"], "partner_address": { - "__id": "base:724f93ec-ddd0-11e0-88ec-701a04e25543.res_partner_address_7wdsjasdjh", + "__id": "base:724f9v70-dv70-1v70-8v70-701a04e25v70.res_partner_address_7wdsjasdjh", "__module": "base", "__model": "res.partner", "phone": "(+32).81.81.37.00", @@ -65,48 +65,48 @@ "zip": "1367", "country_id": ["base:5af1272e-dd26-11e0-b65e-701a04e25543.be", "Belgium"], }, - "company_id": ["base:724f93ec-ddd0-11e0-88ec-701a04e25543.main_company", "Supplier S.A."], + "company_id": ["base:724f9v70-dv70-1v70-8v70-701a04e25v70.main_company", "Supplier S.A."], "company_address": { - "__id": "base:724f93ec-ddd0-11e0-88ec-701a04e25543.main_address", + "__id": "base:724f9v70-dv70-1v70-8v70-701a04e25v70.main_address", "__module": "base", "__model": "res.partner", "city": "Gerompont", "zip": "1367", - "country_id": ["base:724f93ec-ddd0-11e0-88ec-701a04e25543.be", "Belgium"], + "country_id": ["base:724f9v70-dv70-1v70-8v70-701a04e25v70.be", "Belgium"], "phone": "(+32).81.81.37.00", "street": "Chaussee de Namur 40", "street2": "mailbox 34", "bank_ids": [ - ["base:724f93ec-ddd0-11e0-88ec-701a04e25543.res_partner_bank-XiwqnxKWzGbp","Guys bank: 123477777-156113"] + ["base:724f9v70-dv70-1v70-8v70-701a04e25v70.res_partner_bank-XiwqnxKWzGbp","Guys bank: 123477777-156113"] ], }, "order_line": [{ - "__id": "sale:724f93ec-ddd0-11e0-88ec-701a04e25543.sale_order_line-LXEqeuI-SSP0", + "__id": "sale:724f9v70-dv70-1v70-8v70-701a04e25v70.sale_order_line-LXEqeuI-SSP0", "__module": "sale", "__model": "sale.order.line", "__import_module": "purchase", "__import_model": "purchase.order.line", "name": "PC Assemble SC234", - "product_uom": ["product:724f93ec-ddd0-11e0-88ec-701a04e25543.product_uom_unit", "Unit"], + "product_uom": ["product:724f9v70-dv70-1v70-8v70-701a04e25v70.product_uom_unit", "Unit"], "product_qty": 1.0, "date_planned": "2011-09-30", "sequence": 10, "price_unit": 150.0, - "product_id": ["product:724f93ec-ddd0-11e0-88ec-701a04e25543.product_product_3", "[PCSC234] PC Assemble SC234"], + "product_id": ["product:724f9v70-dv70-1v70-8v70-701a04e25v70.product_product_3", "[PCSC234] PC Assemble SC234"], }, { - "__id": "sale:724f93ec-ddd0-11e0-88ec-701a04e25543.sale_order_line-LXEqeadasdad", + "__id": "sale:724f9v70-dv70-1v70-8v70-701a04e25v70.sale_order_line-LXEqeadasdad", "__module": "sale", "__model": "sale.order.line", "__import_module": "purchase", "__import_model": "purchase.order.line", "name": "PC on Demand", - "product_uom": ["product:724f93ec-ddd0-11e0-88ec-701a04e25543.product_uom_unit", "Unit"], + "product_uom": ["product:724f9v70-dv70-1v70-8v70-701a04e25v70.product_uom_unit", "Unit"], "product_qty": 10.0, "sequence": 11, "date_planned": "2011-09-15", "price_unit": 20.0, - "product_id": ["product:724f93ec-ddd0-11e0-88ec-701a04e25543.product_product_5", "[PC-DEM] PC on Demand"], + "product_id": ["product:724f9v70-dv70-1v70-8v70-701a04e25v70.product_product_5", "[PC-DEM] PC on Demand"], }], } new_purchase_order_id = purchase_order_pool.edi_import(cr, uid, edi_document, context=context) @@ -114,6 +114,7 @@ order_new = purchase_order_pool.browse(cr, uid, new_purchase_order_id) # check bank info on partner + assert order_new.partner_id.supplier, "Imported partner should be a supplier, as we just imported the document as a purchase order" assert len(order_new.partner_id.bank_ids) == 1, "Expected 1 bank entry related to partner" bank_info = order_new.partner_id.bank_ids[0] assert bank_info.acc_number == "Guys bank: 123477777-156113", 'Expected "Guys bank: 123477777-156113", got %s' % bank_info.acc_number @@ -133,3 +134,104 @@ assert purchase_line.product_qty == 10 , "product qty is not same" else: raise AssertionError('unknown order line: %s' % purchase_line) +- + "Then I import a sample EDI document of a sale order (v6.1 - to test backwards compatibility)" +- + !python {model: edi.edi}: | + purchase_order_pool = self.pool.get('purchase.order') + edi_document = { + "__id": "sale:724f93ec-ddd0-11e0-88ec-701a04e25543.sale_order_test", + "__module": "sale", + "__model": "sale.order", + "__import_module": "purchase", + "__import_model": "purchase.order", + "__version": [6,1,0], + "name": "SO08v61", + "currency": { + "__id": "base:724f93ec-ddd0-11e0-88ec-701a04e25543.EUR", + "__module": "base", + "__model": "res.currency", + "code": "EUR", + "symbol": "€", + }, + "date_order": "2011-09-13", + "partner_id": ["sale:724f93ec-ddd0-11e0-88ec-701a04e25543.res_partner_test22", "Junjun wala"], + "partner_address": { + "__id": "base:724f93ec-ddd0-11e0-88ec-701a04e25543.res_partner_address_7wdsjasdjh", + "__module": "base", + "__model": "res.partner.address", + "phone": "(+32).81.81.37.00", + "street": "Chaussee de Namur 40", + "city": "Gerompont", + "zip": "1367", + "country_id": ["base:5af1272e-dd26-11e0-b65e-701a04e25543.be", "Belgium"], + }, + "company_id": ["base:724f93ec-ddd0-11e0-88ec-701a04e25543.main_company", "Supplier S.A."], + "company_address": { + "__id": "base:724f93ec-ddd0-11e0-88ec-701a04e25543.main_address", + "__module": "base", + "__model": "res.partner.address", + "city": "Gerompont", + "zip": "1367", + "country_id": ["base:724f93ec-ddd0-11e0-88ec-701a04e25543.be", "Belgium"], + "phone": "(+32).81.81.37.00", + "street": "Chaussee de Namur 40", + "street2": "mailbox 34", + "bank_ids": [ + ["base:724f93ec-ddd0-11e0-88ec-701a04e25543.res_partner_bank-XiwqnxKWzGbp","Another bank: 123477700-156113"] + ], + }, + "order_line": [{ + "__id": "sale:724f93ec-ddd0-11e0-88ec-701a04e25543.sale_order_line-LXEqeuI-SSP0", + "__module": "sale", + "__model": "sale.order.line", + "__import_module": "purchase", + "__import_model": "purchase.order.line", + "name": "Basic PC", + "product_uom": ["product:724f93ec-ddd0-11e0-88ec-701a04e25543.product_uom_unit", "PCE"], + "product_qty": 1.0, + "date_planned": "2011-09-30", + "sequence": 10, + "price_unit": 150.0, + "product_id": ["product:724f93ec-ddd0-11e0-88ec-701a04e25543.product_product_pc1", "[PC1] Basic PC"], + }, + { + "__id": "sale:724f93ec-ddd0-11e0-88ec-701a04e25543.sale_order_line-LXEqeadasdad", + "__module": "sale", + "__model": "sale.order.line", + "__import_module": "purchase", + "__import_model": "purchase.order.line", + "name": "Medium PC", + "product_uom": ["product:724f93ec-ddd0-11e0-88ec-701a04e25543.product_uom_unit", "PCE"], + "product_qty": 10.0, + "sequence": 11, + "date_planned": "2011-09-15", + "price_unit": 20.0, + "product_id": ["product:724f93ec-ddd0-11e0-88ec-701a04e25543.product_product_pc3", "[PC3] Medium PC"], + }], + } + new_purchase_order_id = purchase_order_pool.edi_import(cr, uid, edi_document, context=context) + assert new_purchase_order_id, 'Purchase order import failed' + order_new = purchase_order_pool.browse(cr, uid, new_purchase_order_id) + + # check bank info on partner + assert order_new.partner_id.supplier, "Imported partner should be a supplier, as we just imported the document as a purchase order" + assert len(order_new.partner_id.bank_ids) == 1, "Expected 1 bank entry related to partner" + bank_info = order_new.partner_id.bank_ids[0] + assert bank_info.acc_number == "Another bank: 123477700-156113", 'Expected "Another bank: 123477700-156113", got %s' % bank_info.acc_number + + assert order_new.pricelist_id.name == 'Default Purchase Pricelist' , "Default Purchase Pricelist was not automatically assigned" + assert order_new.amount_total == 350, "Amount total is not same" + assert order_new.amount_untaxed == 350, "untaxed amount is not same" + assert len(order_new.order_line) == 2, "Purchase order lines number mismatch" + for purchase_line in order_new.order_line: + if purchase_line.name == 'Basic PC': + assert purchase_line.product_uom.name == "PCE" , "uom is not same" + assert purchase_line.price_unit == 150 , "unit price is not same, got %s, expected 150"%(purchase_line.price_unit,) + assert purchase_line.product_qty == 1 , "product qty is not same" + elif purchase_line.name == 'Medium PC': + assert purchase_line.product_uom.name == "PCE" , "uom is not same" + assert purchase_line.price_unit == 20 , "unit price is not same, got %s, expected 20"%(purchase_line.price_unit,) + assert purchase_line.product_qty == 10 , "product qty is not same" + else: + raise AssertionError('unknown order line: %s' % purchase_line) \ No newline at end of file diff --git a/addons/sale/edi/sale_order.py b/addons/sale/edi/sale_order.py index 0ca1b55898c..15389f1481c 100644 --- a/addons/sale/edi/sale_order.py +++ b/addons/sale/edi/sale_order.py @@ -88,34 +88,36 @@ class sale_order(osv.osv, EDIMixin): edi_doc_list.append(edi_doc) return edi_doc_list - def _edi_import_company(self, cr, uid, edi_document, context=None): # TODO: for multi-company setups, we currently import the document in the # user's current company, but we should perhaps foresee a way to select # the desired company among the user's allowed companies self._edi_requires_attributes(('company_id','company_address'), edi_document) - res_partner_obj = self.pool.get('res.partner') + res_partner = self.pool.get('res.partner') - # imported company_address = new partner address - _, src_company_name = edi_document.pop('company_id') + xid, company_name = edi_document.pop('company_id') + # Retrofit address info into a unified partner info (changed in v7 - used to keep them separate) + company_address_edi = edi_document.pop('company_address') + company_address_edi['name'] = company_name + company_address_edi['is_company'] = True + company_address_edi['__import_model'] = 'res.partner' + company_address_edi['__id'] = xid # override address ID, as of v7 they should be the same anyway + if company_address_edi.get('logo'): + company_address_edi['image'] = company_address_edi.pop('logo') + company_address_edi['customer'] = True + partner_id = res_partner.edi_import(cr, uid, company_address_edi, context=context) - address_info = edi_document.pop('company_address') - address_info['supplier'] = True - if 'name' not in address_info: - address_info['name'] = src_company_name + # modify edi_document to refer to new partner + partner = res_partner.browse(cr, uid, partner_id, context=context) + partner_edi_m2o = self.edi_m2o(cr, uid, partner, context=context) + edi_document['partner_id'] = partner_edi_m2o + edi_document['partner_invoice_id'] = partner_edi_m2o + edi_document['partner_shipping_id'] = partner_edi_m2o - address_id = res_partner_obj.edi_import(cr, uid, address_info, context=context) + edi_document.pop('partner_address', None) # ignored, that's supposed to be our own address! + return partner_id - # modify edi_document to refer to new partner/address - partner_address = res_partner_obj.browse(cr, uid, address_id, context=context) - edi_document.pop('partner_address', False) # ignored - address_edi_m2o = self.edi_m2o(cr, uid, partner_address, context=context) - edi_document['partner_id'] = address_edi_m2o - edi_document['partner_invoice_id'] = address_edi_m2o - edi_document['partner_shipping_id'] = address_edi_m2o - - return address_id def _edi_get_pricelist(self, cr, uid, partner_id, currency, context=None): # TODO: refactor into common place for purchase/sale, e.g. into product module diff --git a/addons/sale/test/edi_sale_order.yml b/addons/sale/test/edi_sale_order.yml index 65a5887fe40..2db03cadf59 100644 --- a/addons/sale/test/edi_sale_order.yml +++ b/addons/sale/test/edi_sale_order.yml @@ -32,64 +32,64 @@ edi_doc = self.generate_edi(cr, uid, [so]) assert isinstance(json.loads(edi_doc)[0], dict), 'EDI doc should be a JSON dict' - - Then I import a sample EDI document of a purchase order + "Then I import a sample EDI document of a purchase order (v7.0)" - !python {model: edi.edi}: | sale_order_pool = self.pool.get('sale.order') edi_document = { - "__id": "purchase:5af1272e-dd26-11e0-b65e-701a04e25543.purchase_order_test", + "__id": "purchase:5af12v70-dv70-1v70-bv70-701a04e25v70.purchase_order_test", "__module": "purchase", "__model": "purchase.order", "__import_module": "sale", "__import_model": "sale.order", - "__version": [6,1,0], + "__version": [7,0,0], "name": "PO00011", "date_order": "2011-09-12", "currency": { - "__id": "base:5af1272e-dd26-11e0-b65e-701a04e25543.EUR", + "__id": "base:5af12v70-dv70-1v70-bv70-701a04e25v70.EUR", "__module": "base", "__model": "res.currency", "code": "EUR", "symbol": "€", }, - "company_id": ["base:5af1272e-dd26-11e0-b65e-701a04e25543.main_company", "Client S.A."], + "company_id": ["base:5af12v70-dv70-1v70-bv70-701a04e25v70.main_company", "Client S.A."], "company_address": { - "__id": "base:5af1272e-dd26-11e0-b65e-701a04e25543.some_address", + "__id": "base:5af12v70-dv70-1v70-bv70-701a04e25v70.some_address", "__module": "base", "__model": "res.partner", "phone": "(+32).81.81.37.00", "street": "Chaussee de Namur 40", "city": "Gerompont", "zip": "1367", - "country_id": ["base:5af1272e-dd26-11e0-b65e-701a04e25543.be", "Belgium"], + "country_id": ["base:5af12v70-dv70-1v70-bv70-701a04e25v70.be", "Belgium"], "bank_ids": [ - ["base:5af1272e-dd26-11e0-b65e-701a04e25543.res_partner_bank-adaWadsadasdDJzGbp","Ladies bank: 032465789-156113"] + ["base:5af12v70-dv70-1v70-bv70-701a04e25v70.res_partner_bank-adaWadsadasdDJzGbp","Ladies bank: 032465789-156113"] ], }, - "partner_id": ["purchase:5af1272e-dd26-11e0-b65e-701a04e25543.res_partner_test20", "jones white"], + "partner_id": ["purchase:5af12v70-dv70-1v70-bv70-701a04e25v70.res_partner_test20", "jones white"], "order_line": [{ - "__id": "purchase:5af1272e-dd26-11e0-b65e-701a04e25543.purchase_order_line-AlhsVDZGoKvJ", + "__id": "purchase:5af12v70-dv70-1v70-bv70-701a04e25v70.purchase_order_line-AlhsVDZGoKvJ", "__module": "purchase", "__model": "purchase.order.line", "__import_module": "sale", "__import_model": "sale.order.line", "name": "PC Assemble SC234", "price_unit": 150.0, - "product_id": ["product:5af1272e-dd26-11e0-b65e-701a04e25543.product_product_3", "[PCSC234] PC Assemble SC234"], + "product_id": ["product:5af12v70-dv70-1v70-bv70-701a04e25v70.product_product_3", "[PCSC234] PC Assemble SC234"], "product_qty": 1.0, - "product_uom": ["product:5af1272e-dd26-11e0-b65e-701a04e25543.product_uom_unit", "Unit"], + "product_uom": ["product:5af12v70-dv70-1v70-bv70-701a04e25v70.product_uom_unit", "Unit"], }, { - "__id": "purchase:5af1272e-dd26-11e0-b65e-701a04e25543.purchase_order_line-Alsads33e", + "__id": "purchase:5af12v70-dv70-1v70-bv70-701a04e25v70.purchase_order_line-Alsads33e", "__module": "purchase", "__model": "purchase.order.line", "__import_module": "sale", "__import_model": "sale.order.line", "name": "PC on Demand", "price_unit": 100.0, - "product_id": ["product:5af1272e-dd26-11e0-b65e-701a04e25543.product_product_5", "[PC-DEM] PC on Demand"], + "product_id": ["product:5af12v70-dv70-1v70-bv70-701a04e25v70.product_product_5", "[PC-DEM] PC on Demand"], "product_qty": 2.0, - "product_uom": ["product:5af1272e-dd26-11e0-b65e-701a04e25543.product_uom_unit", "Unit"], + "product_uom": ["product:5af12v70-dv70-1v70-bv70-701a04e25v70.product_uom_unit", "Unit"], }], } new_sale_order_id = sale_order_pool.edi_import(cr, uid, edi_document, context=context) @@ -97,6 +97,7 @@ order_new = sale_order_pool.browse(cr, uid, new_sale_order_id) # check bank info on partner + assert order_new.partner_id.customer, "Imported partner should be a customer, as we just imported the document as a sale order" assert len(order_new.partner_id.bank_ids) == 1, "Expected 1 bank entry related to partner" bank_info = order_new.partner_id.bank_ids[0] assert bank_info.acc_number == "Ladies bank: 032465789-156113", 'Expected "Ladies bank: 032465789-156113", got %s' % bank_info.acc_number @@ -116,3 +117,103 @@ assert sale_line.product_uom_qty == 2 , "product qty is not same" else: raise AssertionError('unknown order line: %s' % sale_line) +- + "Then I import a sample EDI document of a purchase order (v6.1 - to test backwards compatibility)" +- + !python {model: edi.document}: | + sale_order_pool = self.pool.get('sale.order') + edi_document = { + "__id": "purchase:5af1272e-dd26-11e0-b65e-701a04e25543.purchase_order_test", + "__module": "purchase", + "__model": "purchase.order", + "__import_module": "sale", + "__import_model": "sale.order", + "__version": [6,1,0], + "name": "PO00011-v61", + "date_order": "2011-09-12", + "currency": { + "__id": "base:5af1272e-dd26-11e0-b65e-701a04e25543.EUR", + "__module": "base", + "__model": "res.currency", + "code": "EUR", + "symbol": "€", + }, + "company_id": ["base:5af1272e-dd26-11e0-b65e-701a04e25543.main_company", "Client S.A."], + "company_address": { + "__id": "base:5af1272e-dd26-11e0-b65e-701a04e25543.some_address", + "__module": "base", + "__model": "res.partner.address", + "phone": "(+32).81.81.37.00", + "street": "Chaussee de Namur 40", + "city": "Gerompont", + "zip": "1367", + "country_id": ["base:5af1272e-dd26-11e0-b65e-701a04e25543.be", "Belgium"], + "bank_ids": [ + ["base:5af1272e-dd26-11e0-b65e-701a04e25543.res_partner_bank-adaWadsadasdDJzGbp","Ladies bank: 032465789-156113"] + ], + }, + "partner_id": ["purchase:5af1272e-dd26-11e0-b65e-701a04e25543.res_partner_test20", "jones white"], + "partner_address": { + "__id": "base:5af1272e-dd26-11e0-b65e-701a04e25543.res_partner_address_7wdsjasdjh", + "__module": "base", + "__model": "res.partner.address", + "phone": "(+32).81.81.37.00", + "street": "Chaussee de Namur 40", + "city": "Gerompont", + "zip": "1367", + "country_id": ["base:5af1272e-dd26-11e0-b65e-701a04e25543.be", "Belgium"], + }, + "order_line": [{ + "__id": "purchase:5af1272e-dd26-11e0-b65e-701a04e25543.purchase_order_line-AlhsVDZGoKvJ", + "__module": "purchase", + "__model": "purchase.order.line", + "__import_module": "sale", + "__import_model": "sale.order.line", + "name": "Basic PC", + "date_planned": "2011-09-30", + "price_unit": 150.0, + "product_id": ["product:5af1272e-dd26-11e0-b65e-701a04e25543.product_product_pc1", "[PC1] Basic PC"], + "product_qty": 1.0, + "product_uom": ["product:5af1272e-dd26-11e0-b65e-701a04e25543.product_uom_unit", "PCE"], + }, + { + "__id": "purchase:5af1272e-dd26-11e0-b65e-701a04e25543.purchase_order_line-Alsads33e", + "__module": "purchase", + "__model": "purchase.order.line", + "__import_module": "sale", + "__import_model": "sale.order.line", + "name": "Medium PC", + "date_planned": "2011-09-15", + "price_unit": 100.0, + "product_id": ["product:5af1272e-dd26-11e0-b65e-701a04e25543.product_product_pc3", "[PC3] Medium PC"], + "product_qty": 2.0, + "product_uom": ["product:5af1272e-dd26-11e0-b65e-701a04e25543.product_uom_unit", "PCE"], + }], + } + new_sale_order_id = sale_order_pool.edi_import(cr, uid, edi_document, context=context) + assert new_sale_order_id, 'Sale order import failed' + order_new = sale_order_pool.browse(cr, uid, new_sale_order_id) + + # check bank info on partner + assert order_new.partner_id.customer, "Imported partner should be a customer, as we just imported the document as a sale order" + assert len(order_new.partner_id.bank_ids) == 1, "Expected 1 bank entry related to partner" + bank_info = order_new.partner_id.bank_ids[0] + assert bank_info.acc_number == "Ladies bank: 032465789-156113", 'Expected "Ladies bank: 032465789-156113", got %s' % bank_info.acc_number + + assert order_new.pricelist_id.name == 'Public Pricelist' , "Public Price list was not automatically assigned" + assert order_new.amount_total == 350, "Amount total is wrong" + assert order_new.amount_untaxed == 350, "Untaxed amount is wrong" + assert len(order_new.order_line) == 2, "Sale order lines mismatch" + for sale_line in order_new.order_line: + if sale_line.name == 'Basic PC': + assert sale_line.delay == 18 , "incorrect delay: got %s, expected 18"%(sale_line.delay,) + assert sale_line.product_uom.name == "PCE" , "uom is not same" + assert sale_line.price_unit == 150 , "unit price is not same, got %s, expected 150"%(sale_line.price_unit,) + assert sale_line.product_uom_qty == 1 , "product qty is not same" + elif sale_line.name == 'Medium PC': + assert sale_line.delay == 3 , "incorrect delay: got %s, expected 3"%(sale_line.delay,) + assert sale_line.product_uom.name == "PCE" , "uom is not same" + assert sale_line.price_unit == 100 , "unit price is not same, got %s, expected 100"%(sale_line.price_unit,) + assert sale_line.product_uom_qty == 2 , "product qty is not same" + else: + raise AssertionError('unknown order line: %s' % sale_line) \ No newline at end of file From 46b2a78ea0fb825c3874080614f267c305fffc94 Mon Sep 17 00:00:00 2001 From: Olivier Dony Date: Fri, 19 Oct 2012 12:39:45 +0200 Subject: [PATCH 007/122] [FIX] sale/edi: typo when adding 6.1 EDI testcase bzr revid: odo@openerp.com-20121019103945-mor902q1qzyszhn0 --- addons/sale/test/edi_sale_order.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/sale/test/edi_sale_order.yml b/addons/sale/test/edi_sale_order.yml index 2db03cadf59..78ff1c24da3 100644 --- a/addons/sale/test/edi_sale_order.yml +++ b/addons/sale/test/edi_sale_order.yml @@ -120,7 +120,7 @@ - "Then I import a sample EDI document of a purchase order (v6.1 - to test backwards compatibility)" - - !python {model: edi.document}: | + !python {model: edi.edi}: | sale_order_pool = self.pool.get('sale.order') edi_document = { "__id": "purchase:5af1272e-dd26-11e0-b65e-701a04e25543.purchase_order_test", From ce1226a4a8ebb7e197214be54a8c3c8815e72d6b Mon Sep 17 00:00:00 2001 From: Olivier Dony Date: Fri, 19 Oct 2012 13:11:00 +0200 Subject: [PATCH 008/122] [FIX] sale,edi: fix sale EDI import test + better debug - `delay` field on SO line moved to sale_stock, ignoring it for now - avoid reusing the same bank account in 6.1 test, would cause a test failure because the import would be skipped and the new partner would have no bank account. Bank accounts should be unique in the real world. - log in DEBUG when a relationship record is skipped during EDI import bzr revid: odo@openerp.com-20121019111100-dwf0crocqv43m3ij --- addons/edi/models/edi.py | 3 +++ addons/sale/test/edi_sale_order.yml | 6 ++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/addons/edi/models/edi.py b/addons/edi/models/edi.py index 5edbca11d13..48a04c2a94d 100644 --- a/addons/edi/models/edi.py +++ b/addons/edi/models/edi.py @@ -525,6 +525,9 @@ class EDIMixin(object): model = self.pool.get(model) res_id, _ = model.name_create(cr, uid, value, context=context) target = model.browse(cr, uid, res_id, context=context) + else: + _logger.debug("%s: Importing EDI relationship [%r,%r] - record already exists with ID %s, using it", + self._name, external_id, value, target.id) 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 diff --git a/addons/sale/test/edi_sale_order.yml b/addons/sale/test/edi_sale_order.yml index 78ff1c24da3..24fdfdf2786 100644 --- a/addons/sale/test/edi_sale_order.yml +++ b/addons/sale/test/edi_sale_order.yml @@ -63,7 +63,7 @@ "zip": "1367", "country_id": ["base:5af12v70-dv70-1v70-bv70-701a04e25v70.be", "Belgium"], "bank_ids": [ - ["base:5af12v70-dv70-1v70-bv70-701a04e25v70.res_partner_bank-adaWadsadasdDJzGbp","Ladies bank: 032465789-156113"] + ["base:5af12v70-dv70-1v70-bv70-701a04e25v70.res_partner_bank-adaWadsadasdDJzGbp","Another bank: 032465700-156700"] ], }, "partner_id": ["purchase:5af12v70-dv70-1v70-bv70-701a04e25v70.res_partner_test20", "jones white"], @@ -100,7 +100,7 @@ assert order_new.partner_id.customer, "Imported partner should be a customer, as we just imported the document as a sale order" assert len(order_new.partner_id.bank_ids) == 1, "Expected 1 bank entry related to partner" bank_info = order_new.partner_id.bank_ids[0] - assert bank_info.acc_number == "Ladies bank: 032465789-156113", 'Expected "Ladies bank: 032465789-156113", got %s' % bank_info.acc_number + assert bank_info.acc_number == "Another bank: 032465700-156700", 'Expected "Another bank: 032465700-156700", got %s' % bank_info.acc_number assert order_new.pricelist_id.name == 'Public Pricelist' , "Public Price list was not automatically assigned" assert order_new.amount_total == 350, "Amount total is wrong" @@ -206,12 +206,10 @@ assert len(order_new.order_line) == 2, "Sale order lines mismatch" for sale_line in order_new.order_line: if sale_line.name == 'Basic PC': - assert sale_line.delay == 18 , "incorrect delay: got %s, expected 18"%(sale_line.delay,) assert sale_line.product_uom.name == "PCE" , "uom is not same" assert sale_line.price_unit == 150 , "unit price is not same, got %s, expected 150"%(sale_line.price_unit,) assert sale_line.product_uom_qty == 1 , "product qty is not same" elif sale_line.name == 'Medium PC': - assert sale_line.delay == 3 , "incorrect delay: got %s, expected 3"%(sale_line.delay,) assert sale_line.product_uom.name == "PCE" , "uom is not same" assert sale_line.price_unit == 100 , "unit price is not same, got %s, expected 100"%(sale_line.price_unit,) assert sale_line.product_uom_qty == 2 , "product qty is not same" From 67d4646d092c93f9f78d38f8364242ffacef5415 Mon Sep 17 00:00:00 2001 From: Olivier Dony Date: Tue, 23 Oct 2012 13:42:14 +0200 Subject: [PATCH 009/122] [IMP] sale,purchase,invoice: attach PDF report to `Send by mail` template This is quite useful in general, and partly compensates for partial EDI integration, e.g. when the sender company does not have a portal or any way for customers to see the document. bzr revid: odo@openerp.com-20121023114214-8zpl96jxqvqxv4xw --- addons/account/edi/invoice_action_data.xml | 4 ++++ addons/purchase/edi/purchase_order_action_data.xml | 4 ++++ addons/sale/edi/sale_order_action_data.xml | 4 ++++ 3 files changed, 12 insertions(+) diff --git a/addons/account/edi/invoice_action_data.xml b/addons/account/edi/invoice_action_data.xml index 1ad023c3a60..b4fb6d07fcd 100644 --- a/addons/account/edi/invoice_action_data.xml +++ b/addons/account/edi/invoice_action_data.xml @@ -27,6 +27,8 @@ ${object.partner_id.email or ''} + + Invoice_${(object.number or '').replace('/','_')}_${object.state == 'draft' and 'draft' or ''} @@ -42,7 +44,9 @@ % if object.origin:   Order reference: ${object.origin}
    % endif + % if object.user_id:   Your contact: ${object.user_id.name} + % endif

    % if object.company_id.paypal_account and object.type in ('out_invoice', 'in_refund'): diff --git a/addons/purchase/edi/purchase_order_action_data.xml b/addons/purchase/edi/purchase_order_action_data.xml index 02e7a1c1ae1..fa043b72ce9 100644 --- a/addons/purchase/edi/purchase_order_action_data.xml +++ b/addons/purchase/edi/purchase_order_action_data.xml @@ -24,6 +24,8 @@ ${object.partner_id.email} + + RFQ_${(object.name or '').replace('/','_')} @@ -42,7 +44,9 @@ % if object.partner_ref:   Your reference: ${object.partner_ref}
    % endif + % if object.user_id:   Your contact: ${object.validator.name} + % endif


    diff --git a/addons/sale/edi/sale_order_action_data.xml b/addons/sale/edi/sale_order_action_data.xml index 5ce35bf497d..009f575f00d 100644 --- a/addons/sale/edi/sale_order_action_data.xml +++ b/addons/sale/edi/sale_order_action_data.xml @@ -26,6 +26,8 @@ ${object.partner_invoice_id.email} + + ${(object.name or '').replace('/','_')}_${object.state == 'draft' and 'draft' or ''} @@ -44,7 +46,9 @@ % if object.client_order_ref:   Your reference: ${object.client_order_ref}
    % endif + % if object.user_id:   Your contact: ${object.user_id.name} + % endif

    % if object.order_policy in ('prepaid','manual') and object.company_id.paypal_account and object.state not in ('draft', 'sent'): From 6fadb453259697c10cf2aed0be33c41760dc246b Mon Sep 17 00:00:00 2001 From: Olivier Dony Date: Tue, 23 Oct 2012 13:56:28 +0200 Subject: [PATCH 010/122] [IMP] sale,purchase,invoice: make `Send by mail` action more robust to template/view deletion bzr revid: odo@openerp.com-20121023115628-3wvxcrkgazhi9p75 --- addons/account/account_invoice.py | 24 ++++++++++++++---------- addons/account/edi/invoice.py | 1 - addons/purchase/purchase.py | 25 ++++++++++++++----------- addons/sale/sale.py | 23 +++++++++++++---------- 4 files changed, 41 insertions(+), 32 deletions(-) diff --git a/addons/account/account_invoice.py b/addons/account/account_invoice.py index 57f16473b82..15f000cb90e 100644 --- a/addons/account/account_invoice.py +++ b/addons/account/account_invoice.py @@ -390,28 +390,32 @@ class account_invoice(osv.osv): ''' This function opens a window to compose an email, with the edi invoice template message loaded by default ''' - mod_obj = self.pool.get('ir.model.data') - template = mod_obj.get_object_reference(cr, uid, 'account', 'email_template_edi_invoice') - template_id = template and template[1] or False - res = mod_obj.get_object_reference(cr, uid, 'mail', 'email_compose_message_wizard_form') - res_id = res and res[1] or False + assert len(ids) == 1, 'This option should only be used for a single id at a time.' + ir_model_data = self.pool.get('ir.model.data') + try: + template_id = ir_model_data.get_object_reference(cr, uid, 'account', 'email_template_edi_invoice')[1] + except ValueError: + template_id = False + try: + compose_form_id = ir_model_data.get_object_reference(cr, uid, 'mail', 'email_compose_message_wizard_form')[1] + except ValueError: + compose_form_id = False ctx = dict(context) ctx.update({ 'default_model': 'account.invoice', 'default_res_id': ids[0], - 'default_use_template': True, + 'default_use_template': bool(template_id), 'default_template_id': template_id, }) return { + 'type': 'ir.actions.act_window', 'view_type': 'form', 'view_mode': 'form', 'res_model': 'mail.compose.message', - 'views': [(res_id, 'form')], - 'view_id': res_id, - 'type': 'ir.actions.act_window', + 'views': [(compose_form_id, 'form')], + 'view_id': compose_form_id, 'target': 'new', 'context': ctx, - 'nodestroy': True, } def confirm_paid(self, cr, uid, ids, context=None): diff --git a/addons/account/edi/invoice.py b/addons/account/edi/invoice.py index 80a4b145054..3e27bc5ea99 100644 --- a/addons/account/edi/invoice.py +++ b/addons/account/edi/invoice.py @@ -148,7 +148,6 @@ class account_invoice(osv.osv, EDIMixin): edi_document['partner_id'] = partner_edi_m2o edi_document.pop('partner_address', None) # ignored, that's supposed to be our own address! - return partner_id def edi_import(self, cr, uid, edi_document, context=None): diff --git a/addons/purchase/purchase.py b/addons/purchase/purchase.py index db6ed8b80be..ed8cdb63cef 100644 --- a/addons/purchase/purchase.py +++ b/addons/purchase/purchase.py @@ -349,28 +349,31 @@ class purchase_order(osv.osv): ''' This function opens a window to compose an email, with the edi purchase template message loaded by default ''' - mod_obj = self.pool.get('ir.model.data') - template = mod_obj.get_object_reference(cr, uid, 'purchase', 'email_template_edi_purchase') - template_id = template and template[1] or False - res = mod_obj.get_object_reference(cr, uid, 'mail', 'email_compose_message_wizard_form') - res_id = res and res[1] or False + ir_model_data = self.pool.get('ir.model.data') + try: + template_id = ir_model_data.get_object_reference(cr, uid, 'purchase', 'email_template_edi_purchase')[1] + except ValueError: + template_id = False + try: + compose_form_id = ir_model_data.get_object_reference(cr, uid, 'mail', 'email_compose_message_wizard_form')[1] + except ValueError: + compose_form_id = False ctx = dict(context) ctx.update({ 'default_model': 'purchase.order', 'default_res_id': ids[0], - 'default_use_template': True, + 'default_use_template': bool(template_id), 'default_template_id': template_id, - }) + }) return { + 'type': 'ir.actions.act_window', 'view_type': 'form', 'view_mode': 'form', 'res_model': 'mail.compose.message', - 'views': [(res_id, 'form')], - 'view_id': res_id, - 'type': 'ir.actions.act_window', + 'views': [(compose_form_id, 'form')], + 'view_id': compose_form_id, 'target': 'new', 'context': ctx, - 'nodestroy': True, } #TODO: implement messages system diff --git a/addons/sale/sale.py b/addons/sale/sale.py index a2ee88ab860..3c984b64349 100644 --- a/addons/sale/sale.py +++ b/addons/sale/sale.py @@ -618,29 +618,32 @@ class sale_order(osv.osv): This function opens a window to compose an email, with the edi sale template message loaded by default ''' assert len(ids) == 1, 'This option should only be used for a single id at a time.' - mod_obj = self.pool.get('ir.model.data') - template = mod_obj.get_object_reference(cr, uid, 'sale', 'email_template_edi_sale') - template_id = template and template[1] or False - res = mod_obj.get_object_reference(cr, uid, 'mail', 'email_compose_message_wizard_form') - res_id = res and res[1] or False + ir_model_data = self.pool.get('ir.model.data') + try: + template_id = ir_model_data.get_object_reference(cr, uid, 'sale', 'email_template_edi_sale')[1] + except ValueError: + template_id = False + try: + compose_form_id = ir_model_data.get_object_reference(cr, uid, 'mail', 'email_compose_message_wizard_form')[1] + except ValueError: + compose_form_id = False ctx = dict(context) ctx.update({ 'default_model': 'sale.order', 'default_res_id': ids[0], - 'default_use_template': True, + 'default_use_template': bool(template_id), 'default_template_id': template_id, 'mark_so_as_sent': True }) return { + 'type': 'ir.actions.act_window', 'view_type': 'form', 'view_mode': 'form', 'res_model': 'mail.compose.message', - 'views': [(res_id, 'form')], - 'view_id': res_id, - 'type': 'ir.actions.act_window', + 'views': [(compose_form_id, 'form')], + 'view_id': compose_form_id, 'target': 'new', 'context': ctx, - 'nodestroy': True, } def action_done(self, cr, uid, ids, context=None): From 21b56902b7eb7ad4eabb2b3be97ca42384d12fdc Mon Sep 17 00:00:00 2001 From: Olivier Dony Date: Wed, 24 Oct 2012 14:59:57 +0200 Subject: [PATCH 011/122] [FIX] sale/edi: paypal payment should be possible as soon as SO is not draft Most companies won't mind if customers pay too early. Even if the amount is not 100% correct, it can be adjusted later, and it's better than missing a revenue opportunity. bzr revid: odo@openerp.com-20121024125957-oo8r9zmazzdonhd7 --- addons/sale/edi/sale_order_action_data.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/sale/edi/sale_order_action_data.xml b/addons/sale/edi/sale_order_action_data.xml index 009f575f00d..cfe5277d3ce 100644 --- a/addons/sale/edi/sale_order_action_data.xml +++ b/addons/sale/edi/sale_order_action_data.xml @@ -51,7 +51,7 @@ % endif

    - % if object.order_policy in ('prepaid','manual') and object.company_id.paypal_account and object.state not in ('draft', 'sent'): + % if object.order_policy in ('prepaid','manual') and object.company_id.paypal_account and object.state != 'draft': <% comp_name = quote(object.company_id.name) order_name = quote(object.name) From 20c81b5e2fea00643f234ac83814ce73bae14d12 Mon Sep 17 00:00:00 2001 From: Olivier Dony Date: Wed, 24 Oct 2012 15:15:54 +0200 Subject: [PATCH 012/122] [ADD] portal: added portal.payment.acquirer model portal.payment.acquirer stores payment processor options (formally called payment acquirers). Each acquirer is just a name and an HTML form template, used to render an HTML snippet that can be included in views where a payment option should be displayed. The aquirer model has a generic method for rendering a complete block of HTML to be included in form views directly (with matching CSS): render_payment_block(). This method takes a few parameters to figure out the name/reference, amount, currency, etc. to pay. bzr revid: odo@openerp.com-20121024131554-j01ucniecjmoz3jq --- addons/portal/__init__.py | 2 +- addons/portal/__openerp__.py | 2 + addons/portal/acquirer.py | 96 ++++++++++++++++++++++ addons/portal/acquirer_view.xml | 67 +++++++++++++++ addons/portal/portal_data.xml | 24 ++++++ addons/portal/security/ir.model.access.csv | 2 + addons/portal/static/src/css/portal.css | 60 ++++++++++++++ 7 files changed, 252 insertions(+), 1 deletion(-) create mode 100644 addons/portal/acquirer.py create mode 100644 addons/portal/acquirer_view.xml create mode 100644 addons/portal/static/src/css/portal.css diff --git a/addons/portal/__init__.py b/addons/portal/__init__.py index 2bfc6df0d96..0045a557a49 100644 --- a/addons/portal/__init__.py +++ b/addons/portal/__init__.py @@ -22,6 +22,6 @@ import portal import mail_mail import wizard - +import acquirer # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/portal/__openerp__.py b/addons/portal/__openerp__.py index 66a736c6048..4f37a2205d7 100644 --- a/addons/portal/__openerp__.py +++ b/addons/portal/__openerp__.py @@ -49,8 +49,10 @@ very handy when used in combination with the module 'share'. 'portal_view.xml', 'wizard/portal_wizard_view.xml', 'wizard/share_wizard_view.xml', + 'acquirer_view.xml', ], 'demo': ['portal_demo.xml'], + 'css': ['static/src/css/portal.css'], 'installable': True, } diff --git a/addons/portal/acquirer.py b/addons/portal/acquirer.py new file mode 100644 index 00000000000..922a341b679 --- /dev/null +++ b/addons/portal/acquirer.py @@ -0,0 +1,96 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Business Applications +# Copyright (c) 2012-TODAY 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 logging +from urllib import quote as quote + +from openerp.osv import osv, fields +from openerp.tools import ustr +from openerp.tools.translate import _ + +_logger = logging.getLogger(__name__) +try: + from mako.template import Template as MakoTemplate +except ImportError: + _logger.warning("payment_acquirer: mako templates not available, payment acquirer will not work!") + + +class acquirer(osv.Model): + _name = 'portal.payment.acquirer' + _description = 'Online Payment Acquirer' + + _columns = { + 'name': fields.char('Name', required=True), + 'form_template': fields.text('Payment form template (HTML)', translate=True), + 'visible': fields.boolean('Visible', help="Whether this payment acquirer is currently displayed in portal forms"), + } + + _default = { + 'visible': True, + } + + def render(self, cr, uid, id, object, reference, currency, amount, context=None, **kwargs): + """ Renders the form template of the given acquirer as a mako template """ + if not isinstance(id, (int,long)): + id = id[0] + this = self.browse(cr, uid, id) + if context is None: + context = {} + try: + i18n_kind = _(object._description) # may fail to translate, but at least we try + template = ustr(this.form_template) + result = MakoTemplate(template).render_unicode(object=object, + reference=reference, + currency=currency, + amount=amount, + kind=i18n_kind, + quote=quote, + # context kw would clash with mako internals + ctx=context, + format_exceptions=True) + result = result.strip() + if result == u'False': + result = u'' + return result + except Exception: + _logger.exception("failed to render mako template value for payment.acquirer %s: %r", this.name, template) + return + + def _wrap_payment_block(self, cr, uid, html_block, context=None): + payment_header = _('Pay safely online:') + result = """
    + %s + %%s +
    """ % payment_header + return result % html_block + + def render_payment_block(self, cr, uid, object, reference, currency, amount, context=None, **kwargs): + """ Renders all visible payment acquirer forms for the given rendering context, and + return them wrapped in an appropriate HTML block, ready for direct inclusion + in an OpenERP v7 form view """ + acquirer_ids = self.search(cr, uid, [('visible', '=', True)]) + if not acquirer_ids: + return + html_forms = [] + for this in self.browse(cr, uid, acquirer_ids): + html_forms.append(this.render(object, reference, currency, amount, context=context, **kwargs)) + html_block = '\n'.join(html_forms) + return self._wrap_payment_block(cr, uid, html_block, context=context) diff --git a/addons/portal/acquirer_view.xml b/addons/portal/acquirer_view.xml new file mode 100644 index 00000000000..0e88d47f758 --- /dev/null +++ b/addons/portal/acquirer_view.xml @@ -0,0 +1,67 @@ + + + + + portal.payment.acquirer + +
    + +
    +
    + +
    +

    + This is an HTML form template to submit a payment through this acquirer. + The template will be rendered through mako, so it may use normal mako expressions. + The mako evaluation context provides: +

      +
    • reference: the reference number of the document to pay
    • +
    • kind: the kind of document on which the payment form is rendered (translated to user language, e.g. "Invoice")
    • +
    • currency: the currency record in which the document is issued (e.g. currency.name could be EUR)
    • +
    • amount: the total amount to pay, as a float
    • +
    • object: the document on which the payment form is rendered (usually an invoice or sale order record)
    • +
    • quote(): a method to quote special string character to make them suitable for inclusion in a URL
    • +
    • cr: the current database cursor
    • +
    • uid: the current user id
    • +
    • ctx: the current context dictionary
    • +
    + If the template renders to an empty result in a certain context it will be ignored, as if it was inactive. +

    +
    + +
    +
    +
    +
    +
    + + portal.payment.acquirer + + + + + + + + + portal.payment.acquirer + + + + + + + + + Payment Acquirers + portal.payment.acquirer + + + + + + +
    +
    diff --git a/addons/portal/portal_data.xml b/addons/portal/portal_data.xml index 90a570bc1d5..89e62c8d48e 100644 --- a/addons/portal/portal_data.xml +++ b/addons/portal/portal_data.xml @@ -27,6 +27,30 @@ form + + + + Paypal + + + + +% endif + ]]> + diff --git a/addons/portal/security/ir.model.access.csv b/addons/portal/security/ir.model.access.csv index 9202c7f4087..b6d932bf7ee 100644 --- a/addons/portal/security/ir.model.access.csv +++ b/addons/portal/security/ir.model.access.csv @@ -4,3 +4,5 @@ access_res_partner,res.partner,base.model_res_partner,portal.group_portal,1,0,0, access_res_partner_address,res.partner_address,base.model_res_partner_address,portal.group_portal,1,0,0,0 access_res_partner_category,res.partner_category,base.model_res_partner_category,portal.group_portal,1,0,0,0 access_res_partner_title,res.partner_title,base.model_res_partner_title,portal.group_portal,1,0,0,0 +access_acquirer,portal.payment.acquirer,portal.model_portal_payment_acquirer,,1,0,0,0 +access_acquirer_all,portal.payment.acquirer,portal.model_portal_payment_acquirer,base.group_system,1,1,1,1 diff --git a/addons/portal/static/src/css/portal.css b/addons/portal/static/src/css/portal.css new file mode 100644 index 00000000000..02d0d44e6b3 --- /dev/null +++ b/addons/portal/static/src/css/portal.css @@ -0,0 +1,60 @@ + +.openerp .oe_application .oe_form_sheetbg { + /* Establish a stacking context on top of which the + payment_acquirers::before element can be positioned */ + position: relative; + z-index: 0; +} + +.openerp .payment_acquirers { + margin: -40px 0 -32px -24px; + position: relative; + padding: 10px 15px; + right: -153px; + + background: #729FCF; + background-image: -webkit-gradient(linear, left top, left bottom, from(#729FCF), to(#3465A4)); + background-image: -webkit-linear-gradient(top, #729FCF, #3465A4); + background-image: -moz-linear-gradient(top, #729FCF, #3465A4); + background-image: -ms-linear-gradient(top, #729FCF, #3465A4); + background-image: -o-linear-gradient(top, #729FCF, #3465A4); + background-image: linear-gradient(to bottom, #729FCF, #3465A4); + border-bottom: 1px solid #043574; + + -webkit-box-shadow: 0 4px 20px rgba(0, 0, 0, 0.45); + box-shadow: 0 4px 20px rgba(0, 0, 0, 0.45); +} + +.openerp .payment_acquirers::after { + content: " "; + display: block; + width: 10px; + height: 20px; + position: absolute; + bottom: 0; + right: 1px; + + margin-bottom: -6px; + background: #043574; + + -webkit-transform: skewY(-45deg); + -moz-transform: skewY(-45deg); + -ms-transform: skewY(-45deg); + -o-transform: skewY(-45deg); + transform: skewY(-45deg); + + -webkit-box-shadow: inset 1px -1px 2px black, -1px 1px 3px black; + box-shadow: inset 1px -1px 2px black, -1px 1px 3px black; + + /* push it under all its siblings, just on top of its root + in the z-index stack: div.oe_form_sheetbg */ + z-index: -1; +} + +.openerp .payment_acquirers .payment_header { + font-weight: bold; + font-size: 110%; + padding-right: 15px; + color: white; + text-shadow: 0 1px 1px #729FCF, 0 -1px 1px #3465A4; +} \ No newline at end of file From 21e48c3b96f12878f84909cf09a734eb7032657c Mon Sep 17 00:00:00 2001 From: Olivier Dony Date: Wed, 24 Oct 2012 15:16:47 +0200 Subject: [PATCH 013/122] [ADD] portal_sale: integrate payment acquirer options in sale.order forms bzr revid: odo@openerp.com-20121024131647-hfqgjpftwgygx976 --- addons/portal_sale/__init__.py | 1 + addons/portal_sale/portal_sale.py | 40 +++++++++++++++++++++++++ addons/portal_sale/portal_sale_view.xml | 12 ++++++++ 3 files changed, 53 insertions(+) create mode 100644 addons/portal_sale/portal_sale.py diff --git a/addons/portal_sale/__init__.py b/addons/portal_sale/__init__.py index 26c654db9dd..8cc32ba971e 100644 --- a/addons/portal_sale/__init__.py +++ b/addons/portal_sale/__init__.py @@ -19,3 +19,4 @@ # ############################################################################## +import portal_sale \ No newline at end of file diff --git a/addons/portal_sale/portal_sale.py b/addons/portal_sale/portal_sale.py new file mode 100644 index 00000000000..4e41fd53332 --- /dev/null +++ b/addons/portal_sale/portal_sale.py @@ -0,0 +1,40 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Business Applications +# Copyright (c) 2012 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 . +# +############################################################################## + +from openerp.osv import osv, fields + +class sale_order(osv.Model): + _inherit = 'sale.order' + + _payment_block_proxy = lambda self,*a,**kw: self._portal_payment_block(*a, **kw) + + _columns = { + 'portal_payment_options': fields.function(_payment_block_proxy, type="html", string="Portal Payment Options"), + } + + def _portal_payment_block(self, cr, uid, ids, fieldname, arg, context=None): + result = dict.fromkeys(ids, False) + payment_acquirer = self.pool.get('portal.payment.acquirer') + for this in self.browse(cr, uid, ids, context=context): + if this.state != 'draft': + result[this.id] = payment_acquirer.render_payment_block(cr, uid, this, this.name, + this.pricelist_id.currency_id, this.amount_total, context=context) + return result \ No newline at end of file diff --git a/addons/portal_sale/portal_sale_view.xml b/addons/portal_sale/portal_sale_view.xml index 6b25d87b791..f4607590717 100644 --- a/addons/portal_sale/portal_sale_view.xml +++ b/addons/portal_sale/portal_sale_view.xml @@ -2,6 +2,18 @@ + + sale.order.form.payment + sale.order + + + + + + + + + + + + + Portal Personal Quotations/Sales Orders From 52ee9769f69144ab8050ed70572ddcaffe0dd6c5 Mon Sep 17 00:00:00 2001 From: Olivier Dony Date: Fri, 26 Oct 2012 18:48:03 +0200 Subject: [PATCH 017/122] [IMP] sale_portal: add payment option on invoices, fix state check to display it on sale.order bzr revid: odo@openerp.com-20121026164803-625usw34bnyzmxqu --- addons/portal_sale/portal_sale.py | 21 +++++++++++++++- addons/portal_sale/portal_sale_view.xml | 33 +++++++++++++++++++++---- 2 files changed, 48 insertions(+), 6 deletions(-) diff --git a/addons/portal_sale/portal_sale.py b/addons/portal_sale/portal_sale.py index d45653bd817..09d71fc1d2b 100644 --- a/addons/portal_sale/portal_sale.py +++ b/addons/portal_sale/portal_sale.py @@ -34,7 +34,26 @@ class sale_order(osv.Model): result = dict.fromkeys(ids, False) payment_acquirer = self.pool.get('portal.payment.acquirer') for this in self.browse(cr, uid, ids, context=context): - if this.state != 'draft' and not this.invoiced: + if this.state not in ('draft','cancel') and not this.invoiced: result[this.id] = payment_acquirer.render_payment_block(cr, uid, this, this.name, this.pricelist_id.currency_id, this.amount_total, context=context) + return result + + +class account_invoice(osv.Model): + _inherit = 'account.invoice' + + _payment_block_proxy = lambda self,*a,**kw: self._portal_payment_block(*a, **kw) + + _columns = { + 'portal_payment_options': fields.function(_payment_block_proxy, type="html", string="Portal Payment Options"), + } + + def _portal_payment_block(self, cr, uid, ids, fieldname, arg, context=None): + result = dict.fromkeys(ids, False) + payment_acquirer = self.pool.get('portal.payment.acquirer') + for this in self.browse(cr, uid, ids, context=context): + if this.state not in ('draft','done') and not this.reconciled: + result[this.id] = payment_acquirer.render_payment_block(cr, uid, this, this.number, + this.currency_id, this.residual, context=context) return result \ No newline at end of file diff --git a/addons/portal_sale/portal_sale_view.xml b/addons/portal_sale/portal_sale_view.xml index e1c5a233eb9..f01b35eff12 100644 --- a/addons/portal_sale/portal_sale_view.xml +++ b/addons/portal_sale/portal_sale_view.xml @@ -1,7 +1,8 @@ - + + sale.order.form.payment sale.order @@ -12,6 +13,16 @@ + + account.invoice.form.payment + account.invoice + + + + + + + + + account.config.settings + + + +
    + +
    +
    +
    +
    + + + \ No newline at end of file From 3fd509b634c0c817052244da22affbb7524c3d37 Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Mon, 12 Nov 2012 10:59:41 +0100 Subject: [PATCH 019/122] [IMP] mail: change the counter of the need action menu when a message is read. Actually reload all the widget menu but we can upgrade and change the number only (less request) bzr revid: chm@openerp.com-20121112095941-yitxdd3dpjox4das --- addons/mail/static/src/js/mail.js | 36 +++++++++++++++++++++++++++---- 1 file changed, 32 insertions(+), 4 deletions(-) diff --git a/addons/mail/static/src/js/mail.js b/addons/mail/static/src/js/mail.js index 7acebe9b1df..5832f10bebb 100644 --- a/addons/mail/static/src/js/mail.js +++ b/addons/mail/static/src/js/mail.js @@ -748,7 +748,13 @@ openerp.mail = function (session) { this.ds_notification.call('set_message_read', [ [this.id].concat( this.get_child_ids() ) , this.to_read, this.context]).then(function () { self.$el.removeClass(self.to_read ? 'oe_msg_unread':'oe_msg_read').addClass(self.to_read ? 'oe_msg_read':'oe_msg_unread'); self.to_read = !self.to_read; + // CHM note: put this function inside a check of display message after star/read... + // we can make a function for manualy set the counter (menu.needaction_counter) and don't reload all the widget menu + if( self.options._parents[0].__parentedParent.__parentedParent.get_menu_emails ) { + self.options._parents[0].__parentedParent.__parentedParent.get_menu_emails().widget.do_reload(); + } }); + return false; }, @@ -1556,10 +1562,10 @@ openerp.mail = function (session) { */ init: function (parent, action) { this._super(parent); - var options = action.params || {}; - this.options = options; - this.options.domain = options.domain || []; - this.options.context = options.context || {}; + this.action = action; + this.options = action.params; + this.options.domain = action.params.domain || []; + this.options.context = action.params.context || {}; this.search_results = {'domain': [], 'context': {}, 'groupby': {}} this.ds_msg = new session.web.DataSetSearch(this, 'mail.message'); }, @@ -1573,6 +1579,28 @@ openerp.mail = function (session) { return $.when(searchview_ready, thread_displayed); }, + /** + * crete an object "related_menu" + * contain the menu widget and the the sub menu related of this wall + */ + get_menu_emails: function () { + var self = this; + if (!this.related_menu) { + var menu = this.__parentedParent.__parentedParent.menu; + var sub_menu = _.filter(menu.data.data.children, function (val) {return val.id == 100;})[0]; + + var menu_active = false; + _.find(sub_menu.children, function (sub_menu) { + return _.find(sub_menu.children, function (sub_sub_menu) { + menu_active = sub_sub_menu; + return sub_sub_menu.id == self.action.menu_id; + }); + }); + this.related_menu = {'widget': menu, 'menu': menu_active}; + } + return this.related_menu; + }, + /** * Load the mail.message search view * @param {Object} defaults ?? From c6557b4089b9f204a1e64150e307359df57aa020 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Mon, 12 Nov 2012 17:23:00 +0100 Subject: [PATCH 020/122] [IMP] Demo data, by CHM, taken from old branch, to clean history. bzr revid: tde@openerp.com-20121112162300-3whtwa78qaskpey8 --- addons/mail/data/mail_demo.xml | 101 +++++++++++++++++---------------- 1 file changed, 52 insertions(+), 49 deletions(-) diff --git a/addons/mail/data/mail_demo.xml b/addons/mail/data/mail_demo.xml index f189b10650c..6bef4edc2db 100644 --- a/addons/mail/data/mail_demo.xml +++ b/addons/mail/data/mail_demo.xml @@ -7,6 +7,38 @@ none + + + Hello Demo User! I was wondering whether you had some issues with our secret task about putting cats everywhere in OpenERP. + comment + + + + + + No specific issues, I think everything is clear. + + comment + + + + + Ow, just to be sure... we were talking about lolcats, right ? + + comment + + + + + Absolutely! + + comment + + + + + + mail.group @@ -51,39 +83,6 @@ This month you also get 250 EUR of eco-vouchers if you have been in the company - - - Hello Demo User! I was wondering whether you had some issues with our secret task about putting cats everywhere in OpenERP. - comment - - - - - - No specific issues, I think everything is clear. - - comment - - - - - - Ow, just to be sure... we were talking about lolcats, right ? - - comment - - - - - - Absolutely! - - comment - - - - - Plan to install OpenERP @@ -96,8 +95,10 @@ This month you also get 250 EUR of eco-vouchers if you have been in the company Sophie
    email + + 2012-11-12 9:13:32 ir.attachment @@ -117,9 +118,10 @@ This month you also get 250 EUR of eco-vouchers if you have been in the company comment - + - + + @@ -199,6 +201,7 @@ This month you also get 250 EUR of eco-vouchers if you have been in the company + 2012-11-12 10:53:32 mail.group @@ -216,31 +219,31 @@ This month you also get 250 EUR of eco-vouchers if you have been in the company - mail.group + res.partner + I changed the infrastructure of networks, if there are still changes to be made please do not hesitate to contact me. comment + + + 2012-11-12 9:49:32 + + + Thank you, the networks is perfect now ! Could you add a IP phone for Jhon ? + + comment + + 2012-11-12 10:09:32 - - mail.group - Thank you, the networks is perfect now ! Could you add a IP phone for Jhon ? + + It's right, his internal phone number is 0093 comment - - mail.group - It's right, his internal phone number is 0093 - - comment - - - - - From ac05be9f5823c32b76354b80b6e43c7df3010f44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Mon, 12 Nov 2012 18:09:29 +0100 Subject: [PATCH 021/122] [IMP] mail: removed CSS on p, because of paragraphes used in chatter messages leading to ugly chatter. bzr revid: tde@openerp.com-20121112170929-36xtb03v8khvtnyx --- addons/mail/static/src/css/mail.css | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/addons/mail/static/src/css/mail.css b/addons/mail/static/src/css/mail.css index 1f90c75632f..1bef563d6ff 100644 --- a/addons/mail/static/src/css/mail.css +++ b/addons/mail/static/src/css/mail.css @@ -87,6 +87,10 @@ margin-bottom: 0px; margin-top: 2px; } +.openerp .oe_mail .oe_msg .oe_msg_content .oe_msg_body p{ + margin-top: 0px; + margin-bottom: 0px; +} /* a) Indented Messages */ From 206b015f8b8249e53da8c83ec62ed2503c56cb59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Mon, 12 Nov 2012 18:09:56 +0100 Subject: [PATCH 022/122] [IMP] [DEMO] mail: Wip about demo data. No time enough today, will be continued asap. bzr revid: tde@openerp.com-20121112170956-o31nqximygax6is6 --- addons/mail/__openerp__.py | 5 +- addons/mail/data/mail_demo.xml | 55 ++++++++++---------- addons/mail/data/mail_group_data.xml | 17 +++---- addons/mail/data/mail_group_demo_data.xml | 62 +++++++++++++++++++++++ 4 files changed, 99 insertions(+), 40 deletions(-) create mode 100644 addons/mail/data/mail_group_demo_data.xml diff --git a/addons/mail/__openerp__.py b/addons/mail/__openerp__.py index 9ad3232d396..c535e3f7024 100644 --- a/addons/mail/__openerp__.py +++ b/addons/mail/__openerp__.py @@ -65,7 +65,10 @@ Main Features 'mail_alias_view.xml', 'res_users_view.xml', ], - 'demo': ['data/mail_demo.xml'], + 'demo': [ + 'data/mail_demo.xml', + 'data/mail_group_demo_data.xml', + ], 'installable': True, 'auto_install': False, 'application': True, diff --git a/addons/mail/data/mail_demo.xml b/addons/mail/data/mail_demo.xml index 6bef4edc2db..ef4487d3336 100644 --- a/addons/mail/data/mail_demo.xml +++ b/addons/mail/data/mail_demo.xml @@ -1,11 +1,15 @@ - + + - + none + + none + @@ -35,78 +39,75 @@ comment - - mail.group - Your monthly meal vouchers arrived. You can get them at Christine's office. -This month you also get 250 EUR of eco-vouchers if you have been in the company for more than a year. + Your monthly meal vouchers arrived. You can get them at Christine's office.

    ]]>
    comment +
    mail.group - + Oh, I had forgotten. This month you also get 250 EUR of eco-vouchers if you have been in the company for more than a year.

    ]]>
    comment +
    mail.group - Thanks, but where is Christine's office, if I may ask? (I'm new here) + Thanks! Could you please remind me where is Christine's office, if I may ask? I'm new here!

    ]]>
    comment +
    mail.group - Building B3, second floor on the right :-) + Building B3, second floor on the right :-).

    ]]>
    comment +
    mail.group - Great news, I need to buy a new fridge, I think I can pay it with the eco-vouchers! + Many thanks. Actually that's good news, next year I'll have to buy a new fridge, I think I will pay it with the eco-vouchers!

    ]]>
    comment +
    - - + + Plan to install OpenERP mail.message - - <![CDATA[Email0 inquiry]]> - <div><font size="2">Hello,</font></div><div><font size="2"><br></font></div> - <div><font size="2">I am interested in your company's product and I plan to install OpenERP for my company and affordable price.</font></div><br/> - <div><font size="2">Can you please send me services catalogue?</font></div><br/> - Sophie - + Hello +I am interested in your company's product and I plan to install OpenERP for my company and affordable price. +Can you please send me services catalogue? +Sophie]]> email - + virginie@agrolait.fr - 2012-11-12 9:13:32 - - ir.attachment + bWlncmF0aW9uIHRlc3Q= catalogue 2012.pdf catalogue 2012.pdf - + Re: Plan to install OpenERP Dear Customer,<br/> @@ -117,11 +118,9 @@ This month you also get 250 EUR of eco-vouchers if you have been in the company comment - + - - - + diff --git a/addons/mail/data/mail_group_data.xml b/addons/mail/data/mail_group_data.xml index 11d0ee7d04b..8d002e1ec64 100644 --- a/addons/mail/data/mail_group_data.xml +++ b/addons/mail/data/mail_group_data.xml @@ -1,15 +1,12 @@ - + + - - Sales - Discussion about best sales practices and deals. - Whole Company - Discussion about best sales practices and deals. + Discussion about the company. @@ -18,11 +15,9 @@ notification Welcome to OpenERP! - Your homepage is a summary of messages you received and key information about documents you follow. - -The top menu bar contains all applications you installed. You can use this <i>Settings</i> menu to install more applications, activate others features or give access to new users. - -To setup your preferences (name, email signature, avatar), click on the top right corner. + Your homepage is a summary of messages you received and key information about documents you follow.

    +

    The top menu bar contains all applications you installed. You can use this <i>Settings</i> menu to install more applications, activate others features or give access to new users.

    +

    To setup your preferences (name, email signature, avatar), click on the top right corner.

    ]]>
    diff --git a/addons/mail/data/mail_group_demo_data.xml b/addons/mail/data/mail_group_demo_data.xml new file mode 100644 index 00000000000..c81df963d50 --- /dev/null +++ b/addons/mail/data/mail_group_demo_data.xml @@ -0,0 +1,62 @@ + + + + + + + Best Sales Practices + Discussion about best sales practices and deals. + + + + Board meetings + Board meetings and agenda + + + + RD + Research and development discussion group + + + + Leasing + Leasing, cars and fuel cards + + + + Support + Support team + + + + mail.group + + MESSAGE UNREAD

    ]]>
    + comment + +
    + + mail.group + + MESSAGE UNREAD

    ]]>
    + comment + +
    + + mail.group + + MESSAGE UNREAD LIKED

    ]]>
    + comment + +
    + + mail.group + + MESSAGE UNREAD LIKES

    ]]>
    + comment + +
    +
    +
    + + From cf4d660ce5e38063c2d1a08ebd457779c9805afb Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Tue, 13 Nov 2012 11:58:50 +0100 Subject: [PATCH 023/122] [FIX] mail: do not destroy double message if there are no message.id (for expandable message) bzr revid: chm@openerp.com-20121113105850-ur1h9igelvk4uzcj --- addons/mail/data/mail_demo.xml | 113 +++++++++++++++++------------- addons/mail/static/src/js/mail.js | 2 +- 2 files changed, 64 insertions(+), 51 deletions(-) diff --git a/addons/mail/data/mail_demo.xml b/addons/mail/data/mail_demo.xml index ef4487d3336..b64b0356dbe 100644 --- a/addons/mail/data/mail_demo.xml +++ b/addons/mail/data/mail_demo.xml @@ -133,56 +133,69 @@ Sophie]]>
    ir.attachment - /9j/4AAQSkZJRgABAQEASABIAAD/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkz - ODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2Nj - Y2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wAARCABkAGQDAREA - AhEBAxEB/8QAGgAAAwEBAQEAAAAAAAAAAAAAAAQFAwIBBv/EAD0QAAEDAgMDCAcHAwUAAAAAAAEA - AgMEEQUSsiExchMzNDVBUXFzIjJhkbGzwRQVJGKBwtElg6FCUlPh8P/EABoBAQADAQEBAAAAAAAA - AAAAAAADBAUBAgb/xAAwEQACAQIDBgYBBAMBAAAAAAAAAQIDBBEyMwUSMUFx8BMhNFGx0cEUgZGh - I0LhNf/aAAwDAQACEQMRAD8A+55QFzgA4lpsbDttf6qqoN8D0e5z/sf7l3w5HMQz/kd7k8OQxOJX - SOheIgWyFpDXFtwDbYV1U5DETLcVFwySnDQLNuHOO/Zc227LBevDGJ1kxE2DpYiA6+xrgSMzT3dw - d7wm4xiZtZiwLS+andZrb+g4XdcZuzdbNb22TcGINbi4YbzU7nZTuY7a6+zs3Af5HtTwxidPbihe - MksDWAvuCxxJF/R7O7f4puDE8DcVLiXSwZc7TZrHXDRa43du33puDEoZ/wAjvcvHhyGIZ/yO9yeH - IYgx4e27d1yP1BsvLWDwZ0Uyh9VVB2W4y5Mx2XLf+h7lIm1FYHBSsldTcoMkBIaXNsHG/d2+Kb7X - mzkvJNoq0ji6khcd5YCfcplwBtddAXQBdAF0AXQBdAF0AXQCWI17qIR5YhIX3vd+WwFvYe9V69wq - LimscSalR8TF48DWm5t3mP1FcnmIkZfZYqmSflWkjlG7jbc0W+JUkEnHzB6cMpizKWOItl9Y7QvW - 5FjFoajYIo2xsFmtAA8F7OHSANqANqAEBnJPFE9jJJGtc82aCdpXUmzjkk8GabVw6Iy4i3NPFGwi - WJjnAuHom2z4leazdKm5ik41Km4FNVzS4Uahwj5UZ9wOW4cQNl/YvNtN1YRk+Z6uEqTaXIm108lR - SU8kuXOTKDlFhscB9FS2kt2pBL3+ixYycqcm++JYpubd5j9RVipmKyPafnKjzBpapafAM3Uhwxkq - oo6hkD3ESP8AVGU2O/t/Qrqi2sTy5pPd5my4eidh1RPNV1LJZM7WhrmjKBluXbPbuClqRUUsCClN - ybxGMQLhRvLXFpuNrTY7wvNNYy8z3VbUHgGHlzqGEucXEt2lxuSuTzM7T84oUxLpsHFF8wKSGRkN - TUR1RVM8mKVEMkmaNoJa3KBb0rb1mW9adSrOL4I0qtOMacWuLFH9Nq/Kk1BXLz0z6FK19QM0PUTv - GTW5Q2GlAsXuaXfInz9X0/FNrVfaerDr9Emz9KXfuXKbm3eY/UVNUzECFKwuEU+V7mEzja02PqBW - bdJ8SGu2o+Q5RFz6Gnc5xLnRNJPebLsuLPccqEq3rel4h8HKWOmyGWqipb2lQlgk4SL11XwR/F6n - q8EVqHGXfuOYgPwb9p3t1BR08xJWyMlGWRn2BrJHtb6FwDsN32P+FnXVWcbqME/Jl22hF27bXeA3 - iXTYOKP5gWpDIzOqaiOMP65quF2pY1prVOr+TVr6Ue+Ri/p1X5MmoLSvfTPoZ9r6jv3GaLqJ3jJr - cobDSgWL3NLvkT5+r6fim1qvtPVh1+iTZ+lLv3LlNzbvMfqKmqZiBClZzU3njQFatiC4yjdAB930 - 1/8Aib8AkuLJIZUJ1vW9LxD4OUsdNkMtVFOwUJYJWF2FbVlxsAyPb+r1NV4IrUMz79xyvymieQbg - lu2/5gvFLMiStkZIf61B/a+Ysq89bDv3L9r6Z98h3Eh+Ng4o/mBbEMjMypqI4w/rmq4XaljWmtU6 - v5NWvpR75GL+m1fkyagtK99M+hn2vqO/cYoR/QneMmtyhsNKBYvc0u+QhP1fT8U2tV9p6sOv0SbP - 0pd+5cpubd5j9RU1TMQIUrebm88aArVsQXGU8wOpfPA6ORrAIWta0gb9ltvuVW3ruvjJor2VxKvF - 4rgc4g9kWJ0z3uDWBzSSdw2OV1zjCk3J4ElWUYVE5PBFCCop6jNyMjH5bXt2KCFSM8rxLji0k2uJ - EADm14IBBbFsPG5c2l5W779iPZ+s+/cdYAMBi2D1W6gu2eSPQ9XnGXUSf61B/a+YqF562HfuWrX0 - z75DmJW+2wW3Zo/mBbEMjMypqI5w+33zU7rZTqWNaa1Tq/k1a+lHvkYv6bV93IyagtK99M+hn2vq - Biit9xO3XvJrKhsNKBYvc0u+QhP1fT8U2tV9p6sOv0SbP0pd+5cpubd5j9RU1TMQIUrObm88aArV - sQXGUTwGojhkkjeSHSloZs37CsmwqRWMHxZT2VSm6Mp4eWJ1j22UeDfqrd/6b9/wyLaeX+Pya4Hz - 1Tws/cqmzOEv2PpLz/UnzSvZUPY02bKGhwtvsSR8VLtWtJYUuWGP9/8ADGs60o3saa4PH4ZVZ1DH - wt1BXrPJHoXLzjLqThKyR9GGkkxuja7Z28oFmXNSM7yO6+H/AEmsqkZ20t3liv6KGJdNg4o/mBbc - MjKFTURxh/XNTwnUsa01qnV/JrV9KPfIxf02r8mTUFpXvpn0M619QMUR/oTvGTWVDYaUCxe5pd8h - Cfq+n4ptar7T1Ydfok2fpS79y5T827zH6ipqmYgQpWc1N540BWrYguMpJw3ptN5v7Svn7TXQ2R6G - XV/gcx7nR4D6rVv/AE37/hmdtPL/AB+TXA+eqeFn7lU2Zll+x9Jef6k2p6W3/wB2lNraq6flmBa/ - +jT6P4ZXZ1DHwt1Badllh0NK74y6/kkU/SGefHrCwo+qXUj2R6ap1fwijjZIeHNJa4NaQR2EOut2 - vOVO3lKPH/qKd7Jwi5R4pfk4wRznVz3OJc4xXJPacyy9ntynJs2HJytqbfsvgyqZhDWz5gTyjXsF - u8uH8K/tCtGFHcfFozaFaNO6jF82O0PUTvGTW5LDSgXr3NLvkT5+r6fim1qvtPVh1+iTZ+lLv3Ll - PzbvMfqKmnmIBarhmeJGxxhwdIHg5gP9IH0U1GoocSOrBzWCEKTDquCoikdE0hj8xs8dxH1WZQtn - TqKbYsYO3t3Slxbx+DfEqWqrHgshDdg3vHt/lXbnCtS3F74lW8tpV1hF9+Zph0FTSPlc+EHOGgAP - HZf+VBaUvAT3nxNWvVVTDAUlw6sknDxE0AdheEvaX6ialF8sDNo0JU7qNdvyWPw/sdEdQMNZTch6 - QAF847DdW7eapKKfItV/8jeHMRhw2sZK1xibYSNf647HA/RZytmqyqY+WOJ5sYu3ozhLi23/AChr - Eaeqqz6EAHogbXjvutCtJVKMqa4v7RXuqEqsWlz+znDqWqpJnSPhBuwNADx3qpa0fBbcnxL29/hh - T5pJfwjKqoKuecyNhaBmJ2vHaV7vYfqN3dfAofp5fqIVcfJPEbp4qmLDjTGAFxzbQ8drifqprZql - CMXyL1w/Fba5k/7srM7rxtyuJIHKbrlU61CdSrvuXljiQ2MZW7qObx3sMP7+y3A1zY/TFiXOda97 - XcT9Vbk8XiSDKsnAQAgBACAEAIAQAgBACAEAIAQAgBACAEAIAQAgBACAEAIAQAgBACAEAIAQAgBA - CAEAIAQAgP/Z + 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 + kxzLdwM111ZhJXPm0ixn3/rQxvK6Vd4vn//Z activity graph 2012.jpg activity graph 2012 diff --git a/addons/mail/static/src/js/mail.js b/addons/mail/static/src/js/mail.js index e214168cb25..a95ba1c14c8 100644 --- a/addons/mail/static/src/js/mail.js +++ b/addons/mail/static/src/js/mail.js @@ -1255,7 +1255,7 @@ openerp.mail = function (session) { // check if the message is already create for (var i in self.messages) { - if (self.messages[i] && self.messages[i].id == message.id) { + if (message.id && self.messages[i] && self.messages[i].id == message.id) { console.log('Reload message', message.id); self.messages[i].destroy(); } From 2414585a14ea749a96893d42b70f03a34dc38bf6 Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Tue, 13 Nov 2012 12:16:42 +0100 Subject: [PATCH 024/122] [IMP] mail: demo data bzr revid: chm@openerp.com-20121113111642-3ri3zbg07na1n3w9 --- addons/mail/data/mail_demo.xml | 44 ++++++++++++++++++---------------- 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/addons/mail/data/mail_demo.xml b/addons/mail/data/mail_demo.xml index b64b0356dbe..dcacf4f9fc5 100644 --- a/addons/mail/data/mail_demo.xml +++ b/addons/mail/data/mail_demo.xml @@ -93,14 +93,15 @@ Plan to install OpenERP mail.message - Hello -I am interested in your company's product and I plan to install OpenERP for my company and affordable price. -Can you please send me services catalogue? -Sophie]]> + Hello,
    +I am interested in your company's product and I plan to install OpenERP for my company and affordable price.
    +Can you please send me services catalogue?
    +Virginie

    ]]>
    email virginie@agrolait.fr +
    bWlncmF0aW9uIHRlc3Q= @@ -109,13 +110,13 @@ Sophie]]>
    Re: Plan to install OpenERP - - Dear Customer,<br/> - Thanks for showing interest in our products.<br/> - We have attached the catalogue,<br/> - We would like to know your interests, so let us know when we can call you for more details.<br/> + + Thanks for showing interest in our products.
    + We have attached the catalogue,
    + We would like to know your interests, so let us know when we can call you for more details.
    Regards -
    + ]]>
    comment @@ -202,30 +203,31 @@ Sophie]]>
    mail.group - - Hi,<br/> - The beta OpenERP 7 is scheduled for November 12.<br/> - You will find attached the document for migration from version 6 to 7, and the activity graph for the current year. Good reading.<br/> + + The beta OpenERP 7 is scheduled for November 12.
    + You will find attached the document for migration from version 6 to 7, and the activity graph for the current year. Good reading.
    Sincerely -
    + ]]>
    comment - + 2012-11-12 10:53:32
    mail.group - - Thank you,<br/> - Could you prepare and send us also the document for version 7.1 which will come soon?<br/> + + Could you prepare and send us also the document for version 7.1 which will come soon?
    Sincerely -
    + ]]>
    comment - + +
    From b8f7e37715f4c72d968ad2196fc645aa7f5ae647 Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Tue, 13 Nov 2012 13:56:51 +0100 Subject: [PATCH 025/122] [FIX] mail: openchatter reload message_ids for form view bzr revid: chm@openerp.com-20121113125651-cq67yb0g5n66ej55 --- addons/mail/static/src/js/mail.js | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/addons/mail/static/src/js/mail.js b/addons/mail/static/src/js/mail.js index a95ba1c14c8..65f4a57473d 100644 --- a/addons/mail/static/src/js/mail.js +++ b/addons/mail/static/src/js/mail.js @@ -1530,7 +1530,6 @@ openerp.mail = function (session) { 'display_indented_thread': -1, 'show_reply_button': false, 'show_read_unread_button': false, - 'show_compose_message': this.view.is_action_enabled('edit'), 'show_compact_message': 1, }, this.node.params); @@ -1556,9 +1555,10 @@ openerp.mail = function (session) { return; } - this.node.params = _.extend({ - 'message_ids': this.getParent().fields.message_ids ? this.getParent().fields.message_ids.get_value() : undefined, - }, this.node.params); + this.node.params = _.extend(this.node.params, { + 'message_ids': this.get_value(), + 'show_compose_message': this.view.is_action_enabled('edit'), + }); this.node.context = { 'default_res_id': this.view.datarecord.id || false, 'default_model': this.view.model || false, @@ -1571,7 +1571,6 @@ openerp.mail = function (session) { // create and render Thread widget this.root = new mail.Widget(this, _.extend(this.node, { 'domain' : (this.domain || []).concat([['model', '=', this.view.model], ['res_id', '=', this.view.datarecord.id]]), - })); return this.root.replace(this.$('.oe_mail-placeholder')); From 0f3845bee6a7dfdac381c8e096d606a6f08f28bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Tue, 13 Nov 2012 15:27:59 +0100 Subject: [PATCH 026/122] [FIX] [CLEAN] mail.js: removed references to mail.thread. There shouldnot have been any of them left... bzr revid: tde@openerp.com-20121113142759-wwhd3bssent1861a --- addons/mail/static/src/js/mail.js | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/addons/mail/static/src/js/mail.js b/addons/mail/static/src/js/mail.js index f5d6941d96b..0d0cb9d0b31 100644 --- a/addons/mail/static/src/js/mail.js +++ b/addons/mail/static/src/js/mail.js @@ -1003,10 +1003,7 @@ openerp.mail = function (session) { init: function (parent, datasets, options) { this._super(parent, options); this.domain = options.domain || []; - this.context = _.extend({ - default_model: 'mail.thread', - default_res_id: 0, - default_parent_id: false }, options.context || {}); + this.context = _.extend(options.context || {}); this.options = options.options; this.options.root_thread = (options.options.root_thread != undefined ? options.options.root_thread : this); @@ -1031,7 +1028,7 @@ openerp.mail = function (session) { // object compose message this.compose_message = false; - this.ds_thread = new session.web.DataSetSearch(this, this.context.default_model || 'mail.thread'); + this.ds_thread = new session.web.DataSetSearch(this, this.context.default_model); this.ds_message = new session.web.DataSetSearch(this, 'mail.message'); }, From 0c16b8b4fa96e4c04be679babe71f2edca450cae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20van=20der=20Essen?= Date: Tue, 13 Nov 2012 15:29:20 +0100 Subject: [PATCH 027/122] [IMP] better image preview in attachments bzr revid: fva@openerp.com-20121113142920-hojjecoz6x2vxuz4 --- addons/mail/static/src/css/mail.css | 17 ++++++++++------- addons/mail/static/src/xml/mail.xml | 2 +- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/addons/mail/static/src/css/mail.css b/addons/mail/static/src/css/mail.css index 48b194cf08b..db53eef51d2 100644 --- a/addons/mail/static/src/css/mail.css +++ b/addons/mail/static/src/css/mail.css @@ -218,8 +218,8 @@ .openerp .oe_mail .oe_msg_attachment_list{ display: none; - margin-top: 12px; - margin-bottom: 12px; + margin-top: 4px; + margin-bottom: 4px; } .openerp .oe_mail .oe_msg_composer .oe_msg_attachment_list{ display: block; @@ -227,7 +227,7 @@ .openerp .oe_mail .oe_attachment{ display: inline-block; width: 100px; - margin: 2px; + margin: 4px 2px; min-height: 80px; position: relative; border-radius: 3px; @@ -240,7 +240,7 @@ padding: 1px 3px; margin-top: 50px; margin-bottom: 5px; - background: rgba(124, 123, 173, 0.13); + background: #F4F5FA; overflow: hidden; color: #4c4c4c; text-shadow: none; @@ -296,12 +296,13 @@ .openerp .oe_mail .oe_attachment.oe_preview .oe_name{ position: absolute; bottom: 0px; - margin: 0px; + margin: 3px; left: 0px; right: 0px; max-height: 64px; background: rgba(0,0,0,0.8); color: white; + border-radius: 1px; border-top-left-radius: 0px; border-top-right-radius: 0px; opacity: 0; @@ -330,9 +331,11 @@ position: relative; margin:0px; width: 100px; - height: 100px; - border-radius: 3px; + height: 80px; + border-radius: 1px; + border: solid 3px #FFF; margin-left: -50px; + box-shadow: 0px 3px 10px rgba(0, 0, 0, 0.19); } .openerp .oe_mail .oe_attachment .oe_delete{ display: none; diff --git a/addons/mail/static/src/xml/mail.xml b/addons/mail/static/src/xml/mail.xml index 2ba1733043a..7e394c8ccbb 100644 --- a/addons/mail/static/src/xml/mail.xml +++ b/addons/mail/static/src/xml/mail.xml @@ -84,7 +84,7 @@
    - +
    [
    From b00a0ab7117f65fc59e66a7779441d60ceb9873c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20van=20der=20Essen?= Date: Tue, 13 Nov 2012 15:54:53 +0100 Subject: [PATCH 028/122] [IMP] attachements are now always displayed bzr revid: fva@openerp.com-20121113145453-35v399hqgz201ndj --- addons/mail/static/src/css/mail.css | 1 - addons/mail/static/src/js/mail.js | 15 +-------------- addons/mail/static/src/xml/mail.xml | 7 ------- 3 files changed, 1 insertion(+), 22 deletions(-) diff --git a/addons/mail/static/src/css/mail.css b/addons/mail/static/src/css/mail.css index db53eef51d2..1056b54927c 100644 --- a/addons/mail/static/src/css/mail.css +++ b/addons/mail/static/src/css/mail.css @@ -217,7 +217,6 @@ /* --------------------- ATTACHMENTS --------------------- */ .openerp .oe_mail .oe_msg_attachment_list{ - display: none; margin-top: 4px; margin-bottom: 4px; } diff --git a/addons/mail/static/src/js/mail.js b/addons/mail/static/src/js/mail.js index 0d0cb9d0b31..e06e5fec4de 100644 --- a/addons/mail/static/src/js/mail.js +++ b/addons/mail/static/src/js/mail.js @@ -737,7 +737,7 @@ openerp.mail = function (session) { if(this.thread_level < this.options.display_indented_thread) { this.create_thread(); } - this.$('.oe_msg_attachments, .oe_msg_images').addClass("oe_hidden"); + this.display_attachments(); this.ds_notification = new session.web.DataSetSearch(this, 'mail.notification'); this.ds_message = new session.web.DataSetSearch(this, 'mail.message'); @@ -755,8 +755,6 @@ openerp.mail = function (session) { this.$('.oe_reply').on('click', this.on_message_reply); this.$('.oe_star').on('click', this.on_star); this.$('.oe_msg_vote').on('click', this.on_vote); - this.$('.oe_view_attachments').on('click', this.on_view_attachments); - }, /* Call the on_compose_message on the thread of this message. */ @@ -815,17 +813,6 @@ openerp.mail = function (session) { } }, - /* Call the on_compose_message on the thread of this message. */ - on_view_attachments:function (event) { - event.stopPropagation(); - var self = this; - if (!this.toggle_attachment) { - self.display_attachments(); - this.toggle_attachment = true; - } - this.$('.oe_msg_attachment_list').toggle(200); - }, - /** * Wait a confirmation for delete the message on the DB. * Make an animate destroy diff --git a/addons/mail/static/src/xml/mail.xml b/addons/mail/static/src/xml/mail.xml index 7e394c8ccbb..ab371dfd358 100644 --- a/addons/mail/static/src/xml/mail.xml +++ b/addons/mail/static/src/xml/mail.xml @@ -217,13 +217,6 @@ - - - - 1 Attachment - Attachments - -
    From 5e4c4fe06e01f419c488e7a9cec0d6f0081b4063 Mon Sep 17 00:00:00 2001 From: Olivier Dony Date: Tue, 13 Nov 2012 17:44:35 +0100 Subject: [PATCH 029/122] [IMP] portal,portal_sale: polish/cleanup acquirer settings bzr revid: odo@openerp.com-20121113164435-ids77maq6h13crob --- addons/portal/acquirer.py | 3 +-- addons/portal/acquirer_view.xml | 4 +--- addons/portal_sale/res_config.py | 6 +++--- addons/portal_sale/res_config_view.xml | 2 ++ 4 files changed, 7 insertions(+), 8 deletions(-) diff --git a/addons/portal/acquirer.py b/addons/portal/acquirer.py index 3217b49d846..1361d627105 100644 --- a/addons/portal/acquirer.py +++ b/addons/portal/acquirer.py @@ -23,7 +23,6 @@ import logging from urllib import quote as quote from openerp.osv import osv, fields -from openerp.tools import ustr from openerp.tools.translate import _ from openerp.tools import float_repr @@ -41,7 +40,7 @@ class acquirer(osv.Model): _columns = { 'name': fields.char('Name', required=True), 'form_template': fields.text('Payment form template (HTML)', translate=True, required=True), - 'visible': fields.boolean('Visible', help="Whether this payment acquirer is currently displayed in portal forms"), + 'visible': fields.boolean('Visible', help="Make this payment acquirer available in portal forms (Customer invoices, etc.)"), } _default = { diff --git a/addons/portal/acquirer_view.xml b/addons/portal/acquirer_view.xml index 0e88d47f758..f9be9963711 100644 --- a/addons/portal/acquirer_view.xml +++ b/addons/portal/acquirer_view.xml @@ -54,14 +54,12 @@ + Payment Acquirers portal.payment.acquirer - - - diff --git a/addons/portal_sale/res_config.py b/addons/portal_sale/res_config.py index 09382c98d53..d96a63f173e 100644 --- a/addons/portal_sale/res_config.py +++ b/addons/portal_sale/res_config.py @@ -25,8 +25,8 @@ class sale_portal_config_settings(osv.TransientModel): _inherit = 'account.config.settings' _columns = { - 'group_payment_options': fields.boolean('Show payment buttons', + 'group_payment_options': fields.boolean('Show payment buttons to employees too', implied_group='portal_sale.group_payment_options', - help="Show online payment options to all employees on Sale Orders and Customer Invoices. " - "If not enabled, these options will only be visible to portal users"), + help="Show online payment options on Sale Orders and Customer Invoices to employees. " + "If not checked, these options are only visible to portal users."), } \ No newline at end of file diff --git a/addons/portal_sale/res_config_view.xml b/addons/portal_sale/res_config_view.xml index 50664a43d36..ce33a1a1a72 100644 --- a/addons/portal_sale/res_config_view.xml +++ b/addons/portal_sale/res_config_view.xml @@ -11,6 +11,8 @@
    From 62b376307b0607ca90674b1847ecdbfb658b59e4 Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Wed, 14 Nov 2012 09:26:59 +0100 Subject: [PATCH 030/122] [IMP] mail: change the counter of the need action menu when a message is read. Actually reload all the widget menu but we can upgrade and change the number only (less request) bzr revid: chm@openerp.com-20121114082659-31vxgq5synhdpobl --- addons/mail/static/src/js/mail.js | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/addons/mail/static/src/js/mail.js b/addons/mail/static/src/js/mail.js index e06e5fec4de..485b382d7c1 100644 --- a/addons/mail/static/src/js/mail.js +++ b/addons/mail/static/src/js/mail.js @@ -849,8 +849,8 @@ openerp.mail = function (session) { msg.renderElement(); msg.start(); } - if( self.options.root_thread.__parentedParent.__parentedParent.get_menu_emails ) { - self.options.root_thread.__parentedParent.__parentedParent.get_menu_emails().do_reload(); + if( self.options.root_thread.__parentedParent.__parentedParent.do_reload_menu_emails ) { + self.options.root_thread.__parentedParent.__parentedParent.do_reload_menu_emails(); } }); @@ -1623,14 +1623,17 @@ openerp.mail = function (session) { * crete an object "related_menu" * contain the menu widget and the the sub menu related of this wall */ - get_menu_emails: function () { - var self = this; - if (!this.related_menu) { - var menu = this.__parentedParent.__parentedParent.menu; - var sub_menu = _.filter(menu.data.data.children, function (val) {return val.id == 100;})[0]; - this.related_menu = menu; - } - return this.related_menu; + do_reload_menu_emails: function () { + var menu = this.__parentedParent.__parentedParent.menu; + return this.rpc("/web/menu/load", {'menu_id': 100}).done(function(r) { + _.each(menu.data.data.children, function (val) { + if (val.id == 100) { + val.children = _.find(r.data.children, function (r_val) {return r_val.id == 100;}).children; + } + }); + var r = menu.data; + menu.menu_loaded(r); + }); }, /** From 4a91e273a8c0ead6ca39255724b74b06e730eade Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Wed, 14 Nov 2012 11:47:17 +0100 Subject: [PATCH 031/122] [IMP] mail: unactivate reload menu bzr revid: chm@openerp.com-20121114104717-zi5yl3knyhf7xgev --- addons/mail/static/src/js/mail.js | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/addons/mail/static/src/js/mail.js b/addons/mail/static/src/js/mail.js index 485b382d7c1..39d843b7e70 100644 --- a/addons/mail/static/src/js/mail.js +++ b/addons/mail/static/src/js/mail.js @@ -1625,15 +1625,15 @@ openerp.mail = function (session) { */ do_reload_menu_emails: function () { var menu = this.__parentedParent.__parentedParent.menu; - return this.rpc("/web/menu/load", {'menu_id': 100}).done(function(r) { - _.each(menu.data.data.children, function (val) { - if (val.id == 100) { - val.children = _.find(r.data.children, function (r_val) {return r_val.id == 100;}).children; - } - }); - var r = menu.data; - menu.menu_loaded(r); - }); + // return this.rpc("/web/menu/load", {'menu_id': 100}).done(function(r) { + // _.each(menu.data.data.children, function (val) { + // if (val.id == 100) { + // val.children = _.find(r.data.children, function (r_val) {return r_val.id == 100;}).children; + // } + // }); + // var r = menu.data; + // menu.menu_loaded(r); + // }); }, /** From 758115c1a56a83d804b71e583073403decdc4ee4 Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Wed, 14 Nov 2012 11:47:21 +0100 Subject: [PATCH 032/122] [IMP] mail: add date on messages for the datademo bzr revid: chm@openerp.com-20121114104721-8b5ajc21ii7cp8a2 --- addons/mail/data/mail_demo.xml | 55 ++++++++++++++++++++-------------- 1 file changed, 33 insertions(+), 22 deletions(-) diff --git a/addons/mail/data/mail_demo.xml b/addons/mail/data/mail_demo.xml index dcacf4f9fc5..988c2cbdae1 100644 --- a/addons/mail/data/mail_demo.xml +++ b/addons/mail/data/mail_demo.xml @@ -49,6 +49,7 @@ comment + mail.group @@ -58,6 +59,7 @@ comment + mail.group @@ -67,6 +69,7 @@ comment + @@ -77,7 +80,8 @@ comment - + + mail.group @@ -87,29 +91,31 @@ comment + - Plan to install OpenERP + Plan to install servers mail.message Hello,
    -I am interested in your company's product and I plan to install OpenERP for my company and affordable price.
    +I am interested in your company's product and I plan to install 2 servers for my company.
    Can you please send me services catalogue?
    Virginie

    ]]>
    email virginie@agrolait.fr - + +
    - + - + ir.attachment bWlncmF0aW9uIHRlc3Q= migration.doc migration.doc - + ir.attachment /9j/4AAQSkZJRgABAQEASABIAAD/2wBDAAUDBAQEAwUEBAQFBQUGBwwIBwcHBw8LCwkMEQ8SEhEP @@ -201,38 +208,39 @@ Virginie

    ]]>
    activity graph 2012.jpg activity graph 2012
    - + mail.group - The beta OpenERP 7 is scheduled for November 12.
    - You will find attached the document for migration from version 6 to 7, and the activity graph for the current year. Good reading.
    + The next version of catalogue price list is scheduled for this next month.
    + You will find attached the catalogue and the activity graph for the current year. Good reading.
    Sincerely ]]>
    comment - + - 2012-11-12 10:53:32 +
    - + mail.group - Could you prepare and send us also the document for version 7.1 which will come soon?
    + Could you add the price list of us services into this document ?
    Sincerely ]]>
    comment - + +
    - + res.partner I changed the infrastructure of networks, if there are still changes to be made please do not hesitate to contact me. @@ -241,23 +249,26 @@ Virginie

    ]]>
    2012-11-12 9:49:32 +
    - + Thank you, the networks is perfect now ! Could you add a IP phone for Jhon ? - + comment 2012-11-12 10:09:32 + - + It's right, his internal phone number is 0093 - + comment + From da27871daeb6eab880a9123c44b5074569f9dc97 Mon Sep 17 00:00:00 2001 From: Olivier Dony Date: Wed, 14 Nov 2012 12:38:23 +0100 Subject: [PATCH 033/122] [IMP] sale,portal_sale: make action xids more explicit, for use in signup URLs as #action=action_xid bzr revid: odo@openerp.com-20121114113823-38i21sacrqlzk9id --- addons/portal_sale/portal_sale_view.xml | 8 ++++---- addons/sale/sale_view.xml | 12 ++++++------ 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/addons/portal_sale/portal_sale_view.xml b/addons/portal_sale/portal_sale_view.xml index 6e53f103b4f..d6c2f288205 100644 --- a/addons/portal_sale/portal_sale_view.xml +++ b/addons/portal_sale/portal_sale_view.xml @@ -29,7 +29,7 @@ Override the original action to set another help field and/or another context field, more suited for portal members --> - + Quotations ir.actions.act_window sale.order @@ -39,7 +39,7 @@ You don't have any quotation. - + Sale Orders ir.actions.act_window sale.order @@ -104,9 +104,9 @@ + action="action_quotations_portal" sequence="10"/> + action="action_orders_portal" sequence="20"/> - + Sale Orders ir.actions.act_window sale.order @@ -377,9 +377,9 @@

    - + - + Sales in Exception ir.actions.act_window sale.order @@ -390,7 +390,7 @@ - + Sales Order in Progress ir.actions.act_window sale.order @@ -401,7 +401,7 @@ - + Quotations ir.actions.act_window sale.order @@ -427,7 +427,7 @@ From b925d494b5a54543de75113ef33df4486e9d9133 Mon Sep 17 00:00:00 2001 From: Olivier Dony Date: Wed, 14 Nov 2012 13:06:22 +0100 Subject: [PATCH 034/122] [IMP] acquirer: improved acquirer view explanations bzr revid: odo@openerp.com-20121114120622-f3jr1chrt3snl42r --- addons/portal/acquirer_view.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/portal/acquirer_view.xml b/addons/portal/acquirer_view.xml index f9be9963711..a415a431ad2 100644 --- a/addons/portal/acquirer_view.xml +++ b/addons/portal/acquirer_view.xml @@ -14,8 +14,8 @@

    This is an HTML form template to submit a payment through this acquirer. - The template will be rendered through mako, so it may use normal mako expressions. - The mako evaluation context provides: + The template will be rendered with Mako, so it may use Mako expressions. + The Mako evaluation context provides:

    • reference: the reference number of the document to pay
    • kind: the kind of document on which the payment form is rendered (translated to user language, e.g. "Invoice")
    • From c97933935b972c64e4179cf3cf9dce1cae18ed49 Mon Sep 17 00:00:00 2001 From: Olivier Dony Date: Wed, 14 Nov 2012 13:07:42 +0100 Subject: [PATCH 035/122] [IMP] portal_sale: more accurate menu name in module description bzr revid: odo@openerp.com-20121114120742-j34vab3ubfi0jqty --- addons/portal_sale/__openerp__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/portal_sale/__openerp__.py b/addons/portal_sale/__openerp__.py index fd1d143d1e2..3ed124c0beb 100644 --- a/addons/portal_sale/__openerp__.py +++ b/addons/portal_sale/__openerp__.py @@ -41,7 +41,7 @@ via the following menus: If online payment acquirers are configured, portal users will also be given the opportunity to pay online on their Sale Orders and Invoices that are not paid yet. Paypal is included -by default, you simply need to configure a Paypal account in the Accounting settings. +by default, you simply need to configure a Paypal account in the Accounting/Invoicing settings. """, 'author': 'OpenERP SA', 'depends': ['sale_stock','portal'], From a43662d1254dba1333cdc74bf01a3c7dcef76de7 Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Wed, 14 Nov 2012 13:20:33 +0100 Subject: [PATCH 036/122] [IMP] mail: change the header title and description for each mailbox and group discussion bzr revid: chm@openerp.com-20121114122033-dl70fqty2kbd5gj1 --- addons/mail/data/mail_demo.xml | 3 +-- addons/mail/mail_group.py | 1 + addons/mail/mail_group_view.xml | 11 +++++++++++ addons/mail/static/src/js/mail.js | 2 +- addons/mail/static/src/xml/mail.xml | 8 +++++++- 5 files changed, 21 insertions(+), 4 deletions(-) diff --git a/addons/mail/data/mail_demo.xml b/addons/mail/data/mail_demo.xml index 988c2cbdae1..4866749cdae 100644 --- a/addons/mail/data/mail_demo.xml +++ b/addons/mail/data/mail_demo.xml @@ -80,7 +80,6 @@ comment - @@ -268,7 +267,7 @@ Virginie

      ]]>
      - + diff --git a/addons/mail/mail_group.py b/addons/mail/mail_group.py index d4c9c565bf3..448d11230ba 100644 --- a/addons/mail/mail_group.py +++ b/addons/mail/mail_group.py @@ -133,6 +133,7 @@ class mail_group(osv.Model): 'context': {'default_model': 'mail.group', 'default_res_id': mail_group_id}, 'res_model': 'mail.message', 'thread_level': 1, + 'header_description': vals['description'], } cobj = self.pool.get('ir.actions.client') newref = cobj.copy(cr, SUPERUSER_ID, ref[1], default={'params': str(params), 'name': vals['name']}, context=context) diff --git a/addons/mail/mail_group_view.xml b/addons/mail/mail_group_view.xml index 214f6edf571..3f931327114 100644 --- a/addons/mail/mail_group_view.xml +++ b/addons/mail/mail_group_view.xml @@ -6,6 +6,17 @@ Discussion Group mail.wall mail.message + { + 'search_default_message_unread': True + } + { + 'read_action': 'read' + } + +

      + No message in this group. +

      +
      diff --git a/addons/mail/static/src/js/mail.js b/addons/mail/static/src/js/mail.js index 39d843b7e70..6cd7c576781 100644 --- a/addons/mail/static/src/js/mail.js +++ b/addons/mail/static/src/js/mail.js @@ -1591,7 +1591,7 @@ openerp.mail = function (session) { this.action = _.clone(action); this.domain = this.action.params.domain || this.action.domain || []; - this.context = this.action.params.context || this.action.context || {}; + this.context = _.extend(this.action.params.context || {}, this.action.context || {}); this.defaults = {}; for (var key in this.context) { diff --git a/addons/mail/static/src/xml/mail.xml b/addons/mail/static/src/xml/mail.xml index ab371dfd358..2b9db8f195f 100644 --- a/addons/mail/static/src/xml/mail.xml +++ b/addons/mail/static/src/xml/mail.xml @@ -137,9 +137,15 @@

      - Email box +

      + +
      + + + +
      I am interested in your company's product and I plan to buy a new laptop having latest technologies and affordable price.
      Can you please send me product catalogue?
      + ]]>
      email @@ -557,12 +557,11 @@ Andrew
      crm.lead comment - Dear Customer, -Thanks for showing interest in our products. -We have attached the catalogue, -We would like to know your interests, so let us know when we can call you for more details. - -Regards + +Thanks for showing interest in our products.
      +We have attached the catalogue,
      +We would like to know your interests, so let us know when we can call you for more details.
      +Regards]]>
      @@ -572,7 +571,7 @@ Regards comment <div>Thanks for the information,</div><div>I will visit the store soon.</div> - + @@ -581,7 +580,7 @@ Regards comment <font color="#1f1f1f">Can you tell me if the store is open at 9:00 PM?</b></font> - + @@ -590,7 +589,10 @@ Regards Yes, its open till 10:00 PM, you are welcome! email + + + Inquiry diff --git a/addons/mail/data/mail_demo.xml b/addons/mail/data/mail_demo.xml index c7891efb51b..4ba223f6c45 100644 --- a/addons/mail/data/mail_demo.xml +++ b/addons/mail/data/mail_demo.xml @@ -70,7 +70,6 @@ - mail.group diff --git a/addons/mail/static/src/xml/mail.xml b/addons/mail/static/src/xml/mail.xml index 2b9db8f195f..deab58eca00 100644 --- a/addons/mail/static/src/xml/mail.xml +++ b/addons/mail/static/src/xml/mail.xml @@ -206,13 +206,11 @@
    -

    - +

    + +

    - - -

    From 7fc4f67e4ce95e5817f1a48e2ad1f2c4b0ec33e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Wed, 14 Nov 2012 14:43:56 +0100 Subject: [PATCH 039/122] [FIX] mail.group: fixed a description key not always present in mail.group creation. bzr revid: tde@openerp.com-20121114134356-5lbdx1tciw8tz2w0 --- addons/mail/mail_group.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/mail/mail_group.py b/addons/mail/mail_group.py index 448d11230ba..73e808daac3 100644 --- a/addons/mail/mail_group.py +++ b/addons/mail/mail_group.py @@ -133,7 +133,7 @@ class mail_group(osv.Model): 'context': {'default_model': 'mail.group', 'default_res_id': mail_group_id}, 'res_model': 'mail.message', 'thread_level': 1, - 'header_description': vals['description'], + 'header_description': vals.get('description'), } cobj = self.pool.get('ir.actions.client') newref = cobj.copy(cr, SUPERUSER_ID, ref[1], default={'params': str(params), 'name': vals['name']}, context=context) From 4011dd8760975bc55ca30ae1b4b68c210d7a3e7b Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Wed, 14 Nov 2012 15:19:36 +0100 Subject: [PATCH 040/122] [FIX] mail_follower: clear the subtype_list when reload (delete double value) bzr revid: chm@openerp.com-20121114141936-atyfapg9qia3avsc --- addons/crm/crm_lead_demo.xml | 9 +++++---- addons/mail/static/src/js/mail_followers.js | 1 + 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/addons/crm/crm_lead_demo.xml b/addons/crm/crm_lead_demo.xml index 26306edbaa6..5dde8f2ce3d 100644 --- a/addons/crm/crm_lead_demo.xml +++ b/addons/crm/crm_lead_demo.xml @@ -551,6 +551,7 @@ Andrew
    Hello,
    I am interested in your company's product and I plan to buy a new laptop having latest technologies and affordable price.
    Can you please send me product catalogue?
    ]]>
    email + Re: Plan to buy a Laptop @@ -563,7 +564,7 @@ We have attached the catalogue,
    We would like to know your interests, so let us know when we can call you for more details.
    Regards]]>
    - + Re: Plan to buy a Laptop @@ -572,7 +573,7 @@ Regards]]> comment <div>Thanks for the information,</div><div>I will visit the store soon.</div> - + Re: Plan to buy a Laptop @@ -581,7 +582,7 @@ Regards]]> comment <font color="#1f1f1f">Can you tell me if the store is open at 9:00 PM?</b></font> - + Re: Plan to buy a Laptop @@ -590,7 +591,7 @@ Regards]]> Yes, its open till 10:00 PM, you are welcome! email - + diff --git a/addons/mail/static/src/js/mail_followers.js b/addons/mail/static/src/js/mail_followers.js index 7bb019cde4f..d299b9eb6f6 100644 --- a/addons/mail/static/src/js/mail_followers.js +++ b/addons/mail/static/src/js/mail_followers.js @@ -194,6 +194,7 @@ openerp_mail_followers = function(session, mail) { display_subtypes:function (data) { var self = this; var subtype_list_ul = this.$('.oe_subtype_list'); + subtype_list_ul.empty(); var records = data[this.view.datarecord.id || this.view.dataset.ids[0]].message_subtype_data; _(records).each(function (record, record_name) { record.name = record_name; From 52349a7525af50f978691d389bd41d397bd69e53 Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Wed, 14 Nov 2012 16:00:47 +0100 Subject: [PATCH 041/122] [IMP] mail and crm: demodata for search (has attachment) and expandable bzr revid: chm@openerp.com-20121114150047-f2d30euntwjurnt4 --- addons/mail/data/mail_demo.xml | 97 +++++++++++++++++++++-- addons/mail/data/mail_group_demo_data.xml | 29 ------- 2 files changed, 91 insertions(+), 35 deletions(-) diff --git a/addons/mail/data/mail_demo.xml b/addons/mail/data/mail_demo.xml index 4ba223f6c45..08cf45bffd4 100644 --- a/addons/mail/data/mail_demo.xml +++ b/addons/mail/data/mail_demo.xml @@ -10,8 +10,86 @@ none + + + bWlncmF0aW9uIHRlc3Q= + my_attachment.xls + my_attachment.xls + + + mail.thread + Comment with attachment + Demo data with attachment and others messages + comment + + + + + + + mail.thread + MESSAGE

    ]]>
    + comment + + + + +
    + + mail.thread + MESSAGE

    ]]>
    + comment + + + + +
    + + mail.thread + MESSAGE

    ]]>
    + comment + + + + +
    + + mail.thread + MESSAGE

    ]]>
    + comment + + + + +
    + + bWlncmF0aW9uIHRlc3Q= + my_other_attachment.ai + my_other_attachment.ai + + + mail.thread + MESSAGE

    ]]>
    + comment + + + + + +
    + + mail.thread + MESSAGE

    ]]>
    + comment + + + + +
    + + mail.thread Hello Demo User! I was wondering whether you had some issues with our secret task about putting cats everywhere in OpenERP. comment @@ -19,6 +97,7 @@ + mail.thread No specific issues, I think everything is clear. comment @@ -26,6 +105,7 @@ + mail.thread Ow, just to be sure... we were talking about lolcats, right ? comment @@ -93,12 +173,13 @@ + mail.thread Plan to install servers - mail.message Hello,
    -I am interested in your company's product and I plan to install 2 servers for my company.
    -Can you please send me services catalogue?
    -Virginie

    ]]>
    + I am interested in your company's product and I plan to install 2 servers for my company.
    + Can you please send me services catalogue?
    + Virginie

    + ]]>
    email virginie@agrolait.fr @@ -106,10 +187,12 @@ Virginie

    ]]>
    + + From b581043859bc402e778d1426233154906584f834 Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Wed, 14 Nov 2012 16:53:25 +0100 Subject: [PATCH 044/122] [FIX] mail: expandable insert after bzr revid: chm@openerp.com-20121114155325-kuqyke9hcfmb0yyb --- addons/mail/static/src/js/mail.js | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/addons/mail/static/src/js/mail.js b/addons/mail/static/src/js/mail.js index fb0634a606d..006f9529272 100644 --- a/addons/mail/static/src/js/mail.js +++ b/addons/mail/static/src/js/mail.js @@ -599,10 +599,10 @@ openerp.mail = function (session) { this.parent_thread.context ]).done(function (record) { var thread = self.parent_thread; - if (self.options.display_indented_thread < self.thread_level && thread.parent_message) { - var hread = thread.parent_message.parent_thread; - } var root = thread == self.options.root_thread; + if (self.options.display_indented_thread < self.thread_level && thread.parent_message) { + var thread = thread.parent_message.parent_thread; + } // create object and attach to the thread object thread.message_fetch([['id', 'child_of', [self.id]]], false, [record], function (arg, data) { var message = thread.create_message_object( data[0] ); @@ -1268,10 +1268,9 @@ openerp.mail = function (session) { this.$('.oe_view_nocontent').remove(); - if (dom_insert_after) { message.insertAfter(dom_insert_after); - }if (prepend) { + } else if (prepend) { message.prependTo(self.$el); } else { message.appendTo(self.$el); From 3c8f8915b227fc4f7e8fa519d7240941c4029f23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Wed, 14 Nov 2012 16:58:10 +0100 Subject: [PATCH 045/122] [FIX] mail: expandables: expandable was placed at a wrong place in the message list. bzr revid: tde@openerp.com-20121114155810-q284caaual2sk8ka --- addons/mail/mail_message.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/addons/mail/mail_message.py b/addons/mail/mail_message.py index 9fd476d9d7f..e7288a46853 100644 --- a/addons/mail/mail_message.py +++ b/addons/mail/mail_message.py @@ -377,7 +377,9 @@ class mail_message(osv.Model): id_max = child_id elif nb > 0: exp_domain = [('id', '>=', id_min), ('id', '<=', id_max), ('id', 'child_of', message_id)] - messages.append(_get_expandable(exp_domain, nb, message_id, False)) + idx = [msg.get('id') for msg in messages].index(child_id) + 1 + # messages.append(_get_expandable(exp_domain, nb, message_id, False)) + messages.insert(idx, _get_expandable(exp_domain, nb, message_id, False)) id_min, id_max, nb = max(child_ids), 0, 0 else: id_min, id_max, nb = max(child_ids), 0, 0 From b387836284c86d1e976487a7638d2a821459614e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Wed, 14 Nov 2012 17:30:07 +0100 Subject: [PATCH 046/122] [IMP] mail.group: updating the descrpition, also update the description in the params of the client action related to the mail group. bzr revid: tde@openerp.com-20121114163007-91z50xmkepnc436l --- addons/mail/mail_group.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/addons/mail/mail_group.py b/addons/mail/mail_group.py index 73e808daac3..c589b54d4f9 100644 --- a/addons/mail/mail_group.py +++ b/addons/mail/mail_group.py @@ -114,7 +114,7 @@ class mail_group(osv.Model): alias_id = mail_alias.create_unique_alias(cr, uid, # Using '+' allows using subaddressing for those who don't # have a catchall domain setup. - {'alias_name': "group+"+vals['name']}, + {'alias_name': "group+" + vals['name']}, model_name=self._name, context=context) vals['alias_id'] = alias_id @@ -161,6 +161,13 @@ class mail_group(osv.Model): result = super(mail_group, self).write(cr, uid, ids, vals, context=context) if vals.get('group_ids'): self._subscribe_users(cr, uid, ids, context=context) + # if description is changed: update client action + if vals.get('description'): + cobj = self.pool.get('ir.actions.client') + for action in [group.action for group in self.browse(cr, SUPERUSER_ID, ids, context=context) if group.action]: + new_params = action.params + new_params['header_description'] = vals.get('description') + cobj.write(cr, SUPERUSER_ID, [action.id], {'params': str(new_params)}, context=context) return result def action_follow(self, cr, uid, ids, context=None): From 3f655858d89b6910c24fa3dbc8a85adcc20a8046 Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Thu, 15 Nov 2012 11:05:42 +0100 Subject: [PATCH 047/122] [IMP] mail: the placeholder of textarea on compose message can be custom with an attribute placeholder on the field bzr revid: chm@openerp.com-20121115100542-7gigxjnxjloqt8ue --- addons/mail/static/src/js/mail.js | 7 ++++++- addons/mail/static/src/xml/mail.xml | 13 ++++++++++--- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/addons/mail/static/src/js/mail.js b/addons/mail/static/src/js/mail.js index 006f9529272..7d874a8d1fe 100644 --- a/addons/mail/static/src/js/mail.js +++ b/addons/mail/static/src/js/mail.js @@ -1231,6 +1231,7 @@ openerp.mail = function (session) { 'default_parent_id': self.id, }}); } else { + data.record_name= (data.record_name != '' && data.record_name) || (self.parent_message && self.parent_message.record_name); var message = new mail.ThreadMessage(self, data, {'context':{ 'default_model': data.model, 'default_res_id': data.res_id, @@ -1447,6 +1448,7 @@ openerp.mail = function (session) { 'show_record_name' : false, 'show_compose_message' : false, 'show_compact_message' : false, + 'compose_placeholder': false, 'view_inbox': false, 'message_ids': undefined, }, this.action.params); @@ -1511,7 +1513,6 @@ openerp.mail = function (session) { init: function (parent, node) { this._super.apply(this, arguments); this.node = _.clone(node); - this.node.params = _.extend({ 'display_indented_thread': -1, 'show_reply_button': false, @@ -1520,6 +1521,10 @@ openerp.mail = function (session) { 'show_compact_message': 1, }, this.node.params); + if (this.node.attrs.placeholder) { + this.node.params.compose_placeholder = this.node.attrs.placeholder; + } + this.domain = this.node.params && this.node.params.domain || []; }, diff --git a/addons/mail/static/src/xml/mail.xml b/addons/mail/static/src/xml/mail.xml index deab58eca00..f4518dc6fa7 100644 --- a/addons/mail/static/src/xml/mail.xml +++ b/addons/mail/static/src/xml/mail.xml @@ -39,8 +39,9 @@
    -