From cffa820e30441306cdb254633cf2db2e9f11354d Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Wed, 23 Jan 2013 12:39:02 +0100 Subject: [PATCH 01/68] [IMP] mail_alias: get_alias method return a list of dict (id, email, global) bzr revid: chm@openerp.com-20130123113902-suek7ycw1jm6h3sa --- addons/mail/mail_alias.py | 45 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/addons/mail/mail_alias.py b/addons/mail/mail_alias.py index d9c49d833ab..8e76efef859 100644 --- a/addons/mail/mail_alias.py +++ b/addons/mail/mail_alias.py @@ -22,6 +22,7 @@ import logging import re import unicodedata +import ast from openerp.osv import fields, osv from openerp.tools import ustr @@ -196,3 +197,47 @@ class mail_alias(osv.Model): model_id = self.pool.get('ir.model').search(cr, uid, [('model', '=', model_name)], context=context)[0] vals['alias_model_id'] = model_id return self.create(cr, uid, vals, context=context) + + def get_alias(self, cr, uid, model, alias_defaults={}, context=None): + """Return the mail alias + """ + model_id = self.pool.get('ir.model').search(cr, uid, [('model', '=', model)], context=context)[0] + + result = [] + # get the value with required attribute + domain = [('alias_model_id', '=', model_id)] + if alias_defaults: + for item in alias_defaults.items(): + domain += ['|', '|', '|', + ('alias_defaults', 'like', ("%%'%s': %s%%" % (item[0], item[1]))), + ('alias_defaults', 'like', ("%%'%s':%s%%" % (item[0], item[1]))), + ('alias_defaults', 'like', ("%%'%s': '%s'%%" % (item[0], item[1]))), + ('alias_defaults', 'like', ("%%'%s':'%s'%%" % (item[0], item[1])))] + else: + domain += [('alias_defaults', 'like', "{}")] + + ids = self.search(cr, uid, domain, context=context) + if ids: + for record in self.browse(cr, uid, ids, context=context): + test = True + if alias_defaults: + for item in ast.literal_eval(record.alias_defaults).items(): + if alias_defaults.get(item[0]) == None or alias_defaults.get(item[0]) != item[1]: + test = False + continue + if test: + result.append( {'id': record.id, 'email': "%s@%s" % (record.alias_name, record.alias_domain), 'global': False}) + + # get the default value + if alias_defaults: + domain = [('alias_model_id', '=', model_id)] + for item in alias_defaults.items(): + domain += [ + ('alias_defaults', 'not like', ("%%'%s'%%" % (item[0])))] + + ids = self.search(cr, uid, domain, context=context) + if ids: + for record in self.browse(cr, uid, ids, context=context): + result.append( {'id': record.id, 'email': "%s@%s" % (record.alias_name, record.alias_domain), 'global': True}) + + return result From dd185ca108804cc2c0ba515858289166021f6845 Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Wed, 23 Jan 2013 12:43:36 +0100 Subject: [PATCH 02/68] [IMP] mail_alias: add the context help_alias to project, crm lead, crm issue, res partner lead bzr revid: chm@openerp.com-20130123114336-mgnafjnfk7yckd6q --- addons/crm/crm_lead_menu.xml | 13 +++++++++++-- addons/crm/res_partner_view.xml | 7 +++++-- addons/project/project_view.xml | 7 ++++++- addons/project_issue/project_issue_menu.xml | 3 +++ addons/project_issue/project_issue_view.xml | 15 ++++++++++++++- 5 files changed, 39 insertions(+), 6 deletions(-) diff --git a/addons/crm/crm_lead_menu.xml b/addons/crm/crm_lead_menu.xml index 8c38ed41a1c..623131cbf79 100644 --- a/addons/crm/crm_lead_menu.xml +++ b/addons/crm/crm_lead_menu.xml @@ -9,7 +9,11 @@ ['|', ('type','=','lead'), ('type','=',False)] - {'default_type':'lead', 'stage_type':'lead'} + { + 'default_type':'lead', + 'stage_type':'lead', + 'help_alias': {'type': 'lead'} + }

Click to create an unqualified lead. @@ -44,7 +48,12 @@ crm.lead kanban,tree,graph,form,calendar [('type','=','opportunity')] - {'stage_type': 'opportunity', 'default_type': 'opportunity', 'default_user_id': uid} + { + 'stage_type': 'opportunity', + 'default_type': 'opportunity', + 'default_user_id': uid, + 'help_alias': {'type': 'lead'} + } diff --git a/addons/crm/res_partner_view.xml b/addons/crm/res_partner_view.xml index 00a071fa954..a879dc49771 100644 --- a/addons/crm/res_partner_view.xml +++ b/addons/crm/res_partner_view.xml @@ -30,8 +30,11 @@ crm.lead kanban,tree,form,graph,calendar [('type','=','opportunity')] - {'search_default_partner_id': active_id, - 'stage_type': 'opportunity', 'default_type': 'opportunity'} + { + 'search_default_partner_id': active_id, + 'stage_type': 'opportunity', + 'default_type': 'opportunity', + 'help_alias': 'alias_defaults': {'type': 'lead'} diff --git a/addons/project/project_view.xml b/addons/project/project_view.xml index b102c01193d..8059cb0b78a 100644 --- a/addons/project/project_view.xml +++ b/addons/project/project_view.xml @@ -50,7 +50,11 @@ Tasks project.task kanban,tree,form,calendar,gantt,graph - {'search_default_project_id': [active_id], 'default_project_id': active_id} + { + 'search_default_project_id': [active_id], + 'default_project_id': active_id, + 'help_alias': {'project_id': active_id} + }

@@ -612,6 +616,7 @@ project.task kanban,tree,form,calendar,gantt,graph + {'help_alias': {}}

Click to create a new task. diff --git a/addons/project_issue/project_issue_menu.xml b/addons/project_issue/project_issue_menu.xml index 78841f56156..38d0e830af8 100644 --- a/addons/project_issue/project_issue_menu.xml +++ b/addons/project_issue/project_issue_menu.xml @@ -13,6 +13,9 @@ + { + 'help_alias': {} + }

Click to report a new issue. diff --git a/addons/project_issue/project_issue_view.xml b/addons/project_issue/project_issue_view.xml index 77375450e9a..4ee6508c3b4 100644 --- a/addons/project_issue/project_issue_view.xml +++ b/addons/project_issue/project_issue_view.xml @@ -301,7 +301,20 @@ form Issues kanban,tree,form,calendar,graph - {'search_default_project_id': [active_id], 'default_project_id': active_id} + { + 'search_default_project_id': [active_id], + 'default_project_id': active_id, + 'help_alias': {'project_id': active_id} + } + +

+ Click to report a new issue. +

+ The OpenERP issues tacker allows you to efficiantly manage things + like internal requests, software development bugs, customer + complaints, project troubles, material breakdowns, etc. +

+
From e3a7ae5ac20d2c8f7c3bf60c9c25480c3f935f96 Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Wed, 23 Jan 2013 13:18:55 +0100 Subject: [PATCH 03/68] [IMP] mail_alias: add the context help_alias to hr applicant bzr revid: chm@openerp.com-20130123121855-je4gi42vf9xoe8rz --- addons/hr_recruitment/hr_recruitment_menu.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/addons/hr_recruitment/hr_recruitment_menu.xml b/addons/hr_recruitment/hr_recruitment_menu.xml index dbd4335d730..e8865042cff 100644 --- a/addons/hr_recruitment/hr_recruitment_menu.xml +++ b/addons/hr_recruitment/hr_recruitment_menu.xml @@ -9,6 +9,7 @@ kanban,tree,form,graph,calendar + {'help_alias': {}}

Click to add a new job applicant. From 074ed6434dc378e68cd941d409337fbf4b910ad1 Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Wed, 23 Jan 2013 14:35:11 +0100 Subject: [PATCH 04/68] [IMP] mail_alias: add test and comment bzr revid: chm@openerp.com-20130123133511-urqh79myokm32cgg --- addons/mail/mail_alias.py | 4 +- addons/mail/tests/__init__.py | 3 +- addons/mail/tests/test_mail_alias.py | 59 ++++++++++++++++++++++++++++ 3 files changed, 64 insertions(+), 2 deletions(-) create mode 100644 addons/mail/tests/test_mail_alias.py diff --git a/addons/mail/mail_alias.py b/addons/mail/mail_alias.py index 8e76efef859..0784303d886 100644 --- a/addons/mail/mail_alias.py +++ b/addons/mail/mail_alias.py @@ -199,7 +199,9 @@ class mail_alias(osv.Model): return self.create(cr, uid, vals, context=context) def get_alias(self, cr, uid, model, alias_defaults={}, context=None): - """Return the mail alias + """Return the mail alias for a document + This method is used by the web client (method web.view.insert_alias) + Arguments: model and content of alias_defaults column """ model_id = self.pool.get('ir.model').search(cr, uid, [('model', '=', model)], context=context)[0] diff --git a/addons/mail/tests/__init__.py b/addons/mail/tests/__init__.py index b945da54655..5d581e40276 100644 --- a/addons/mail/tests/__init__.py +++ b/addons/mail/tests/__init__.py @@ -19,10 +19,11 @@ # ############################################################################## -from . import test_mail_message, test_mail_features, test_message_read, test_invite +from . import test_mail_message, test_mail_features, test_message_read, test_invite, test_mail_alias checks = [ test_mail_message, + test_mail_alias, test_mail_features, test_message_read, test_invite, diff --git a/addons/mail/tests/test_mail_alias.py b/addons/mail/tests/test_mail_alias.py new file mode 100644 index 00000000000..803d45a8a65 --- /dev/null +++ b/addons/mail/tests/test_mail_alias.py @@ -0,0 +1,59 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Business Applications +# Copyright (c) 2012-TODAY OpenERP S.A. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +from openerp.tools import mute_logger +from openerp.tests import common + +class test_mail_alias(common.TransactionCase): + + def setUp(self): + super(test_mail_alias, self).setUp() + cr, uid = self.cr, self.uid + + # Usefull models + self.ir_model = self.registry('ir.model') + self.mail_alias = self.registry('mail.alias') + + #@mute_logger('openerp.addons.base.ir.ir_model', 'openerp.osv.orm') + def test_00_mail_alias(self): + """ Testing mail_group access rights and basic mail_thread features """ + cr, uid = self.cr, self.uid + + alias_name_0 = "global+alias+test_0" + alias_name_1 = "document+alias+test_1" + alias_defaults_1 = {'field_pigs': 11} + alias_name_2 = "document+alias+test_2" + alias_defaults_2 = {'field_pigs': 112} + + # Create an alias + partner_model_id = self.ir_model.search(cr, uid, [('model', '=', 'mail.alias')])[0] + alias_id_0 = self.mail_alias.create(cr, uid, + {'alias_model_id': partner_model_id, 'alias_name': alias_name_0, 'alias_defaults': {}}) + alias_id_1 = self.mail_alias.create(cr, uid, + {'alias_model_id': partner_model_id, 'alias_name': alias_name_1, 'alias_defaults': alias_defaults_1}) + alias_id_2 = self.mail_alias.create(cr, uid, + {'alias_model_id': partner_model_id, 'alias_name': alias_name_2, 'alias_defaults': alias_defaults_2}) + + # alias of the model and alias for a docmuent + alias = self.mail_alias.get_alias(cr, uid, 'mail.alias', {'field_pigs': 11}) + self.assertEqual(len(alias), 2, "get_alias don't return the alias of the document and the default alias of the model") + self.assertEqual(alias[0].get('id'), alias_id_1, "get_alias don't return the alias of the document") + self.assertEqual(alias[1].get('id'), alias_id_0, "get_alias don't return the default alias of the model") \ No newline at end of file From 6f91398ce9baccd659d81e4fd6f64674716b092e Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Wed, 23 Jan 2013 14:47:51 +0100 Subject: [PATCH 05/68] [IMP] mail_alias: add documentation bzr revid: chm@openerp.com-20130123134751-ka74ff0guzsjod1c --- addons/mail/doc/mail_alias.rst | 37 ++++++++++++++++++++++++++++++++++ addons/mail/mail_alias.py | 6 ++++-- 2 files changed, 41 insertions(+), 2 deletions(-) create mode 100644 addons/mail/doc/mail_alias.rst diff --git a/addons/mail/doc/mail_alias.rst b/addons/mail/doc/mail_alias.rst new file mode 100644 index 00000000000..fa5a2fe0fda --- /dev/null +++ b/addons/mail/doc/mail_alias.rst @@ -0,0 +1,37 @@ +.. _mail_alias: + +mail.alias +============ + +Models ++++++++ + +``mail.alias`` is a class for mapping of an email address with a given OpenERP Document model. It is used by OpenERP's mail gateway when processing incoming emails sent to the system. If the recipient address (To) of the message matches a Mail Alias, the message will be either processed following the rules of that alias. If the message is a reply it will be attached to the existing discussion on the corresponding record, otherwise a new record of the corresponding model will be created. +This is meant to be used in combination with a catch-all email configuration on the company's mail server, so that as soon as a new mail.alias is created, it becomes immediately usable and OpenERP will accept email for it. + +.. versionchanged:: 7.1 + +Some Fields ++++++++++++ + + - ``alias_name`` : + The name of the email alias, e.g. 'jobs' + - ``alias_model_id`` : + The model (OpenERP Document Kind) to which this alias corresponds. Any incoming email that does not reply to an existing record will cause the creation of a new record of this model (e.g. a Project Task) + - ``alias_defaults`` : + A Python dictionary that will be evaluated to provide default values when creating new records for this alias. + - ``alias_domain`` : + +Methods ++++++++ + + - ``name_get`` : + Return the mail alias display alias_name, inclusing the implicit mail catchall domain from config. + e.g. `jobs@openerp.my.openerp.com` or `sales@openerp.my.openerp.com` + - ``create_unique_alias`` : + Creates an email.alias record according to the values provided in ``vals``, with 2 alterations: the ``alias_name`` value may be suffixed in order to make it unique, and the ``alias_model_id`` value will set to the model ID of the ``model_name`` value, if provided, + - ``get_alias`` : + Return the mail alias for a document (or the default mail alias of the model). + Arguments: + model (model OpenERP) + alias_defaults (A Python dictionary to provide default values when creating new records for this alias.) \ No newline at end of file diff --git a/addons/mail/mail_alias.py b/addons/mail/mail_alias.py index 0784303d886..f7cf115be55 100644 --- a/addons/mail/mail_alias.py +++ b/addons/mail/mail_alias.py @@ -199,9 +199,11 @@ class mail_alias(osv.Model): return self.create(cr, uid, vals, context=context) def get_alias(self, cr, uid, model, alias_defaults={}, context=None): - """Return the mail alias for a document + """Return the mail alias for a document (or the default mail alias of the model) This method is used by the web client (method web.view.insert_alias) - Arguments: model and content of alias_defaults column + Arguments: + model (model OpenERP) + alias_defaults (A Python dictionary to provide default values when creating new records for this alias.) """ model_id = self.pool.get('ir.model').search(cr, uid, [('model', '=', model)], context=context)[0] From 21938b80ff53265672c955522c30f0f0b0e1c608 Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Fri, 25 Jan 2013 12:04:34 +0100 Subject: [PATCH 06/68] [IMP] crm: Sales Teams menu with breadcrum bzr revid: chm@openerp.com-20130125110434-whqnmhrvdqj0r9gh --- addons/crm/__openerp__.py | 3 + addons/crm/crm.py | 16 +++ addons/crm/crm_lead_data.xml | 1 + addons/crm/crm_salesteams.xml | 151 ++++++++++++++++++++++++ addons/crm/crm_view.xml | 94 +++++++-------- addons/crm/security/ir.model.access.csv | 2 +- addons/crm/static/src/css/crm.css | 22 ++++ 7 files changed, 242 insertions(+), 47 deletions(-) create mode 100644 addons/crm/crm_salesteams.xml create mode 100644 addons/crm/static/src/css/crm.css diff --git a/addons/crm/__openerp__.py b/addons/crm/__openerp__.py index 4a792abc9ee..46ce37f188c 100644 --- a/addons/crm/__openerp__.py +++ b/addons/crm/__openerp__.py @@ -80,6 +80,8 @@ Dashboard for CRM will include: 'crm_lead_view.xml', 'crm_lead_menu.xml', + 'crm_salesteams.xml', + 'crm_meeting_menu.xml', 'crm_phonecall_view.xml', @@ -113,6 +115,7 @@ Dashboard for CRM will include: 'test/ui/duplicate_lead.yml', 'test/ui/delete_lead.yml', ], + 'css': ['static/src/css/crm.css'], 'installable': True, 'application': True, 'auto_install': False, diff --git a/addons/crm/crm.py b/addons/crm/crm.py index df6d5e12b66..9fa6b6281f7 100644 --- a/addons/crm/crm.py +++ b/addons/crm/crm.py @@ -109,6 +109,20 @@ class crm_case_section(osv.osv): def get_full_name(self, cr, uid, ids, field_name, arg, context=None): return dict(self.name_get(cr, uid, ids, context=context)) + def get_number_leads(self, cr, uid, section_ids, field_name, arg, context=None): + res = dict.fromkeys(section_ids, 0) + lead_obj = self.pool.get('crm.lead') + for section_id in section_ids: + res[section_id] = lead_obj.search(cr, uid, [("section_id", "=", section_id), '|', '|', ("type", "=", "lead"), ("type", "=", "both"), ("type", "=", False), ('state', 'not in', ['done', 'cancel'])], count=True, context=context) + return res + + def get_number_opportunities(self, cr, uid, section_ids, field_name, arg, context=None): + res = dict.fromkeys(section_ids, 0) + lead_obj = self.pool.get('crm.lead') + for section_id in section_ids: + res[section_id] = lead_obj.search(cr, uid, [("section_id", "=", section_id), '|', ("type", "=", "opportunity"), ("type", "=", "both"), ('state', 'not in', ['done', 'cancel'])], context=context, count=True) + return res + _columns = { 'name': fields.char('Sales Team', size=64, required=True, translate=True), 'complete_name': fields.function(get_full_name, type='char', size=256, readonly=True, store=True), @@ -128,6 +142,8 @@ class crm_case_section(osv.osv): 'alias_id': fields.many2one('mail.alias', 'Alias', ondelete="cascade", required=True, help="The email address associated with this team. New emails received will automatically " "create new leads assigned to the team."), + 'number_lead': fields.function(get_number_leads, type='integer', readonly=True), + 'number_opportunity': fields.function(get_number_opportunities, type='integer', readonly=True), } def _get_stage_common(self, cr, uid, context): diff --git a/addons/crm/crm_lead_data.xml b/addons/crm/crm_lead_data.xml index bb590f49d73..d516b209864 100644 --- a/addons/crm/crm_lead_data.xml +++ b/addons/crm/crm_lead_data.xml @@ -45,6 +45,7 @@ Won + done diff --git a/addons/crm/crm_salesteams.xml b/addons/crm/crm_salesteams.xml new file mode 100644 index 00000000000..5bed5606b72 --- /dev/null +++ b/addons/crm/crm_salesteams.xml @@ -0,0 +1,151 @@ + + + + + + + + Leads + crm.lead + tree,form + ['|', ('type','=','lead'), ('type','=',False)] + { + 'search_default_section_id': [active_id], + 'default_section_id': active_id, + 'search_default_new': True, + 'search_default_open': True + } + +

+ Click to create a new lead. +

+ Use leads if you need a qualification step before creating an + opportunity or a customer. It can be a business card you received, + a contact form filled in your website, or a file of unqualified + prospects you import, etc. +

+ Once qualified, the lead can be converted into a business + opportunity and/or a new customer in your address book. +

+
+ + + + + + Leads + crm.lead + kanban,tree,form + [('type','=','opportunity')] + + { + 'search_default_section_id': [active_id], + 'default_section_id': active_id, + 'search_default_new': True, + 'search_default_open': True + } + +

+ Click to create a new lead. +

+ Use leads if you need a qualification step before creating an + opportunity or a customer. It can be a business card you received, + a contact form filled in your website, or a file of unqualified + prospects you import, etc. +

+ Once qualified, the lead can be converted into a business + opportunity and/or a new customer in your address book. +

+
+
+ + + + + crm.case.section.kanban + crm.case.section + + + + + + + + + + + +
+
+ í + +
+
+

+ +
+ + () +
+
+
+

+ +
+ + + +
+
+ + + +
+
+
+
+
+
+
+ + + + + Sales Teams + crm.case.section + form + kanban,tree,form + + +

+ Click to define a new sales team. +

+ Use sales team to organize your different salespersons or + departments into separate teams. Each team will work in + its own list of opportunities. +

+
+
+ + + + \ No newline at end of file diff --git a/addons/crm/crm_view.xml b/addons/crm/crm_view.xml index 2c156ca2ac2..23d71ef51d4 100644 --- a/addons/crm/crm_view.xml +++ b/addons/crm/crm_view.xml @@ -77,56 +77,58 @@ crm.case.section
- + - - - - - - - - - - - - - - - - @@ -94,11 +100,6 @@ - - diff --git a/addons/crm/res_config.py b/addons/crm/res_config.py index 229ad0189ff..dcafecdabba 100644 --- a/addons/crm/res_config.py +++ b/addons/crm/res_config.py @@ -26,9 +26,6 @@ class crm_configuration(osv.osv_memory): _inherit = ['sale.config.settings', 'fetchmail.config.settings'] _columns = { - 'fetchmail_lead': fields.boolean("Create leads from incoming mails", - fetchmail_model='crm.lead', fetchmail_name='Incoming Leads', - help="""Allows you to configure your incoming mail server, and create leads from incoming emails."""), 'group_fund_raising': fields.boolean("Manage Fund Raising", implied_group='crm.group_fund_raising', help="""Allows you to trace and manage your activities for fund raising."""), diff --git a/addons/crm/res_config_view.xml b/addons/crm/res_config_view.xml index 9534c8620ee..ba0b7e693c7 100644 --- a/addons/crm/res_config_view.xml +++ b/addons/crm/res_config_view.xml @@ -23,19 +23,6 @@ - - - - diff --git a/addons/crm_claim/__init__.py b/addons/crm_claim/__init__.py index 2012c227adf..7395ea83fe5 100644 --- a/addons/crm_claim/__init__.py +++ b/addons/crm_claim/__init__.py @@ -21,7 +21,6 @@ import crm_claim import report -import res_config # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/crm_claim/__openerp__.py b/addons/crm_claim/__openerp__.py index 78dfba2ed53..61257265f1b 100644 --- a/addons/crm_claim/__openerp__.py +++ b/addons/crm_claim/__openerp__.py @@ -41,7 +41,6 @@ automatically new claims based on incoming emails. 'crm_claim_menu.xml', 'security/ir.model.access.csv', 'report/crm_claim_report_view.xml', - 'res_config_view.xml', 'crm_claim_data.xml', ], 'demo': ['crm_claim_demo.xml'], diff --git a/addons/crm_claim/res_config.py b/addons/crm_claim/res_config.py deleted file mode 100644 index aa0cb7ffa20..00000000000 --- a/addons/crm_claim/res_config.py +++ /dev/null @@ -1,32 +0,0 @@ -# -*- coding: utf-8 -*- -############################################################################## -# -# OpenERP, Open Source Business Applications -# Copyright (C) 2004-2012 OpenERP S.A. (). -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# -############################################################################## - -from openerp.osv import fields, osv - -class crm_claim_settings(osv.osv_memory): - _name = 'sale.config.settings' - _inherit = ['sale.config.settings', 'fetchmail.config.settings'] - - _columns = { - 'fetchmail_claim': fields.boolean("Create claims from incoming mails", - fetchmail_model='crm.claim', fetchmail_name='Incoming Claims', - help="""Allows you to configure your incoming mail server, and create claims from incoming emails."""), - } diff --git a/addons/crm_claim/res_config_view.xml b/addons/crm_claim/res_config_view.xml deleted file mode 100644 index 79474f1fb00..00000000000 --- a/addons/crm_claim/res_config_view.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - crm_claim settings - sale.config.settings - - - -
-
- -
-
-
-
- -
-
diff --git a/addons/hr/hr_view.xml b/addons/hr/hr_view.xml index dc65fa80e8b..8ef3c85ec77 100644 --- a/addons/hr/hr_view.xml +++ b/addons/hr/hr_view.xml @@ -336,7 +336,8 @@ - + +
- + + + diff --git a/addons/mail/mail_group_view.xml b/addons/mail/mail_group_view.xml index fba192b18bc..95af1df5967 100644 --- a/addons/mail/mail_group_view.xml +++ b/addons/mail/mail_group_view.xml @@ -69,39 +69,38 @@ - +

+
- -
-
+
- - - - - - - -
- This group is visible by everyone, - including your customers if you installed - the portal module. -
-
- Only the invited followers can read the - discussions on this group. -
-
+ + + + + + +
+ This group is visible by everyone, + including your customers if you installed + the portal module. +
+
+ Only the invited followers can read the + discussions on this group. +
diff --git a/addons/mail/static/src/css/mail_group.css b/addons/mail/static/src/css/mail_group.css index c1cefee9070..4f2b8a16dd0 100644 --- a/addons/mail/static/src/css/mail_group.css +++ b/addons/mail/static/src/css/mail_group.css @@ -14,6 +14,10 @@ padding: 0px 18px; } +.openerp .oe_form_sheetbg.openerp_mail_group_sheet .oe_avatar { + padding-top: 3px; +} + /* Resize footer width */ .openerp .oe_form div.oe_mail_group_footer { max-width: 80%; @@ -21,7 +25,7 @@ /* Resize group description */ .openerp .oe_form_sheetbg.openerp_mail_group_sheet .oe_form_field_text > textarea { - height: 40px; + height: 60px; } /* ------------------------------ */ diff --git a/addons/project/project_view.xml b/addons/project/project_view.xml index 8059cb0b78a..dd54f41bb2d 100644 --- a/addons/project/project_view.xml +++ b/addons/project/project_view.xml @@ -105,6 +105,12 @@ + + + @@ -135,13 +141,6 @@ - -
- -
-
@@ -273,6 +272,12 @@
+ +
+ + + +
From ffa9a978c48e9e693f83859863cfaacbab4f08ff Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Fri, 1 Feb 2013 10:21:43 +0100 Subject: [PATCH 08/68] [IMP] salesteams bzr revid: chm@openerp.com-20130201092143-1y8zg4u1mxcgy2yz --- addons/crm/crm_salesteams.xml | 24 +++++++----------------- addons/crm/res_partner_view.xml | 3 ++- 2 files changed, 9 insertions(+), 18 deletions(-) diff --git a/addons/crm/crm_salesteams.xml b/addons/crm/crm_salesteams.xml index e796ac789d0..6c32deb79cf 100644 --- a/addons/crm/crm_salesteams.xml +++ b/addons/crm/crm_salesteams.xml @@ -10,10 +10,7 @@ tree,form ['|', ('type','=','lead'), ('type','=',False)] { - 'search_default_section_id': [active_id], - 'default_section_id': active_id, - 'search_default_new': True, - 'search_default_open': True + 'search_default_section_id': [active_id], 'default_section_id': active_id, 'search_default_new': True, 'search_default_open': True, 'help_alias': {'type': "lead", 'section_id': active_id} }

@@ -39,10 +36,7 @@ [('type','=','opportunity')] { - 'search_default_section_id': [active_id], - 'default_section_id': active_id, - 'search_default_new': True, - 'search_default_open': True + 'search_default_section_id': [active_id], 'default_section_id': active_id, 'search_default_new': True, 'search_default_open': True, 'help_alias': {'type': "lead", 'section_id': active_id} }

@@ -95,16 +89,12 @@

diff --git a/addons/crm/res_partner_view.xml b/addons/crm/res_partner_view.xml index a879dc49771..9faf86b12a6 100644 --- a/addons/crm/res_partner_view.xml +++ b/addons/crm/res_partner_view.xml @@ -34,7 +34,8 @@ 'search_default_partner_id': active_id, 'stage_type': 'opportunity', 'default_type': 'opportunity', - 'help_alias': 'alias_defaults': {'type': 'lead'} + 'help_alias': {'type': 'lead'} + } From 18da8cdc5b22e63f3f43e941408cbe98d2c2e368 Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Fri, 1 Feb 2013 12:56:42 +0100 Subject: [PATCH 09/68] [IMP] crm,project,mail: css for alias bzr revid: chm@openerp.com-20130201115642-n1wijg4exsibju84 --- addons/crm/__openerp__.py | 1 + addons/crm/crm_salesteams.xml | 31 ++++++++--------------- addons/crm/static/src/css/crm.css | 17 +++++++++++++ addons/crm/static/src/js/crm.js | 11 ++++++++ addons/mail/mail_group_view.xml | 3 +-- addons/project/project_view.xml | 10 +++----- addons/project/static/src/css/project.css | 17 +++++++++++++ 7 files changed, 60 insertions(+), 30 deletions(-) create mode 100644 addons/crm/static/src/js/crm.js diff --git a/addons/crm/__openerp__.py b/addons/crm/__openerp__.py index 46ce37f188c..1ae67f1fb55 100644 --- a/addons/crm/__openerp__.py +++ b/addons/crm/__openerp__.py @@ -116,6 +116,7 @@ Dashboard for CRM will include: 'test/ui/delete_lead.yml', ], 'css': ['static/src/css/crm.css'], + 'js': ['static/src/js/crm.js'], 'installable': True, 'application': True, 'auto_install': False, diff --git a/addons/crm/crm_salesteams.xml b/addons/crm/crm_salesteams.xml index 6c32deb79cf..e6caa03c042 100644 --- a/addons/crm/crm_salesteams.xml +++ b/addons/crm/crm_salesteams.xml @@ -59,7 +59,7 @@ crm.case.section.kanban crm.case.section - + @@ -70,29 +70,24 @@ -
+
-

- -
- - () -
-
-
-

+

+
+ %% +
@@ -101,12 +96,6 @@
- -
- - - -
diff --git a/addons/crm/static/src/css/crm.css b/addons/crm/static/src/css/crm.css index 06c612561e6..e9f7abfa7ae 100644 --- a/addons/crm/static/src/css/crm.css +++ b/addons/crm/static/src/css/crm.css @@ -19,4 +19,21 @@ -box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2); } +.oe_kanban_crm_salesteams_alias { + margin: -8px 0 8px 0; +} +.oe_kanban_crm_salesteams_alias .oe_e { + font-size: 30px; + line-height: 6px; + vertical-align: top; + margin-right: 3px; + color: white; + text-shadow: 0px 0px 2px rgba(0, 0, 0, 1); + float: left; +} + +.oe_kanban_crm_salesteams_alias small { + display: block; + margin-left: 20px; +} \ No newline at end of file diff --git a/addons/crm/static/src/js/crm.js b/addons/crm/static/src/js/crm.js new file mode 100644 index 00000000000..e027313d6dc --- /dev/null +++ b/addons/crm/static/src/js/crm.js @@ -0,0 +1,11 @@ +openerp.crm = function(openerp) { + openerp.web_kanban.KanbanRecord.include({ + on_card_clicked: function() { + if (this.view.dataset.model === 'crm.case.section') { + this.$('.oe_kanban_crm_salesteams_list a').first().click(); + } else { + this._super.apply(this, arguments); + } + }, + }); +}; diff --git a/addons/mail/mail_group_view.xml b/addons/mail/mail_group_view.xml index 95af1df5967..feb62e9aea4 100644 --- a/addons/mail/mail_group_view.xml +++ b/addons/mail/mail_group_view.xml @@ -75,11 +75,10 @@

-
diff --git a/addons/project/project_view.xml b/addons/project/project_view.xml index dd54f41bb2d..893eae68dcd 100644 --- a/addons/project/project_view.xml +++ b/addons/project/project_view.xml @@ -246,8 +246,10 @@ diff --git a/addons/project/static/src/css/project.css b/addons/project/static/src/css/project.css index 1ea3c705105..e4d2196d476 100644 --- a/addons/project/static/src/css/project.css +++ b/addons/project/static/src/css/project.css @@ -62,4 +62,21 @@ -box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2); } +.oe_kanban_project_alias { + margin: -8px 0 8px 0; +} +.oe_kanban_project_alias .oe_e { + font-size: 30px; + line-height: 6px; + vertical-align: top; + margin-right: 3px; + color: white; + text-shadow: 0px 0px 2px rgba(0, 0, 0, 1); + float: left; +} + +.oe_kanban_project_alias small { + display: block; + margin-left: 20px; +} \ No newline at end of file From bd8cefa073eb97368edef60308d2a1ab722331e6 Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Mon, 4 Feb 2013 16:00:58 +0100 Subject: [PATCH 10/68] [IMP] project: use dynamic_help to add alias on help bzr revid: chm@openerp.com-20130204150058-x2erdwbt71d1lz1p --- addons/crm/crm_lead_menu.xml | 6 +- addons/crm/crm_salesteams.xml | 62 +++++++++++++++---- addons/crm/res_partner_view.xml | 3 +- addons/hr_recruitment/hr_recruitment_menu.xml | 1 - addons/mail/mail_alias.py | 57 +++-------------- addons/project/project.py | 10 +++ addons/project/project_view.xml | 5 +- addons/project_issue/project_issue_menu.xml | 3 - addons/project_issue/project_issue_view.xml | 3 +- 9 files changed, 71 insertions(+), 79 deletions(-) diff --git a/addons/crm/crm_lead_menu.xml b/addons/crm/crm_lead_menu.xml index 623131cbf79..823e0595354 100644 --- a/addons/crm/crm_lead_menu.xml +++ b/addons/crm/crm_lead_menu.xml @@ -11,8 +11,7 @@ { 'default_type':'lead', - 'stage_type':'lead', - 'help_alias': {'type': 'lead'} + 'stage_type':'lead' }

@@ -51,8 +50,7 @@ { 'stage_type': 'opportunity', 'default_type': 'opportunity', - 'default_user_id': uid, - 'help_alias': {'type': 'lead'} + 'default_user_id': uid } diff --git a/addons/crm/crm_salesteams.xml b/addons/crm/crm_salesteams.xml index e6caa03c042..9a76c98a985 100644 --- a/addons/crm/crm_salesteams.xml +++ b/addons/crm/crm_salesteams.xml @@ -9,8 +9,10 @@ crm.lead tree,form ['|', ('type','=','lead'), ('type','=',False)] + + { - 'search_default_section_id': [active_id], 'default_section_id': active_id, 'search_default_new': True, 'search_default_open': True, 'help_alias': {'type': "lead", 'section_id': active_id} + 'search_default_section_id': [active_id], 'default_section_id': active_id, 'default_type':'lead', 'stage_type':'lead' }

@@ -27,32 +29,67 @@ + + + tree + + + + + + + form + + + + - Leads + Opportunities crm.lead - kanban,tree,form + kanban,tree,graph,form,calendar [('type','=','opportunity')] + { - 'search_default_section_id': [active_id], 'default_section_id': active_id, 'search_default_new': True, 'search_default_open': True, 'help_alias': {'type': "lead", 'section_id': active_id} + 'search_default_section_id': [active_id], 'default_section_id': active_id, 'stage_type': 'opportunity', 'default_type': 'opportunity', 'default_user_id': uid }

- Click to create a new lead. + Click to create a new opportunity.

- Use leads if you need a qualification step before creating an - opportunity or a customer. It can be a business card you received, - a contact form filled in your website, or a file of unqualified - prospects you import, etc. + OpenERP helps you keep track of your sales pipeline to follow + up potential sales and better forecast your future revenues.

- Once qualified, the lead can be converted into a business - opportunity and/or a new customer in your address book. + You will be able to plan meetings and phone calls from + opportunities, convert them into quotations, attach related + documents, track all discussions, and much more.

+ + + kanban + + + + + + + tree + + + + + + + form + + + + @@ -65,7 +102,6 @@ - @@ -80,7 +116,7 @@

-
+
%%
diff --git a/addons/crm/res_partner_view.xml b/addons/crm/res_partner_view.xml index 9faf86b12a6..150c1eeebbe 100644 --- a/addons/crm/res_partner_view.xml +++ b/addons/crm/res_partner_view.xml @@ -33,8 +33,7 @@ { 'search_default_partner_id': active_id, 'stage_type': 'opportunity', - 'default_type': 'opportunity', - 'help_alias': {'type': 'lead'} + 'default_type': 'opportunity' } diff --git a/addons/hr_recruitment/hr_recruitment_menu.xml b/addons/hr_recruitment/hr_recruitment_menu.xml index e8865042cff..dbd4335d730 100644 --- a/addons/hr_recruitment/hr_recruitment_menu.xml +++ b/addons/hr_recruitment/hr_recruitment_menu.xml @@ -9,7 +9,6 @@ kanban,tree,form,graph,calendar - {'help_alias': {}}

Click to add a new job applicant. diff --git a/addons/mail/mail_alias.py b/addons/mail/mail_alias.py index f7cf115be55..a079448487d 100644 --- a/addons/mail/mail_alias.py +++ b/addons/mail/mail_alias.py @@ -118,8 +118,13 @@ class mail_alias(osv.Model): mail catchall domain from config. e.g. `jobs@openerp.my.openerp.com` or `sales@openerp.my.openerp.com` """ - return [(record['id'], "%s@%s" % (record['alias_name'], record['alias_domain'])) - for record in self.read(cr, uid, ids, ['alias_name', 'alias_domain'], context=context)] + res = [] + for record in self.browse(cr, uid, ids, context=context): + if record.alias_name and record.alias_domain: + res.append((record['id'], "%s@%s" % (record.alias_name, record.alias_domain))) + else: + res.append((record['id'], False)) + return res def _find_unique(self, cr, uid, name, context=None): """Find a unique alias name similar to ``name``. If ``name`` is @@ -197,51 +202,3 @@ class mail_alias(osv.Model): model_id = self.pool.get('ir.model').search(cr, uid, [('model', '=', model_name)], context=context)[0] vals['alias_model_id'] = model_id return self.create(cr, uid, vals, context=context) - - def get_alias(self, cr, uid, model, alias_defaults={}, context=None): - """Return the mail alias for a document (or the default mail alias of the model) - This method is used by the web client (method web.view.insert_alias) - Arguments: - model (model OpenERP) - alias_defaults (A Python dictionary to provide default values when creating new records for this alias.) - """ - model_id = self.pool.get('ir.model').search(cr, uid, [('model', '=', model)], context=context)[0] - - result = [] - # get the value with required attribute - domain = [('alias_model_id', '=', model_id)] - if alias_defaults: - for item in alias_defaults.items(): - domain += ['|', '|', '|', - ('alias_defaults', 'like', ("%%'%s': %s%%" % (item[0], item[1]))), - ('alias_defaults', 'like', ("%%'%s':%s%%" % (item[0], item[1]))), - ('alias_defaults', 'like', ("%%'%s': '%s'%%" % (item[0], item[1]))), - ('alias_defaults', 'like', ("%%'%s':'%s'%%" % (item[0], item[1])))] - else: - domain += [('alias_defaults', 'like', "{}")] - - ids = self.search(cr, uid, domain, context=context) - if ids: - for record in self.browse(cr, uid, ids, context=context): - test = True - if alias_defaults: - for item in ast.literal_eval(record.alias_defaults).items(): - if alias_defaults.get(item[0]) == None or alias_defaults.get(item[0]) != item[1]: - test = False - continue - if test: - result.append( {'id': record.id, 'email': "%s@%s" % (record.alias_name, record.alias_domain), 'global': False}) - - # get the default value - if alias_defaults: - domain = [('alias_model_id', '=', model_id)] - for item in alias_defaults.items(): - domain += [ - ('alias_defaults', 'not like', ("%%'%s'%%" % (item[0])))] - - ids = self.search(cr, uid, domain, context=context) - if ids: - for record in self.browse(cr, uid, ids, context=context): - result.append( {'id': record.id, 'email': "%s@%s" % (record.alias_name, record.alias_domain), 'global': True}) - - return result diff --git a/addons/project/project.py b/addons/project/project.py index f89ce8391fc..f2b104315d0 100644 --- a/addons/project/project.py +++ b/addons/project/project.py @@ -887,8 +887,18 @@ class task(base_stage, osv.osv): for f in res['fields']: if 'Hours' in res['fields'][f]['string']: res['fields'][f]['string'] = res['fields'][f]['string'].replace('Hours',tm) + return res + + def dynamic_help(self, cr, uid, help, context=None): + if context.get('default_project_id'): + project_id = self.pool.get('project.project').browse(cr, uid, context.get('default_project_id'), context=context) + alias = project_id.alias_id and project_id.alias_id.name_get() or False + if alias and alias[0] and alias[0][1]: + help = "%s%s" % (help, _("

You can also create documents by sending an email to: %s
" % alias[0][1])) + return help + # ---------------------------------------- # Case management # ---------------------------------------- diff --git a/addons/project/project_view.xml b/addons/project/project_view.xml index 893eae68dcd..da05f4ba259 100644 --- a/addons/project/project_view.xml +++ b/addons/project/project_view.xml @@ -53,7 +53,6 @@ { 'search_default_project_id': [active_id], 'default_project_id': active_id, - 'help_alias': {'project_id': active_id} } @@ -232,7 +231,6 @@ - @@ -247,7 +245,7 @@

-
+
%%
@@ -617,7 +615,6 @@ project.task kanban,tree,form,calendar,gantt,graph - {'help_alias': {}}

Click to create a new task. diff --git a/addons/project_issue/project_issue_menu.xml b/addons/project_issue/project_issue_menu.xml index 38d0e830af8..78841f56156 100644 --- a/addons/project_issue/project_issue_menu.xml +++ b/addons/project_issue/project_issue_menu.xml @@ -13,9 +13,6 @@ - { - 'help_alias': {} - }

Click to report a new issue. diff --git a/addons/project_issue/project_issue_view.xml b/addons/project_issue/project_issue_view.xml index 4ee6508c3b4..2cdf8f0c943 100644 --- a/addons/project_issue/project_issue_view.xml +++ b/addons/project_issue/project_issue_view.xml @@ -303,8 +303,7 @@ kanban,tree,form,calendar,graph { 'search_default_project_id': [active_id], - 'default_project_id': active_id, - 'help_alias': {'project_id': active_id} + 'default_project_id': active_id }

From d45be56572a5c53da81019da88a39551167fdd29 Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Tue, 5 Feb 2013 12:10:05 +0100 Subject: [PATCH 11/68] [FIX] mail_alias: remove test for removed method get_alias bzr revid: chm@openerp.com-20130205111005-e339w5chgz6zrv6m --- addons/mail/tests/test_mail_alias.py | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/addons/mail/tests/test_mail_alias.py b/addons/mail/tests/test_mail_alias.py index 803d45a8a65..2bd3e345a49 100644 --- a/addons/mail/tests/test_mail_alias.py +++ b/addons/mail/tests/test_mail_alias.py @@ -50,10 +50,4 @@ class test_mail_alias(common.TransactionCase): alias_id_1 = self.mail_alias.create(cr, uid, {'alias_model_id': partner_model_id, 'alias_name': alias_name_1, 'alias_defaults': alias_defaults_1}) alias_id_2 = self.mail_alias.create(cr, uid, - {'alias_model_id': partner_model_id, 'alias_name': alias_name_2, 'alias_defaults': alias_defaults_2}) - - # alias of the model and alias for a docmuent - alias = self.mail_alias.get_alias(cr, uid, 'mail.alias', {'field_pigs': 11}) - self.assertEqual(len(alias), 2, "get_alias don't return the alias of the document and the default alias of the model") - self.assertEqual(alias[0].get('id'), alias_id_1, "get_alias don't return the alias of the document") - self.assertEqual(alias[1].get('id'), alias_id_0, "get_alias don't return the default alias of the model") \ No newline at end of file + {'alias_model_id': partner_model_id, 'alias_name': alias_name_2, 'alias_defaults': alias_defaults_2}) \ No newline at end of file From 01cddc42a5dc5f0996426f0243e06300d2345def Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Tue, 5 Feb 2013 12:22:09 +0100 Subject: [PATCH 12/68] [IMP] project: help alias in bold bzr revid: chm@openerp.com-20130205112209-nsn8m1fd3j8aje8j --- addons/project/project.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/project/project.py b/addons/project/project.py index f2b104315d0..407b8257d7d 100644 --- a/addons/project/project.py +++ b/addons/project/project.py @@ -896,7 +896,7 @@ class task(base_stage, osv.osv): project_id = self.pool.get('project.project').browse(cr, uid, context.get('default_project_id'), context=context) alias = project_id.alias_id and project_id.alias_id.name_get() or False if alias and alias[0] and alias[0][1]: - help = "%s%s" % (help, _("

You can also create documents by sending an email to: %s
" % alias[0][1])) + help = "%s%s" % (help, _("
You can also create documents by sending an email to: %s
" % alias[0][1])) return help # ---------------------------------------- From 3dd59aa69b237ecdb5bd3abb193fd3e2abb97b15 Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Tue, 5 Feb 2013 14:39:33 +0100 Subject: [PATCH 13/68] [IMP] project: multi alias if no default_project_id bzr revid: chm@openerp.com-20130205133933-0x3s16gh4ftnx21y --- addons/project/project.py | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/addons/project/project.py b/addons/project/project.py index 407b8257d7d..8e6462ccba3 100644 --- a/addons/project/project.py +++ b/addons/project/project.py @@ -892,11 +892,24 @@ class task(base_stage, osv.osv): def dynamic_help(self, cr, uid, help, context=None): + alias_txt = "" if context.get('default_project_id'): project_id = self.pool.get('project.project').browse(cr, uid, context.get('default_project_id'), context=context) alias = project_id.alias_id and project_id.alias_id.name_get() or False if alias and alias[0] and alias[0][1]: - help = "%s%s" % (help, _("
You can also create documents by sending an email to: %s
" % alias[0][1])) + alias_txt = alias[0][1] + else: + model_id = self.pool.get('ir.model').search(cr, uid, [("model", "=", self._name)], context=context)[0] + alias_obj = self.pool.get('mail.alias') + alias_nb = 0 + alias_ids = alias_obj.search(cr, uid, [("alias_model_id", "=", model_id)], context=context, limit=5) + if alias_ids: + for alias in alias_obj.browse(cr, uid, alias_ids, context=context): + email = "%s@%s" % (alias.alias_name, alias.alias_domain) + alias_txt = "%s%s%s" % (alias_txt, (alias_nb and ", " or " "), email) + alias_nb += 1 + if alias_txt: + help = "%s %s" % (help, _("
You can also create documents by sending an email to: %s
" % alias_txt)) return help # ---------------------------------------- From a58fb0df5c061f432871cf37673507bd12110632 Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Tue, 5 Feb 2013 15:51:01 +0100 Subject: [PATCH 14/68] [IMP] project: display group with empty message bzr revid: chm@openerp.com-20130205145101-h6jk9uw8av79aygp --- addons/project/project.py | 5 ++--- addons/project/static/src/css/project.css | 4 ++++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/addons/project/project.py b/addons/project/project.py index 8e6462ccba3..244def53c47 100644 --- a/addons/project/project.py +++ b/addons/project/project.py @@ -605,8 +605,7 @@ class task(base_stage, osv.osv): search_domain = [] project_id = self._resolve_project_id_from_context(cr, uid, context=context) if project_id: - search_domain += ['|', ('project_ids', '=', project_id)] - search_domain += [('id', 'in', ids)] + search_domain += [('project_ids', '=', project_id)] stage_ids = stage_obj._search(cr, uid, search_domain, order=order, access_rights_uid=access_rights_uid, context=context) result = stage_obj.name_get(cr, access_rights_uid, stage_ids, context=context) # restore order of the search @@ -909,7 +908,7 @@ class task(base_stage, osv.osv): alias_txt = "%s%s%s" % (alias_txt, (alias_nb and ", " or " "), email) alias_nb += 1 if alias_txt: - help = "%s %s" % (help, _("
You can also create documents by sending an email to: %s
" % alias_txt)) + help = "%s %s" % (help, _("
You can also create documents by sending an email to: %s
" % alias_txt)) return help # ---------------------------------------- diff --git a/addons/project/static/src/css/project.css b/addons/project/static/src/css/project.css index e4d2196d476..99bcd960e0f 100644 --- a/addons/project/static/src/css/project.css +++ b/addons/project/static/src/css/project.css @@ -1,3 +1,7 @@ +.oe_list .oe_view_nocontent_create_alias { + padding-left: 78px; +} + .oe_kanban_project { width: 220px; min-height: 160px; From bfcbb3f6198220e83a45b5d71ea6e8a07a8e288d Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Tue, 5 Feb 2013 17:10:02 +0100 Subject: [PATCH 15/68] [IMP] crm: dynamic_help bzr revid: chm@openerp.com-20130205161002-3dxect9a9x43852z --- addons/crm/crm_lead.py | 24 ++++++++++++++++++++++++ addons/project/project.py | 2 +- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/addons/crm/crm_lead.py b/addons/crm/crm_lead.py index 4455663ca9a..d675753bcb2 100644 --- a/addons/crm/crm_lead.py +++ b/addons/crm/crm_lead.py @@ -84,6 +84,30 @@ class crm_lead(base_stage, format_address, osv.osv): }, } + def dynamic_help(self, cr, uid, help, context=None): + alias_txt = "" + if context.get('default_section_id'): + project_id = self.pool.get('crm.case.section').browse(cr, uid, context.get('default_section_id'), context=context) + alias = project_id.alias_id and project_id.alias_id.name_get() or False + if alias and alias[0] and alias[0][1]: + alias_txt = alias[0][1] + else: + model_id = self.pool.get('ir.model').search(cr, uid, [("model", "=", self._name)], context=context)[0] + alias_obj = self.pool.get('mail.alias') + alias_nb = 0 + alias_ids = alias_obj.search(cr, uid, [("alias_model_id", "=", model_id)], context=context, limit=5) + if alias_ids: + for alias in alias_obj.browse(cr, uid, alias_ids, context=context): + email = "%s@%s" % (alias.alias_name, alias.alias_domain) + alias_txt = "%s%s%s" % (alias_txt, (alias_nb and ", " or " "), email) + alias_nb += 1 + if alias_txt: + if context.get('default_type', False) == "opportunity": + help = "%s %s" % (help, _("
You can also create opportunities by sending an email to: %s
" % alias_txt)) + else: + help = "%s %s" % (help, _("
You can also create lead by sending an email to: %s
" % alias_txt)) + return help + def create(self, cr, uid, vals, context=None): if context is None: context = {} diff --git a/addons/project/project.py b/addons/project/project.py index 244def53c47..91dfc858113 100644 --- a/addons/project/project.py +++ b/addons/project/project.py @@ -908,7 +908,7 @@ class task(base_stage, osv.osv): alias_txt = "%s%s%s" % (alias_txt, (alias_nb and ", " or " "), email) alias_nb += 1 if alias_txt: - help = "%s %s" % (help, _("
You can also create documents by sending an email to: %s
" % alias_txt)) + help = "%s %s" % (help, _("
You can also create tasks by sending an email to: %s
" % alias_txt)) return help # ---------------------------------------- From b76f4c7a4553ed6ebf62a5fdc01c687a62ca49af Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Wed, 6 Feb 2013 10:44:14 +0100 Subject: [PATCH 16/68] [IMP] salesteams: add sales order and quotation bzr revid: chm@openerp.com-20130206094414-8f7kp19dam6su991 --- addons/crm/crm.py | 12 ++--- addons/crm/crm_lead.py | 27 +++--------- addons/crm/crm_salesteams.xml | 12 ++--- addons/crm/static/src/css/crm.css | 4 ++ addons/mail/mail_thread.py | 26 +++++++++++ addons/project/project.py | 26 +++-------- addons/sale/sale_view.xml | 1 + addons/sale_crm/sale_crm.py | 21 +++++++++ addons/sale_crm/sale_crm_view.xml | 73 +++++++++++++++++++++++++++++++ 9 files changed, 148 insertions(+), 54 deletions(-) diff --git a/addons/crm/crm.py b/addons/crm/crm.py index 9fa6b6281f7..c00b5ff2597 100644 --- a/addons/crm/crm.py +++ b/addons/crm/crm.py @@ -109,17 +109,17 @@ class crm_case_section(osv.osv): def get_full_name(self, cr, uid, ids, field_name, arg, context=None): return dict(self.name_get(cr, uid, ids, context=context)) - def get_number_leads(self, cr, uid, section_ids, field_name, arg, context=None): - res = dict.fromkeys(section_ids, 0) + def get_number_leads(self, cr, uid, ids, field_name, arg, context=None): + res = dict.fromkeys(ids, 0) lead_obj = self.pool.get('crm.lead') - for section_id in section_ids: + for section_id in ids: res[section_id] = lead_obj.search(cr, uid, [("section_id", "=", section_id), '|', '|', ("type", "=", "lead"), ("type", "=", "both"), ("type", "=", False), ('state', 'not in', ['done', 'cancel'])], count=True, context=context) return res - def get_number_opportunities(self, cr, uid, section_ids, field_name, arg, context=None): - res = dict.fromkeys(section_ids, 0) + def get_number_opportunities(self, cr, uid, ids, field_name, arg, context=None): + res = dict.fromkeys(ids, 0) lead_obj = self.pool.get('crm.lead') - for section_id in section_ids: + for section_id in ids: res[section_id] = lead_obj.search(cr, uid, [("section_id", "=", section_id), '|', ("type", "=", "opportunity"), ("type", "=", "both"), ('state', 'not in', ['done', 'cancel'])], context=context, count=True) return res diff --git a/addons/crm/crm_lead.py b/addons/crm/crm_lead.py index d675753bcb2..20d9339ede5 100644 --- a/addons/crm/crm_lead.py +++ b/addons/crm/crm_lead.py @@ -85,28 +85,11 @@ class crm_lead(base_stage, format_address, osv.osv): } def dynamic_help(self, cr, uid, help, context=None): - alias_txt = "" - if context.get('default_section_id'): - project_id = self.pool.get('crm.case.section').browse(cr, uid, context.get('default_section_id'), context=context) - alias = project_id.alias_id and project_id.alias_id.name_get() or False - if alias and alias[0] and alias[0][1]: - alias_txt = alias[0][1] - else: - model_id = self.pool.get('ir.model').search(cr, uid, [("model", "=", self._name)], context=context)[0] - alias_obj = self.pool.get('mail.alias') - alias_nb = 0 - alias_ids = alias_obj.search(cr, uid, [("alias_model_id", "=", model_id)], context=context, limit=5) - if alias_ids: - for alias in alias_obj.browse(cr, uid, alias_ids, context=context): - email = "%s@%s" % (alias.alias_name, alias.alias_domain) - alias_txt = "%s%s%s" % (alias_txt, (alias_nb and ", " or " "), email) - alias_nb += 1 - if alias_txt: - if context.get('default_type', False) == "opportunity": - help = "%s %s" % (help, _("
You can also create opportunities by sending an email to: %s
" % alias_txt)) - else: - help = "%s %s" % (help, _("
You can also create lead by sending an email to: %s
" % alias_txt)) - return help + if context.get('default_type', None) == 'lead': + context['dynamic_help_model'] = 'crm.case.section' + context['dynamic_help_id'] = context.get('default_section_id', None) + context['dynamic_help_documents'] = _("leads") + return super(crm_lead, self).dynamic_help(cr, uid, help, context=context) def create(self, cr, uid, vals, context=None): if context is None: diff --git a/addons/crm/crm_salesteams.xml b/addons/crm/crm_salesteams.xml index 9a76c98a985..3c55f0198f7 100644 --- a/addons/crm/crm_salesteams.xml +++ b/addons/crm/crm_salesteams.xml @@ -51,7 +51,7 @@ kanban,tree,graph,form,calendar [('type','=','opportunity')] - + { 'search_default_section_id': [active_id], 'default_section_id': active_id, 'stage_type': 'opportunity', 'default_type': 'opportunity', 'default_user_id': uid } @@ -120,12 +120,12 @@ %%
diff --git a/addons/crm/static/src/css/crm.css b/addons/crm/static/src/css/crm.css index e9f7abfa7ae..a263393e8fa 100644 --- a/addons/crm/static/src/css/crm.css +++ b/addons/crm/static/src/css/crm.css @@ -36,4 +36,8 @@ .oe_kanban_crm_salesteams_alias small { display: block; margin-left: 20px; +} + +.oe_kanban_crm_salesteams_list a { + white-space: nowrap; } \ No newline at end of file diff --git a/addons/mail/mail_thread.py b/addons/mail/mail_thread.py index d75a9199369..27ca09136d6 100644 --- a/addons/mail/mail_thread.py +++ b/addons/mail/mail_thread.py @@ -35,6 +35,7 @@ from openerp import SUPERUSER_ID from openerp.addons.mail.mail_message import decode from openerp.osv import fields, osv from openerp.tools.safe_eval import safe_eval as eval +from openerp.tools.translate import _ _logger = logging.getLogger(__name__) @@ -88,6 +89,31 @@ class mail_thread(osv.AbstractModel): # :param function lambda: returns whether the tracking should record using this subtype _track = {} + def dynamic_help(self, cr, uid, help, context=None): + if not context.get('dynamic_help_model', None): + return help + + alias_txt = "" + if context.get('dynamic_help_id', None): + object_id = self.pool.get(context.get('dynamic_help_model')).browse(cr, uid, context.get('dynamic_help_id'), context=context) + alias = object_id.alias_id and object_id.alias_id.name_get() or False + if alias and alias[0] and alias[0][1]: + alias_txt = alias[0][1] + else: + model_id = self.pool.get('ir.model').search(cr, uid, [("model", "=", self._name)], context=context)[0] + alias_obj = self.pool.get('mail.alias') + alias_nb = 0 + alias_ids = alias_obj.search(cr, uid, [("alias_model_id", "=", model_id)], context=context, limit=5) + if alias_ids: + for alias in alias_obj.browse(cr, uid, alias_ids, context=context): + email = "%s@%s" % (alias.alias_name, alias.alias_domain) + alias_txt = "%s%s%s" % (alias_txt, (alias_nb and ", " or " "), email) + alias_nb += 1 + if alias_txt: + help = "%s %s" % (help, _("
You can also create %s by sending an email to: %s
" % (context.get('dynamic_help_documents', _("documents")), alias_txt))) + + return help + def _get_message_data(self, cr, uid, ids, name, args, context=None): """ Computes: - message_unread: has uid unread message for the document diff --git a/addons/project/project.py b/addons/project/project.py index 91dfc858113..a35ecfe4ece 100644 --- a/addons/project/project.py +++ b/addons/project/project.py @@ -891,26 +891,12 @@ class task(base_stage, osv.osv): def dynamic_help(self, cr, uid, help, context=None): - alias_txt = "" - if context.get('default_project_id'): - project_id = self.pool.get('project.project').browse(cr, uid, context.get('default_project_id'), context=context) - alias = project_id.alias_id and project_id.alias_id.name_get() or False - if alias and alias[0] and alias[0][1]: - alias_txt = alias[0][1] - else: - model_id = self.pool.get('ir.model').search(cr, uid, [("model", "=", self._name)], context=context)[0] - alias_obj = self.pool.get('mail.alias') - alias_nb = 0 - alias_ids = alias_obj.search(cr, uid, [("alias_model_id", "=", model_id)], context=context, limit=5) - if alias_ids: - for alias in alias_obj.browse(cr, uid, alias_ids, context=context): - email = "%s@%s" % (alias.alias_name, alias.alias_domain) - alias_txt = "%s%s%s" % (alias_txt, (alias_nb and ", " or " "), email) - alias_nb += 1 - if alias_txt: - help = "%s %s" % (help, _("
You can also create tasks by sending an email to: %s
" % alias_txt)) - return help - + context['dynamic_help_model'] = 'project.project' + context['dynamic_help_id'] = context.get('default_project_id', None) + context['dynamic_help_documents'] = _("tasks") + print context + return super(task, self).dynamic_help(cr, uid, help, context=context) + # ---------------------------------------- # Case management # ---------------------------------------- diff --git a/addons/sale/sale_view.xml b/addons/sale/sale_view.xml index 18fdb739923..bf5ccf8ab7b 100644 --- a/addons/sale/sale_view.xml +++ b/addons/sale/sale_view.xml @@ -340,6 +340,7 @@

+ diff --git a/addons/sale_crm/sale_crm.py b/addons/sale_crm/sale_crm.py index 1f3f85d5ed1..00a6503f70a 100644 --- a/addons/sale_crm/sale_crm.py +++ b/addons/sale_crm/sale_crm.py @@ -29,6 +29,27 @@ class sale_order(osv.osv): domain="['|',('section_id','=',section_id),('section_id','=',False), ('object_id.model', '=', 'crm.lead')]") } +class crm_case_section(osv.osv): + _inherit = 'crm.case.section' + + def get_number_saleorder(self, cr, uid, ids, field_name, arg, context=None): + res = dict.fromkeys(ids, 0) + obj = self.pool.get('sale.order') + for section_id in ids: + res[section_id] = obj.search(cr, uid, [("section_id", "=", section_id), ('state','not in',('draft','sent','cancel'))], context=context, count=True) + return res + + def get_number_quotation(self, cr, uid, ids, field_name, arg, context=None): + res = dict.fromkeys(ids, 0) + obj = self.pool.get('sale.order') + for section_id in ids: + res[section_id] = obj.search(cr, uid, [("section_id", "=", section_id), ('state','in',('draft','sent','cancel'))], context=context, count=True) + return res + + _columns = { + 'number_saleorder': fields.function(get_number_saleorder, type='integer', readonly=True), + 'number_quotation': fields.function(get_number_quotation, type='integer', readonly=True), + } class res_users(osv.Model): _inherit = 'res.users' diff --git a/addons/sale_crm/sale_crm_view.xml b/addons/sale_crm/sale_crm_view.xml index 0b5fce2f5cd..4c96e8b2cc5 100644 --- a/addons/sale_crm/sale_crm_view.xml +++ b/addons/sale_crm/sale_crm_view.xml @@ -113,5 +113,78 @@ + + + + Sales Orders + ir.actions.act_window + sale.order + form + tree,form,calendar,graph + + [('state','not in',('draft','sent','cancel'))] + { + 'search_default_section_id': [active_id], 'default_section_id': active_id + } + +

+ Click to create a quotation that can be converted into a sales + order. +

+ OpenERP will help you efficiently handle the complete sales flow: + quotation, sales order, delivery, invoicing and payment. +

+
+
+ + + Quotations + ir.actions.act_window + sale.order + form + + tree,form,calendar,graph + { + 'search_default_section_id': [active_id], 'default_section_id': active_id, 'show_address': 1 + } + [('state','in',('draft','sent','cancel'))] + + +

+ Click to create a quotation, the first step of a new sale. +

+ OpenERP will help you handle efficiently the complete sale flow: + from the quotation to the sales order, the + delivery, the invoicing and the payment collection. +

+ The social feature helps you organize discussions on each sales + order, and allow your customers to keep track of the evolution + of the sales order. +

+
+
+ + + crm.case.section.kanban + crm.case.section + + + + + + + + + + + QuotationQuotations + + + Sales OrderSales Orders + + + + + From 0c4a6566399121699d3ee7aedae660a53163ad8a Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Wed, 6 Feb 2013 12:57:36 +0100 Subject: [PATCH 17/68] [IMP] salesteams: add account, crm: on_change user_id, change the salesteams bzr revid: chm@openerp.com-20130206115736-fw3coo0u50itvjlq --- addons/crm/crm.py | 22 +++++++++++----------- addons/crm/crm_lead.py | 7 +++++++ addons/crm/crm_lead_view.xml | 4 ++-- addons/crm/crm_salesteams.xml | 8 +++++--- addons/crm/static/src/css/crm.css | 2 +- addons/sale_crm/sale_crm.py | 24 ++++++++++-------------- addons/sale_crm/sale_crm_view.xml | 15 +++++++++++++++ 7 files changed, 51 insertions(+), 31 deletions(-) diff --git a/addons/crm/crm.py b/addons/crm/crm.py index c00b5ff2597..471ba1613d8 100644 --- a/addons/crm/crm.py +++ b/addons/crm/crm.py @@ -109,19 +109,18 @@ class crm_case_section(osv.osv): def get_full_name(self, cr, uid, ids, field_name, arg, context=None): return dict(self.name_get(cr, uid, ids, context=context)) - def get_number_leads(self, cr, uid, ids, field_name, arg, context=None): + def get_number_items(self, cr, uid, ids, model, domain, context=None): res = dict.fromkeys(ids, 0) - lead_obj = self.pool.get('crm.lead') + obj = self.pool.get(model) for section_id in ids: - res[section_id] = lead_obj.search(cr, uid, [("section_id", "=", section_id), '|', '|', ("type", "=", "lead"), ("type", "=", "both"), ("type", "=", False), ('state', 'not in', ['done', 'cancel'])], count=True, context=context) + res[section_id] = obj.search(cr, uid, [("section_id", "=", section_id)] + domain, count=True, context=context) return res - def get_number_opportunities(self, cr, uid, ids, field_name, arg, context=None): - res = dict.fromkeys(ids, 0) - lead_obj = self.pool.get('crm.lead') - for section_id in ids: - res[section_id] = lead_obj.search(cr, uid, [("section_id", "=", section_id), '|', ("type", "=", "opportunity"), ("type", "=", "both"), ('state', 'not in', ['done', 'cancel'])], context=context, count=True) - return res + def _get_number_leads(self, cr, uid, ids, field_name, arg, context=None): + return self.get_number_items(cr, uid, ids, 'crm.lead', ['|', '|', ("type", "=", "lead"), ("type", "=", "both"), ("type", "=", False), ('state', 'not in', ['done', 'cancel'])], context=context) + + def _get_number_opportunities(self, cr, uid, ids, field_name, arg, context=None): + return self.get_number_items(cr, uid, ids, 'crm.lead', ['|', ("type", "=", "opportunity"), ("type", "=", "both"), ('state', 'not in', ['done', 'cancel'])], context=context) _columns = { 'name': fields.char('Sales Team', size=64, required=True, translate=True), @@ -142,8 +141,9 @@ class crm_case_section(osv.osv): 'alias_id': fields.many2one('mail.alias', 'Alias', ondelete="cascade", required=True, help="The email address associated with this team. New emails received will automatically " "create new leads assigned to the team."), - 'number_lead': fields.function(get_number_leads, type='integer', readonly=True), - 'number_opportunity': fields.function(get_number_opportunities, type='integer', readonly=True), + 'number_lead': fields.function(_get_number_leads, type='integer', readonly=True), + 'number_opportunity': fields.function(_get_number_opportunities, type='integer', readonly=True), + 'color': fields.integer('Color Index'), } def _get_stage_common(self, cr, uid, context): diff --git a/addons/crm/crm_lead.py b/addons/crm/crm_lead.py index aec5e353d48..3f23284f03a 100644 --- a/addons/crm/crm_lead.py +++ b/addons/crm/crm_lead.py @@ -90,6 +90,13 @@ class crm_lead(base_stage, format_address, osv.osv): context['dynamic_help_documents'] = _("leads") return super(crm_lead, self).dynamic_help(cr, uid, help, context=context) + def onchange_user_id(self, cr, uid, ids, section_id, user_id, context=None): + if user_id: + section_ids = self.pool.get('crm.case.section').search(cr, uid, ['|', ('user_id', '=', user_id), ('member_ids', '=', user_id)], context=context) + if section_ids and (not section_id or section_id not in section_ids): + section_id = section_ids[0] + return {'value': {'section_id': section_id}} + def create(self, cr, uid, vals, context=None): if context is None: context = {} diff --git a/addons/crm/crm_lead_view.xml b/addons/crm/crm_lead_view.xml index 3e9249aa6fa..3f5c5449f87 100644 --- a/addons/crm/crm_lead_view.xml +++ b/addons/crm/crm_lead_view.xml @@ -152,7 +152,7 @@ --> - +