From 19de91d4b9da23bf27b44b45bca814a5e1ad5405 Mon Sep 17 00:00:00 2001 From: "Mayur Maheshwari (OpenERP)" Date: Wed, 15 Feb 2012 17:33:31 +0530 Subject: [PATCH 001/236] [FIX]purchase: removed wait ad wait_auth which unnecessary lp bug: https://launchpad.net/bugs/932059 fixed bzr revid: mma@tinyerp.com-20120215120331-7uc0ybsv90oayfw2 --- addons/purchase/purchase.py | 1 - addons/purchase/purchase_view.xml | 3 +-- addons/purchase_requisition/purchase_requisition.py | 2 +- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/addons/purchase/purchase.py b/addons/purchase/purchase.py index 5432067191d..b7c757c7468 100644 --- a/addons/purchase/purchase.py +++ b/addons/purchase/purchase.py @@ -143,7 +143,6 @@ class purchase_order(osv.osv): STATE_SELECTION = [ ('draft', 'Request for Quotation'), - ('wait', 'Waiting'), ('confirmed', 'Waiting Approval'), ('approved', 'Approved'), ('except_picking', 'Shipping Exception'), diff --git a/addons/purchase/purchase_view.xml b/addons/purchase/purchase_view.xml index ec53ae76a7a..c72c985d8fa 100644 --- a/addons/purchase/purchase_view.xml +++ b/addons/purchase/purchase_view.xml @@ -196,13 +196,12 @@ - - - - + + + + ''')).getroot() @@ -104,15 +105,15 @@ class test_view_validation(unittest2.TestCase): assert not valid_att_in_field(invalid_form) assert valid_att_in_field(valid_form) - assert not valid_field_view(invalid_form) - assert valid_field_view(valid_form) + assert not valid_view(invalid_form) + assert valid_view(valid_form) def test_all_label_validation(self): assert not valid_att_in_label(invalid_form) assert valid_att_in_label(valid_form) - assert not valid_label_view(invalid_form) - assert valid_label_view(valid_form) + assert not valid_view(invalid_form) + assert valid_view(valid_form) def test_form_string_validation(self): assert not valid_att_in_form(invalid_form) @@ -153,15 +154,15 @@ class test_view_validation(unittest2.TestCase): assert not valid_type_in_colspan(invalid_form) assert valid_type_in_colspan(valid_form) - assert not valid_colspan_view(invalid_form) - assert valid_colspan_view(valid_form) + assert not valid_view(invalid_form) + assert valid_view(valid_form) def test_col_datatype_validation(self): assert not valid_type_in_col(invalid_form) assert valid_type_in_col(valid_form) - assert not valid_col_view(invalid_form) - assert valid_col_view(valid_form) + assert not valid_view(invalid_form) + assert valid_view(valid_form) if __name__ == '__main__': diff --git a/openerp/tools/view_validation.py b/openerp/tools/view_validation.py index 4bb47c54551..820d6ae96e5 100644 --- a/openerp/tools/view_validation.py +++ b/openerp/tools/view_validation.py @@ -42,41 +42,17 @@ def valid_type_in_col(arch): return False return True -def valid_colspan_view(arch): - for pred in [valid_type_in_colspan]: - if not pred(arch): - return False - return True - -def valid_col_view(arch): - for pred in [valid_type_in_col]: - if not pred(arch): - return False - return True - -def valid_field_view(arch): - for pred in [valid_att_in_field]: - if not pred(arch): - return False - return True - -def valid_label_view(arch): - for pred in [valid_att_in_label]: - if not pred(arch): - return False - return True - def valid_view(arch): if arch.tag == 'form': - for pred in [valid_page_in_book,valid_att_in_form]: + for pred in [valid_page_in_book,valid_att_in_form,valid_type_in_colspan,valid_type_in_col,valid_att_in_field,valid_att_in_label]: if not pred(arch): return False elif arch.tag == 'graph': - for pred in [valid_field_in_graph]: + for pred in [valid_field_in_graph,valid_type_in_colspan,valid_type_in_col,valid_att_in_field,valid_att_in_label]: if not pred(arch): return False elif arch.tag == 'tree': - for pred in [valid_field_in_tree]: + for pred in [valid_field_in_tree,valid_type_in_colspan,valid_type_in_col,valid_att_in_field,valid_att_in_label]: if not pred(arch): return False return True From b00e6af86c1dba10b94533be94fc4f15759b64ae Mon Sep 17 00:00:00 2001 From: Vo Minh Thu Date: Mon, 6 Aug 2012 11:10:08 +0200 Subject: [PATCH 026/236] [FIX] xml validation: removed duplicated tests. bzr revid: vmt@openerp.com-20120806091008-b4ve91aholkm67l4 --- openerp/tests/test_view_validation.py | 36 +++++++-------------------- 1 file changed, 9 insertions(+), 27 deletions(-) diff --git a/openerp/tests/test_view_validation.py b/openerp/tests/test_view_validation.py index e5050ead517..548c652c7a6 100644 --- a/openerp/tests/test_view_validation.py +++ b/openerp/tests/test_view_validation.py @@ -98,71 +98,53 @@ class test_view_validation(unittest2.TestCase): assert not valid_page_in_book(invalid_form) assert valid_page_in_book(valid_form) - assert not valid_view(invalid_form) - assert valid_view(valid_form) - def test_all_field_validation(self): assert not valid_att_in_field(invalid_form) assert valid_att_in_field(valid_form) - assert not valid_view(invalid_form) - assert valid_view(valid_form) - def test_all_label_validation(self): assert not valid_att_in_label(invalid_form) assert valid_att_in_label(valid_form) - - assert not valid_view(invalid_form) - assert valid_view(valid_form) def test_form_string_validation(self): assert not valid_att_in_form(invalid_form) assert valid_att_in_form(valid_form) - assert not valid_view(invalid_form) - assert valid_view(valid_form) - def test_graph_field_validation(self): assert not valid_field_in_graph(invalid_graph) assert valid_field_in_graph(valid_graph) - - assert not valid_view(invalid_graph) - assert valid_view(valid_graph) def test_graph_string_validation(self): assert not valid_field_in_graph(invalid_graph) assert valid_field_in_graph(valid_graph) - - assert not valid_view(invalid_graph) - assert valid_view(valid_graph) def test_tree_field_validation(self): assert not valid_field_in_tree(invalid_tree) assert valid_field_in_tree(valid_tree) - assert not valid_view(invalid_tree) - assert valid_view(valid_tree) - def test_tree_string_validation(self): assert not valid_field_in_tree(invalid_tree) assert valid_field_in_tree(valid_tree) - - assert not valid_view(invalid_tree) - assert valid_view(valid_tree) def test_colspan_datatype_validation(self): assert not valid_type_in_colspan(invalid_form) assert valid_type_in_colspan(valid_form) - - assert not valid_view(invalid_form) - assert valid_view(valid_form) def test_col_datatype_validation(self): assert not valid_type_in_col(invalid_form) assert valid_type_in_col(valid_form) + def test_form_view(self): assert not valid_view(invalid_form) assert valid_view(valid_form) + + def test_tree_view(self): + assert not valid_view(invalid_tree) + assert valid_view(valid_tree) + + def test_graph_view(self): + assert not valid_view(invalid_graph) + assert valid_view(valid_graph) if __name__ == '__main__': From 4a8668589aa787e552ae8f15d4bf13a828f81f1a Mon Sep 17 00:00:00 2001 From: Vo Minh Thu Date: Mon, 6 Aug 2012 11:11:44 +0200 Subject: [PATCH 027/236] [IMP] xml validation: white spaces. bzr revid: vmt@openerp.com-20120806091144-t5jjnbnyqu6sk8wf --- openerp/tests/test_view_validation.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/openerp/tests/test_view_validation.py b/openerp/tests/test_view_validation.py index 548c652c7a6..4e28bf4d482 100644 --- a/openerp/tests/test_view_validation.py +++ b/openerp/tests/test_view_validation.py @@ -9,7 +9,7 @@ import openerp from openerp.tools.view_validation import * invalid_form = etree.parse(StringIO('''\ -
+
@@ -97,7 +97,7 @@ class test_view_validation(unittest2.TestCase): def test_page_validation(self): assert not valid_page_in_book(invalid_form) assert valid_page_in_book(valid_form) - + def test_all_field_validation(self): assert not valid_att_in_field(invalid_form) assert valid_att_in_field(valid_form) @@ -105,7 +105,7 @@ class test_view_validation(unittest2.TestCase): def test_all_label_validation(self): assert not valid_att_in_label(invalid_form) assert valid_att_in_label(valid_form) - + def test_form_string_validation(self): assert not valid_att_in_form(invalid_form) assert valid_att_in_form(valid_form) @@ -117,7 +117,7 @@ class test_view_validation(unittest2.TestCase): def test_graph_string_validation(self): assert not valid_field_in_graph(invalid_graph) assert valid_field_in_graph(valid_graph) - + def test_tree_field_validation(self): assert not valid_field_in_tree(invalid_tree) assert valid_field_in_tree(valid_tree) @@ -125,19 +125,19 @@ class test_view_validation(unittest2.TestCase): def test_tree_string_validation(self): assert not valid_field_in_tree(invalid_tree) assert valid_field_in_tree(valid_tree) - + def test_colspan_datatype_validation(self): assert not valid_type_in_colspan(invalid_form) assert valid_type_in_colspan(valid_form) - + def test_col_datatype_validation(self): assert not valid_type_in_col(invalid_form) assert valid_type_in_col(valid_form) - + def test_form_view(self): assert not valid_view(invalid_form) assert valid_view(valid_form) - + def test_tree_view(self): assert not valid_view(invalid_tree) assert valid_view(valid_tree) From be06e66caadd54fad0dfc41abcefc79722e5e7be Mon Sep 17 00:00:00 2001 From: Vo Minh Thu Date: Mon, 6 Aug 2012 11:18:52 +0200 Subject: [PATCH 028/236] [IMP] xml validation: added logging for invalid input. bzr revid: vmt@openerp.com-20120806091852-yftb14cw1mrvc3hu --- openerp/tools/view_validation.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/openerp/tools/view_validation.py b/openerp/tools/view_validation.py index b9fef105579..f6f26840c64 100644 --- a/openerp/tools/view_validation.py +++ b/openerp/tools/view_validation.py @@ -1,5 +1,9 @@ """ View validation code (using assertions, not the RNG schema). """ +import logging + +_logger = logging.getLogger(__name__) + def valid_page_in_book(arch): """A `page` node must be below a `book` node.""" @@ -56,15 +60,18 @@ def valid_view(arch): for pred in [valid_page_in_book,valid_att_in_form,valid_type_in_colspan,\ valid_type_in_col,valid_att_in_field,valid_att_in_label]: if not pred(arch): + _logger.error('Invalid XML: %s', pred.__doc__) return False elif arch.tag == 'graph': for pred in [valid_field_in_graph,valid_type_in_colspan,valid_type_in_col,\ valid_att_in_field,valid_att_in_label]: if not pred(arch): + _logger.error('Invalid XML: %s', pred.__doc__) return False elif arch.tag == 'tree': for pred in [valid_field_in_tree,valid_type_in_colspan,valid_type_in_col,\ valid_att_in_field,valid_att_in_label]: if not pred(arch): + _logger.error('Invalid XML: %s', pred.__doc__) return False return True From 3614cc9aaa8693e79037a74788a371a45868c792 Mon Sep 17 00:00:00 2001 From: Jigar Amin - OpenERP Date: Mon, 6 Aug 2012 15:28:54 +0530 Subject: [PATCH 029/236] [FIX] fixed the predicated for tree view must have string and field and button attrib only bzr revid: jam@tinyerp.com-20120806095854-6vwpgzjqtc0qwn5b --- openerp/tools/view_validation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openerp/tools/view_validation.py b/openerp/tools/view_validation.py index f6f26840c64..09155ae3624 100644 --- a/openerp/tools/view_validation.py +++ b/openerp/tools/view_validation.py @@ -17,7 +17,7 @@ def valid_field_in_graph(arch): def valid_field_in_tree(arch): """A `field` and `button` node must be below a `tree` node.""" - return not arch.xpath('//tree[not((field) and (button) and (@string))]') + return not arch.xpath('//tree[not((field) or (button)) and (@string)]') def valid_att_in_field(arch): From 6c48585a91a41d6f7e32d3d6f8d033a5d0a3ee51 Mon Sep 17 00:00:00 2001 From: Jigar Amin - OpenERP Date: Mon, 6 Aug 2012 16:06:31 +0530 Subject: [PATCH 030/236] [FIX] impoved the message bzr revid: jam@tinyerp.com-20120806103631-tzmpq4g48urbic5l --- openerp/tools/view_validation.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/openerp/tools/view_validation.py b/openerp/tools/view_validation.py index 09155ae3624..40e9e5be1e0 100644 --- a/openerp/tools/view_validation.py +++ b/openerp/tools/view_validation.py @@ -16,7 +16,7 @@ def valid_field_in_graph(arch): def valid_field_in_tree(arch): - """A `field` and `button` node must be below a `tree` node.""" + """A `field` and `button` node must be below a `tree` node. And tree must have `string` attribute.""" return not arch.xpath('//tree[not((field) or (button)) and (@string)]') @@ -26,12 +26,12 @@ def valid_att_in_field(arch): def valid_att_in_label(arch): - """A `for` and `string` attribute must be in a `label` node.""" + """A `for` and `string` attribute must be on a `label` node.""" return not arch.xpath('//label[not ((@for) or (@string))]') def valid_att_in_form(arch): - """A `string` attribute must be in a `form` node.""" + """A `string` attribute must be on a `form` node.""" return not arch.xpath('//form[not (@string)]') From 3d16cbb9a53b44185e9ccc2b3660f5f2efd9f9e0 Mon Sep 17 00:00:00 2001 From: "Twinkle Christian (OpenERP)" Date: Mon, 6 Aug 2012 16:12:13 +0530 Subject: [PATCH 031/236] [IMP]improvr viewa in base bzr revid: tch@tinyerp.com-20120806104213-3xmv2tzk85ilstef --- openerp/addons/base/res/res_config.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openerp/addons/base/res/res_config.xml b/openerp/addons/base/res/res_config.xml index e043afb0b7e..07b31a1072f 100644 --- a/openerp/addons/base/res/res_config.xml +++ b/openerp/addons/base/res/res_config.xml @@ -5,7 +5,7 @@ res.config form - +
- + ''')).getroot() diff --git a/openerp/tools/view_validation.py b/openerp/tools/view_validation.py index 40e9e5be1e0..e4324d143f1 100644 --- a/openerp/tools/view_validation.py +++ b/openerp/tools/view_validation.py @@ -12,12 +12,22 @@ def valid_page_in_book(arch): def valid_field_in_graph(arch): """A `field` node must be below a `graph` node.""" - return not arch.xpath('//graph[not ((field) and (@string))]') + if arch.xpath('//graph[not (@string)]'): + return False + for child in arch.xpath('/graph/child::*'): + if child.tag != 'field': + return False + return True def valid_field_in_tree(arch): """A `field` and `button` node must be below a `tree` node. And tree must have `string` attribute.""" - return not arch.xpath('//tree[not((field) or (button)) and (@string)]') + if arch.xpath('//tree[not (@string)]'): + return False + for child in arch.xpath('/tree/child::*'): + if child.tag not in ('field', 'button'): + return False + return True def valid_att_in_field(arch): @@ -57,20 +67,18 @@ def valid_type_in_col(arch): def valid_view(arch): if arch.tag == 'form': - for pred in [valid_page_in_book,valid_att_in_form,valid_type_in_colspan,\ - valid_type_in_col,valid_att_in_field,valid_att_in_label]: + for pred in [valid_page_in_book, valid_att_in_form, valid_type_in_colspan,\ + valid_type_in_col, valid_att_in_field, valid_att_in_label]: if not pred(arch): _logger.error('Invalid XML: %s', pred.__doc__) return False elif arch.tag == 'graph': - for pred in [valid_field_in_graph,valid_type_in_colspan,valid_type_in_col,\ - valid_att_in_field,valid_att_in_label]: + for pred in [valid_field_in_graph, valid_att_in_field]: if not pred(arch): _logger.error('Invalid XML: %s', pred.__doc__) return False elif arch.tag == 'tree': - for pred in [valid_field_in_tree,valid_type_in_colspan,valid_type_in_col,\ - valid_att_in_field,valid_att_in_label]: + for pred in [valid_field_in_tree, valid_att_in_field]: if not pred(arch): _logger.error('Invalid XML: %s', pred.__doc__) return False From ce5a49fd4c67db6ae43a163d9b672675c6b09e65 Mon Sep 17 00:00:00 2001 From: "Twinkle Christian (OpenERP)" Date: Tue, 7 Aug 2012 10:30:07 +0530 Subject: [PATCH 037/236] [IMP]improve views in account bzr revid: tch@tinyerp.com-20120807050007-frozee480m1e2ux9 --- .../account_voucher/account_voucher_view.xml | 26 +++++++++---------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/addons/account_voucher/account_voucher_view.xml b/addons/account_voucher/account_voucher_view.xml index f58f6b9c33e..5af75e245fa 100644 --- a/addons/account_voucher/account_voucher_view.xml +++ b/addons/account_voucher/account_voucher_view.xml @@ -6,20 +6,18 @@ account.voucher tree - - - - - - - - - - - - - - + + + + + + + + + + + + From ae1304d42d4dd0ea2bf8e82ab8ea5aa18364ef16 Mon Sep 17 00:00:00 2001 From: "Twinkle Christian (OpenERP)" Date: Tue, 7 Aug 2012 11:48:55 +0530 Subject: [PATCH 038/236] [IMP]improve views bzr revid: tch@tinyerp.com-20120807061855-lbq954eh05i4akpi --- addons/hr_holidays/hr_holidays_view.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/hr_holidays/hr_holidays_view.xml b/addons/hr_holidays/hr_holidays_view.xml index 4469fa73fbe..79fd193afc6 100644 --- a/addons/hr_holidays/hr_holidays_view.xml +++ b/addons/hr_holidays/hr_holidays_view.xml @@ -92,7 +92,7 @@ form 1 -
+
diff --git a/addons/lunch/lunch_view.xml b/addons/lunch/lunch_view.xml index d953dfbd1a9..a18362df93b 100644 --- a/addons/lunch/lunch_view.xml +++ b/addons/lunch/lunch_view.xml @@ -23,7 +23,7 @@ Order lunch.order - +
- - - -
-

Followers

-
    -
    - - -
  • - - -
  • - +
    +
    + + + +
    +
    +

    Followers

    +
      +
      +
      + + +
    • + + +
    • + + From 6aa4f80b2d9696a8dcbcc970bbd656b5842b02d4 Mon Sep 17 00:00:00 2001 From: Olivier Dony Date: Fri, 10 Aug 2012 15:19:19 +0200 Subject: [PATCH 090/236] [IMP] mail: support multi routing + cleanup/lint bzr revid: odo@openerp.com-20120810131919-1zkxu41eq9oy4c74 --- addons/mail/mail_thread.py | 100 ++++++++++++++++++------------------- 1 file changed, 50 insertions(+), 50 deletions(-) diff --git a/addons/mail/mail_thread.py b/addons/mail/mail_thread.py index bee3eb416ef..3a2c79bbe58 100644 --- a/addons/mail/mail_thread.py +++ b/addons/mail/mail_thread.py @@ -27,7 +27,6 @@ import time import xmlrpclib from email.utils import parsedate from email.message import Message -from operator import itemgetter from osv import osv, fields from mail_message import decode, to_email @@ -37,6 +36,11 @@ from tools.safe_eval import safe_eval as eval _logger = logging.getLogger(__name__) + +def decode_header(message, header, separator=' '): + return separator.join(map(decode,message.get_all(header, []))) + + class mail_thread(osv.Model): '''Mixin model, meant to be inherited by any model that needs to act as a discussion topic on which messages can be attached. @@ -154,10 +158,9 @@ class mail_thread(osv.Model): message_obj = self.pool.get('mail.message') notification_obj = self.pool.get('mail.notification') - body = vals.get('body_html', '') if vals.get('content_subtype') == 'html' else vals.get('body_text', '') # automatically subscribe the writer of the message - if vals['user_id']: + if vals.get('user_id'): self.message_subscribe(cr, uid, [thread_id], [vals['user_id']], context=context) # create message @@ -176,12 +179,11 @@ class mail_thread(osv.Model): notification_obj.create(cr, uid, {'user_id': id, 'message_id': msg_id}, context=context) # create the email to send - email_id = self.message_create_notify_by_email(cr, uid, vals, user_to_push_ids, context=context) + self.message_create_notify_by_email(cr, uid, vals, user_to_push_ids, context=context) return msg_id def message_get_user_ids_to_notify(self, cr, uid, thread_ids, new_msg_vals, context=None): - subscription_obj = self.pool.get('mail.subscription') # get body body = new_msg_vals.get('body_html', '') if new_msg_vals.get('content_subtype') == 'html' else new_msg_vals.get('body_text', '') @@ -304,7 +306,6 @@ class mail_thread(osv.Model): threads = model_pool.browse(cr, uid, threads, context=context) ir_attachment = self.pool.get('ir.attachment') - mail_message = self.pool.get('mail.message') new_msg_ids = [] for thread in threads: @@ -504,10 +505,6 @@ class mail_thread(osv.Model): """ Retrieve all attachments names """ map_id_to_name = dict((attachment_id, '') for message in messages for attachment_id in message['attachment_ids']) - map_id_to_name = {} - for msg in messages: - for attach_id in msg["attachment_ids"]: - map_id_to_name[attach_id] = '' # use empty string as a placeholder ids = map_id_to_name.keys() names = self.pool.get('ir.attachment').name_get(cr, uid, ids, context=context) @@ -577,6 +574,8 @@ class mail_thread(osv.Model): custom_values=None, context=None): """Attempt to figure out the correct target model, thread_id, custom_values and user_id to use for an incoming message. + Multiple values may be returned, if a message had multiple + recipients matching existing mail.aliases, for example. The following heuristics are used, in this order: 1. If the message replies to an existing thread_id, and @@ -601,13 +600,13 @@ class mail_thread(osv.Model): :param int thread_id: optional ID of the record/thread from ``model`` to which this mail should be attached. Only used if the message does not reply to an existing thread and does not match any mail alias. - :return: model, thread_id, custom_values, user_id + :return: list of [model, thread_id, custom_values, user_id] """ assert isinstance(message, Message), 'message must be an email.message.Message at this point' message_id = message.get('Message-Id') # 1. Verify if this is a reply to an existing thread - references = message.get('References') or message.get('In-Reply-To') + references = decode_header(message, 'References') or decode_header(message, 'In-Reply-To') ref_match = references and tools.reference_re.search(references) if ref_match: thread_id = int(ref_match.group(1)) @@ -617,45 +616,47 @@ class mail_thread(osv.Model): and hasattr(model_pool, 'message_update'): _logger.debug('Routing mail with Message-Id %s: direct reply to model:%s, thread_id:%s, custom_values:%s, uid:%s', message_id, model, thread_id, custom_values, uid) - return model, thread_id, custom_values, uid + return [(model, thread_id, custom_values, uid)] # 2. Look for a matching mail.alias entry # Delivered-To is a safe bet in most modern MTAs, but we have to fallback on To + Cc values # for all the odd MTAs out there, as there is no standard header for the envelope's `rcpt_to` value. - rcpt_to = message.get_all('Delivered-To', []) or (message.get_all('To', []) + message.get_all('Cc', [])) - local_parts = [e.split('@')[0] for e in to_email(u','.join(map(decode,rcpt_to)))] + rcpt_tos = decode_header(message, 'Delivered-To') or \ + (decode_header(message, 'To') + decode_header(message, 'Cc') \ + + decode_header(message, 'Resent-To') + decode_header(message, 'Resent-Cc')) + local_parts = [e.split('@')[0] for e in to_email(','.join(rcpt_tos))] if local_parts: mail_alias = self.pool.get('mail.alias') alias_ids = mail_alias.search(cr, uid, [('alias_name', 'in', local_parts)]) if alias_ids: - if len(alias_ids) > 1: - _logger.warning('Multiple mail.aliases match for mail with Message-Id %s, keeping first one only: %s', - message_id, alias_ids) - alias = mail_alias.browse(cr, uid, alias_ids[0], context=context) - user_id = alias.alias_user_id.id - if not user_id: - user_id = self._message_find_user_id(cr, uid, message, context=context) - _logger.debug('Routing mail with Message-Id %s: direct alias match: model:%s, thread_id:%s, custom_values:%s, uid:%s', - message_id, model, thread_id, custom_values, uid) - return alias.alias_model_id.model, alias.alias_force_thread_id, \ - eval(alias.alias_defaults), user_id + routes = [] + for alias in mail_alias.browse(cr, uid, alias_ids, context=context): + user_id = alias.alias_user_id.id + if not user_id: + user_id = self._message_find_user_id(cr, uid, message, context=context) + routes.append((alias.alias_model_id.model, alias.alias_force_thread_id, \ + eval(alias.alias_defaults), user_id)) + _logger.debug('Routing mail with Message-Id %s: direct alias match: %r', message_id, routes) + return routes # 3. Fallback to the provided parameters, if they work model_pool = self.pool.get(model) + if not thread_id: + # Legacy: fallback to matching [ID] in the Subject + match = tools.res_re.search(decode_header(message, 'Subject')) + thread_id = match and match.group(1) assert thread_id and hasattr(model_pool, 'message_update') or hasattr(model_pool, 'message_new'), \ "No possible route found for incoming message with Message-Id %s. " \ "Create an appropriate mail.alias or force the destination model." - if not model_pool.exists(cr, uid, thread_id): + if thread_id and not model_pool.exists(cr, uid, thread_id): _logger.warning('Received mail reply to missing document %s! Ignoring and creating new document instead for Message-Id %s', thread_id, message_id) thread_id = None _logger.debug('Routing mail with Message-Id %s: fallback to model:%s, thread_id:%s, custom_values:%s, uid:%s', message_id, model, thread_id, custom_values, uid) - return model, thread_id, custom_values, uid + return [(model, thread_id, custom_values, uid)] - - def message_process(self, cr, uid, model, message, custom_values=None, save_original=False, strip_attachments=False, thread_id=None, context=None): @@ -699,29 +700,29 @@ class mail_thread(osv.Model): if isinstance(message, unicode): message = message.encode('utf-8') msg_txt = email.message_from_string(message) - model, thread_id, custom_values, user_id = self.message_route(cr, uid, msg_txt, model, - thread_id, custom_values, - context=context) - if self._name != model: - context.update({'thread_model': model}) + routes = self.message_route(cr, uid, msg_txt, model, + thread_id, custom_values, + context=context) msg = self.pool.get('mail.message').parse_message(msg_txt, save_original=save_original, context=context) msg['state'] = 'received' if strip_attachments and 'attachments' in msg: del msg['attachments'] - - model_pool = self.pool.get(model) - assert thread_id and hasattr(model_pool, 'message_update') or hasattr(model_pool, 'message_new'), \ - "Undeliverable mail with Message-Id %s, model %s does not accept incoming emails" % \ - (msg['message-id'], model) - if thread_id and hasattr(model_pool, 'message_update'): - model_pool.message_update(cr, user_id, [thread_id], msg, context=context) - else: - thread_id = model_pool.message_new(cr, user_id, msg, custom_values, context=context) - - # Forward the email to other followers - self.message_forward(cr, uid, model, [thread_id], msg_txt, context=context) - model_pool.message_mark_as_unread(cr, uid, [thread_id], context=context) - return thread_id + for model, thread_id, custom_values, user_id in routes: + if self._name != model: + context.update({'thread_model': model}) + model_pool = self.pool.get(model) + assert thread_id and hasattr(model_pool, 'message_update') or hasattr(model_pool, 'message_new'), \ + "Undeliverable mail with Message-Id %s, model %s does not accept incoming emails" % \ + (msg['message-id'], model) + if thread_id and hasattr(model_pool, 'message_update'): + model_pool.message_update(cr, user_id, [thread_id], msg, context=context) + else: + thread_id = model_pool.message_new(cr, user_id, msg, custom_values, context=context) + + # Forward the email to other followers + self.message_forward(cr, uid, model, [thread_id], msg_txt, context=context) + model_pool.message_mark_as_unread(cr, uid, [thread_id], context=context) + return True def message_new(self, cr, uid, msg_dict, custom_values=None, context=None): """Called by ``message_process`` when a new message is received @@ -811,7 +812,6 @@ class mail_thread(osv.Model): """ model_pool = self.pool.get(model) smtp_server_obj = self.pool.get('ir.mail_server') - mail_message = self.pool.get('mail.message') for res in model_pool.browse(cr, uid, thread_ids, context=context): if hasattr(model_pool, 'message_thread_followers'): followers = model_pool.message_thread_followers(cr, uid, [res.id])[res.id] From 2da4b1b3f5ed22289fb8db6d664b4e5dabd12810 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Fri, 10 Aug 2012 16:05:49 +0200 Subject: [PATCH 091/236] [FIX] base.sql: added a partner_id integer field on res.users, to avoid the ORM being unable to set a not null constraint on it. bzr revid: tde@openerp.com-20120810140549-w70l7nzwn4kt1oav --- openerp/addons/base/base.sql | 3 ++- openerp/addons/base/res/res_users.py | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/openerp/addons/base/base.sql b/openerp/addons/base/base.sql index 7b532736165..c6ca6dbb76d 100644 --- a/openerp/addons/base/base.sql +++ b/openerp/addons/base/base.sql @@ -155,6 +155,7 @@ CREATE TABLE res_users ( -- No FK references below, will be added later by ORM -- (when the destination rows exist) company_id int, + partner_id int, primary key(id) ); alter table res_users add constraint res_users_login_uniq unique (login); @@ -383,7 +384,7 @@ CREATE TABLE ir_model_relation ( -- Users --------------------------------- -insert into res_users (id,login,password,name,active,company_id,lang) values (1,'admin','admin','Administrator',True,1,'en_US'); +insert into res_users (id,login,password,name,active,company_id,partner_id,lang) values (1,'admin','admin','Administrator',True,1,1,'en_US'); insert into ir_model_data (name,module,model,noupdate,res_id) values ('user_root','base','res.users',True,1); -- Compatibility purpose, to remove V6.0 diff --git a/openerp/addons/base/res/res_users.py b/openerp/addons/base/res/res_users.py index 93291cb2bdd..ab3674a09d9 100644 --- a/openerp/addons/base/res/res_users.py +++ b/openerp/addons/base/res/res_users.py @@ -152,13 +152,13 @@ class users(osv.osv): # context is set. 'company_id': fields.many2one('res.company', 'Company', required=True, help='The company this user is currently working for.', context={'user_preference': True}), - 'context_company_id': fields.many2one('res.company', 'Company', required=True, - help='The company this user is currently working for.', context={'user_preference': True}), + # 'context_company_id': fields.many2one('res.company', 'Company', required=True, + # help='The company this user is currently working for.', context={'user_preference': True}), 'company_ids':fields.many2many('res.company','res_company_users_rel','user_id','cid','Companies'), # backward compatibility fields 'user_email': fields.related('email', type='char', deprecated='Use the email field instead of user_email. This field will be removed as of OpenERP 7.1.'), - 'date': fields.related('date', type='date', + 'date': fields.related('date', type='date', store=True, deprecated='use the login_date field instead of date. This field will be removed as of OpenERP 7.1.'), } From 7657aedc4ea77c9ad38fb1e177872d4d6c888837 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Fri, 10 Aug 2012 16:12:19 +0200 Subject: [PATCH 092/236] [IMP] auth_ldap, auth_openid, base_crypt: update login_date instead of date on res.users. bzr revid: tde@openerp.com-20120810141219-qa0howq34k03ynxh --- addons/auth_ldap/users_ldap.py | 2 +- addons/auth_openid/res_users.py | 2 +- addons/base_crypt/crypt.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/addons/auth_ldap/users_ldap.py b/addons/auth_ldap/users_ldap.py index e4615907c79..47fc41c3645 100644 --- a/addons/auth_ldap/users_ldap.py +++ b/addons/auth_ldap/users_ldap.py @@ -255,7 +255,7 @@ class users(osv.osv): cr, SUPERUSER_ID, conf, login, entry) if user_id: cr.execute("""UPDATE res_users - SET date=now() AT TIME ZONE 'UTC' + SET login_date=now() AT TIME ZONE 'UTC' WHERE login=%s""", (tools.ustr(login),)) cr.commit() diff --git a/addons/auth_openid/res_users.py b/addons/auth_openid/res_users.py index 3fb8cefcbd4..506c7e1c094 100644 --- a/addons/auth_openid/res_users.py +++ b/addons/auth_openid/res_users.py @@ -66,7 +66,7 @@ class res_users(osv.osv): else: with utils.cursor(db) as cr: cr.execute("""UPDATE res_users - SET date=now() AT TIME ZONE 'UTC' + SET login_date=now() AT TIME ZONE 'UTC' WHERE login=%s AND openid_key=%s AND active=%s RETURNING id""", (tools.ustr(login), tools.ustr(password), True)) res = cr.fetchone() diff --git a/addons/base_crypt/crypt.py b/addons/base_crypt/crypt.py index f7e200560a3..b27dad22363 100644 --- a/addons/base_crypt/crypt.py +++ b/addons/base_crypt/crypt.py @@ -213,7 +213,7 @@ class users(osv.osv): # Check if the encrypted password matches against the one in the db. cr.execute("""UPDATE res_users - SET date=now() AT TIME ZONE 'UTC' + SET login_date=now() AT TIME ZONE 'UTC' WHERE id=%s AND password=%s AND active RETURNING id""", (int(id), encrypted_pw.encode('utf-8'))) From 18f1bd6fb5c7092efdffb1ad7e3fd905ecbcd96b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Fri, 10 Aug 2012 16:12:34 +0200 Subject: [PATCH 093/236] [IMP] res_users: update login_date instead of date at login. bzr revid: tde@openerp.com-20120810141234-yntr5ye3evepjakg --- openerp/addons/base/res/res_users.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openerp/addons/base/res/res_users.py b/openerp/addons/base/res/res_users.py index ab3674a09d9..66fa4f420de 100644 --- a/openerp/addons/base/res/res_users.py +++ b/openerp/addons/base/res/res_users.py @@ -372,7 +372,7 @@ class users(osv.osv): AND active FOR UPDATE NOWAIT""", (tools.ustr(login), tools.ustr(password))) cr.execute("""UPDATE res_users - SET date = now() AT TIME ZONE 'UTC' + SET login_date = now() AT TIME ZONE 'UTC' WHERE login=%s AND password=%s AND active RETURNING id""", (tools.ustr(login), tools.ustr(password))) From 620b7e9b118f102d03aed6935ac1978fd2963809 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Fri, 10 Aug 2012 16:43:39 +0200 Subject: [PATCH 094/236] [IMP] Addons: user_email -> email. bzr revid: tde@openerp.com-20120810144339-30ro9omgfxtjtjyz --- addons/account/edi/invoice_action_data.xml | 8 ++++---- .../cron_account_analytic_account.py | 4 ++-- addons/auth_signup/auth_signup.py | 4 ++-- addons/base_action_rule/base_action_rule.py | 8 ++++---- addons/base_status/base_stage.py | 14 +++++++------- addons/base_status/base_state.py | 2 +- addons/crm/crm_action_rule.py | 4 ++-- addons/crm/crm_lead.py | 6 +++--- .../wizard/crm_forward_to_partner.py | 13 +++++-------- addons/event/email_template.xml | 4 ++-- addons/event/event.py | 2 +- addons/hr/hr.py | 2 +- addons/hr_recruitment/hr_recruitment.py | 2 +- addons/lunch/report/order.rml | 2 +- addons/mail/data/mail_group_data.xml | 2 +- addons/mail/mail_message.py | 11 ++++++++--- addons/mail/mail_thread.py | 10 +++++----- addons/mail/res_users.py | 15 ++++++++++----- addons/mail/wizard/mail_compose_message.py | 6 +++--- addons/portal_crm/wizard/contact.py | 2 +- addons/project/project.py | 2 +- addons/project_issue/project_issue.py | 2 +- addons/project_mailgate/project_mailgate.py | 2 +- .../edi/purchase_order_action_data.xml | 8 ++++---- addons/sale/edi/sale_order_action_data.xml | 8 ++++---- addons/share/wizard/share_wizard.py | 18 +++++++++--------- addons/survey/survey.py | 2 +- addons/survey/wizard/survey_answer.py | 4 ++-- 28 files changed, 87 insertions(+), 80 deletions(-) diff --git a/addons/account/edi/invoice_action_data.xml b/addons/account/edi/invoice_action_data.xml index ce837c6662b..0eec6d27785 100644 --- a/addons/account/edi/invoice_action_data.xml +++ b/addons/account/edi/invoice_action_data.xml @@ -38,7 +38,7 @@ Automated Invoice Notification Mail - ${object.user_id.user_email or object.company_id.email or 'noreply@localhost'} + ${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 ''} @@ -58,7 +58,7 @@ % if object.origin:   Order reference: ${object.origin}
      % endif -   Your contact: ${object.user_id.name} +   Your contact: ${object.user_id.name}

      @@ -133,7 +133,7 @@ A new invoice is available for ${object.partner_id.name}: % if object.origin: | Order reference: ${object.origin} % endif - | Your contact: ${object.user_id.name} ${object.user_id.user_email and '<%s>'%(object.user_id.user_email) or ''} + | Your contact: ${object.user_id.name} ${object.user_id.email and '<%s>'%(object.user_id.email) or ''} You can view the invoice document, download it and pay online using the following link: ${ctx.get('edi_web_url_view') or 'n/a'} @@ -160,7 +160,7 @@ Thank you for choosing ${object.company_id.name}! -- -${object.user_id.name} ${object.user_id.user_email and '<%s>'%(object.user_id.user_email) or ''} +${object.user_id.name} ${object.user_id.email and '<%s>'%(object.user_id.email) or ''} ${object.company_id.name} % if object.company_id.street: ${object.company_id.street or ''} diff --git a/addons/account_analytic_analysis/cron_account_analytic_account.py b/addons/account_analytic_analysis/cron_account_analytic_account.py index caa9067b227..065fdc5b907 100644 --- a/addons/account_analytic_analysis/cron_account_analytic_account.py +++ b/addons/account_analytic_analysis/cron_account_analytic_account.py @@ -53,7 +53,7 @@ class analytic_account(osv.osv): ('name', 'not ilike', 'maintenance'), ('partner_id', '!=', False), ('user_id', '!=', False), - ('user_id.user_email', '!=', False), + ('user_id.email', '!=', False), ('state', 'in', ('draft', 'open')), '|', ('date', '<', time.strftime('%Y-%m-%d')), ('date', '=', False), ] @@ -70,7 +70,7 @@ class analytic_account(osv.osv): for user, data in users.iteritems(): subject = '[OPENERP] Reporting: Analytic Accounts' body = Template(MAKO_TEMPLATE).render_unicode(user=user, partners=data) - tools.email_send('noreply@openerp.com', [user.user_email, ], subject, body) + tools.email_send('noreply@openerp.com', [user.email, ], subject, body) return True diff --git a/addons/auth_signup/auth_signup.py b/addons/auth_signup/auth_signup.py index ebc72b3aeac..fedce607206 100644 --- a/addons/auth_signup/auth_signup.py +++ b/addons/auth_signup/auth_signup.py @@ -4,7 +4,7 @@ class res_users(osv.Model): _inherit = 'res.users' _sql_constraints = [ - ('email_uniq', 'UNIQUE (user_email)', 'You can not have two users with the same email!') + ('email_uniq', 'UNIQUE (email)', 'You can not have two users with the same email!') ] class signup_signup(osv.TransientModel): @@ -24,7 +24,7 @@ class signup_signup(osv.TransientModel): new_user = { 'name': values['name'], 'login': values['email'], - 'user_email': values['email'], + 'email': values['email'], 'password': values['password'], 'active': True, } diff --git a/addons/base_action_rule/base_action_rule.py b/addons/base_action_rule/base_action_rule.py index 7699256985c..b6eacda63c0 100644 --- a/addons/base_action_rule/base_action_rule.py +++ b/addons/base_action_rule/base_action_rule.py @@ -292,7 +292,7 @@ the rule to mark CC(mail to any other person defined in actions)."), 'object_description': hasattr(obj, 'description') and obj.description or False, 'object_user': hasattr(obj, 'user_id') and (obj.user_id and obj.user_id.name) or '/', 'object_user_email': hasattr(obj, 'user_id') and (obj.user_id and \ - obj.user_id.user_email) or '/', + obj.user_id.email) or '/', 'object_user_phone': hasattr(obj, 'partner_address_id') and (obj.partner_address_id and \ obj.partner_address_id.phone) or '/', 'partner': hasattr(obj, 'partner_id') and (obj.partner_id and obj.partner_id.name) or '/', @@ -319,8 +319,8 @@ the rule to mark CC(mail to any other person defined in actions)."), mail_message = self.pool.get('mail.message') body = self.format_mail(obj, body) if not emailfrom: - if hasattr(obj, 'user_id') and obj.user_id and obj.user_id.user_email: - emailfrom = obj.user_id.user_email + if hasattr(obj, 'user_id') and obj.user_id and obj.user_id.email: + emailfrom = obj.user_id.email name = '[%d] %s' % (obj.id, tools.ustr(obj.name)) emailfrom = tools.ustr(emailfrom) @@ -419,7 +419,7 @@ the rule to mark CC(mail to any other person defined in actions)."), emails = [] if hasattr(obj, 'user_id') and action.act_mail_to_user: if obj.user_id: - emails.append(obj.user_id.user_email) + emails.append(obj.user_id.email) if action.act_mail_to_watchers: emails += (action.act_email_cc or '').split(',') diff --git a/addons/base_status/base_stage.py b/addons/base_status/base_stage.py index 44e9de89162..775de51394c 100644 --- a/addons/base_status/base_stage.py +++ b/addons/base_status/base_stage.py @@ -57,7 +57,7 @@ class base_stage(object): if not context or not context.get('portal'): return False user = self.pool.get('res.users').browse(cr, uid, uid, context=context) - return user.user_email + return user.email def _get_default_user(self, cr, uid, context=None): """ Gives current user id @@ -301,15 +301,15 @@ class base_stage(object): for case in self.browse(cr, uid, ids, context=context): if not destination and not case.email_from: return False - if not case.user_id.user_email: + if not case.user_id.email: return False if destination and case.section_id.user_id: - case_email = case.section_id.user_id.user_email + case_email = case.section_id.user_id.email else: - case_email = case.user_id.user_email + case_email = case.user_id.email src = case_email - dest = case.user_id.user_email or "" + dest = case.user_id.email or "" body = case.description or "" for message in case.message_ids: if message.email_from and message.body_text: @@ -366,8 +366,8 @@ class base_stage(object): l=[] if case.email_cc: l.append(case.email_cc) - if case.user_id and case.user_id.user_email: - l.append(case.user_id.user_email) + if case.user_id and case.user_id.email: + l.append(case.user_id.email) res[case.id] = l return res diff --git a/addons/base_status/base_state.py b/addons/base_status/base_state.py index 4247e67f435..8fa2f92e22a 100644 --- a/addons/base_status/base_state.py +++ b/addons/base_status/base_state.py @@ -55,7 +55,7 @@ class base_state(object): if not context or not context.get('portal'): return False user = self.pool.get('res.users').browse(cr, uid, uid, context=context) - return user.user_email + return user.email def _get_default_user(self, cr, uid, context=None): """ Gives current user id diff --git a/addons/crm/crm_action_rule.py b/addons/crm/crm_action_rule.py index 96d182113c8..3e3bdc90d08 100644 --- a/addons/crm/crm_action_rule.py +++ b/addons/crm/crm_action_rule.py @@ -49,8 +49,8 @@ class base_action_rule(osv.osv): mail_message = self.pool.get('mail.message') body = self.format_mail(obj, body) if not emailfrom: - if hasattr(obj, 'user_id') and obj.user_id and obj.user_id.user_email: - emailfrom = obj.user_id.user_email + if hasattr(obj, 'user_id') and obj.user_id and obj.user_id.email: + emailfrom = obj.user_id.email name = '[%d] %s' % (obj.id, tools.ustr(obj.name)) emailfrom = tools.ustr(emailfrom) diff --git a/addons/crm/crm_lead.py b/addons/crm/crm_lead.py index 29d3eefec70..451dd795a94 100644 --- a/addons/crm/crm_lead.py +++ b/addons/crm/crm_lead.py @@ -243,7 +243,7 @@ class crm_lead(base_stage, osv.osv): 'partner_address_name': fields.related('partner_id', 'name', type='char', string='Partner Contact Name', readonly=True), 'partner_address_email': fields.related('partner_id', 'email', type='char', string='Partner Contact Email', readonly=True), 'company_currency': fields.related('company_id', 'currency_id', 'symbol', type='char', string='Company Currency', readonly=True), - 'user_email': fields.related('user_id', 'user_email', type='char', string='User Email', readonly=True), + 'user_email': fields.related('user_id', 'email', type='char', string='User Email', readonly=True), 'user_login': fields.related('user_id', 'login', type='char', string='User Login', readonly=True), # Fields for address, due to separation from crm and res.partner @@ -692,11 +692,11 @@ class crm_lead(base_stage, osv.osv): """ #TOFIX: mail template should be used here instead of fix subject, body text. message = self.pool.get('mail.message') - email_to = lead.user_id and lead.user_id.user_email + email_to = lead.user_id and lead.user_id.email if not email_to: return False - email_from = lead.section_id and lead.section_id.user_id and lead.section_id.user_id.user_email or email_to + email_from = lead.section_id and lead.section_id.user_id and lead.section_id.user_id.email or email_to partner = lead.partner_id and lead.partner_id.name or lead.partner_name subject = "lead %s converted into opportunity" % lead.name body = "Info \n Id : %s \n Subject: %s \n Partner: %s \n Description : %s " % (lead.id, lead.name, lead.partner_id.name, lead.description) diff --git a/addons/crm_partner_assign/wizard/crm_forward_to_partner.py b/addons/crm_partner_assign/wizard/crm_forward_to_partner.py index 2bc2d67d00a..d479f8b1bd5 100644 --- a/addons/crm_partner_assign/wizard/crm_forward_to_partner.py +++ b/addons/crm_partner_assign/wizard/crm_forward_to_partner.py @@ -43,16 +43,13 @@ class crm_lead_forward_to_partner(osv.osv_memory): _defaults = { 'send_to' : 'email', 'history': 'latest', - 'email_from': lambda self, cr, uid, *a: self.pool.get('res.users')._get_email_from(cr, uid, uid)[uid], + 'email_from': lambda s, cr, uid, c: s.pool.get('res.users').browse(cr, uid, uid, c).email, } - - - def on_change_email(self, cr, uid, ids, user): + def on_change_email(self, cr, uid, ids, user, context=None): if not user: return {'value': {'email_to': False}} - email = self.pool.get('res.users')._get_email_from(cr, uid, [user])[user] - return {'value': {'email_to': email}} + return {'value': {'email_to': self.pool.get('res.users').browse(cr, uid, uid, context=context).email}} def on_change_history(self, cr, uid, ids, history_type, context=None): """Gives message body according to type of history selected @@ -80,7 +77,7 @@ class crm_lead_forward_to_partner(osv.osv_memory): partner = partner_obj.browse(cr, uid, [partner_id]) user_id = partner and partner[0].user_id or False data.update({'email_from': partner and partner[0].email or "", - 'email_cc' : user_id and user_id.user_email or '', + 'email_cc' : user_id and user_id.user or '', 'user_id': user_id and user_id.id or False}) return {'value' : data} @@ -185,7 +182,7 @@ class crm_lead_forward_to_partner(osv.osv_memory): if partner_assigned_id: assigned_partner = partner.browse(cr, uid, partner_assigned_id, context=context) user_id = assigned_partner.user_id and assigned_partner.user_id.id or False - email_cc = assigned_partner.user_id and assigned_partner.user_id.user_email or '' + email_cc = assigned_partner.user_id and assigned_partner.user_id.email or '' email = assigned_partner.email res.update({ diff --git a/addons/event/email_template.xml b/addons/event/email_template.xml index 4485dfc785a..2666ece9921 100644 --- a/addons/event/email_template.xml +++ b/addons/event/email_template.xml @@ -4,7 +4,7 @@ Confirmation of the Event - ${object.user_id.user_email or object.company_id.email or 'noreply@' + object.company_id.name + '.com'} + ${object.user_id.email or object.company_id.email or 'noreply@' + object.company_id.name + '.com'} ${object.email} Your registration at ${object.event_id.name} @@ -24,7 +24,7 @@ Confirmation of the Registration - ${object.user_id.user_email or object.company_id.email or 'noreply@' + object.company_id.name + '.com'} + ${object.user_id.email or object.company_id.email or 'noreply@' + object.company_id.name + '.com'} ${object.email} Your registration at ${object.event_id.name} diff --git a/addons/event/event.py b/addons/event/event.py index 4279b8fcd7e..7f0c77661e4 100644 --- a/addons/event/event.py +++ b/addons/event/event.py @@ -230,7 +230,7 @@ class event_event(osv.osv): curr_reg_ids = register_pool.search(cr, uid, [('user_id', '=', user.id), ('event_id', '=' , ids[0])]) #the subscription is done with SUPERUSER_ID because in case we share the kanban view, we want anyone to be able to subscribe if not curr_reg_ids: - curr_reg_ids = [register_pool.create(cr, SUPERUSER_ID, {'event_id': ids[0] ,'email': user.user_email, 'name':user.name, 'user_id': user.id, 'nb_register': num_of_seats})] + curr_reg_ids = [register_pool.create(cr, SUPERUSER_ID, {'event_id': ids[0] ,'email': user.email, 'name':user.name, 'user_id': user.id, 'nb_register': num_of_seats})] else: register_pool.write(cr, uid, curr_reg_ids, {'nb_register': num_of_seats}, context=context) return register_pool.confirm_registration(cr, SUPERUSER_ID, curr_reg_ids, context=context) diff --git a/addons/hr/hr.py b/addons/hr/hr.py index 47432e1f527..966c29cab07 100644 --- a/addons/hr/hr.py +++ b/addons/hr/hr.py @@ -252,7 +252,7 @@ class hr_employee(osv.osv): def onchange_user(self, cr, uid, ids, user_id, context=None): work_email = False if user_id: - work_email = self.pool.get('res.users').browse(cr, uid, user_id, context=context).user_email + work_email = self.pool.get('res.users').browse(cr, uid, user_id, context=context).email return {'value': {'work_email' : work_email}} def _get_default_image(self, cr, uid, context=None): diff --git a/addons/hr_recruitment/hr_recruitment.py b/addons/hr_recruitment/hr_recruitment.py index 1db79172dc5..ee85ecc22a3 100644 --- a/addons/hr_recruitment/hr_recruitment.py +++ b/addons/hr_recruitment/hr_recruitment.py @@ -228,7 +228,7 @@ class hr_applicant(base_stage, osv.Model): multi='day_close', type="float", store=True), 'color': fields.integer('Color Index'), 'emp_id': fields.many2one('hr.employee', 'employee'), - 'user_email': fields.related('user_id', 'user_email', type='char', string='User Email', readonly=True), + 'user_email': fields.related('user_id', 'email', type='char', string='User Email', readonly=True), } _defaults = { diff --git a/addons/lunch/report/order.rml b/addons/lunch/report/order.rml index 30c16ad4894..b09b59bb96b 100644 --- a/addons/lunch/report/order.rml +++ b/addons/lunch/report/order.rml @@ -103,7 +103,7 @@ [[ user.name ]] [[ user.login ]] - [[ user.user_email ]] + [[ user.email ]] diff --git a/addons/mail/data/mail_group_data.xml b/addons/mail/data/mail_group_data.xml index 09a6ca29a2d..49c6fbdc1b6 100644 --- a/addons/mail/data/mail_group_data.xml +++ b/addons/mail/data/mail_group_data.xml @@ -21,7 +21,7 @@ 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 intall more applications, activate others features or give access to new users. +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/mail_message.py b/addons/mail/mail_message.py index b96b6e3791e..8845b3750b9 100644 --- a/addons/mail/mail_message.py +++ b/addons/mail/mail_message.py @@ -93,6 +93,9 @@ class mail_message_common(osv.TransientModel): return result def name_get(self, cr, uid, ids, context=None): + # name_get may receive int id instead of an id list + if isinstance(ids, (int, long)): + ids = [ids] res = [] for message in self.browse(cr, uid, ids, context=context): name = '' @@ -208,12 +211,13 @@ class mail_message(osv.Model): 'partner_id': fields.many2one('res.partner', 'Related partner', help="Deprecated field. Use partner_ids instead."), 'partner_ids': fields.many2many('res.partner', - 'mail_message_destination_partner_rel', + 'mail_message_res_partner_rel', 'message_id', 'partner_id', 'Destination partners', help="When sending emails through the social network composition wizard"\ "you may choose to send a copy of the mail to partners."), 'user_id': fields.many2one('res.users', 'Related User', readonly=1), - 'attachment_ids': fields.many2many('ir.attachment', 'message_attachment_rel', 'message_id', 'attachment_id', 'Attachments'), + 'attachment_ids': fields.many2many('ir.attachment', 'message_attachment_rel', + 'message_id', 'attachment_id', 'Attachments'), 'mail_server_id': fields.many2one('ir.mail_server', 'Outgoing mail server', readonly=1), 'state': fields.selection([ ('outgoing', 'Outgoing'), @@ -371,7 +375,8 @@ class mail_message(osv.Model): } email_msg_id = self.create(cr, uid, msg_vals, context) attachment_ids = [] - for fname, fcontent in attachments.iteritems(): + for attachment in attachments: + fname, fcontent = attachment attachment_data = { 'name': fname, 'datas_fname': fname, diff --git a/addons/mail/mail_thread.py b/addons/mail/mail_thread.py index f0dd023bf06..068dd844829 100644 --- a/addons/mail/mail_thread.py +++ b/addons/mail/mail_thread.py @@ -353,7 +353,7 @@ class mail_thread(osv.Model): data.update({ 'email_to': email_to, 'email_from': email_from or \ - (hasattr(thread, 'user_id') and thread.user_id and thread.user_id.user_email), + (hasattr(thread, 'user_id') and thread.user_id and thread.user_id.email), 'email_cc': email_cc, 'email_bcc': email_bcc, 'references': references, @@ -771,7 +771,7 @@ class mail_thread(osv.Model): for thread in self.browse(cr, uid, ids, context=context): l = set() for message in thread.message_ids: - l.add((message.user_id and message.user_id.user_email) or '') + l.add((message.user_id and message.user_id.email) or '') l.add(message.email_from or '') l.add(message.email_cc or '') res[thread.id] = filter(None, l) @@ -985,9 +985,9 @@ class mail_thread(osv.Model): if not user.notification_email_pref == 'all' and \ not (user.notification_email_pref == 'to_me' and user.id in user_to_push_from_parse_ids): continue - if not user.user_email: + if not user.email: continue - email_to = '%s, %s' % (email_to, user.user_email) + email_to = '%s, %s' % (email_to, user.email) email_to = email_to.lstrip(', ') # did not find any email address: not necessary to create an email @@ -998,7 +998,7 @@ class mail_thread(osv.Model): current_user = res_users_obj.browse(cr, uid, [uid], context=context)[0] email_from = new_msg_values.get('email_from') if not email_from: - email_from = current_user.user_email + email_from = current_user.email # get email content, create it (with mail_message.create) email_values = self.message_create_notify_get_email_dict(cr, uid, new_msg_values, email_from, email_to, context) diff --git a/addons/mail/res_users.py b/addons/mail/res_users.py index 8a590fc318f..c299df588d5 100644 --- a/addons/mail/res_users.py +++ b/addons/mail/res_users.py @@ -40,9 +40,8 @@ class res_users(osv.osv): _columns = { 'notification_email_pref': fields.selection([ - ('all', 'All feeds'), - ('comments', 'Only comments'), - ('to_me', 'Only when sent directly to me'), + ('all', 'All Feeds'), + ('to_me', 'Only send directly to me'), ('none', 'Never') ], 'Receive Feeds by Email', required=True, help="Choose in which case you want to receive an email when you "\ @@ -101,8 +100,14 @@ class res_users(osv.osv): self.message_subscribe(cr, uid, [user_id], [user_id], context=context) # create a welcome message company_name = user.company_id.name if user.company_id else _('the company') - message = _('%s joined the %s network! Take a moment to welcome %s.') % (user.name, company_name, user.name) - self.message_append_note(cr, uid, [user_id], body=message, type='comment', context=context) + message = '''%s has joined %s! Welcome in 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 Settings 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.''' % (user.name, company_name) + self.message_append_note(cr, uid, [user_id], subject='Welcome to OpenERP', body=message, type='comment', content_subtype='html', context=context) return user_id def write(self, cr, uid, ids, vals, context=None): diff --git a/addons/mail/wizard/mail_compose_message.py b/addons/mail/wizard/mail_compose_message.py index d26511464f8..fe87b7584e0 100644 --- a/addons/mail/wizard/mail_compose_message.py +++ b/addons/mail/wizard/mail_compose_message.py @@ -100,7 +100,7 @@ class mail_compose_message(osv.TransientModel): # Try to provide default email_from if not specified yet if not result.get('email_from'): current_user = self.pool.get('res.users').browse(cr, uid, uid, context=context) - result['email_from'] = current_user.user_email or False + result['email_from'] = current_user.email or False return result _columns = { @@ -133,7 +133,7 @@ class mail_compose_message(osv.TransientModel): result.update({ 'model': model, 'res_id': res_id, - 'email_from': user.user_email or tools.config.get('email_from', False), + 'email_from': user.email or tools.config.get('email_from', False), 'body_html': False, 'body_text': False, 'subject': False, @@ -223,7 +223,7 @@ class mail_compose_message(osv.TransientModel): 'dest_partner_ids': dest_partner_ids, 'model': message_data.model or False, 'res_id': message_data.res_id or False, - 'email_from': current_user.user_email or message_data.email_to or False, + 'email_from': current_user.email or message_data.email_to or False, 'email_to': message_data.reply_to or message_data.email_from or False, 'email_cc': message_data.email_cc or False, 'user_id': uid, diff --git a/addons/portal_crm/wizard/contact.py b/addons/portal_crm/wizard/contact.py index 505bb62bb16..036993e1720 100644 --- a/addons/portal_crm/wizard/contact.py +++ b/addons/portal_crm/wizard/contact.py @@ -50,7 +50,7 @@ class crm_contact_us(osv.TransientModel): user = self.pool.get('res.users').browse(cr, uid, uid, context=context) if (user.login != 'anonymous'): - return user.user_email + return user.email else: return None diff --git a/addons/project/project.py b/addons/project/project.py index 707df5607c6..355665152a2 100644 --- a/addons/project/project.py +++ b/addons/project/project.py @@ -794,7 +794,7 @@ class task(base_stage, osv.osv): 'company_id': fields.many2one('res.company', 'Company'), 'id': fields.integer('ID', readonly=True), 'color': fields.integer('Color Index'), - 'user_email': fields.related('user_id', 'user_email', type='char', string='User Email', readonly=True), + 'user_email': fields.related('user_id', 'email', type='char', string='User Email', readonly=True), } _defaults = { diff --git a/addons/project_issue/project_issue.py b/addons/project_issue/project_issue.py index 935935e28ca..33c2693d7bb 100644 --- a/addons/project_issue/project_issue.py +++ b/addons/project_issue/project_issue.py @@ -256,7 +256,7 @@ class project_issue(base_stage, osv.osv): 'inactivity_days': fields.function(_compute_day, string='Days since last action', \ multi='compute_day', type="integer", help="Difference in days between last action and current date"), 'color': fields.integer('Color Index'), - 'user_email': fields.related('user_id', 'user_email', type='char', string='User Email', readonly=True), + 'user_email': fields.related('user_id', 'email', type='char', string='User Email', readonly=True), 'date_action_last': fields.datetime('Last Action', readonly=1), 'date_action_next': fields.datetime('Next Action', readonly=1), 'progress': fields.function(_hours_get, string='Progress (%)', multi='hours', group_operator="avg", help="Computed as: Time Spent / Total Time.", diff --git a/addons/project_mailgate/project_mailgate.py b/addons/project_mailgate/project_mailgate.py index 0ca2687b7f0..ba3cd702760 100644 --- a/addons/project_mailgate/project_mailgate.py +++ b/addons/project_mailgate/project_mailgate.py @@ -73,7 +73,7 @@ class project_tasks(osv.osv): followers = super(project_tasks,self).message_thread_followers(cr, uid, ids, context=context) for task in self.browse(cr, uid, followers.keys(), context=context): task_followers = set(followers[task.id]) - task_followers.add(task.user_id.user_email) + task_followers.add(task.user_id.email) followers[task.id] = filter(None, task_followers) return followers diff --git a/addons/purchase/edi/purchase_order_action_data.xml b/addons/purchase/edi/purchase_order_action_data.xml index 70d402de598..b97da91fa1d 100644 --- a/addons/purchase/edi/purchase_order_action_data.xml +++ b/addons/purchase/edi/purchase_order_action_data.xml @@ -38,7 +38,7 @@ Automated Purchase Order Notification Mail - ${object.validator.user_email or ''} + ${object.validator.email or ''} ${object.company_id.name} Order (Ref ${object.name or 'n/a' }) ${object.partner_id.email} @@ -61,7 +61,7 @@ % if object.partner_ref:   Your reference: ${object.partner_ref}
      % endif -   Your contact: ${object.validator.name} +   Your contact: ${object.validator.name}

      @@ -121,7 +121,7 @@ Here is a ${object.state in ('draft', 'sent') and 'request for quotation' or 'pu % if object.partner_ref: | Your reference: ${object.partner_ref}
      % endif - | Your contact: ${object.validator.name} ${object.validator.user_email and '<%s>'%(object.validator.user_email) or ''} + | Your contact: ${object.validator.name} ${object.validator.email and '<%s>'%(object.validator.email) or ''} You can view the ${object.state in ('draft', 'sent') and 'request for quotation' or 'order confirmation'} and download it using the following link: ${ctx.get('edi_web_url_view') or 'n/a'} @@ -132,7 +132,7 @@ Thank you! -- -${object.validator.name} ${object.validator.user_email and '<%s>'%(object.validator.user_email) or ''} +${object.validator.name} ${object.validator.email and '<%s>'%(object.validator.email) or ''} ${object.company_id.name} % if object.company_id.street: ${object.company_id.street or ''} diff --git a/addons/sale/edi/sale_order_action_data.xml b/addons/sale/edi/sale_order_action_data.xml index 2fe0a8cbfd3..181bd8183d7 100644 --- a/addons/sale/edi/sale_order_action_data.xml +++ b/addons/sale/edi/sale_order_action_data.xml @@ -37,7 +37,7 @@ Automated Sale Order Notification Mail - ${object.user_id.user_email or ''} + ${object.user_id.email or ''} ${object.company_id.name} Order (Ref ${object.name or 'n/a' }) ${object.partner_invoice_id.email} @@ -60,7 +60,7 @@ % if object.client_order_ref:   Your reference: ${object.client_order_ref}
      % endif -   Your contact: ${object.user_id.name} +   Your contact: ${object.user_id.name}

      @@ -139,7 +139,7 @@ Here is your ${object.state in ('draft', 'sent') and 'quotation' or 'order confi % if object.client_order_ref: | Your reference: ${object.client_order_ref}
      % endif - | Your contact: ${object.user_id.name} ${object.user_id.user_email and '<%s>'%(object.user_id.user_email) or ''} + | Your contact: ${object.user_id.name} ${object.user_id.email and '<%s>'%(object.user_id.email) or ''} You can view the ${object.state in ('draft', 'sent') and 'quotation' or 'order confirmation'}, download it and even pay online using the following link: ${ctx.get('edi_web_url_view') or 'n/a'} @@ -166,7 +166,7 @@ Thank you for choosing ${object.company_id.name}! -- -${object.user_id.name} ${object.user_id.user_email and '<%s>'%(object.user_id.user_email) or ''} +${object.user_id.name} ${object.user_id.email and '<%s>'%(object.user_id.email) or ''} ${object.company_id.name} % if object.company_id.street: ${object.company_id.street or ''} diff --git a/addons/share/wizard/share_wizard.py b/addons/share/wizard/share_wizard.py index b14da39633e..598bb085967 100644 --- a/addons/share/wizard/share_wizard.py +++ b/addons/share/wizard/share_wizard.py @@ -196,7 +196,7 @@ class share_wizard(osv.TransientModel): } def has_email(self, cr, uid, context=None): - return bool(self.pool.get('res.users').browse(cr, uid, uid, context=context).user_email) + return bool(self.pool.get('res.users').browse(cr, uid, uid, context=context).email) def go_step_1(self, cr, uid, ids, context=None): wizard_data = self.browse(cr,uid,ids,context)[0] @@ -241,7 +241,7 @@ class share_wizard(osv.TransientModel): if not wizard_data.invite: existing = user_obj.search(cr, UID_ROOT, [('login', '=', new_user)]) else: - existing = user_obj.search(cr, UID_ROOT, [('user_email', '=', new_user)]) + existing = user_obj.search(cr, UID_ROOT, [('email', '=', new_user)]) existing_ids.extend(existing) if existing: new_line = { 'user_id': existing[0], @@ -253,7 +253,7 @@ class share_wizard(osv.TransientModel): 'login': new_user, 'password': new_pass, 'name': new_user, - 'user_email': new_user, + 'email': new_user, 'groups_id': [(6,0,[group_id])], 'share': True, 'message_email_pref': 'all', @@ -825,12 +825,12 @@ class share_wizard(osv.TransientModel): message_obj = self.pool.get('mail.message') notification_obj = self.pool.get('mail.notification') user = self.pool.get('res.users').browse(cr, UID_ROOT, uid) - if not user.user_email: + if not user.email: raise osv.except_osv(_('Email required'), _('The current user must have an email address configured in User Preferences to be able to send outgoing emails.')) # TODO: also send an HTML version of this mail for result_line in wizard_data.result_line_ids: - email_to = result_line.user_id.user_email + email_to = result_line.user_id.email if not email_to: continue subject = _('Invitation to collaborate about %s') % (wizard_data.record_name) @@ -849,20 +849,20 @@ class share_wizard(osv.TransientModel): body += "--\n" body += _("OpenERP is a powerful and user-friendly suite of Business Applications (CRM, Sales, HR, etc.)\n" "It is open source and can be found on http://www.openerp.com.") - msg_id = message_obj.schedule_with_attach(cr, uid, user.user_email, [email_to], subject, body, model='', context=context) + msg_id = message_obj.schedule_with_attach(cr, uid, user.email, [email_to], subject, body, model='', context=context) notification_obj.create(cr, uid, {'user_id': result_line.user_id.id, 'message_id': msg_id}, context=context) def send_emails(self, cr, uid, wizard_data, context=None): _logger.info('Sending share notifications by email...') mail_message = self.pool.get('mail.message') user = self.pool.get('res.users').browse(cr, UID_ROOT, uid) - if not user.user_email: + if not user.email: raise osv.except_osv(_('Email required'), _('The current user must have an email address configured in User Preferences to be able to send outgoing emails.')) # TODO: also send an HTML version of this mail msg_ids = [] for result_line in wizard_data.result_line_ids: - email_to = result_line.user_id.user_email + email_to = result_line.user_id.email if not email_to: continue subject = wizard_data.name @@ -883,7 +883,7 @@ class share_wizard(osv.TransientModel): body += "--\n" body += _("OpenERP is a powerful and user-friendly suite of Business Applications (CRM, Sales, HR, etc.)\n" "It is open source and can be found on http://www.openerp.com.") - msg_ids.append(mail_message.schedule_with_attach(cr, uid, user.user_email, [email_to], subject, body, model='share.wizard', context=context)) + msg_ids.append(mail_message.schedule_with_attach(cr, uid, user.email, [email_to], subject, body, model='share.wizard', context=context)) # force direct delivery, as users expect instant notification mail_message.send(cr, uid, msg_ids, context=context) _logger.info('%d share notification(s) sent.', len(msg_ids)) diff --git a/addons/survey/survey.py b/addons/survey/survey.py index 0a96d1fde1c..93bd48be30c 100644 --- a/addons/survey/survey.py +++ b/addons/survey/survey.py @@ -740,7 +740,7 @@ class survey_request(osv.osv): if user_id: user_obj = self.pool.get('res.users') user = user_obj.browse(cr, uid, user_id, context=context) - return {'value': {'email': user.user_email}} + return {'value': {'email': user.email}} return {} survey_request() diff --git a/addons/survey/wizard/survey_answer.py b/addons/survey/wizard/survey_answer.py index b3f27ed2970..66098b45fa8 100644 --- a/addons/survey/wizard/survey_answer.py +++ b/addons/survey/wizard/survey_answer.py @@ -414,8 +414,8 @@ class survey_question_wiz(osv.osv_memory): file.close() os.remove(addons.get_module_resource('survey', 'report') + survey_data.title + ".pdf") - user_email = user_obj.browse(cr, uid, uid, context).user_email - resp_email = survey_data.responsible_id and survey_data.responsible_id.user_email or False + user_email = user_obj.browse(cr, uid, uid, context).email + resp_email = survey_data.responsible_id and survey_data.responsible_id.email or False if user_email and resp_email: user_name = user_obj.browse(cr, uid, uid, context=context).name From 7d3e405d7d4d9ba2f2f2c759b5647534c08b211e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Fri, 10 Aug 2012 17:13:07 +0200 Subject: [PATCH 095/236] [IMP] Partners created through users are not customer by default. bzr revid: tde@openerp.com-20120810151307-9geyv54nf0tv42lg --- openerp/addons/base/base_data.xml | 1 + openerp/addons/base/res/res_users.py | 7 +++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/openerp/addons/base/base_data.xml b/openerp/addons/base/base_data.xml index 937cca7d53e..b5272596d98 100644 --- a/openerp/addons/base/base_data.xml +++ b/openerp/addons/base/base_data.xml @@ -1090,6 +1090,7 @@ Administrator + diff --git a/openerp/addons/base/res/res_users.py b/openerp/addons/base/res/res_users.py index 66fa4f420de..3e22a937800 100644 --- a/openerp/addons/base/res/res_users.py +++ b/openerp/addons/base/res/res_users.py @@ -152,8 +152,10 @@ class users(osv.osv): # context is set. 'company_id': fields.many2one('res.company', 'Company', required=True, help='The company this user is currently working for.', context={'user_preference': True}), - # 'context_company_id': fields.many2one('res.company', 'Company', required=True, - # help='The company this user is currently working for.', context={'user_preference': True}), + # 'context_company_id': fields.related('context_company_id', rel='res.company', + # string='Company', required=True, context={'user_preference': True}, + # help='The company this user is currently working for.', + # deprecated='Use the context_company_id field instead. This field will be removed as of OpenERP 7.1.'), 'company_ids':fields.many2many('res.company','res_company_users_rel','user_id','cid','Companies'), # backward compatibility fields 'user_email': fields.related('email', type='char', @@ -234,6 +236,7 @@ class users(osv.osv): _defaults = { 'password' : '', 'active' : True, + 'customer': False, 'menu_id': _get_menu, 'company_id': _get_company, 'company_ids': _get_companies, From 69e00d1e346153c2c1151238c44efd0d93bf217c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Fri, 10 Aug 2012 17:57:32 +0200 Subject: [PATCH 096/236] [IMP] res.users: default form view is now partner form view. This is done directly in fields_view_get: if no specific id is given, we call the default partner view. bzr revid: tde@openerp.com-20120810155732-zvnr2xb3b0urc8h2 --- openerp/addons/base/res/res_users.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/openerp/addons/base/res/res_users.py b/openerp/addons/base/res/res_users.py index 3e22a937800..ada625c6bcf 100644 --- a/openerp/addons/base/res/res_users.py +++ b/openerp/addons/base/res/res_users.py @@ -243,6 +243,19 @@ class users(osv.osv): 'groups_id': _get_group, } + def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False, submenu=False): + """ Override of res.users fields_view_get. + - if the view is specified: resume with normal behavior + - else: the default view is overrided and redirected to the partner + view + """ + print view_id + print view_type + if not view_id and view_type == 'form': + print 'acacpornief' + return self.pool.get('res.partner').fields_view_get(cr, uid, view_id, view_type, context, toolbar, submenu) + return super(users, self).fields_view_get(cr, uid, view_id, view_type, context, toolbar, submenu) + # User can write to a few of her own fields (but not her groups for example) SELF_WRITEABLE_FIELDS = ['password', 'signature', 'action_id', 'company_id', 'email', 'name', 'image', 'image_medium', 'image_small'] From 1d0061351135b07bcb987ee6be1dc30700773dab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Fri, 10 Aug 2012 17:57:54 +0200 Subject: [PATCH 097/236] [IMP] mail.thread: res.users: messages appened to res.users are attached to the related partner. bzr revid: tde@openerp.com-20120810155754-c7towsarcawxe1le --- addons/mail/res_users.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/addons/mail/res_users.py b/addons/mail/res_users.py index c299df588d5..3d8ed92609b 100644 --- a/addons/mail/res_users.py +++ b/addons/mail/res_users.py @@ -123,6 +123,23 @@ To setup your preferences (name, email signature, avatar), click on the top righ alias_pool.unlink(cr, uid, alias_ids, context=context) return res + def message_append(self, cr, uid, threads, subject, body_text=None, body_html=None, + type='email', email_date=None, parent_id=False, + content_subtype='plain', state=None, + partner_ids=None, email_from=False, email_to=False, + email_cc=None, email_bcc=None, reply_to=None, + headers=None, message_id=False, references=None, + attachments=None, original=None, context=None): + """ Override of message_append. Messages appened to res.users are + redirected to the related partner. Using partner_id.message_append, + messages will have correct model and id, set to res_partner and + partner_id.id. + """ + for user in self.browse(cr, uid, threads, context=context): + user.partner_id.message_append(subject, body_text, body_html, type, email_date, parent_id, + content_subtype, state, partner_ids, email_from, email_to, email_cc, email_bcc, reply_to, + headers, message_id, references, attachments, original) + def message_search_get_domain(self, cr, uid, ids, context=None): """ Override of message_search_get_domain for partner discussion page. The purpose is to add messages directly sent to user using From d0ff62372965ce74984e5b0c1f5a416e1bd580bf Mon Sep 17 00:00:00 2001 From: "vta vta@openerp.com" <> Date: Sun, 12 Aug 2012 17:07:39 +0200 Subject: [PATCH 098/236] [ADD] Basic functionality. bzr revid: vta@openerp.com-20120812150739-nrdwvxmnnnw8yr54 --- addons/auth_oauth/static/src/js/auth_oauth.js | 59 ++++++++++++++++--- .../auth_oauth/static/src/xml/auth_oauth.xml | 3 +- 2 files changed, 53 insertions(+), 9 deletions(-) diff --git a/addons/auth_oauth/static/src/js/auth_oauth.js b/addons/auth_oauth/static/src/js/auth_oauth.js index fddd4c78ae9..a49d6777e7d 100644 --- a/addons/auth_oauth/static/src/js/auth_oauth.js +++ b/addons/auth_oauth/static/src/js/auth_oauth.js @@ -3,16 +3,61 @@ openerp.auth_oauth = function(instance) { var QWeb = instance.web.qweb; instance.web.Login = instance.web.Login.extend({ - start: function() { - console.log("Tu puta madre!"); + start: function(parent, params) { this._super.apply(this, arguments); + var self = this; + self.$element.on('click', '.oe_login_oauth a', this.on_google_oauth); }, - on_submit: function(ev) { + on_google_oauth: function(ev) { + var url = this._oauth_url(); + window.location = url; }, - do_warn: function(title, msg) { + _oauth_url: function() { + var endpoint = 'https://accounts.google.com/o/oauth2/auth'; + var params = { + response_type: 'token', + client_id: '108010644258-duuhmp6pu7li4tsmnqg7j9rvdeklg0ki.apps.googleusercontent.com', + redirect_uri: 'https://localhost/', + scope: 'https://www.googleapis.com/auth/userinfo.email', + state: 'TEST', + }; + var url = endpoint + '?' + $.param(params); + return url; }, - reset_error_message: function() { - } + // do_warn: function(title, msg) { + // }, + // reset_error_message: function() { + // } }); -}; \ No newline at end of file + instance.web.WebClient = instance.web.WebClient.extend({ + start: function() { + this._super.apply(this, arguments); + // console.log($.deparam(window.location.hash)); + var params = $.deparam(window.location.hash); + if (params.hasOwnProperty('access_token')) { + console.log(params); + // Do login using Google User credentials + var url = { + + }; + } + }, + bind_hashchange: function() { + var state = $.bbq.getState(true); + if (state.hasOwnProperty("access_token")) { + state.action = "login"; + $.bbq.setState(state); + } + this._super(); + + }, + // on_hashchange: function(event) { + // console.log(event); + // this._super.apply(this, arguments); + // }, + }); + +}; + +// https://accounts.google.com/o/oauth2/auth?state=%2Fprofile&redirect_uri=http%3A%2F%2Foauth2-login-demo.appspot.com%2Fcode&response_type=code&client_id=812741506391.apps.googleusercontent.com&approval_prompt=force&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile \ No newline at end of file diff --git a/addons/auth_oauth/static/src/xml/auth_oauth.xml b/addons/auth_oauth/static/src/xml/auth_oauth.xml index 01cf51da9a2..75f168d6c9a 100644 --- a/addons/auth_oauth/static/src/xml/auth_oauth.xml +++ b/addons/auth_oauth/static/src/xml/auth_oauth.xml @@ -5,8 +5,7 @@

      From 875d7541d99fd9bd9eb01d0a2bb7599e8911cf96 Mon Sep 17 00:00:00 2001 From: Antony Lesuisse Date: Sun, 12 Aug 2012 19:06:03 +0200 Subject: [PATCH 099/236] sign up with controller bzr revid: al@openerp.com-20120812170603-mnp54q5xn9htg6vj --- addons/auth_signup/__init__.py | 3 +- addons/auth_signup/__openerp__.py | 5 +- addons/auth_signup/auth_signup.py | 39 -------- addons/auth_signup/controllers/__init__.py | 3 + addons/auth_signup/controllers/main.py | 37 ++++++++ addons/auth_signup/res_users.py | 47 ++++++++++ .../static/src/css/auth_signup.css | 9 -- .../auth_signup/static/src/js/auth_signup.js | 90 +++++-------------- .../static/src/xml/auth_signup.xml | 8 +- 9 files changed, 117 insertions(+), 124 deletions(-) delete mode 100644 addons/auth_signup/auth_signup.py create mode 100644 addons/auth_signup/controllers/__init__.py create mode 100644 addons/auth_signup/controllers/main.py create mode 100644 addons/auth_signup/res_users.py delete mode 100644 addons/auth_signup/static/src/css/auth_signup.css diff --git a/addons/auth_signup/__init__.py b/addons/auth_signup/__init__.py index 2e404949550..8b5f4d767b5 100644 --- a/addons/auth_signup/__init__.py +++ b/addons/auth_signup/__init__.py @@ -1,2 +1,3 @@ +import controllers import res_config -import auth_signup +import res_users diff --git a/addons/auth_signup/__openerp__.py b/addons/auth_signup/__openerp__.py index a869c623db0..3dbe97394a0 100644 --- a/addons/auth_signup/__openerp__.py +++ b/addons/auth_signup/__openerp__.py @@ -6,16 +6,13 @@ 'category': 'Authentication', 'website': 'http://www.openerp.com', 'installable': True, - 'depends': ['auth_anonymous', 'base_setup'], + 'depends': ['base_setup'], 'data': [ 'res_config.xml', ], 'js': [ 'static/src/js/auth_signup.js', ], - 'css': [ - 'static/src/css/auth_signup.css', - ], 'qweb': [ 'static/src/xml/auth_signup.xml', ], diff --git a/addons/auth_signup/auth_signup.py b/addons/auth_signup/auth_signup.py deleted file mode 100644 index ebc72b3aeac..00000000000 --- a/addons/auth_signup/auth_signup.py +++ /dev/null @@ -1,39 +0,0 @@ -from openerp.osv import osv, fields - -class res_users(osv.Model): - _inherit = 'res.users' - - _sql_constraints = [ - ('email_uniq', 'UNIQUE (user_email)', 'You can not have two users with the same email!') - ] - -class signup_signup(osv.TransientModel): - _name = 'auth.signup' - - # TODO add captcha - _columns = { - 'name': fields.char('Name', size=64), - 'email': fields.char('Email', size=64), - 'password': fields.char('Password', size=64), - } - - def create(self, cr, uid, values, context=None): - # NOTE here, invalid values raises exceptions to avoid storing - # sensitive data into the database (which then are available to anyone) - - new_user = { - 'name': values['name'], - 'login': values['email'], - 'user_email': values['email'], - 'password': values['password'], - 'active': True, - } - - user_template_id = self.pool.get('ir.config_parameter').get_param(cr, uid, 'auth.signup_template_user_id', 0) - if user_template_id: - self.pool.get('res.users').copy(cr, 1, user_template_id, new_user, context=context) - else: - self.pool.get('res.users').create(cr, 1, new_user, context=context) - - # Dont store anything - return 0 diff --git a/addons/auth_signup/controllers/__init__.py b/addons/auth_signup/controllers/__init__.py new file mode 100644 index 00000000000..e11f9ba81bb --- /dev/null +++ b/addons/auth_signup/controllers/__init__.py @@ -0,0 +1,3 @@ +import main + +# vim:expandtab:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/auth_signup/controllers/main.py b/addons/auth_signup/controllers/main.py new file mode 100644 index 00000000000..7b84c2e2214 --- /dev/null +++ b/addons/auth_signup/controllers/main.py @@ -0,0 +1,37 @@ +import logging + +import werkzeug.urls + +import openerp.modules.registry +import openerp.addons.web.controllers.main +import openerp.addons.web.common.http as openerpweb + +_logger = logging.getLogger(__name__) + +class OpenIDController(openerpweb.Controller): + _cp_path = '/auth_signup' + + @openerpweb.httprequest + def signup(self, req, dbname, name, login, password): + registry = openerp.modules.registry.RegistryManager.get(dbname) + cr = registry.db.cursor() + try: + try: + u = registry.get('res.users') + r = u.auth_signup(cr, 1, name, login, password) + cr.commit() + return openerp.addons.web.controllers.main.login_and_redirect(req, dbname, login, password) + # or + req.authenticate(*r) + url = "/" + except AttributeError: + # auth_signup is not installed + url = "/#action=auth_signup&error=1" + except Exception,e: + # signup error + url = "/#action=auth_signup&error=2" + finally: + cr.close() + return werkzeug.utils.redirect(url) + +# vim:expandtab:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/auth_signup/res_users.py b/addons/auth_signup/res_users.py new file mode 100644 index 00000000000..46f264c6729 --- /dev/null +++ b/addons/auth_signup/res_users.py @@ -0,0 +1,47 @@ +import openerp +from openerp.osv import osv, fields + +class res_users(osv.Model): + _inherit = 'res.users' + + def auth_signup_create(self, cr, uid, new_user, context=None): + user_template_id = self.pool.get('ir.config_parameter').get_param(cr, uid, 'auth.signup_template_user_id', 0) + if user_template_id: + self.pool.get('res.users').copy(cr, 1, user_template_id, new_user, context=context) + else: + self.pool.get('res.users').create(cr, 1, new_user, context=context) + + def auth_signup_check(self, cr, uid, login, key, context=None): + res = self.search(cr, uid, [("login","=",login)]) + if res: + user_id = res[0]['id'] + self.check(cr.dbname, user_id, key) + return user_id + return False + + def auth_signup(self, cr, uid, name, login, password, context=None): + r = (cr.dbname, login, password) + try: + # check for existing user + if not self.auth_signup_check(cr, uid, login, password): + print "NEW USER" + # new user + new_user = { + 'name': name, + 'login': login, + 'user_email': login, + 'password': password, + 'active': True, + } + self.auth_signup_create(cr,uid, new_user) + return r + else: + print "Existing same" + # already existing with same password + return r + except openerp.exceptions.AccessDenied: + print "Existing different" + # already existing with diffrent password + raise + +# diff --git a/addons/auth_signup/static/src/css/auth_signup.css b/addons/auth_signup/static/src/css/auth_signup.css deleted file mode 100644 index 1e8d7d9d8d8..00000000000 --- a/addons/auth_signup/static/src/css/auth_signup.css +++ /dev/null @@ -1,9 +0,0 @@ -.openerp .oe_login .oe_login_pane ul.oe_signup a { - color: #eeeeee; - margin: 0 8px; -} -.openerp .oe_login .oe_login_pane ul.oe_signup a:hover { - text-decoration: underline; -} - - diff --git a/addons/auth_signup/static/src/js/auth_signup.js b/addons/auth_signup/static/src/js/auth_signup.js index 7384fe1e5f5..aba6822739d 100644 --- a/addons/auth_signup/static/src/js/auth_signup.js +++ b/addons/auth_signup/static/src/js/auth_signup.js @@ -1,65 +1,38 @@ openerp.auth_signup = function(instance) { + instance.auth_signup = instance.auth_signup || {}; var _t = instance.web._t; instance.web.Login.include({ start: function() { var self = this; - this.$('a.oe_signup').click(function() { - var db = self.$("form [name=db]").val(); - if (!db) { - self.do_warn(_t("Login"), _t("No database selected!")); - return false; - } - - var cnx = instance.connection; - if (cnx.session_is_valid()) { - self._signup(); - } else { - cnx.session_authenticate(db, 'anonymous', 'anonymous', true).then(function() { - self._signup(); - }).fail(function(error, event) { - console.log(error); - // cannot log as anonymous or auth_signup not installed - self.do_warn(_t('Sign Up'), _.str.sprintf(_t('Signup functionnality is not available for database %s'), db), true); - }); - } + var dbname = self.$("form [name=db]").val(); + self.do_action({ + type: 'ir.actions.client', + tag: 'auth_signup.signup', + params: {'dbname': dbname}, + target: 'new', + name: 'Sign up' + }); return true; }); return this._super(); - }, - - _signup: function() { - this.do_action({ - type: 'ir.actions.client', - tag: 'auth_signup.signup', - target: 'new', - name: 'Sign up' - }); - } }); - instance.auth_signup = instance.auth_signup || {}; instance.auth_signup.Signup = instance.web.Widget.extend({ template: 'auth_signup.signup', - init: function() { - this._super.apply(this, arguments); - this.dataset = new instance.web.DataSet(this, 'auth.signup'); + init: function(parent, params) { + this.params = params; + return this._super(); }, start: function() { var self = this; - this.$('input[type=password]').change(function() { + this.$('input[name=password_confirmation]').keyup(function() { var v = $(this).val(); - var e = !_.isEmpty(v); - if (e) { - e =_.all(self.$('input[type=password]'), function(i) { - return $(i).val() === v; - }); - } var $b = self.$('button'); - if (e) { + if (_.isEmpty(v) || self.$('input[name=password]').val() === v) { $b.removeAttr('disabled'); } else { $b.attr('disabled', 'disabled'); @@ -70,36 +43,19 @@ openerp.auth_signup = function(instance) { if(ev) { ev.preventDefault(); } - var name = self.$('input[name=name]').val(); - var email = self.$('input[name=email]').val(); - var password = self.$('input[name=password]').val(); - - self.dataset.create({ - name: name, - email: email, - password: password - }, function() { - self.do_action({ - type: 'ir.actions.client', - tag: 'login', - params: { - db: instance.connection.db, - login: email, - password: password, - login_successful: function() { - self.do_action('home'); - } - } - }); - }); + var params = { + dbname : self.params.dbname, + name: self.$('input[name=name]').val(), + login: self.$('input[name=email]').val(), + password: self.$('input[name=password]').val(), + }; + var url = "/auth_signup/signup?" + $.param(params); + window.location = url; return false; - }); - return $.when(this._super()); + return this._super(); } - }); instance.web.client_actions.add("auth_signup.signup", "instance.auth_signup.Signup"); - }; diff --git a/addons/auth_signup/static/src/xml/auth_signup.xml b/addons/auth_signup/static/src/xml/auth_signup.xml index 92343d96281..c2eec846d15 100644 --- a/addons/auth_signup/static/src/xml/auth_signup.xml +++ b/addons/auth_signup/static/src/xml/auth_signup.xml @@ -14,10 +14,10 @@
      - Name = - Email = - Password = - Confirmation = + Name =
      + Email =
      + Password =
      + Confirmation =
      From 4dc0440cb1900b05bf1f84e6bdd33fe6746c0b25 Mon Sep 17 00:00:00 2001 From: Antony Lesuisse Date: Sun, 12 Aug 2012 19:43:06 +0200 Subject: [PATCH 100/236] wip options bzr revid: al@openerp.com-20120812174306-p47bfuzo2r030r3t --- addons/auth_signup/res_users.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/addons/auth_signup/res_users.py b/addons/auth_signup/res_users.py index 46f264c6729..1b73dc2f622 100644 --- a/addons/auth_signup/res_users.py +++ b/addons/auth_signup/res_users.py @@ -5,6 +5,9 @@ class res_users(osv.Model): _inherit = 'res.users' def auth_signup_create(self, cr, uid, new_user, context=None): + # add login, email, name passowrd + # if options groups + # add groups user_template_id = self.pool.get('ir.config_parameter').get_param(cr, uid, 'auth.signup_template_user_id', 0) if user_template_id: self.pool.get('res.users').copy(cr, 1, user_template_id, new_user, context=context) From 7ff74cc4b118e317a8fc25a5a507b807deeafd26 Mon Sep 17 00:00:00 2001 From: Antony Lesuisse Date: Mon, 13 Aug 2012 01:26:12 +0200 Subject: [PATCH 101/236] oauth wip bzr revid: al@openerp.com-20120812232612-9cib8w333no9hg3d --- addons/auth_oauth/__init__.py | 22 +-------- addons/auth_oauth/controllers/__init__.py | 3 ++ addons/auth_oauth/controllers/main.py | 39 ++++++++++++++++ addons/auth_oauth/res_users.py | 40 ++++++++++++++++ addons/auth_oauth/static/src/js/auth_oauth.js | 46 ++++++------------- 5 files changed, 97 insertions(+), 53 deletions(-) create mode 100644 addons/auth_oauth/controllers/__init__.py create mode 100644 addons/auth_oauth/controllers/main.py create mode 100644 addons/auth_oauth/res_users.py diff --git a/addons/auth_oauth/__init__.py b/addons/auth_oauth/__init__.py index a55097cb836..68bb6c79406 100644 --- a/addons/auth_oauth/__init__.py +++ b/addons/auth_oauth/__init__.py @@ -1,20 +1,2 @@ -# -*- coding: utf-8 -*- -############################################################################## -# -# OpenERP, Open Source Management Solution -# Copyright (C) 2010-2011 OpenERP s.a. (). -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# -############################################################################## \ No newline at end of file +import controllers +import res_users diff --git a/addons/auth_oauth/controllers/__init__.py b/addons/auth_oauth/controllers/__init__.py new file mode 100644 index 00000000000..e11f9ba81bb --- /dev/null +++ b/addons/auth_oauth/controllers/__init__.py @@ -0,0 +1,3 @@ +import main + +# vim:expandtab:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/auth_oauth/controllers/main.py b/addons/auth_oauth/controllers/main.py new file mode 100644 index 00000000000..ea50c6a23e6 --- /dev/null +++ b/addons/auth_oauth/controllers/main.py @@ -0,0 +1,39 @@ +import logging + +import werkzeug.urls + +import openerp.modules.registry +import openerp.addons.web.controllers.main +import openerp.addons.web.common.http as openerpweb + +_logger = logging.getLogger(__name__) + +class OAuthController(openerpweb.Controller): + _cp_path = '/auth_oauth' + + @openerpweb.httprequest + def signin(self, req, **kw): + dbname = kw.get("state") + registry = openerp.modules.registry.RegistryManager.get(dbname) + cr = registry.db.cursor() + try: + try: + u = registry.get('res.users') + r = u.auth_oauth(cr, 1, kw) + cr.commit() + return openerp.addons.web.controllers.main.login_and_redirect(req, *r) + # or + req.authenticate(*r) + url = "/" + except AttributeError: + # auth_signup is not installed + url = "/#action=auth_signup&error=1" + except Exception,e: + # signup error + url = "/#action=auth_signup&error=2" + finally: + cr.close() + return "" + return werkzeug.utils.redirect(url) + +# vim:expandtab:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/auth_oauth/res_users.py b/addons/auth_oauth/res_users.py new file mode 100644 index 00000000000..68e9a31e3eb --- /dev/null +++ b/addons/auth_oauth/res_users.py @@ -0,0 +1,40 @@ +import urllib2 + +import openerp + +from openerp.osv import osv, fields + +class res_users(osv.Model): + _inherit = 'res.users' + + def auth_oauth(self, cr, uid, params, context=None): + print params + url = 'https://www.googleapis.com/oauth2/v1/tokeninfo?access_token=' + params.get('access_token') + f = urllib2.urlopen(url) + validation = f.read() + print validation + r = (cr.dbname, login, password) + try: + # check for existing user + if not self.auth_signup_check(cr, uid, login, password): + print "NEW USER" + # new user + new_user = { + 'name': name, + 'login': login, + 'user_email': login, + 'password': password, + 'active': True, + } + self.auth_signup_create(cr,uid, new_user) + return r + else: + print "Existing same" + # already existing with same password + return r + except openerp.exceptions.AccessDenied: + print "Existing different" + # already existing with diffrent password + raise + +# diff --git a/addons/auth_oauth/static/src/js/auth_oauth.js b/addons/auth_oauth/static/src/js/auth_oauth.js index a49d6777e7d..057865cab4e 100644 --- a/addons/auth_oauth/static/src/js/auth_oauth.js +++ b/addons/auth_oauth/static/src/js/auth_oauth.js @@ -1,5 +1,4 @@ openerp.auth_oauth = function(instance) { - var QWeb = instance.web.qweb; instance.web.Login = instance.web.Login.extend({ @@ -8,56 +7,37 @@ openerp.auth_oauth = function(instance) { var self = this; self.$element.on('click', '.oe_login_oauth a', this.on_google_oauth); }, - on_google_oauth: function(ev) { - var url = this._oauth_url(); - window.location = url; - }, - _oauth_url: function() { + oauth_url: function(state) { var endpoint = 'https://accounts.google.com/o/oauth2/auth'; - var params = { + var params = { response_type: 'token', client_id: '108010644258-duuhmp6pu7li4tsmnqg7j9rvdeklg0ki.apps.googleusercontent.com', redirect_uri: 'https://localhost/', scope: 'https://www.googleapis.com/auth/userinfo.email', - state: 'TEST', + state: state, }; var url = endpoint + '?' + $.param(params); return url; }, - // do_warn: function(title, msg) { - // }, - // reset_error_message: function() { - // } + on_google_oauth: function(ev) { + var dbname = self.$("form [name=db]").val(); + var url = this.oauth_url(dbname); + window.location = url; + }, }); instance.web.WebClient = instance.web.WebClient.extend({ start: function() { this._super.apply(this, arguments); - // console.log($.deparam(window.location.hash)); var params = $.deparam(window.location.hash); if (params.hasOwnProperty('access_token')) { - console.log(params); - // Do login using Google User credentials - var url = { - - }; + // fix params for python marshmalling + params.state = params["#state"] + delete params["#state"] + var url = "/auth_oauth/signin" + '?' + $.param(params); + window.location = url; } }, - bind_hashchange: function() { - var state = $.bbq.getState(true); - if (state.hasOwnProperty("access_token")) { - state.action = "login"; - $.bbq.setState(state); - } - this._super(); - - }, - // on_hashchange: function(event) { - // console.log(event); - // this._super.apply(this, arguments); - // }, }); }; - -// https://accounts.google.com/o/oauth2/auth?state=%2Fprofile&redirect_uri=http%3A%2F%2Foauth2-login-demo.appspot.com%2Fcode&response_type=code&client_id=812741506391.apps.googleusercontent.com&approval_prompt=force&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile \ No newline at end of file From d946d35ee0590829b16b4403145a2b25b52be251 Mon Sep 17 00:00:00 2001 From: Antony Lesuisse Date: Mon, 13 Aug 2012 02:01:49 +0200 Subject: [PATCH 102/236] oauth wip bzr revid: al@openerp.com-20120813000149-lslqyhszzz8axhrv --- addons/auth_signup/res_users.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/addons/auth_signup/res_users.py b/addons/auth_signup/res_users.py index 1b73dc2f622..1c9e531c180 100644 --- a/addons/auth_signup/res_users.py +++ b/addons/auth_signup/res_users.py @@ -5,9 +5,14 @@ class res_users(osv.Model): _inherit = 'res.users' def auth_signup_create(self, cr, uid, new_user, context=None): - # add login, email, name passowrd - # if options groups - # add groups + # new_user: + # login + # email + # name (optional) + # partner_id (optional) + # groups (optional) + # sign (for partner_id and groups) + # user_template_id = self.pool.get('ir.config_parameter').get_param(cr, uid, 'auth.signup_template_user_id', 0) if user_template_id: self.pool.get('res.users').copy(cr, 1, user_template_id, new_user, context=context) From db7e49ca91d483213c8ba61d4314411c899e0f23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Mon, 13 Aug 2012 10:10:54 +0200 Subject: [PATCH 103/236] [FIX] project_timesheet tests: user creation should also have its partner. bzr revid: tde@openerp.com-20120813081054-csyaq8p7lf7e1nvh --- addons/mail/res_users.py | 1 - .../test/worktask_entry_to_timesheetline_entry.yml | 6 ++++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/addons/mail/res_users.py b/addons/mail/res_users.py index 3d8ed92609b..6a18560de31 100644 --- a/addons/mail/res_users.py +++ b/addons/mail/res_users.py @@ -85,7 +85,6 @@ class res_users(osv.osv): cr.execute('ALTER TABLE res_users ALTER COLUMN alias_id SET NOT NULL') except Exception: pass - def create(self, cr, uid, data, context=None): # create default alias same as the login diff --git a/addons/project_timesheet/test/worktask_entry_to_timesheetline_entry.yml b/addons/project_timesheet/test/worktask_entry_to_timesheetline_entry.yml index 214aa04d25b..8b58791f699 100644 --- a/addons/project_timesheet/test/worktask_entry_to_timesheetline_entry.yml +++ b/addons/project_timesheet/test/worktask_entry_to_timesheetline_entry.yml @@ -1,11 +1,13 @@ - Create a user 'HR Manager' - + !record {model: res.partner, id: res_partner_hrmanager0}: + name: HR Manager + lang: en_US !record {model: res.users, id: res_users_hrmanager0}: company_id: base.main_company - lang: en_US + partner_id: res_partner_hrmanager0 login: hr - name: HR Manager password: hr groups_id: - base.group_hr_manager From 55e9fdf3606f3ce79b593ceefa5a554614ee75f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Mon, 13 Aug 2012 11:16:27 +0200 Subject: [PATCH 104/236] [FIX] res.users: defer onchange_type calls from partner form view to the partner. bzr revid: tde@openerp.com-20120813091627-nfv0vkfjo87jhplp --- openerp/addons/base/res/res_users.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/openerp/addons/base/res/res_users.py b/openerp/addons/base/res/res_users.py index ada625c6bcf..f8c745edc10 100644 --- a/openerp/addons/base/res/res_users.py +++ b/openerp/addons/base/res/res_users.py @@ -171,6 +171,14 @@ class users(osv.osv): } } + def onchange_type(self, cr, uid, ids, is_company, context=None): + """ Wrapper on the user.partner onchange_type, because some calls to the + partner form view applied to the user may trigger the + partner.onchange_type method, but applied to the user object. + """ + partner_ids = [user.partner_id.id for user in self.browse(cr, uid, ids, context=context)] + return self.pool.get('res_partner').onchange_type(cr, uid, partner_ids, is_company, context=context) + def read(self,cr, uid, ids, fields=None, context=None, load='_classic_read'): def override_password(o): if 'password' in o and ( 'id' not in o or o['id'] != uid ): From e120d9a699247c6fbdfbf21648a71e321642b2bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Mon, 13 Aug 2012 11:17:19 +0200 Subject: [PATCH 105/236] [REV] Reverted last fixes. Think it comes from outer space. bzr revid: tde@openerp.com-20120813091719-6551uziq8ts4kj6a --- .../test/worktask_entry_to_timesheetline_entry.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/addons/project_timesheet/test/worktask_entry_to_timesheetline_entry.yml b/addons/project_timesheet/test/worktask_entry_to_timesheetline_entry.yml index 8b58791f699..8bb570bd7d8 100644 --- a/addons/project_timesheet/test/worktask_entry_to_timesheetline_entry.yml +++ b/addons/project_timesheet/test/worktask_entry_to_timesheetline_entry.yml @@ -1,9 +1,6 @@ - Create a user 'HR Manager' - - !record {model: res.partner, id: res_partner_hrmanager0}: - name: HR Manager - lang: en_US !record {model: res.users, id: res_users_hrmanager0}: company_id: base.main_company partner_id: res_partner_hrmanager0 From 659f3cc996922959ab314666909115ff829dfc04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Mon, 13 Aug 2012 11:36:41 +0200 Subject: [PATCH 106/236] [FIX] Bloody res_partner should be res.partner. bzr revid: tde@openerp.com-20120813093641-ssyfm4au52nupbi1 --- openerp/addons/base/res/res_users.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openerp/addons/base/res/res_users.py b/openerp/addons/base/res/res_users.py index f8c745edc10..9e0abb446cf 100644 --- a/openerp/addons/base/res/res_users.py +++ b/openerp/addons/base/res/res_users.py @@ -177,7 +177,7 @@ class users(osv.osv): partner.onchange_type method, but applied to the user object. """ partner_ids = [user.partner_id.id for user in self.browse(cr, uid, ids, context=context)] - return self.pool.get('res_partner').onchange_type(cr, uid, partner_ids, is_company, context=context) + return self.pool.get('res.partner').onchange_type(cr, uid, partner_ids, is_company, context=context) def read(self,cr, uid, ids, fields=None, context=None, load='_classic_read'): def override_password(o): From 4067f46ff7fd75966cec799fb223ec944b108a9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Mon, 13 Aug 2012 11:36:56 +0200 Subject: [PATCH 107/236] [IMP] base.sql: no need to have a 'name' column on res.users I think. bzr revid: tde@openerp.com-20120813093656-ywab7wjdpc5gwl02 --- openerp/addons/base/base.sql | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/openerp/addons/base/base.sql b/openerp/addons/base/base.sql index c6ca6dbb76d..441fe536a0a 100644 --- a/openerp/addons/base/base.sql +++ b/openerp/addons/base/base.sql @@ -146,7 +146,6 @@ select setval('ir_ui_menu_id_seq', 2); CREATE TABLE res_users ( id serial NOT NULL, - name varchar(64) not null, active boolean default True, login varchar(64) NOT NULL UNIQUE, password varchar(64) default null, @@ -384,7 +383,7 @@ CREATE TABLE ir_model_relation ( -- Users --------------------------------- -insert into res_users (id,login,password,name,active,company_id,partner_id,lang) values (1,'admin','admin','Administrator',True,1,1,'en_US'); +insert into res_users (id,login,password,active,company_id,partner_id,lang) values (1,'admin','admin',True,1,1,'en_US'); insert into ir_model_data (name,module,model,noupdate,res_id) values ('user_root','base','res.users',True,1); -- Compatibility purpose, to remove V6.0 From 0e554c738d870a88ed4e426ef1ea105bfc96db77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Mon, 13 Aug 2012 12:06:22 +0200 Subject: [PATCH 108/236] [FIX] Fixed last revision, about name removel in base.sql and so on. bzr revid: tde@openerp.com-20120813100622-jhqv244dskhlh2er --- openerp/addons/base/res/res_users.py | 2 +- openerp/service/web_services.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/openerp/addons/base/res/res_users.py b/openerp/addons/base/res/res_users.py index 9e0abb446cf..115b78d93e6 100644 --- a/openerp/addons/base/res/res_users.py +++ b/openerp/addons/base/res/res_users.py @@ -110,7 +110,7 @@ class users(osv.osv): } _name = "res.users" _description = 'Users' - _order = 'name' + _order = 'login' def _set_new_password(self, cr, uid, id, name, value, args, context=None): if value is False: diff --git a/openerp/service/web_services.py b/openerp/service/web_services.py index ccb753acdc8..7c08003bf7a 100644 --- a/openerp/service/web_services.py +++ b/openerp/service/web_services.py @@ -77,7 +77,7 @@ def _initialize_db(serv, id, db_name, demo, lang, user_password): cr.execute('UPDATE res_users SET password=%s, lang=%s, active=True WHERE login=%s', ( user_password, lang, 'admin')) - cr.execute('SELECT login, password, name ' \ + cr.execute('SELECT login, password ' \ ' FROM res_users ' \ ' ORDER BY login') serv.actions[id].update(users=cr.dictfetchall(), clean=True) From 401bbbc940100bc655a0d85f93ae49e850b6e25c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Mon, 13 Aug 2012 12:18:47 +0200 Subject: [PATCH 109/236] [IMP] res.users: added a wrapper on onchange_address, for partner form view delegated to res.users. bzr revid: tde@openerp.com-20120813101847-rmctiebnhm2pmfcz --- openerp/addons/base/res/res_users.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/openerp/addons/base/res/res_users.py b/openerp/addons/base/res/res_users.py index 115b78d93e6..f4335357a4b 100644 --- a/openerp/addons/base/res/res_users.py +++ b/openerp/addons/base/res/res_users.py @@ -179,6 +179,14 @@ class users(osv.osv): partner_ids = [user.partner_id.id for user in self.browse(cr, uid, ids, context=context)] return self.pool.get('res.partner').onchange_type(cr, uid, partner_ids, is_company, context=context) + def onchange_address(self, cr, uid, ids, use_parent_address, parent_id, context=None): + """ Wrapper on the user.partner onchange_address, because some calls to the + partner form view applied to the user may trigger the + partner.onchange_type method, but applied to the user object. + """ + partner_ids = [user.partner_id.id for user in self.browse(cr, uid, ids, context=context)] + return self.pool.get('res.partner').onchange_address(cr, uid, partner_ids, is_company, context=context) + def read(self,cr, uid, ids, fields=None, context=None, load='_classic_read'): def override_password(o): if 'password' in o and ( 'id' not in o or o['id'] != uid ): From f4402a11445f05b33449554f3697840703cc1770 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Mon, 13 Aug 2012 12:41:35 +0200 Subject: [PATCH 110/236] [FIX] Wrapper on onchange_address. bzr revid: tde@openerp.com-20120813104135-6ft7wh4ssdl7ouid --- openerp/addons/base/res/res_users.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openerp/addons/base/res/res_users.py b/openerp/addons/base/res/res_users.py index f4335357a4b..573d0468f18 100644 --- a/openerp/addons/base/res/res_users.py +++ b/openerp/addons/base/res/res_users.py @@ -185,7 +185,7 @@ class users(osv.osv): partner.onchange_type method, but applied to the user object. """ partner_ids = [user.partner_id.id for user in self.browse(cr, uid, ids, context=context)] - return self.pool.get('res.partner').onchange_address(cr, uid, partner_ids, is_company, context=context) + return self.pool.get('res.partner').onchange_address(cr, uid, partner_ids, use_parent_address, parent_id, context=context) def read(self,cr, uid, ids, fields=None, context=None, load='_classic_read'): def override_password(o): From f80c2478120e4fcf4e80f5c2932328dce88218b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Mon, 13 Aug 2012 12:54:20 +0200 Subject: [PATCH 111/236] [FIX] Still fixing stpid bugs. bzr revid: tde@openerp.com-20120813105420-stxm7cjc981bj8fq --- .../test/worktask_entry_to_timesheetline_entry.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/addons/project_timesheet/test/worktask_entry_to_timesheetline_entry.yml b/addons/project_timesheet/test/worktask_entry_to_timesheetline_entry.yml index 8bb570bd7d8..fad8e2af2c5 100644 --- a/addons/project_timesheet/test/worktask_entry_to_timesheetline_entry.yml +++ b/addons/project_timesheet/test/worktask_entry_to_timesheetline_entry.yml @@ -3,7 +3,6 @@ - !record {model: res.users, id: res_users_hrmanager0}: company_id: base.main_company - partner_id: res_partner_hrmanager0 login: hr password: hr groups_id: From c2c27b18582db97b0d17f9c32291f28c76cf8edb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Mon, 13 Aug 2012 13:15:21 +0200 Subject: [PATCH 112/236] [FIX$] This time, it's the good fix. bzr revid: tde@openerp.com-20120813111521-uws1uophrd39krfg --- .../test/worktask_entry_to_timesheetline_entry.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/addons/project_timesheet/test/worktask_entry_to_timesheetline_entry.yml b/addons/project_timesheet/test/worktask_entry_to_timesheetline_entry.yml index fad8e2af2c5..e670f5bae06 100644 --- a/addons/project_timesheet/test/worktask_entry_to_timesheetline_entry.yml +++ b/addons/project_timesheet/test/worktask_entry_to_timesheetline_entry.yml @@ -3,6 +3,7 @@ - !record {model: res.users, id: res_users_hrmanager0}: company_id: base.main_company + name: HR Manager login: hr password: hr groups_id: From 7341bd30cc02a4360406864a17fd2e8b801cd6b3 Mon Sep 17 00:00:00 2001 From: niv-openerp Date: Mon, 13 Aug 2012 13:46:19 +0200 Subject: [PATCH 113/236] Added html field type bzr revid: nicolas.vanhoren@openerp.com-20120813114619-lqr9zu0rkz6737rp --- openerp/osv/fields.py | 3 +++ openerp/osv/orm.py | 1 + 2 files changed, 4 insertions(+) diff --git a/openerp/osv/fields.py b/openerp/osv/fields.py index 4ff23956050..b361ab664b6 100644 --- a/openerp/osv/fields.py +++ b/openerp/osv/fields.py @@ -227,6 +227,9 @@ class char(_column): class text(_column): _type = 'text' +class html(text): + _type = 'html' + import __builtin__ class float(_column): diff --git a/openerp/osv/orm.py b/openerp/osv/orm.py index 563c514726c..069664cfebe 100644 --- a/openerp/osv/orm.py +++ b/openerp/osv/orm.py @@ -545,6 +545,7 @@ FIELDS_TO_PGTYPES = { fields.boolean: 'bool', fields.integer: 'int4', fields.text: 'text', + fields.html: 'text', fields.date: 'date', fields.datetime: 'timestamp', fields.binary: 'bytea', From d8796d429cf0a1b1df896944445ad2c6f91a8859 Mon Sep 17 00:00:00 2001 From: niv-openerp Date: Mon, 13 Aug 2012 13:46:38 +0200 Subject: [PATCH 114/236] Now uses the html field type for cl editor bzr revid: nicolas.vanhoren@openerp.com-20120813114638-pla647nupeha1tim --- addons/web/static/src/js/view_form.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/web/static/src/js/view_form.js b/addons/web/static/src/js/view_form.js index baf8c151b83..1ee5d8477f6 100644 --- a/addons/web/static/src/js/view_form.js +++ b/addons/web/static/src/js/view_form.js @@ -4802,7 +4802,7 @@ instance.web.form.widgets = new instance.web.Registry({ 'email' : 'instance.web.form.FieldEmail', 'url' : 'instance.web.form.FieldUrl', 'text' : 'instance.web.form.FieldText', - 'text_html' : 'instance.web.form.FieldTextHtml', + 'html' : 'instance.web.form.FieldTextHtml', 'date' : 'instance.web.form.FieldDate', 'datetime' : 'instance.web.form.FieldDatetime', 'selection' : 'instance.web.form.FieldSelection', From f7d274850e9ff73f5ef3e572935c341a3b435a0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Mon, 13 Aug 2012 14:22:07 +0200 Subject: [PATCH 115/236] [IMP] [CLEAN] res_partner: image_medium used in view, because image_small was too small; cleaned some print statemetns in res_users. bzr revid: tde@openerp.com-20120813122207-04f91lvor03g1xek --- openerp/addons/base/res/res_partner_view.xml | 2 +- openerp/addons/base/res/res_users.py | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/openerp/addons/base/res/res_partner_view.xml b/openerp/addons/base/res/res_partner_view.xml index b5bfda2f0a0..c26987cafaa 100644 --- a/openerp/addons/base/res/res_partner_view.xml +++ b/openerp/addons/base/res/res_partner_view.xml @@ -99,7 +99,7 @@
      - +