diff --git a/addons/account/report/account_invoice_report_view.xml b/addons/account/report/account_invoice_report_view.xml index bf95ba39d65..aec1aa17001 100644 --- a/addons/account/report/account_invoice_report_view.xml +++ b/addons/account/report/account_invoice_report_view.xml @@ -73,7 +73,7 @@ - + diff --git a/addons/crm/__init__.py b/addons/crm/__init__.py index 1cd494b845f..6da405201fc 100644 --- a/addons/crm/__init__.py +++ b/addons/crm/__init__.py @@ -20,7 +20,6 @@ ############################################################################## import crm -import crm_segmentation import crm_lead import sales_team import calendar_event diff --git a/addons/crm/__openerp__.py b/addons/crm/__openerp__.py index e84d4e86333..35421729c01 100644 --- a/addons/crm/__openerp__.py +++ b/addons/crm/__openerp__.py @@ -108,7 +108,6 @@ Dashboard for CRM will include: 'test/lead2opportunity_assign_salesmen.yml', 'test/crm_lead_merge.yml', 'test/crm_lead_cancel.yml', - 'test/segmentation.yml', 'test/phonecalls.yml', 'test/crm_lead_onchange.yml', 'test/crm_lead_copy.yml', diff --git a/addons/crm/crm.py b/addons/crm/crm.py index c3108c44e8f..1367dcca641 100644 --- a/addons/crm/crm.py +++ b/addons/crm/crm.py @@ -51,7 +51,7 @@ class crm_tracking_campaign(osv.Model): _rec_name = "name" _columns = { 'name': fields.char('Campaign Name', required=True, translate=True), - 'section_id': fields.many2one('crm.case.section', 'Sales Team'), + 'team_id': fields.many2one('crm.team', 'Sales Team', oldname='section_id'), } @@ -69,7 +69,7 @@ class crm_tracking_mixin(osv.AbstractModel): _name = 'crm.tracking.mixin' _columns = { - 'campaign_id': fields.many2one('crm.tracking.campaign', 'Campaign', # old domain ="['|',('section_id','=',section_id),('section_id','=',False)]" + 'campaign_id': fields.many2one('crm.tracking.campaign', 'Campaign', # old domain ="['|',('team_id','=',team_id),('team_id','=',False)]" help="This is a name that helps you keep track of your different campaign efforts Ex: Fall_Drive, Christmas_Special"), 'source_id': fields.many2one('crm.tracking.source', 'Source', help="This is the source of the link Ex: Search Engine, another domain, or name of email list"), 'medium_id': fields.many2one('crm.tracking.medium', 'Channel', help="This is the method of delivery. Ex: Postcard, Email, or Banner Ad"), @@ -106,13 +106,13 @@ class crm_tracking_mixin(osv.AbstractModel): } -class crm_case_stage(osv.osv): +class crm_stage(osv.Model): """ Model for case stages. This models the main stages of a document management flow. Main CRM objects (leads, opportunities, project issues, ...) will now use only stages, instead of state and stages. Stages are for example used to display the kanban view of records. """ - _name = "crm.case.stage" + _name = "crm.stage" _description = "Stage of case" _rec_name = 'name' _order = "sequence" @@ -123,10 +123,10 @@ class crm_case_stage(osv.osv): 'probability': fields.float('Probability (%)', required=True, help="This percentage depicts the default/average probability of the Case for this stage to be a success"), 'on_change': fields.boolean('Change Probability Automatically', help="Setting this stage will change the probability automatically on the opportunity."), 'requirements': fields.text('Requirements'), - 'section_ids': fields.many2many('crm.case.section', 'section_stage_rel', 'stage_id', 'section_id', string='Sections', - help="Link between stages and sales teams. When set, this limitate the current stage to the selected sales teams."), + 'team_ids': fields.many2many('crm.team', 'crm_team_stage_rel', 'stage_id', 'team_id', string='Teams', + help="Link between stages and sales teams. When set, this limitate the current stage to the selected sales teams."), 'case_default': fields.boolean('Default to New Sales Team', - help="If you check this field, this stage will be proposed by default on each sales team. It will not assign this stage to existing teams."), + help="If you check this field, this stage will be proposed by default on each sales team. It will not assign this stage to existing teams."), 'fold': fields.boolean('Folded in Kanban View', help='This stage is folded in the kanban view when' 'there are no records in that stage to display.'), @@ -144,35 +144,4 @@ class crm_case_stage(osv.osv): 'case_default': True, } - -class crm_case_categ(osv.osv): - """ Category of Case """ - _name = "crm.case.categ" - _description = "Category of Case" - _columns = { - 'name': fields.char('Name', required=True, translate=True), - 'section_id': fields.many2one('crm.case.section', 'Sales Team'), - 'object_id': fields.many2one('ir.model', 'Object Name'), - } - - def _find_object_id(self, cr, uid, context=None): - """Finds id for case object""" - context = context or {} - object_id = context.get('object_id', False) - ids = self.pool.get('ir.model').search(cr, uid, ['|', ('id', '=', object_id), ('model', '=', context.get('object_name', False))]) - return ids and ids[0] or False - _defaults = { - 'object_id': _find_object_id - } - - -class crm_payment_mode(osv.osv): - """ Payment Mode for Fund """ - _name = "crm.payment.mode" - _description = "CRM Payment Mode" - _columns = { - 'name': fields.char('Name', required=True), - 'section_id': fields.many2one('crm.case.section', 'Sales Team'), - } - # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/crm/crm_action_rule_demo.xml b/addons/crm/crm_action_rule_demo.xml index 797ac77d1b8..ad5a936924a 100644 --- a/addons/crm/crm_action_rule_demo.xml +++ b/addons/crm/crm_action_rule_demo.xml @@ -41,8 +41,8 @@ True ir.actions.server code - sales_team = self.pool.get('ir.model.data').get_object(cr, uid, 'sales_team', 'section_sales_department') -object.write({'section_id': sales_team.id}) + sales_team = self.pool.get('ir.model.data').get_object(cr, uid, 'sales_team', 'team_sales_department') +object.write({'team_id': sales_team.id}) diff --git a/addons/crm/crm_data.xml b/addons/crm/crm_data.xml index f3d27547bdd..325062521c0 100644 --- a/addons/crm/crm_data.xml +++ b/addons/crm/crm_data.xml @@ -50,39 +50,19 @@ Google Adwords - + + + True sales - - - - Cash - - - - - Check - - - - - Credit Card - - - - - Demand Draft - - - info - + diff --git a/addons/crm/crm_demo.xml b/addons/crm/crm_demo.xml index 71e21b3392d..e7b19415a49 100644 --- a/addons/crm/crm_demo.xml +++ b/addons/crm/crm_demo.xml @@ -1,12 +1,27 @@ - - - Odoo partners - True - + + + + + + + + + Indirect Sales + IM + + + + + Marketing + SPD + + + + diff --git a/addons/crm/crm_lead.py b/addons/crm/crm_lead.py index fde4a2d3618..ed2b7d814b3 100644 --- a/addons/crm/crm_lead.py +++ b/addons/crm/crm_lead.py @@ -37,7 +37,7 @@ CRM_LEAD_FIELDS_TO_MERGE = ['name', 'campaign_id', 'company_id', 'country_id', - 'section_id', + 'team_id', 'state_id', 'stage_id', 'medium_id', @@ -86,36 +86,34 @@ class crm_lead(format_address, osv.osv): def get_empty_list_help(self, cr, uid, help, context=None): context = dict(context or {}) if context.get('default_type') == 'lead': - context['empty_list_help_model'] = 'crm.case.section' - context['empty_list_help_id'] = context.get('default_section_id') + context['empty_list_help_model'] = 'crm.team' + context['empty_list_help_id'] = context.get('default_team_id') context['empty_list_help_document_name'] = _("leads") return super(crm_lead, self).get_empty_list_help(cr, uid, help, context=context) - def _get_default_section_id(self, cr, uid, user_id=False, context=None): - """ Gives default section by checking if present in the context """ - section_id = self._resolve_section_id_from_context(cr, uid, context=context) or False - if not section_id: - section_id = self.pool.get('res.users').browse(cr, uid, user_id or uid, context).default_section_id.id or False - return section_id + def _get_default_team_id(self, cr, uid, user_id=False, context=None): + """ Gives default team by checking if present in the context """ + team_id = self._resolve_team_id_from_context(cr, uid, context=context) or False + return team_id def _get_default_stage_id(self, cr, uid, context=None): """ Gives default stage_id """ - section_id = self._get_default_section_id(cr, uid, context=context) - return self.stage_find(cr, uid, [], section_id, [('fold', '=', False)], context=context) + team_id = self._get_default_team_id(cr, uid, context=context) + return self.stage_find(cr, uid, [], team_id, [('fold', '=', False)], context=context) - def _resolve_section_id_from_context(self, cr, uid, context=None): - """ Returns ID of section based on the value of 'section_id' + def _resolve_team_id_from_context(self, cr, uid, context=None): + """ Returns ID of team based on the value of 'team_id' context key, or None if it cannot be resolved to a single Sales Team. """ if context is None: context = {} - if type(context.get('default_section_id')) in (int, long): - return context.get('default_section_id') - if isinstance(context.get('default_section_id'), basestring): - section_ids = self.pool.get('crm.case.section').name_search(cr, uid, name=context['default_section_id'], context=context) - if len(section_ids) == 1: - return int(section_ids[0][0]) + if type(context.get('default_team_id')) in (int, long): + return context.get('default_team_id') + if isinstance(context.get('default_team_id'), basestring): + team_ids = self.pool.get('crm.team').name_search(cr, uid, name=context['default_team_id'], context=context) + if len(team_ids) == 1: + return int(team_ids[0][0]) return None def _resolve_type_from_context(self, cr, uid, context=None): @@ -128,19 +126,19 @@ class crm_lead(format_address, osv.osv): def _read_group_stage_ids(self, cr, uid, ids, domain, read_group_order=None, access_rights_uid=None, context=None): access_rights_uid = access_rights_uid or uid - stage_obj = self.pool.get('crm.case.stage') + stage_obj = self.pool.get('crm.stage') order = stage_obj._order # lame hack to allow reverting search, should just work in the trivial case if read_group_order == 'stage_id desc': order = "%s desc" % order - # retrieve section_id from the context and write the domain + # retrieve team_id from the context and write the domain # - ('id', 'in', 'ids'): add columns that should be present # - OR ('case_default', '=', True), ('fold', '=', False): add default columns that are not folded - # - OR ('section_ids', '=', section_id), ('fold', '=', False) if section_id: add section columns that are not folded + # - OR ('team_ids', '=', team_id), ('fold', '=', False) if team_id: add team columns that are not folded search_domain = [] - section_id = self._resolve_section_id_from_context(cr, uid, context=context) - if section_id: - search_domain += ['|', ('section_ids', '=', section_id)] + team_id = self._resolve_team_id_from_context(cr, uid, context=context) + if team_id: + search_domain += ['|', ('team_ids', '=', team_id)] search_domain += [('id', 'in', ids)] else: search_domain += ['|', ('id', 'in', ids), ('case_default', '=', True)] @@ -213,14 +211,13 @@ class crm_lead(format_address, osv.osv): 'date_action_last': fields.datetime('Last Action', readonly=1), 'date_action_next': fields.datetime('Next Action', readonly=1), 'email_from': fields.char('Email', size=128, help="Email address of the contact", select=1), - 'section_id': fields.many2one('crm.case.section', 'Sales Team', + 'team_id': fields.many2one('crm.team', 'Sales Team', oldname='section_id', select=True, track_visibility='onchange', help='When sending mails, the default email address is taken from the sales team.'), 'create_date': fields.datetime('Creation Date', readonly=True), 'email_cc': fields.text('Global CC', help="These email addresses will be added to the CC field of all inbound and outbound emails for this record before being sent. Separate multiple email addresses with a comma"), 'description': fields.text('Notes'), 'write_date': fields.datetime('Update Date', readonly=True), - 'categ_ids': fields.many2many('crm.case.categ', 'crm_lead_category_rel', 'lead_id', 'category_id', 'Tags', \ - domain="['|', ('section_id', '=', section_id), ('section_id', '=', False), ('object_id.model', '=', 'crm.lead')]", help="Classify and analyze your lead/opportunity categories like: Training, Service"), + 'tag_ids': fields.many2many('crm.lead.tag', 'crm_lead_tag_rel', 'lead_id', 'tag_id', 'Tags', help="Classify and analyze your lead/opportunity categories like: Training, Service"), 'contact_name': fields.char('Contact Name', size=64), 'partner_name': fields.char("Customer Name", size=64,help='The name of the future partner company that will be created while converting the lead into opportunity', select=1), 'opt_out': fields.boolean('Opt-Out', oldname='optout', @@ -229,8 +226,8 @@ class crm_lead(format_address, osv.osv): 'type': fields.selection([ ('lead','Lead'), ('opportunity','Opportunity'), ],'Type', select=True, help="Type is used to separate Leads and Opportunities"), 'priority': fields.selection(crm.AVAILABLE_PRIORITIES, 'Priority', select=True), 'date_closed': fields.datetime('Closed', readonly=True, copy=False), - 'stage_id': fields.many2one('crm.case.stage', 'Stage', track_visibility='onchange', select=True, - domain="['&', ('section_ids', '=', section_id), '|', ('type', '=', type), ('type', '=', 'both')]"), + 'stage_id': fields.many2one('crm.stage', 'Stage', track_visibility='onchange', select=True, + domain="['&', ('team_ids', '=', team_id), '|', ('type', '=', type), ('type', '=', 'both')]"), 'user_id': fields.many2one('res.users', 'Salesperson', select=True, track_visibility='onchange'), 'referred': fields.char('Referred By'), 'date_open': fields.datetime('Assigned', readonly=True), @@ -273,8 +270,6 @@ class crm_lead(format_address, osv.osv): 'function': fields.char('Function'), 'title': fields.many2one('res.partner.title', 'Title'), 'company_id': fields.many2one('res.company', 'Company', select=1), - 'payment_mode': fields.many2one('crm.payment.mode', 'Payment Mode', \ - domain="[('section_id','=',section_id)]"), 'planned_cost': fields.float('Planned Costs'), 'meeting_count': fields.function(_meeting_count, string='# Meetings', type='integer'), } @@ -284,7 +279,7 @@ class crm_lead(format_address, osv.osv): 'type': 'lead', 'user_id': lambda s, cr, uid, c: uid, 'stage_id': lambda s, cr, uid, c: s._get_default_stage_id(cr, uid, c), - 'section_id': lambda s, cr, uid, c: s._get_default_section_id(cr, uid, context=c), + 'team_id': lambda s, cr, uid, c: s._get_default_team_id(cr, uid, context=c), 'company_id': lambda s, cr, uid, c: s.pool.get('res.company')._company_default_get(cr, uid, 'crm.lead', context=c), 'priority': lambda *a: crm.AVAILABLE_PRIORITIES[0][0], 'color': 0, @@ -298,7 +293,7 @@ class crm_lead(format_address, osv.osv): def onchange_stage_id(self, cr, uid, ids, stage_id, context=None): if not stage_id: return {'value': {}} - stage = self.pool.get('crm.case.stage').browse(cr, uid, stage_id, context=context) + stage = self.pool.get('crm.stage').browse(cr, uid, stage_id, context=context) if not stage.on_change: return {'value': {}} vals = {'probability': stage.probability} @@ -327,20 +322,20 @@ class crm_lead(format_address, osv.osv): return {'value': values} def on_change_user(self, cr, uid, ids, user_id, context=None): - """ When changing the user, also set a section_id or restrict section id + """ When changing the user, also set a team_id or restrict team id to the ones user_id is member of. """ - section_id = self._get_default_section_id(cr, uid, user_id=user_id, context=context) or False - if user_id and not section_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: - section_id = section_ids[0] - return {'value': {'section_id': section_id}} + team_id = self._get_default_team_id(cr, uid, context=context) + if user_id and not team_id: + team_ids = self.pool.get('crm.team').search(cr, uid, ['|', ('user_id', '=', user_id), ('member_ids', '=', user_id)], context=context) + if team_ids: + team_id = team_ids[0] + return {'value': {'team_id': team_id}} - def stage_find(self, cr, uid, cases, section_id, domain=None, order='sequence', context=None): + def stage_find(self, cr, uid, cases, team_id, domain=None, order='sequence', context=None): """ Override of the base.stage method Parameter of the stage search taken from the lead: - type: stage type must be the same or 'both' - - section_id: if set, stages must belong to this section or + - team_id: if set, stages must belong to this team or be a default stage; if not set, stages must be default stages """ @@ -350,25 +345,25 @@ class crm_lead(format_address, osv.osv): context = {} # check whether we should try to add a condition on type avoid_add_type_term = any([term for term in domain if len(term) == 3 if term[0] == 'type']) - # collect all section_ids - section_ids = set() + # collect all team_ids + team_ids = set() types = ['both'] if not cases and context.get('default_type'): ctx_type = context.get('default_type') types += [ctx_type] - if section_id: - section_ids.add(section_id) + if team_id: + team_ids.add(team_id) for lead in cases: - if lead.section_id: - section_ids.add(lead.section_id.id) + if lead.team_id: + team_ids.add(lead.team_id.id) if lead.type not in types: types.append(lead.type) - # OR all section_ids and OR with case_default + # OR all team_ids and OR with case_default search_domain = [] - if section_ids: - search_domain += [('|')] * len(section_ids) - for section_id in section_ids: - search_domain.append(('section_ids', '=', section_id)) + if team_ids: + search_domain += [('|')] * len(team_ids) + for team_id in team_ids: + search_domain.append(('team_ids', '=', team_id)) search_domain.append(('case_default', '=', True)) # AND with cases types if not avoid_add_type_term: @@ -376,7 +371,7 @@ class crm_lead(format_address, osv.osv): # AND with the domain in parameter search_domain += list(domain) # perform search, return the first found - stage_ids = self.pool.get('crm.case.stage').search(cr, uid, search_domain, order=order, limit=1, context=context) + stage_ids = self.pool.get('crm.stage').search(cr, uid, search_domain, order=order, limit=1, context=context) if stage_ids: return stage_ids[0] return False @@ -386,7 +381,7 @@ class crm_lead(format_address, osv.osv): """ stages_leads = {} for lead in self.browse(cr, uid, ids, context=context): - stage_id = self.stage_find(cr, uid, [lead], lead.section_id.id or False, [('probability', '=', 0.0), ('fold', '=', True), ('sequence', '>', 1)], context=context) + stage_id = self.stage_find(cr, uid, [lead], lead.team_id.id or False, [('probability', '=', 0.0), ('fold', '=', True), ('sequence', '>', 1)], context=context) if stage_id: if stages_leads.get(stage_id): stages_leads[stage_id].append(lead.id) @@ -406,7 +401,7 @@ class crm_lead(format_address, osv.osv): """ stages_leads = {} for lead in self.browse(cr, uid, ids, context=context): - stage_id = self.stage_find(cr, uid, [lead], lead.section_id.id or False, [('probability', '=', 100.0), ('fold', '=', True)], context=context) + stage_id = self.stage_find(cr, uid, [lead], lead.team_id.id or False, [('probability', '=', 100.0), ('fold', '=', True)], context=context) if stage_id: if stages_leads.get(stage_id): stages_leads[stage_id].append(lead.id) @@ -425,11 +420,11 @@ class crm_lead(format_address, osv.osv): """ Escalates case to parent level """ for case in self.browse(cr, uid, ids, context=context): data = {'active': True} - if case.section_id.parent_id: - data['section_id'] = case.section_id.parent_id.id - if case.section_id.parent_id.change_responsible: - if case.section_id.parent_id.user_id: - data['user_id'] = case.section_id.parent_id.user_id.id + if case.team_id.parent_id: + data['team_id'] = case.team_id.parent_id.id + if case.team_id.parent_id.change_responsible: + if case.team_id.parent_id.user_id: + data['user_id'] = case.team_id.parent_id.user_id.id else: raise osv.except_osv(_('Error!'), _("You are already at the top level of your sales-team category.\nTherefore you cannot escalate furthermore.")) self.write(cr, uid, [case.id], data, context=context) @@ -629,7 +624,7 @@ class crm_lead(format_address, osv.osv): self._merge_opportunity_attachments(cr, uid, highest, opportunities, context=context) self._merge_opportunity_phonecalls(cr, uid, highest, opportunities, context=context) - def merge_opportunity(self, cr, uid, ids, user_id=False, section_id=False, context=None): + def merge_opportunity(self, cr, uid, ids, user_id=False, team_id=False, context=None): """ Different cases of merge: - merge leads together = 1 new lead @@ -668,8 +663,8 @@ class crm_lead(format_address, osv.osv): if user_id: merged_data['user_id'] = user_id - if section_id: - merged_data['section_id'] = section_id + if team_id: + merged_data['team_id'] = team_id # Merge notifications about loss of information opportunities = [highest] @@ -678,10 +673,10 @@ class crm_lead(format_address, osv.osv): self.merge_dependences(cr, uid, highest.id, tail_opportunities, context=context) # Check if the stage is in the stages of the sales team. If not, assign the stage with the lowest sequence - if merged_data.get('section_id'): - section_stage_ids = self.pool.get('crm.case.stage').search(cr, uid, [('section_ids', 'in', merged_data['section_id']), ('type', '=', merged_data.get('type'))], order='sequence', context=context) - if merged_data.get('stage_id') not in section_stage_ids: - merged_data['stage_id'] = section_stage_ids and section_stage_ids[0] or False + if merged_data.get('team_id'): + team_stage_ids = self.pool.get('crm.stage').search(cr, uid, [('team_ids', 'in', merged_data['team_id']), ('type', '=', merged_data.get('type'))], order='sequence', context=context) + if merged_data.get('stage_id') not in team_stage_ids: + merged_data['stage_id'] = team_stage_ids and team_stage_ids[0] or False # Write merged data into first opportunity self.write(cr, uid, [highest.id], merged_data, context=context) # Delete tail opportunities @@ -690,13 +685,13 @@ class crm_lead(format_address, osv.osv): return highest.id - def _convert_opportunity_data(self, cr, uid, lead, customer, section_id=False, context=None): - crm_stage = self.pool.get('crm.case.stage') + def _convert_opportunity_data(self, cr, uid, lead, customer, team_id=False, context=None): + crm_stage = self.pool.get('crm.stage') contact_id = False if customer: contact_id = self.pool.get('res.partner').address_get(cr, uid, [customer.id])['default'] - if not section_id: - section_id = lead.section_id and lead.section_id.id or False + if not team_id: + team_id = lead.team_id and lead.team_id.id or False val = { 'planned_revenue': lead.planned_revenue, 'probability': lead.probability, @@ -709,10 +704,10 @@ class crm_lead(format_address, osv.osv): 'phone': customer and customer.phone or lead.phone, } if not lead.stage_id or lead.stage_id.type=='lead': - val['stage_id'] = self.stage_find(cr, uid, [lead], section_id, [('type', 'in', ('opportunity', 'both'))], context=context) + val['stage_id'] = self.stage_find(cr, uid, [lead], team_id, [('type', 'in', ('opportunity', 'both'))], context=context) return val - def convert_opportunity(self, cr, uid, ids, partner_id, user_ids=False, section_id=False, context=None): + def convert_opportunity(self, cr, uid, ids, partner_id, user_ids=False, team_id=False, context=None): customer = False if partner_id: partner = self.pool.get('res.partner') @@ -721,11 +716,11 @@ class crm_lead(format_address, osv.osv): # TDE: was if lead.state in ('done', 'cancel'): if lead.probability == 100 or (lead.probability == 0 and lead.stage_id.fold): continue - vals = self._convert_opportunity_data(cr, uid, lead, customer, section_id, context=context) + vals = self._convert_opportunity_data(cr, uid, lead, customer, team_id, context=context) self.write(cr, uid, [lead.id], vals, context=context) - if user_ids or section_id: - self.allocate_salesman(cr, uid, ids, user_ids, section_id, context=context) + if user_ids or team_id: + self.allocate_salesman(cr, uid, ids, user_ids, team_id, context=context) return True @@ -734,7 +729,7 @@ class crm_lead(format_address, osv.osv): vals = {'name': name, 'user_id': lead.user_id.id, 'comment': lead.description, - 'section_id': lead.section_id.id or False, + 'team_id': lead.team_id.id or False, 'parent_id': parent_id, 'phone': lead.phone, 'mobile': lead.mobile, @@ -793,7 +788,7 @@ class crm_lead(format_address, osv.osv): continue if not partner_id and action == 'create': partner_id = self._create_lead_partner(cr, uid, lead, context) - self.pool['res.partner'].write(cr, uid, partner_id, {'section_id': lead.section_id and lead.section_id.id or False}) + self.pool['res.partner'].write(cr, uid, partner_id, {'team_id': lead.team_id and lead.team_id.id or False}) if partner_id: lead.write({'partner_id': partner_id}, context=context) partner_ids[lead.id] = partner_id @@ -817,7 +812,7 @@ class crm_lead(format_address, osv.osv): for lead_id in ids: value = {} if team_id: - value['section_id'] = team_id + value['team_id'] = team_id if user_ids: value['user_id'] = user_ids[index] # Cycle through user_ids @@ -826,7 +821,7 @@ class crm_lead(format_address, osv.osv): self.write(cr, uid, [lead_id], value, context=context) return True - def schedule_phonecall(self, cr, uid, ids, schedule_time, call_summary, desc, phone, contact_name, user_id=False, section_id=False, categ_id=False, action='schedule', context=None): + def schedule_phonecall(self, cr, uid, ids, schedule_time, call_summary, desc, phone, contact_name, user_id=False, team_id=False, categ_id=False, action='schedule', context=None): """ :param string action: ('schedule','Schedule a call'), ('log','Log a call') """ @@ -840,8 +835,8 @@ class crm_lead(format_address, osv.osv): except ValueError: pass for lead in self.browse(cr, uid, ids, context=context): - if not section_id: - section_id = lead.section_id and lead.section_id.id or False + if not team_id: + team_id = lead.team_id and lead.team_id.id or False if not user_id: user_id = lead.user_id and lead.user_id.id or False vals = { @@ -851,7 +846,7 @@ class crm_lead(format_address, osv.osv): 'categ_id': categ_id or False, 'description': desc or '', 'date': schedule_time, - 'section_id': section_id or False, + 'team_id': team_id or False, 'partner_id': lead.partner_id and lead.partner_id.id or False, 'partner_phone': phone or lead.phone or (lead.partner_id and lead.partner_id.phone or False), 'partner_mobile': lead.partner_id and lead.partner_id.mobile or False, @@ -919,7 +914,7 @@ class crm_lead(format_address, osv.osv): 'default_opportunity_id': lead.type == 'opportunity' and lead.id or False, 'default_partner_id': lead.partner_id and lead.partner_id.id or False, 'default_partner_ids': partner_ids, - 'default_section_id': lead.section_id and lead.section_id.id or False, + 'default_team_id': lead.team_id and lead.team_id.id or False, 'default_name': lead.name, } return res @@ -928,8 +923,8 @@ class crm_lead(format_address, osv.osv): context = dict(context or {}) if vals.get('type') and not context.get('default_type'): context['default_type'] = vals.get('type') - if vals.get('section_id') and not context.get('default_section_id'): - context['default_section_id'] = vals.get('section_id') + if vals.get('team_id') and not context.get('default_team_id'): + context['default_team_id'] = vals.get('team_id') if vals.get('user_id'): vals['date_open'] = fields.datetime.now() @@ -957,7 +952,7 @@ class crm_lead(format_address, osv.osv): lead = self.browse(cr, uid, id, context=context) local_context = dict(context) local_context.setdefault('default_type', lead.type) - local_context.setdefault('default_section_id', lead.section_id.id) + local_context.setdefault('default_team_id', lead.team_id.id) if lead.type == 'opportunity': default['date_open'] = fields.datetime.now() else: @@ -966,8 +961,8 @@ class crm_lead(format_address, osv.osv): def get_empty_list_help(self, cr, uid, help, context=None): context = dict(context or {}) - context['empty_list_help_model'] = 'crm.case.section' - context['empty_list_help_id'] = context.get('default_section_id', None) + context['empty_list_help_model'] = 'crm.team' + context['empty_list_help_id'] = context.get('default_team_id', None) context['empty_list_help_document_name'] = _("opportunity") if context.get('default_type') == 'lead': context['empty_list_help_document_name'] = _("lead") @@ -980,9 +975,9 @@ class crm_lead(format_address, osv.osv): def message_get_reply_to(self, cr, uid, ids, context=None): """ Override to get the reply_to of the parent project. """ leads = self.browse(cr, SUPERUSER_ID, ids, context=context) - section_ids = set([lead.section_id.id for lead in leads if lead.section_id]) - aliases = self.pool['crm.case.section'].message_get_reply_to(cr, uid, list(section_ids), context=context) - return dict((lead.id, aliases.get(lead.section_id and lead.section_id.id or 0, False)) for lead in leads) + team_ids = set([lead.team_id.id for lead in leads if lead.team_id]) + aliases = self.pool['crm.team'].message_get_reply_to(cr, uid, list(team_ids), context=context) + return dict((lead.id, aliases.get(lead.team_id and lead.team_id.id or 0, False)) for lead in leads) def get_formview_id(self, cr, uid, id, context=None): obj = self.browse(cr, uid, id, context=context) @@ -1092,4 +1087,12 @@ class crm_lead(format_address, osv.osv): break return res +class crm_lead_tag(osv.Model): + _name = "crm.lead.tag" + _description = "Category of lead" + _columns = { + 'name': fields.char('Name', required=True, translate=True), + 'team_id': fields.many2one('crm.team', 'Sales Team'), + } + # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/crm/crm_lead_data.xml b/addons/crm/crm_lead_data.xml index 8ac7b88f85d..e10f80a4fbb 100644 --- a/addons/crm/crm_lead_data.xml +++ b/addons/crm/crm_lead_data.xml @@ -3,7 +3,7 @@ - + New 1 0 @@ -11,7 +11,7 @@ 1 both - + Dead 1 1 @@ -20,7 +20,7 @@ 30 lead - + Qualification 1 20 @@ -28,21 +28,21 @@ 40 opportunity - + Proposition 1 40 50 opportunity - + Negotiation 1 60 60 opportunity - + Won 1 1 @@ -51,7 +51,7 @@ 70 opportunity - + Lost 1 1 @@ -61,7 +61,7 @@ opportunity - + Fall Drive - + Christmas Special - + Email Campaign - Services - + Email Campaign - Products - + - + Product - - + - + Software - - + - + Services - - + - + Information - - + - + Design - - + - + Training - - + - + Consulting - - + - + Other - - + @@ -157,32 +149,32 @@ Lead Created 10 - crm.case.section + crm.team - section_id + team_id Opportunity Stage Changed 11 - crm.case.section + crm.team - section_id + team_id Opportunity Won 12 - crm.case.section + crm.team - section_id + team_id Opportunity Lost 13 - crm.case.section + crm.team - section_id + team_id @@ -636,12 +637,12 @@ Andrew Wavre 1300 - + 2 Send Catalogue by Email - + diff --git a/addons/crm/crm_lead_menu.xml b/addons/crm/crm_lead_menu.xml index 2569b85972d..90a09b18759 100644 --- a/addons/crm/crm_lead_menu.xml +++ b/addons/crm/crm_lead_menu.xml @@ -2,7 +2,7 @@ - + Leads crm.lead tree,form @@ -12,7 +12,7 @@ { 'default_type':'lead', 'stage_type':'lead', - 'empty_list_help_model': 'crm.case.section', + 'empty_list_help_model': 'crm.team', 'needaction_menu_ref': 'crm.menu_crm_opportunities', 'search_default_unassigned':1, } @@ -30,7 +30,7 @@ - + Opportunities crm.lead kanban,tree,graph,form,calendar @@ -59,28 +59,28 @@ kanban - + tree - + form - + + action="crm_lead_all_leads"/> diff --git a/addons/crm/crm_lead_view.xml b/addons/crm/crm_lead_view.xml index 91e866ec95d..0dd740b47c8 100644 --- a/addons/crm/crm_lead_view.xml +++ b/addons/crm/crm_lead_view.xml @@ -7,7 +7,7 @@ Stage - Search - crm.case.stage + crm.stage @@ -21,9 +21,9 @@ Stages - crm.case.stage + crm.stage form - +

Click to set a new stage in your lead/opportunity pipeline. @@ -40,14 +40,35 @@ LEADS/OPPORTUNITIES CATEGORIES --> - - + + crm.lead.tag.form + crm.lead.tag + +

+ + + + +
+
+
+ + + crm.lead.tag.tree + crm.lead.tag + + + + + + + + + Sales Tags - crm.case.categ + crm.lead.tag form - - - [('object_id.model', '=', 'crm.lead')] +

Click to define a new sales tag. @@ -60,7 +81,7 @@ - @@ -95,7 +116,7 @@ @@ -116,9 +137,8 @@ + context="{'default_name': contact_name, 'default_street': street, 'default_city': city, 'default_state_id': state_id, 'default_zip': zip, 'default_country_id': country_id, 'default_function': function, 'default_phone': phone, 'default_mobile': mobile, 'default_fax': fax, 'default_email': email_from, 'default_user_id': user_id, 'default_team_id': team_id}"/>

@@ -146,22 +166,18 @@ - - + @@ -228,7 +244,7 @@ - + @@ -277,8 +293,8 @@
  • Edit...
  • Delete
  • -
  • Send Email
  • -
  • Calls
  • +
  • Send Email
  • +
  • Calls
  • Schedule Meeting
    @@ -325,8 +341,8 @@ - - + + @@ -346,7 +362,7 @@ help="Leads that did not ask not to be included in mass mailing campaigns"/> - + @@ -376,12 +392,12 @@ @@ -425,19 +441,15 @@ - - - + @@ -490,7 +502,6 @@ - @@ -523,7 +534,7 @@ - + @@ -541,8 +552,8 @@ - - + + @@ -564,7 +575,7 @@ - + diff --git a/addons/crm/crm_phonecall.py b/addons/crm/crm_phonecall.py index b983dbfd4b3..ebf8d5f571c 100644 --- a/addons/crm/crm_phonecall.py +++ b/addons/crm/crm_phonecall.py @@ -36,7 +36,7 @@ class crm_phonecall(osv.osv): 'date_action_last': fields.datetime('Last Action', readonly=1), 'date_action_next': fields.datetime('Next Action', readonly=1), 'create_date': fields.datetime('Creation Date' , readonly=True), - 'section_id': fields.many2one('crm.case.section', 'Sales Team', \ + 'team_id': fields.many2one('crm.team', 'Sales Team', oldname='section_id',\ select=True, help='Sales team to which Case belongs to.'), 'user_id': fields.many2one('res.users', 'Responsible'), 'partner_id': fields.many2one('res.partner', 'Contact'), @@ -57,9 +57,7 @@ class crm_phonecall(osv.osv): 'name': fields.char('Call Summary', required=True), 'active': fields.boolean('Active', required=False), 'duration': fields.float('Duration', help='Duration in minutes and seconds.'), - 'categ_id': fields.many2one('crm.case.categ', 'Category', \ - domain="['|',('section_id','=',section_id),('section_id','=',False),\ - ('object_id.model', '=', 'crm.phonecall')]"), + 'categ_id': fields.many2one('crm.phonecall.category', 'Category'), 'partner_phone': fields.char('Phone'), 'partner_mobile': fields.char('Mobile'), 'priority': fields.selection([('0','Low'), ('1','Normal'), ('2','High')], 'Priority'), @@ -111,7 +109,7 @@ class crm_phonecall(osv.osv): return True def schedule_another_phonecall(self, cr, uid, ids, schedule_time, call_summary, \ - user_id=False, section_id=False, categ_id=False, action='schedule', context=None): + user_id=False, team_id=False, categ_id=False, action='schedule', context=None): """ action :('schedule','Schedule a call'), ('log','Log a call') """ @@ -124,8 +122,8 @@ class crm_phonecall(osv.osv): except ValueError: pass for call in self.browse(cr, uid, ids, context=context): - if not section_id: - section_id = call.section_id and call.section_id.id or False + if not team_id: + team_id = call.team_id and call.team_id.id or False if not user_id: user_id = call.user_id and call.user_id.id or False if not schedule_time: @@ -136,7 +134,7 @@ class crm_phonecall(osv.osv): 'categ_id' : categ_id or False, 'description' : call.description or False, 'date' : schedule_time, - 'section_id' : section_id or False, + 'team_id' : team_id or False, 'partner_id': call.partner_id and call.partner_id.id or False, 'partner_phone' : call.partner_phone, 'partner_mobile' : call.partner_mobile, @@ -164,7 +162,7 @@ class crm_phonecall(osv.osv): if opportunity_id: opportunity = self.pool.get('crm.lead').browse(cr, uid, opportunity_id, context=context) values = { - 'section_id' : opportunity.section_id and opportunity.section_id.id or False, + 'team_id' : opportunity.team_id and opportunity.team_id.id or False, 'partner_phone' : opportunity.phone, 'partner_mobile' : opportunity.mobile, 'partner_id' : opportunity.partner_id and opportunity.partner_id.id or False, @@ -245,7 +243,7 @@ class crm_phonecall(osv.osv): 'probability': probability, 'partner_id': partner_id or False, 'mobile': default_contact and default_contact.mobile, - 'section_id': call.section_id and call.section_id.id or False, + 'team_id': call.team_id and call.team_id.id or False, 'description': call.description or False, 'priority': call.priority, 'type': 'opportunity', @@ -300,4 +298,12 @@ class crm_phonecall(osv.osv): def _call_set_partner_send_note(self, cr, uid, ids, context=None): return self.message_post(cr, uid, ids, body=_("Partner has been created."), context=context) +class crm_phonecall_category(osv.Model): + _name = "crm.phonecall.category" + _description = "Category of phonecall" + _columns = { + 'name': fields.char('Name', required=True, translate=True), + 'team_id': fields.many2one('crm.team', 'Sales Team'), + } + # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/crm/crm_phonecall_data.xml b/addons/crm/crm_phonecall_data.xml index ce82a9a7b51..0eb5c999b27 100644 --- a/addons/crm/crm_phonecall_data.xml +++ b/addons/crm/crm_phonecall_data.xml @@ -4,16 +4,13 @@ - + Inbound - - - + - + Outbound - - + diff --git a/addons/crm/crm_phonecall_demo.xml b/addons/crm/crm_phonecall_demo.xml index 8563a38b075..d36aabbc5f0 100644 --- a/addons/crm/crm_phonecall_demo.xml +++ b/addons/crm/crm_phonecall_demo.xml @@ -11,7 +11,7 @@ Left the message done +34 934 340 230 - + @@ -24,7 +24,7 @@ Need more information on the proposed deal done +44 121 690 4596 - + @@ -37,7 +37,7 @@ Ask for convenient time of meeting open +1 786 525 0724 - + @@ -50,7 +50,7 @@ done (077) 582-4035 (077) 341-3591 - + @@ -63,7 +63,7 @@ More information on the proposed deal pending +1 312 349 2324 - + @@ -74,7 +74,7 @@ Proposal for discount offer open +34 230 953 485 - + diff --git a/addons/crm/crm_phonecall_menu.xml b/addons/crm/crm_phonecall_menu.xml index 6141b5fb1d6..7c76cd7342e 100644 --- a/addons/crm/crm_phonecall_menu.xml +++ b/addons/crm/crm_phonecall_menu.xml @@ -16,7 +16,7 @@ - + Phone Calls crm.phonecall form @@ -30,28 +30,28 @@ tree - + calendar - + form - + - + Logged Calls crm.phonecall form @@ -78,28 +78,28 @@ tree - + calendar - + form - + + action="crm_phonecall_category_phone_incoming0" /> - + Scheduled Calls crm.phonecall form @@ -125,27 +125,27 @@ tree - + calendar - + form - + + action="crm_phonecall_category_phone_outgoing0"/> diff --git a/addons/crm/crm_phonecall_view.xml b/addons/crm/crm_phonecall_view.xml index 3c208dde991..7ae15f49cad 100644 --- a/addons/crm/crm_phonecall_view.xml +++ b/addons/crm/crm_phonecall_view.xml @@ -3,14 +3,37 @@ - - + + + + crm.phonecall.category.form + crm.phonecall.category + +
    + + + + +
    +
    +
    + + + crm.phonecall.category.tree + crm.phonecall.category + + + + + + + + + Phonecall Categories - crm.case.categ + crm.phonecall.category form - - [('object_id.model', '=', 'crm.phonecall')] - +

    Click to add a new category. @@ -21,7 +44,7 @@ - @@ -97,11 +120,10 @@

    min(s)
    - - + @@ -130,7 +152,6 @@ invisible="1"/> @@ -174,7 +195,7 @@ - + @@ -184,7 +205,7 @@ - diff --git a/addons/crm/crm_report_view.xml b/addons/crm/crm_report_view.xml index 1312917b59b..8aaa1e7a385 100644 --- a/addons/crm/crm_report_view.xml +++ b/addons/crm/crm_report_view.xml @@ -2,17 +2,17 @@ - + - + CRM Report - Teams and Type(Tree) - report.crm.case.section.categ2 + report.crm.team.categ2 - + @@ -23,18 +23,18 @@ - + - + CRM Report - Teams and Type(Form) - report.crm.case.section.categ2 + report.crm.team.categ2
    - @@ -47,59 +47,59 @@ - + - + CRM Report - Teams and Type(Graph) - report.crm.case.section.categ2 + report.crm.team.categ2 - - + - + CRM Report - Teams and Type(Select) - report.crm.case.section.categ2 + report.crm.team.categ2 - + - + - - Cases By Section and Category - report.crm.case.section.categ2 + + Cases By team and Category + report.crm.team.categ2 form graph,tree - + - + - + CRM Report - Teams and Stage(Tree) - report.crm.case.section.stage + report.crm.team.stage - + @@ -109,18 +109,18 @@ - + - + CRM Report - Teams and Stage(Form) - report.crm.case.section.stage + report.crm.team.stage - @@ -132,57 +132,57 @@ - + - + CRM Report - Teams and Stage(Graph) - report.crm.case.section.stage + report.crm.team.stage - + - + - + CRM Report - Teams and Stage(Select) - report.crm.case.section.stage + report.crm.team.stage - + - + - - Cases By Section and Stage - report.crm.case.section.stage + + Cases By team and Stage + report.crm.team.stage form graph,tree - + - + - + CRM Report - Team, Category and Stage(Tree) - report.crm.case.section.categ.stage + report.crm.team.categ.stage - + @@ -192,18 +192,18 @@ - + - + CRM Report - Team, Category and Stage(Form) - report.crm.case.section.categ.stage + report.crm.team.categ.stage - + - + @@ -214,57 +214,57 @@ - + - - CRM Report - Section, Category and Stage(Select) - report.crm.case.section.categ.stage + + CRM Report - Team, Category and Stage(Select) + report.crm.team.categ.stage - + - + - + - - CRM Report - Section, Category and Stage(Select) - report.crm.case.section.categ.stage + + CRM Report - Team, Category and Stage(Select) + report.crm.team.categ.stage - + - + - + - - Cases By Section ,Category and Stage - report.crm.case.section.categ.stage + + Cases By Team ,Category and Stage + report.crm.team.categ.stage form tree,graph - + - + - - CRM Report - Section, Category and Type(Tree) - report.crm.case.section.categ.categ2 + + CRM Report - Team, Category and Type(Tree) + report.crm.team.categ.categ2 - + - + @@ -275,18 +275,18 @@ - + - - CRM Report - Section, Category and Type(Form) - report.crm.case.section.categ.categ2 + + CRM Report - Team, Category and Type(Form) + report.crm.team.categ.categ2 - + - + @@ -298,44 +298,44 @@ - + - - CRM Report - Section, Category and Type(Select) - report.crm.case.section.categ.categ2 + + CRM Report - Team, Category and Type(Select) + report.crm.team.categ.categ2 - + - + - - CRM Report - Section, Category and Type(Select) - report.crm.case.section.categ.categ2 + + CRM Report - Team, Category and Type(Select) + report.crm.team.categ.categ2 - + - + - + - - Cases By Section ,Category and Category2 - report.crm.case.section.categ.categ2 + + Cases By Team ,Category and Category2 + report.crm.team.categ.categ2 form tree,graph - + diff --git a/addons/crm/crm_segmentation.py b/addons/crm/crm_segmentation.py deleted file mode 100644 index 16c1588738f..00000000000 --- a/addons/crm/crm_segmentation.py +++ /dev/null @@ -1,185 +0,0 @@ -# -*- coding: utf-8 -*- -############################################################################## -# -# OpenERP, Open Source Management Solution -# Copyright (C) 2004-2010 Tiny SPRL (). -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# -############################################################################## - -from openerp.osv import fields,osv,orm - -class crm_segmentation(osv.osv): - ''' - A segmentation is a tool to automatically assign categories on partners. - These assignations are based on criterions. - ''' - _name = "crm.segmentation" - _description = "Partner Segmentation" - - _columns = { - 'name': fields.char('Name', required=True, help='The name of the segmentation.'), - 'description': fields.text('Description'), - 'categ_id': fields.many2one('res.partner.category', 'Partner Category',\ - required=True, help='The partner category that will be \ -added to partners that match the segmentation criterions after computation.'), - 'exclusif': fields.boolean('Exclusive', help='Check if the category is limited to partners that match the segmentation criterions.\ - \nIf checked, remove the category from partners that doesn\'t match segmentation criterions'), - 'state': fields.selection([('not running','Not Running'),\ - ('running','Running')], 'Execution Status', readonly=True), - 'partner_id': fields.integer('Max Partner ID processed'), - 'segmentation_line': fields.one2many('crm.segmentation.line', \ - 'segmentation_id', 'Criteria', required=True, copy=True), - 'sales_purchase_active': fields.boolean('Use The Sales Purchase Rules', help='Check if you want to use this tab as part of the segmentation rule. If not checked, the criteria beneath will be ignored') - } - _defaults = { - 'partner_id': lambda *a: 0, - 'state': lambda *a: 'not running', - } - - def process_continue(self, cr, uid, ids, start=False): - - """ @param self: The object pointer - @param cr: the current row, from the database cursor, - @param uid: the current user’s ID for security checks, - @param ids: List of Process continue’s IDs""" - - partner_obj = self.pool.get('res.partner') - categs = self.read(cr, uid, ids, ['categ_id', 'exclusif', 'sales_purchase_active']) - for categ in categs: - if start: - if categ['exclusif']: - cr.execute('delete from res_partner_res_partner_category_rel \ - where category_id=%s', (categ['categ_id'][0],)) - partner_obj.invalidate_cache(cr, uid, ['category_id']) - - id = categ['id'] - - cr.execute('select id from res_partner order by id ') - partners = [x[0] for x in cr.fetchall()] - - if categ['sales_purchase_active']: - to_remove_list=[] - cr.execute('select id from crm_segmentation_line where segmentation_id=%s', (id,)) - line_ids = [x[0] for x in cr.fetchall()] - - for pid in partners: - if (not self.pool.get('crm.segmentation.line').test(cr, uid, line_ids, pid)): - to_remove_list.append(pid) - for pid in to_remove_list: - partners.remove(pid) - - for partner in partner_obj.browse(cr, uid, partners): - category_ids = [categ_id.id for categ_id in partner.category_id] - if categ['categ_id'][0] not in category_ids: - cr.execute('insert into res_partner_res_partner_category_rel (category_id,partner_id) \ - values (%s,%s)', (categ['categ_id'][0], partner.id)) - partner_obj.invalidate_cache(cr, uid, ['category_id'], [partner.id]) - - self.write(cr, uid, [id], {'state':'not running', 'partner_id':0}) - return True - - def process_stop(self, cr, uid, ids, *args): - - """ @param self: The object pointer - @param cr: the current row, from the database cursor, - @param uid: the current user’s ID for security checks, - @param ids: List of Process stop’s IDs""" - - return self.write(cr, uid, ids, {'state':'not running', 'partner_id':0}) - - def process_start(self, cr, uid, ids, *args): - - """ @param self: The object pointer - @param cr: the current row, from the database cursor, - @param uid: the current user’s ID for security checks, - @param ids: List of Process start’s IDs """ - - self.write(cr, uid, ids, {'state':'running', 'partner_id':0}) - return self.process_continue(cr, uid, ids, start=True) - -class crm_segmentation_line(osv.osv): - """ Segmentation line """ - _name = "crm.segmentation.line" - _description = "Segmentation line" - - _columns = { - 'name': fields.char('Rule Name', required=True), - 'segmentation_id': fields.many2one('crm.segmentation', 'Segmentation'), - 'expr_name': fields.selection([('sale','Sale Amount'), - ('purchase','Purchase Amount')], 'Control Variable', required=True), - 'expr_operator': fields.selection([('<','<'),('=','='),('>','>')], 'Operator', required=True), - 'expr_value': fields.float('Value', required=True), - 'operator': fields.selection([('and','Mandatory Expression'),\ - ('or','Optional Expression')],'Mandatory / Optional', required=True), - } - _defaults = { - 'expr_name': lambda *a: 'sale', - 'expr_operator': lambda *a: '>', - 'operator': lambda *a: 'and' - } - def test(self, cr, uid, ids, partner_id): - - """ @param self: The object pointer - @param cr: the current row, from the database cursor, - @param uid: the current user’s ID for security checks, - @param ids: List of Test’s IDs """ - - expression = {'<': lambda x,y: x':lambda x,y:x>y} - ok = False - lst = self.read(cr, uid, ids) - for l in lst: - cr.execute('select * from ir_module_module where name=%s and state=%s', ('account','installed')) - if cr.fetchone(): - if l['expr_name']=='sale': - cr.execute('SELECT SUM(l.price_unit * l.quantity) ' \ - 'FROM account_invoice_line l, account_invoice i ' \ - 'WHERE (l.invoice_id = i.id) ' \ - 'AND i.partner_id = %s '\ - 'AND i.type = \'out_invoice\'', - (partner_id,)) - value = cr.fetchone()[0] or 0.0 - cr.execute('SELECT SUM(l.price_unit * l.quantity) ' \ - 'FROM account_invoice_line l, account_invoice i ' \ - 'WHERE (l.invoice_id = i.id) ' \ - 'AND i.partner_id = %s '\ - 'AND i.type = \'out_refund\'', - (partner_id,)) - value -= cr.fetchone()[0] or 0.0 - elif l['expr_name']=='purchase': - cr.execute('SELECT SUM(l.price_unit * l.quantity) ' \ - 'FROM account_invoice_line l, account_invoice i ' \ - 'WHERE (l.invoice_id = i.id) ' \ - 'AND i.partner_id = %s '\ - 'AND i.type = \'in_invoice\'', - (partner_id,)) - value = cr.fetchone()[0] or 0.0 - cr.execute('SELECT SUM(l.price_unit * l.quantity) ' \ - 'FROM account_invoice_line l, account_invoice i ' \ - 'WHERE (l.invoice_id = i.id) ' \ - 'AND i.partner_id = %s '\ - 'AND i.type = \'in_refund\'', - (partner_id,)) - value -= cr.fetchone()[0] or 0.0 - res = expression[l['expr_operator']](value, l['expr_value']) - if (not res) and (l['operator']=='and'): - return False - if res: - return True - return True - - -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: - diff --git a/addons/crm/crm_view.xml b/addons/crm/crm_view.xml index 42618e55792..1fb8696cd80 100644 --- a/addons/crm/crm_view.xml +++ b/addons/crm/crm_view.xml @@ -109,9 +109,9 @@ - - crm.case.stage.tree - crm.case.stage + + crm.stage.tree + crm.stage @@ -124,9 +124,9 @@ - - crm.case.stage.form - crm.case.stage + + crm.stage.form + crm.stage @@ -146,48 +146,18 @@ - +
    - + Stages - crm.case.stage + crm.stage form - - - - - - - - crm.case.categ.form - crm.case.categ - -
    - - - - - -
    -
    -
    - - - - - crm.case.categ.tree - crm.case.categ - - - - - - + @@ -198,7 +168,7 @@ - +
    @@ -212,7 +182,7 @@
    - +
    @@ -232,163 +202,5 @@ groups="base.group_no_one" parent="base.menu_crm_config_lead"/> - - - - - crm.segmentation.line.tree - crm.segmentation.line - - - - - - - - - - - - - - - crm.segmentation.line.form - crm.segmentation.line - -
    - - - - - - - - - -
    -
    -
    - - - - - crm.segmentation.form - crm.segmentation - -
    -
    -
    - - - - - - - - - - - - - - - - - -
    -
    -
    - - - - - crm.segmentation.tree - crm.segmentation - - - - - - - - - - - Segmentation - crm.segmentation - form - - - - - Contacts Segmentation - crm.segmentation - form - tree,form - -

    - Click to define a new customer segmentation. -

    - Create specific categories which you can assign to your - contacts to better manage your interactions with them. The - segmentation tool is able to assign categories to contacts - according to criteria you set. -

    -
    -
    - - - - - - - crm.payment.mode.tree - crm.payment.mode - - - - - - - - - - - - crm.payment.mode.form - crm.payment.mode - -
    - - - - -
    -
    -
    - - - - - Payment Mode - crm.payment.mode - form - tree,form - -
    diff --git a/addons/crm/report/crm_lead_report.py b/addons/crm/report/crm_lead_report.py index 6f74cad074e..73bd0498d88 100644 --- a/addons/crm/report/crm_lead_report.py +++ b/addons/crm/report/crm_lead_report.py @@ -45,13 +45,13 @@ class crm_lead_report(osv.Model): 'delay_expected': fields.float('Overpassed Deadline',digits=(16,2),readonly=True, group_operator="avg"), 'user_id':fields.many2one('res.users', 'User', readonly=True), - 'section_id':fields.many2one('crm.case.section', 'Sales Team', readonly=True), + 'team_id':fields.many2one('crm.team', 'Sales Team', oldname='section_id', readonly=True), 'country_id':fields.many2one('res.country', 'Country', readonly=True), 'company_id': fields.many2one('res.company', 'Company', readonly=True), 'probability': fields.float('Probability',digits=(16,2),readonly=True, group_operator="avg"), 'planned_revenue': fields.float('Total Revenue',digits=(16,2),readonly=True), # TDE FIXME master: rename into total_revenue 'probable_revenue': fields.float('Expected Revenue', digits=(16,2),readonly=True), # TDE FIXME master: rename into expected_revenue - 'stage_id': fields.many2one ('crm.case.stage', 'Stage', readonly=True, domain="[('section_ids', '=', section_id)]"), + 'stage_id': fields.many2one ('crm.stage', 'Stage', readonly=True, domain="[('team_ids', '=', team_id)]"), 'partner_id': fields.many2one('res.partner', 'Partner' , readonly=True), 'company_id': fields.many2one('res.company', 'Company', readonly=True), 'priority': fields.selection(crm.AVAILABLE_PRIORITIES, 'Priority'), @@ -86,7 +86,7 @@ class crm_lead_report(osv.Model): c.type, c.company_id, c.priority, - c.section_id, + c.team_id, c.campaign_id, c.source_id, c.medium_id, diff --git a/addons/crm/report/crm_lead_report_view.xml b/addons/crm/report/crm_lead_report_view.xml index 4c3fa310e49..aeac2097b12 100644 --- a/addons/crm/report/crm_lead_report_view.xml +++ b/addons/crm/report/crm_lead_report_view.xml @@ -2,13 +2,13 @@ - + crm.lead.report.graph crm.lead.report - + @@ -32,7 +32,7 @@ Long Term Revenue crm.lead.report - {'group_by': ['country_id', 'section_id'], 'col_group_by': ['date_deadline'], 'measures': ['planned_revenue']} + {'group_by': ['country_id', 'team_id'], 'col_group_by': ['date_deadline'], 'measures': ['planned_revenue']} Revenue Per Lead @@ -44,7 +44,7 @@ Overpassed Deadline crm.lead.report - {'group_by': ['section_id'], 'col_group_by': ['partner_id'], 'measures': ['delay_expected']} + {'group_by': ['team_id'], 'col_group_by': ['partner_id'], 'measures': ['delay_expected']} By Salespersons @@ -59,7 +59,7 @@ {'group_by': ['create_date:month', 'country_id']} - + crm.lead.report.select crm.lead.report @@ -74,18 +74,18 @@ domain="[('probability', '=', 100), ('stage_id.on_change', '=', 1)]"/> - - + - + @@ -98,7 +98,7 @@ - + @@ -109,7 +109,7 @@ - + Leads Analysis crm.lead.report diff --git a/addons/crm/report/crm_opportunity_report.py b/addons/crm/report/crm_opportunity_report.py index 8300448124e..7230f94b3d4 100644 --- a/addons/crm/report/crm_opportunity_report.py +++ b/addons/crm/report/crm_opportunity_report.py @@ -46,13 +46,13 @@ class crm_opportunity_report(osv.Model): 'delay_expected': fields.float('Overpassed Deadline',digits=(16,2),readonly=True, group_operator="avg"), 'user_id':fields.many2one('res.users', 'User', readonly=True), - 'section_id':fields.many2one('crm.case.section', 'Sales Team', readonly=True), + 'team_id':fields.many2one('crm.team', 'Sales Team', oldname='section_id', readonly=True), 'country_id':fields.many2one('res.country', 'Country', readonly=True), 'company_id': fields.many2one('res.company', 'Company', readonly=True), 'probability': fields.float('Probability',digits=(16,2),readonly=True, group_operator="avg"), 'total_revenue': fields.float('Total Revenue',digits=(16,2),readonly=True), 'expected_revenue': fields.float('Expected Revenue', digits=(16,2),readonly=True), - 'stage_id': fields.many2one ('crm.case.stage', 'Stage', readonly=True, domain="[('section_ids', '=', section_id)]"), + 'stage_id': fields.many2one ('crm.stage', 'Stage', readonly=True, domain="[('team_ids', '=', team_id)]"), 'partner_id': fields.many2one('res.partner', 'Partner' , readonly=True), 'company_id': fields.many2one('res.company', 'Company', readonly=True), 'priority': fields.selection(crm.AVAILABLE_PRIORITIES, 'Priority'), @@ -82,7 +82,7 @@ class crm_opportunity_report(osv.Model): c.type, c.company_id, c.priority, - c.section_id, + c.team_id, c.campaign_id, c.source_id, c.medium_id, diff --git a/addons/crm/report/crm_opportunity_report_view.xml b/addons/crm/report/crm_opportunity_report_view.xml index 0b58e103e48..d99eca3fcde 100644 --- a/addons/crm/report/crm_opportunity_report_view.xml +++ b/addons/crm/report/crm_opportunity_report_view.xml @@ -2,7 +2,7 @@ - + crm.opportunity.report.graph crm.opportunity.report @@ -29,7 +29,7 @@ crm.opportunity.report [('type','=','opportunity'), ('probability', '=', 100), ('stage_id.on_change', '=', 1)] - {'group_by': ['section_id'], 'col_group_by': ['date_last_stage_update:month'], 'measures': ['nbr_cases', 'delay_close']} + {'group_by': ['team_id'], 'col_group_by': ['date_last_stage_update:month'], 'measures': ['nbr_cases', 'delay_close']} Top Opportunities @@ -51,7 +51,7 @@ {'group_by': ['create_date:month', 'country_id']} - + crm.opportunity.report.select crm.opportunity.report @@ -66,18 +66,18 @@ domain="[('probability', '=', 100), ('stage_id.on_change', '=', 1)]"/> - - + - + @@ -90,7 +90,7 @@ - + diff --git a/addons/crm/report/crm_phonecall_report.py b/addons/crm/report/crm_phonecall_report.py index 4df59c301ab..58b34df596a 100644 --- a/addons/crm/report/crm_phonecall_report.py +++ b/addons/crm/report/crm_phonecall_report.py @@ -33,15 +33,15 @@ AVAILABLE_STATES = [ class crm_phonecall_report(osv.osv): - """ Phone calls by user and section """ + """ Phone calls by user and team """ _name = "crm.phonecall.report" - _description = "Phone calls by user and section" + _description = "Phone calls by user and team" _auto = False _columns = { 'user_id':fields.many2one('res.users', 'User', readonly=True), - 'section_id':fields.many2one('crm.case.section', 'Section', readonly=True), + 'team_id':fields.many2one('crm.team', 'team', oldname='section_id', readonly=True), 'priority': fields.selection([('0','Low'), ('1','Normal'), ('2','High')], 'Priority'), 'nbr': fields.integer('# of Cases', readonly=True), # TDE FIXME master: rename into nbr_cases 'state': fields.selection(AVAILABLE_STATES, 'Status', readonly=True), @@ -49,9 +49,7 @@ class crm_phonecall_report(osv.osv): 'delay_close': fields.float('Delay to close', digits=(16,2),readonly=True, group_operator="avg",help="Number of Days to close the case"), 'duration': fields.float('Duration', digits=(16,2),readonly=True, group_operator="avg"), 'delay_open': fields.float('Delay to open',digits=(16,2),readonly=True, group_operator="avg",help="Number of Days to open the case"), - 'categ_id': fields.many2one('crm.case.categ', 'Category', \ - domain="[('section_id','=',section_id),\ - ('object_id.model', '=', 'crm.phonecall')]"), + 'categ_id': fields.many2one('crm.phonecall.category', 'Category'), 'partner_id': fields.many2one('res.partner', 'Partner' , readonly=True), 'company_id': fields.many2one('res.company', 'Company', readonly=True), 'opening_date': fields.datetime('Opening Date', readonly=True, select=True), @@ -60,7 +58,7 @@ class crm_phonecall_report(osv.osv): def init(self, cr): - """ Phone Calls By User And Section + """ Phone Calls By User And Team @param cr: the current row, from the database cursor, """ tools.drop_view_if_exists(cr, 'crm_phonecall_report') @@ -72,7 +70,7 @@ class crm_phonecall_report(osv.osv): c.date_closed as date_closed, c.state, c.user_id, - c.section_id, + c.team_id, c.categ_id, c.partner_id, c.duration, diff --git a/addons/crm/report/crm_phonecall_report_view.xml b/addons/crm/report/crm_phonecall_report_view.xml index d9f35646d98..1401ec91171 100644 --- a/addons/crm/report/crm_phonecall_report_view.xml +++ b/addons/crm/report/crm_phonecall_report_view.xml @@ -2,14 +2,14 @@ - + crm.phonecall.report.graph crm.phonecall.report - + @@ -23,25 +23,25 @@ crm.phonecall.report [('state','=','done')] - {'group_by': ['section_id'], 'col_group_by': ['categ_id'], 'measures': ['nbr', 'duration']} + {'group_by': ['team_id'], 'col_group_by': ['categ_id'], 'measures': ['nbr', 'duration']} Delay To Close crm.phonecall.report [('state','=','done')] - {'group_by': ['section_id'], 'col_group_by': ['categ_id'], 'measures': ['delay_close']} + {'group_by': ['team_id'], 'col_group_by': ['categ_id'], 'measures': ['delay_close']} Phone Calls To Do crm.phonecall.report [('state','in',('draft','open'))] - {'group_by': ['section_id'], 'measures': ['nbr']} + {'group_by': ['team_id'], 'measures': ['nbr']} - + crm.phonecall.report.select @@ -55,11 +55,11 @@ - - @@ -70,7 +70,7 @@ - + @@ -80,7 +80,7 @@ - + Phone Calls Analysis diff --git a/addons/crm/report/report_businessopp.py b/addons/crm/report/report_businessopp.py deleted file mode 100644 index c057673d57f..00000000000 --- a/addons/crm/report/report_businessopp.py +++ /dev/null @@ -1,187 +0,0 @@ -# -*- coding: utf-8 -*- -############################################################################## -# -# OpenERP, Open Source Management Solution -# Copyright (C) 2004-2010 Tiny SPRL (). -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# -############################################################################## - -import os, time - -import random -import StringIO - -from openerp.report.render import render -from openerp.report.interface import report_int -from pychart import * - -theme.use_color = 1 - -class external_pdf(render): - - """ Generate External PDF """ - - def __init__(self, pdf): - render.__init__(self) - self.pdf = pdf - self.output_type = 'pdf' - - def _render(self): - return self.pdf - -class report_custom(report_int): - - """ Create Custom Report """ - - def create(self, cr, uid, ids, datas, context=None): - - """ @param cr: the current row, from the database cursor, - @param uid: the current user’s ID for security checks, - @param ids: List of IDs - @param context: A standard dictionary for contextual values """ - - assert len(ids), 'You should provide some ids!' - responsible_data = {} - responsible_names = {} - data = [] - minbenef = 999999999999999999999 - maxbenef = 0 - - cr.execute('select probability, planned_revenue, planned_cost, user_id,\ - res_users.name as name from crm_case left join res_users on \ - (crm_case.user_id=res_users.id) where crm_case.id IN %s order by user_id',(tuple(ids),)) - - res = cr.dictfetchall() - for row in res: - proba = row['probability'] or 0 / 100.0 - cost = row['planned_cost'] or 0 - revenue = row['planned_revenue'] or 0 - userid = row['user_id'] or 0 - - benefit = revenue - cost - if benefit > maxbenef: - maxbenef = benefit - if benefit < minbenef: - minbenef = benefit - - tuple_benefit = (proba * 100, benefit) - responsible_data.setdefault(userid, []) - responsible_data[userid].append(tuple_benefit) - - tuple_benefit = (proba * 100, cost, benefit) - data.append(tuple_benefit) - - responsible_names[userid] = (row['name'] or '/').replace('/','//') - - minbenef -= maxbenef * 0.05 - maxbenef *= 1.2 - - ratio = 0.5 - minmaxdiff2 = (maxbenef - minbenef)/2 - - for l in responsible_data.itervalues(): - for i in range(len(l)): - percent, benef = l[i] - proba = percent/100 - - current_ratio = 1 + (ratio-1) * proba - - newbenef = minmaxdiff2 + ((benef - minbenef - minmaxdiff2) * current_ratio) - - l[i] = (percent, newbenef) - -#TODO: -#-group by "categorie de probabilites ds graphe du haut" -#-echelle variable - - pdf_string = StringIO.StringIO() - can = canvas.init(fname = pdf_string, format = 'pdf') - - chart_object.set_defaults(line_plot.T, line_style=None) - - xaxis = axis.X(label=None, format="%d%%", tic_interval=20) - yaxis = axis.Y() - - x_range_a, x_range_b = (0, 100) - y_range_a, y_range_b = (minbenef, maxbenef) - if y_range_a == 0.0: - y_range_a += 0.0001 - - ar = area.T( - size = (300,200), - y_grid_interval = 10000, - y_grid_style = None, - x_range = (x_range_a, x_range_b), - y_range = (y_range_a, y_range_b), - x_axis = xaxis, - y_axis = None, - legend = legend.T() - ) - - #import pydb; pydb.debugger() - for k, d in responsible_data.iteritems(): - fill = fill_style.Plain(bgcolor=color.T(r=random.random(), g=random.random(), b=random.random())) - tick = tick_mark.Square(size=6, fill_style=fill) - ar.add_plot(line_plot.T(label=responsible_names[k], data=d, tick_mark=tick)) - - ar.draw(can) - - # second graph (top right) - ar = area.T(legend = legend.T(), - size = (200,100), - loc = (100,250), - x_grid_interval = lambda min, max: [40,60,80,100], - x_grid_style = line_style.gray70_dash1, - x_range = (33, 100), - x_axis = axis.X(label=None, minor_tic_interval = lambda min,max: [50, 70, 90],\ - format=lambda x: ""), - y_axis = axis.Y(label="Planned amounts")) - - bar_plot.fill_styles.reset(); - plot1 = bar_plot.T(label="Cost", data=data, fill_style=fill_style.red) - plot2 = bar_plot.T(label="Revenue", data=data, hcol=2, stack_on = plot1, fill_style=fill_style.blue) - - ar.add_plot(plot1, plot2) - - ar.draw(can) - - # diagonal "pipeline" lines - can.line(line_style.black, 0, 200, 300, 150) - can.line(line_style.black, 0, 0, 300, 50) - - # vertical lines - ls = line_style.T(width=0.4, color=color.gray70, dash=(2, 2)) - for x in range(120, 300, 60): - can.line(ls, x, 0, x, 250) - - # draw arrows to the right - a = arrow.fat1 - for y in range(60, 150, 10): - a.draw([(285, y), (315, y)], can=can) - - # close canvas so that the file is written to "disk" - can.close() - - self.obj = external_pdf(pdf_string.getvalue()) - self.obj.render() - - pdf_string.close() - return (self.obj.pdf, 'pdf') - -report_custom('report.crm.case') - -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: - diff --git a/addons/crm/res_config.py b/addons/crm/res_config.py index d48e66e286c..b41f872fa26 100644 --- a/addons/crm/res_config.py +++ b/addons/crm/res_config.py @@ -55,7 +55,7 @@ class crm_configuration(osv.TransientModel): cr, uid, [ ('alias_model_id.model', '=', 'crm.lead'), ('alias_force_thread_id', '=', False), - ('alias_parent_model_id.model', '=', 'crm.case.section'), + ('alias_parent_model_id.model', '=', 'crm.team'), ('alias_parent_thread_id', '=', False), ('alias_defaults', '=', '{}') ], context=context) @@ -74,7 +74,7 @@ class crm_configuration(osv.TransientModel): for record in self.browse(cr, uid, ids, context=context): alias_id = self._find_default_lead_alias_id(cr, uid, context=context) if not alias_id: - create_ctx = dict(context, alias_model_name='crm.lead', alias_parent_model_name='crm.case.section') + create_ctx = dict(context, alias_model_name='crm.lead', alias_parent_model_name='crm.team') alias_id = self.pool['mail.alias'].create(cr, uid, {'alias_name': record.alias_prefix}, context=create_ctx) else: mail_alias.write(cr, uid, alias_id, {'alias_name': record.alias_prefix}, context=context) diff --git a/addons/crm/res_partner.py b/addons/crm/res_partner.py index fd898017e13..5bf8cacb8cf 100644 --- a/addons/crm/res_partner.py +++ b/addons/crm/res_partner.py @@ -41,7 +41,7 @@ class res_partner(osv.osv): return res _columns = { - 'section_id': fields.many2one('crm.case.section', 'Sales Team'), + 'team_id': fields.many2one('crm.team', 'Sales Team', oldname='section_id'), 'opportunity_ids': fields.one2many('crm.lead', 'partner_id',\ 'Opportunities', domain=[('type', '=', 'opportunity')]), 'meeting_ids': fields.many2many('calendar.event', 'calendar_event_res_partner_rel','res_partner_id', 'calendar_event_id', @@ -69,9 +69,8 @@ class res_partner(osv.osv): return value def make_opportunity(self, cr, uid, ids, opportunity_summary, planned_revenue=0.0, probability=0.0, partner_id=None, context=None): - categ_obj = self.pool.get('crm.case.categ') - categ_ids = categ_obj.search(cr, uid, [('object_id.model','=','crm.lead')]) lead_obj = self.pool.get('crm.lead') + tag_ids = self.pool['crm.lead.tag'].search(cr, uid, []) opportunity_ids = {} for partner in self.browse(cr, uid, ids, context=context): if not partner_id: @@ -81,7 +80,7 @@ class res_partner(osv.osv): 'planned_revenue' : planned_revenue, 'probability' : probability, 'partner_id' : partner_id, - 'categ_ids' : categ_ids and categ_ids[0:1] or [], + 'tag_ids' : tag_ids and tag_ids[0] or [], 'type': 'opportunity' }, context=context) opportunity_ids[partner_id] = opportunity_id diff --git a/addons/crm/res_partner_view.xml b/addons/crm/res_partner_view.xml index 3b6c4dcaa87..f2b33724e8f 100644 --- a/addons/crm/res_partner_view.xml +++ b/addons/crm/res_partner_view.xml @@ -78,7 +78,7 @@ - + view.res.partner.form.crm.inherited1 res.partner @@ -87,12 +87,12 @@ - + diff --git a/addons/crm_claim/security/ir.model.access.csv b/addons/crm_claim/security/ir.model.access.csv index 303624288ce..582ba9bb6e0 100644 --- a/addons/crm_claim/security/ir.model.access.csv +++ b/addons/crm_claim/security/ir.model.access.csv @@ -4,3 +4,6 @@ access_crm_claim_user,crm.claim.user,model_crm_claim,base.group_sale_salesman,1, access_crm_claim_stage_user,crm.claim.stage.user,model_crm_claim_stage,base.group_sale_salesman,1,1,1,1 access_crm_claim_report_manager,crm.claim.report.manager,model_crm_claim_report,base.group_sale_manager,1,1,1,1 access_crm_claim_partner_manager,crm.claim.partner.manager,model_crm_claim,base.group_partner_manager,1,0,0,0 +access_crm_claim_category,crm_claim_category,model_crm_claim_category,base.group_user,1,0,0,0 +access_crm_claim_category_salesman,crm_claim_category salesman,model_crm_claim_category,base.group_sale_salesman,1,1,1,0 +access_crm_claim_category_manager,crm_claim_category manager,model_crm_claim_category,base.group_sale_manager,1,1,1,1 diff --git a/addons/crm_helpdesk/crm_helpdesk.py b/addons/crm_helpdesk/crm_helpdesk.py index 3800efd7cf4..6286a025ae9 100644 --- a/addons/crm_helpdesk/crm_helpdesk.py +++ b/addons/crm_helpdesk/crm_helpdesk.py @@ -46,7 +46,7 @@ class crm_helpdesk(osv.osv): 'write_date': fields.datetime('Update Date' , readonly=True), 'date_deadline': fields.date('Deadline'), 'user_id': fields.many2one('res.users', 'Responsible'), - 'section_id': fields.many2one('crm.case.section', 'Sales Team', \ + 'team_id': fields.many2one('crm.team', 'Sales Team', oldname='section_id',\ select=True, help='Responsible sales team. Define Responsible user and Email account for mail gateway.'), 'company_id': fields.many2one('res.company', 'Company'), 'date_closed': fields.datetime('Closed', readonly=True), @@ -61,9 +61,7 @@ class crm_helpdesk(osv.osv): 'planned_cost': fields.float('Planned Costs'), 'priority': fields.selection([('0','Low'), ('1','Normal'), ('2','High')], 'Priority'), 'probability': fields.float('Probability (%)'), - 'categ_id': fields.many2one('crm.case.categ', 'Category', \ - domain="['|',('section_id','=',False),('section_id','=',section_id),\ - ('object_id.model', '=', 'crm.helpdesk')]"), + 'categ_id': fields.many2one('crm.helpdesk.category', 'Category'), 'duration': fields.float('Duration', states={'done': [('readonly', True)]}), 'state': fields.selection( [('draft', 'New'), @@ -108,9 +106,9 @@ class crm_helpdesk(osv.osv): """ Escalates case to parent level """ data = {'active': True} for case in self.browse(cr, uid, ids, context=context): - if case.section_id and case.section_id.parent_id: - parent_id = case.section_id.parent_id - data['section_id'] = parent_id.id + if case.team_id and case.team_id.parent_id: + parent_id = case.team_id.parent_id + data['team_id'] = parent_id.id if parent_id.change_responsible and parent_id.user_id: data['user_id'] = parent_id.user_id.id else: @@ -141,4 +139,12 @@ class crm_helpdesk(osv.osv): defaults.update(custom_values) return super(crm_helpdesk, self).message_new(cr, uid, msg, custom_values=defaults, context=context) +class crm_helpdesk_category(osv.Model): + _name = "crm.helpdesk.category" + _description = "Helpdesk Category" + _columns = { + 'name': fields.char('Name', required=True, translate=True), + 'team_id': fields.many2one('crm.team', 'Sales Team'), + } + # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/crm_helpdesk/crm_helpdesk_data.xml b/addons/crm_helpdesk/crm_helpdesk_data.xml index bc3adea8b38..70d86d2413a 100644 --- a/addons/crm_helpdesk/crm_helpdesk_data.xml +++ b/addons/crm_helpdesk/crm_helpdesk_data.xml @@ -2,7 +2,7 @@ diff --git a/addons/crm_helpdesk/crm_helpdesk_demo.xml b/addons/crm_helpdesk/crm_helpdesk_demo.xml index 83b6b03f355..c3503aefd42 100644 --- a/addons/crm_helpdesk/crm_helpdesk_demo.xml +++ b/addons/crm_helpdesk/crm_helpdesk_demo.xml @@ -7,7 +7,7 @@ 1 draft - + Download old version of Odoo? @@ -19,7 +19,7 @@ 1 draft - + Can not able to connect to Server @@ -31,7 +31,7 @@ 2 draft - + Documentation for CRM? diff --git a/addons/crm_helpdesk/crm_helpdesk_view.xml b/addons/crm_helpdesk/crm_helpdesk_view.xml index 9264f8707bf..a15c4f8ade8 100644 --- a/addons/crm_helpdesk/crm_helpdesk_view.xml +++ b/addons/crm_helpdesk/crm_helpdesk_view.xml @@ -6,15 +6,37 @@ groups="base.group_no_one" parent="base.menu_base_config" sequence="60" /> - + + + + crm.helpdesk.category.form + crm.helpdesk.category + +
    + + + + +
    +
    +
    + + + crm.helpdesk.category.tree + crm.helpdesk.category + + + + + + + Helpdesk Categories - crm.case.categ + crm.helpdesk.category form - - [('object_id.model', '=', 'crm.helpdesk')] - + Create and manage helpdesk categories to better manage and classify your support requests. @@ -37,7 +59,7 @@ - + @@ -52,7 +74,7 @@ - +
    @@ -103,7 +125,7 @@ - + @@ -138,15 +160,15 @@ - - + - + diff --git a/addons/crm_helpdesk/report/crm_helpdesk_report.py b/addons/crm_helpdesk/report/crm_helpdesk_report.py index 355daee5d7e..c75f0de3178 100644 --- a/addons/crm_helpdesk/report/crm_helpdesk_report.py +++ b/addons/crm_helpdesk/report/crm_helpdesk_report.py @@ -41,7 +41,7 @@ class crm_helpdesk_report(osv.osv): _columns = { 'date': fields.datetime('Date', readonly=True), 'user_id':fields.many2one('res.users', 'User', readonly=True), - 'section_id':fields.many2one('crm.case.section', 'Section', readonly=True), + 'team_id':fields.many2one('crm.team', 'Team', readonly=True, oldname='section_id'), 'nbr': fields.integer('# of Requests', readonly=True), # TDE FIXME master: rename into nbr_requests 'state': fields.selection(AVAILABLE_STATES, 'Status', readonly=True), 'delay_close': fields.float('Delay to Close',digits=(16,2),readonly=True, group_operator="avg"), @@ -51,9 +51,7 @@ class crm_helpdesk_report(osv.osv): 'priority': fields.selection([('5', 'Lowest'), ('4', 'Low'), \ ('3', 'Normal'), ('2', 'High'), ('1', 'Highest')], 'Priority'), 'channel_id': fields.many2one('crm.tracking.medium', 'Channel'), - 'categ_id': fields.many2one('crm.case.categ', 'Category', \ - domain="[('section_id','=',section_id),\ - ('object_id.model', '=', 'crm.helpdesk')]"), + 'categ_id': fields.many2one('crm.helpdesk.category', 'Category'), 'planned_cost': fields.float('Planned Costs'), 'create_date': fields.datetime('Creation Date' , readonly=True, select=True), 'date_closed': fields.datetime('Close Date', readonly=True, select=True), @@ -78,7 +76,7 @@ class crm_helpdesk_report(osv.osv): c.date_closed, c.state, c.user_id, - c.section_id, + c.team_id, c.partner_id, c.company_id, c.priority, @@ -94,7 +92,7 @@ class crm_helpdesk_report(osv.osv): crm_helpdesk c where c.active = 'true' group by c.date,\ - c.state, c.user_id,c.section_id,c.priority,\ + c.state, c.user_id,c.team_id,c.priority,\ c.partner_id,c.company_id,c.date_deadline,c.create_date,c.date,c.date_closed,\ c.categ_id,c.channel_id,c.planned_cost,c.id )""") diff --git a/addons/crm_helpdesk/report/crm_helpdesk_report_view.xml b/addons/crm_helpdesk/report/crm_helpdesk_report_view.xml index b64a9fade61..6dd1f57a43d 100644 --- a/addons/crm_helpdesk/report/crm_helpdesk_report_view.xml +++ b/addons/crm_helpdesk/report/crm_helpdesk_report_view.xml @@ -10,7 +10,7 @@ - + @@ -30,11 +30,11 @@ - + - + - + @@ -45,7 +45,7 @@ - + diff --git a/addons/crm_helpdesk/security/ir.model.access.csv b/addons/crm_helpdesk/security/ir.model.access.csv index 1897f2a6ac9..6b0c0ba05ec 100644 --- a/addons/crm_helpdesk/security/ir.model.access.csv +++ b/addons/crm_helpdesk/security/ir.model.access.csv @@ -2,3 +2,7 @@ id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink access_crm_helpdesk_manager,crm.helpdesk.manager,model_crm_helpdesk,base.group_sale_manager,1,1,1,1 access_crm_helpdesk_user,crm.helpdesk.user,model_crm_helpdesk,base.group_sale_salesman,1,1,1,0 access_report_crm_helpdesk_manager,report.crm.helpdesk.manager,model_crm_helpdesk_report,base.group_sale_manager,1,1,1,1 +access_crm_helpdesk_category,crm_helpdesk_category,model_crm_helpdesk_category,base.group_user,1,0,0,0 +access_crm_helpdesk_category_salesman,crm_helpdesk_category salesman,model_crm_helpdesk_category,base.group_sale_salesman,1,1,1,0 +access_crm_helpdesk_category_manager,crm_helpdesk_category manager,model_crm_helpdesk_category,base.group_sale_manager,1,1,1,1 + diff --git a/addons/crm_partner_assign/crm_lead.py b/addons/crm_partner_assign/crm_lead.py index c0dd061f511..dc7c25347af 100644 --- a/addons/crm_partner_assign/crm_lead.py +++ b/addons/crm_partner_assign/crm_lead.py @@ -54,5 +54,5 @@ class crm_lead(osv.osv): else: salesmans_leads[salesman_id] = [lead.id] for salesman_id, lead_ids in salesmans_leads.items(): - salesteam_id = self.on_change_user(cr, uid, lead_ids, salesman_id, context=None)['value'].get('section_id') - self.write(cr, uid, lead_ids, {'user_id': salesman_id, 'section_id': salesteam_id}, context=context) + salesteam_id = self.on_change_user(cr, uid, lead_ids, salesman_id, context=None)['value'].get('team_id') + self.write(cr, uid, lead_ids, {'user_id': salesman_id, 'team_id': salesteam_id}, context=context) diff --git a/addons/crm_partner_assign/crm_lead_demo.xml b/addons/crm_partner_assign/crm_lead_demo.xml index c9c81e74c94..56a2f9c6211 100644 --- a/addons/crm_partner_assign/crm_lead_demo.xml +++ b/addons/crm_partner_assign/crm_lead_demo.xml @@ -12,9 +12,9 @@ Reseller Edinburgh - + 2 - + Hi, diff --git a/addons/crm_partner_assign/crm_partner_assign.py b/addons/crm_partner_assign/crm_partner_assign.py index 011a6ffdbf8..7bd6d92a1de 100644 --- a/addons/crm_partner_assign/crm_partner_assign.py +++ b/addons/crm_partner_assign/crm_partner_assign.py @@ -125,7 +125,7 @@ class crm_lead(osv.osv): self.assign_geo_localize(cr, uid, [lead.id], lead.partner_latitude, lead.partner_longitude, context=context) partner = res_partner.browse(cr, uid, partner_id, context=context) if partner.user_id: - salesteam_id = partner.section_id and partner.section_id.id or False + salesteam_id = partner.team_id and partner.team_id.id or False for lead_id in ids: self.allocate_salesman(cr, uid, [lead_id], [partner.user_id.id], team_id=salesteam_id, context=context) self.write(cr, uid, [lead.id], {'date_assign': fields.date.context_today(self,cr,uid,context=context), 'partner_assigned_id': partner_id}, context=context) diff --git a/addons/crm_partner_assign/crm_partner_assign_data.xml b/addons/crm_partner_assign/crm_partner_assign_data.xml index cffee0a43ad..a052626ddea 100644 --- a/addons/crm_partner_assign/crm_partner_assign_data.xml +++ b/addons/crm_partner_assign/crm_partner_assign_data.xml @@ -1,14 +1,14 @@ - + Assigned lead - + To Recycle diff --git a/addons/crm_partner_assign/crm_portal_view.xml b/addons/crm_partner_assign/crm_portal_view.xml index 92200497e8c..29a65e43866 100644 --- a/addons/crm_partner_assign/crm_portal_view.xml +++ b/addons/crm_partner_assign/crm_portal_view.xml @@ -18,7 +18,7 @@ - +
-
- -
diff --git a/addons/portal_claim/portal_claim_view.xml b/addons/portal_claim/portal_claim_view.xml index 83c38b43b4e..27128572c12 100644 --- a/addons/portal_claim/portal_claim_view.xml +++ b/addons/portal_claim/portal_claim_view.xml @@ -2,7 +2,7 @@ - + Claims crm.claim form @@ -22,7 +22,7 @@ + action="crm_claim_category_claim0" sequence="10"/> diff --git a/addons/portal_project_issue/security/ir.model.access.csv b/addons/portal_project_issue/security/ir.model.access.csv index 65eff9bed1b..60d7d34e348 100644 --- a/addons/portal_project_issue/security/ir.model.access.csv +++ b/addons/portal_project_issue/security/ir.model.access.csv @@ -1,4 +1,4 @@ id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink access_issues,project_issue,project_issue.model_project_issue,base.group_portal,1,0,0,0 -access_case_section,crm_case_section,sales_team.model_crm_case_section,base.group_portal,1,0,0,0 +access_case_section,crm_team,sales_team.model_crm_team,base.group_portal,1,0,0,0 access_issues_public,project_issue,project_issue.model_project_issue,base.group_public,1,0,0,0 \ No newline at end of file diff --git a/addons/project_issue/project_issue.py b/addons/project_issue/project_issue.py index fb34ee2fc5c..741abeeb99a 100644 --- a/addons/project_issue/project_issue.py +++ b/addons/project_issue/project_issue.py @@ -106,7 +106,7 @@ class project_issue(osv.Model): # lame hack to allow reverting search, should just work in the trivial case if read_group_order == 'stage_id desc': order = "%s desc" % order - # retrieve section_id from the context and write the domain + # retrieve team_id from the context and write the domain # - ('id', 'in', 'ids'): add columns that should be present # - OR ('case_default', '=', True), ('fold', '=', False): add default columns that are not folded # - OR ('project_ids', 'in', project_id), ('fold', '=', False) if project_id: add project columns that are not folded @@ -230,7 +230,7 @@ class project_issue(osv.Model): 'days_since_creation': fields.function(_compute_day, string='Days since creation date', \ multi='compute_day', type="integer", help="Difference in days between creation date and current date"), 'date_deadline': fields.date('Deadline'), - 'section_id': fields.many2one('crm.case.section', 'Sales Team', \ + 'team_id': fields.many2one('crm.team', 'Sales Team', oldname='section_id',\ select=True, help='Sales team to which Case belongs to.\ Define Responsible user and Email account for mail gateway.'), 'partner_id': fields.many2one('res.partner', 'Contact', select=1), @@ -371,28 +371,28 @@ class project_issue(osv.Model): return {'value': {'date_closed': fields.datetime.now()}} return {'value': {'date_closed': False}} - def stage_find(self, cr, uid, cases, section_id, domain=[], order='sequence', context=None): + def stage_find(self, cr, uid, cases, team_id, domain=[], order='sequence', context=None): """ Override of the base.stage method Parameter of the stage search taken from the issue: - type: stage type must be the same or 'both' - - section_id: if set, stages must belong to this section or + - team_id: if set, stages must belong to this team or be a default case """ if isinstance(cases, (int, long)): cases = self.browse(cr, uid, cases, context=context) - # collect all section_ids - section_ids = [] - if section_id: - section_ids.append(section_id) + # collect all team_ids + team_ids = [] + if team_id: + team_ids.append(team_id) for task in cases: if task.project_id: - section_ids.append(task.project_id.id) - # OR all section_ids and OR with case_default + team_ids.append(task.project_id.id) + # OR all team_ids and OR with case_default search_domain = [] - if section_ids: - search_domain += [('|')] * (len(section_ids)-1) - for section_id in section_ids: - search_domain.append(('project_ids', '=', section_id)) + if team_ids: + search_domain += [('|')] * (len(team_ids)-1) + for team_id in team_ids: + search_domain.append(('project_ids', '=', team_id)) search_domain += list(domain) # perform search, return the first found stage_ids = self.pool.get('project.task.type').search(cr, uid, search_domain, order=order, context=context) diff --git a/addons/project_issue/project_issue_demo.xml b/addons/project_issue/project_issue_demo.xml index d55dd648aa9..ef012a1a6e9 100644 --- a/addons/project_issue/project_issue_demo.xml +++ b/addons/project_issue/project_issue_demo.xml @@ -38,7 +38,7 @@ 0 - + @@ -54,7 +54,7 @@ 1 - + Program not giving proper output @@ -66,7 +66,7 @@ 0 - + @@ -82,7 +82,7 @@ 1 - + @@ -95,7 +95,7 @@ 1 - + @@ -108,7 +108,7 @@ 1 - + @@ -124,7 +124,7 @@ 2 - + @@ -137,7 +137,7 @@ 2 - + @@ -162,7 +162,7 @@ 2 - + @@ -175,7 +175,7 @@ 0 - + @@ -188,7 +188,7 @@ 1 - + @@ -202,7 +202,7 @@ 1 - + @@ -216,7 +216,7 @@ 1 - + @@ -229,7 +229,7 @@ 0 - + @@ -242,7 +242,7 @@ 2 - + diff --git a/addons/project_issue/report/project_issue_report.py b/addons/project_issue/report/project_issue_report.py index 25802a1ad05..d248e332aa6 100644 --- a/addons/project_issue/report/project_issue_report.py +++ b/addons/project_issue/report/project_issue_report.py @@ -29,7 +29,7 @@ class project_issue_report(osv.osv): _auto = False _columns = { - 'section_id':fields.many2one('crm.case.section', 'Sale Team', readonly=True), + 'team_id':fields.many2one('crm.team', 'Sale Team', oldname='section_id', readonly=True), 'company_id': fields.many2one('res.company', 'Company', readonly=True), 'opening_date': fields.datetime('Date of Opening', readonly=True), 'create_date': fields.datetime('Create Date', readonly=True), @@ -66,7 +66,7 @@ class project_issue_report(osv.osv): c.user_id, c.working_hours_open, c.working_hours_close, - c.section_id, + c.team_id, c.stage_id, date(c.date_closed) as date_closed, c.company_id as company_id, diff --git a/addons/project_issue/security/ir.model.access.csv b/addons/project_issue/security/ir.model.access.csv index 400e118a6d0..dd6617c07d8 100644 --- a/addons/project_issue/security/ir.model.access.csv +++ b/addons/project_issue/security/ir.model.access.csv @@ -5,6 +5,6 @@ access_project_issue_version_project,project_issue_version manager,model_project access_project_issue_version_project_user,project_issue_version user,model_project_issue_version,project.group_project_user,1,0,0,0 access_resource_calendar_project_manager,resource.calendar.project.manager,resource.model_resource_calendar,project.group_project_manager,1,1,1,1 access_project_issue_report_user,project.issue.report user,model_project_issue_report,project.group_project_user,1,0,0,0 -access_crm_case_section,crm.case.section,sales_team.model_crm_case_section,project.group_project_user,1,0,0,0 +access_crm_team,crm.team,sales_team.model_crm_team,project.group_project_user,1,0,0,0 access_project_issue_salesman,project.issue,model_project_issue,base.group_sale_salesman,1,0,0,0 access_project_issue_manager,project.issue,model_project_issue,base.group_sale_manager,1,0,0,0 diff --git a/addons/sale/report/invoice_report.py b/addons/sale/report/invoice_report.py index e66daddcfa8..af497df5f53 100644 --- a/addons/sale/report/invoice_report.py +++ b/addons/sale/report/invoice_report.py @@ -23,19 +23,19 @@ from openerp.osv import fields,osv class account_invoice_report(osv.osv): _inherit = 'account.invoice.report' _columns = { - 'section_id': fields.many2one('crm.case.section', 'Sales Team'), + 'team_id': fields.many2one('crm.team', 'Sales Team', oldname='section_id'), } _depends = { - 'account.invoice': ['section_id'], + 'account.invoice': ['team_id'], } def _select(self): - return super(account_invoice_report, self)._select() + ", sub.section_id as section_id" + return super(account_invoice_report, self)._select() + ", sub.team_id as team_id" def _sub_select(self): - return super(account_invoice_report, self)._sub_select() + ", ai.section_id as section_id" + return super(account_invoice_report, self)._sub_select() + ", ai.team_id as team_id" def _group_by(self): - return super(account_invoice_report, self)._group_by() + ", ai.section_id" + return super(account_invoice_report, self)._group_by() + ", ai.team_id" # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/sale/report/sale_report.py b/addons/sale/report/sale_report.py index 731a326010e..bb32fd37eb3 100644 --- a/addons/sale/report/sale_report.py +++ b/addons/sale/report/sale_report.py @@ -53,7 +53,7 @@ class sale_report(osv.osv): ], 'Order Status', readonly=True), 'pricelist_id': fields.many2one('product.pricelist', 'Pricelist', readonly=True), 'analytic_account_id': fields.many2one('account.analytic.account', 'Analytic Account', readonly=True), - 'section_id': fields.many2one('crm.case.section', 'Sales Team'), + 'team_id': fields.many2one('crm.team', 'Sales Team', oldname='section_id'), } _order = 'date desc' @@ -75,7 +75,7 @@ class sale_report(osv.osv): t.categ_id as categ_id, s.pricelist_id as pricelist_id, s.project_id as analytic_account_id, - s.section_id as section_id + s.team_id as team_id """ return select_str @@ -104,7 +104,7 @@ class sale_report(osv.osv): s.state, s.pricelist_id, s.project_id, - s.section_id + s.team_id """ return group_by_str diff --git a/addons/sale/report/sale_report_view.xml b/addons/sale/report/sale_report_view.xml index a9d6b6067a4..7ddeaf041e1 100644 --- a/addons/sale/report/sale_report_view.xml +++ b/addons/sale/report/sale_report_view.xml @@ -7,7 +7,7 @@ sale.report - + @@ -32,7 +32,7 @@ By Salesteam sale.report - {'group_by': ['date:month', 'section_id']} + {'group_by': ['date:month', 'team_id']}
By Product @@ -62,7 +62,7 @@
- + diff --git a/addons/sale/sale.py b/addons/sale/sale.py index 99fb5c96081..af257f8d22e 100644 --- a/addons/sale/sale.py +++ b/addons/sale/sale.py @@ -154,26 +154,24 @@ class sale_order(osv.osv): raise osv.except_osv(_('Error!'), _('There is no default company for the current user!')) return company_id - def _get_default_section_id(self, cr, uid, context=None): - """ Gives default section by checking if present in the context """ - section_id = self._resolve_section_id_from_context(cr, uid, context=context) or False - if not section_id: - section_id = self.pool.get('res.users').browse(cr, uid, uid, context).default_section_id.id or False - return section_id + def _get_default_team_id(self, cr, uid, context=None): + """ Gives default team by checking if present in the context """ + team_id = self._resolve_team_id_from_context(cr, uid, context=context) or False + return team_id - def _resolve_section_id_from_context(self, cr, uid, context=None): - """ Returns ID of section based on the value of 'section_id' + def _resolve_team_id_from_context(self, cr, uid, context=None): + """ Returns ID of team based on the value of 'team_id' context key, or None if it cannot be resolved to a single Sales Team. """ if context is None: context = {} - if type(context.get('default_section_id')) in (int, long): - return context.get('default_section_id') - if isinstance(context.get('default_section_id'), basestring): - section_ids = self.pool.get('crm.case.section').name_search(cr, uid, name=context['default_section_id'], context=context) - if len(section_ids) == 1: - return int(section_ids[0][0]) + if type(context.get('default_team_id')) in (int, long): + return context.get('default_team_id') + if isinstance(context.get('default_team_id'), basestring): + team_ids = self.pool.get('crm.team').name_search(cr, uid, name=context['default_team_id'], context=context) + if len(team_ids) == 1: + return int(team_ids[0][0]) return None _columns = { @@ -242,7 +240,7 @@ class sale_order(osv.osv): 'payment_term': fields.many2one('account.payment.term', 'Payment Term'), 'fiscal_position': fields.many2one('account.fiscal.position', 'Fiscal Position'), 'company_id': fields.many2one('res.company', 'Company'), - 'section_id': fields.many2one('crm.case.section', 'Sales Team', change_default=True), + 'team_id': fields.many2one('crm.team', 'Sales Team', oldname='section_id', change_default=True), 'procurement_group_id': fields.many2one('procurement.group', 'Procurement group', copy=False), 'product_id': fields.related('order_line', 'product_id', type='many2one', relation='product.product', string='Product'), } @@ -257,7 +255,7 @@ class sale_order(osv.osv): 'partner_invoice_id': lambda self, cr, uid, context: context.get('partner_id', False) and self.pool.get('res.partner').address_get(cr, uid, [context['partner_id']], ['invoice'])['invoice'], 'partner_shipping_id': lambda self, cr, uid, context: context.get('partner_id', False) and self.pool.get('res.partner').address_get(cr, uid, [context['partner_id']], ['delivery'])['delivery'], 'note': lambda self, cr, uid, context: self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id.sale_note, - 'section_id': lambda s, cr, uid, c: s._get_default_section_id(cr, uid, c), + 'team_id': lambda s, cr, uid, c: s._get_default_team_id(cr, uid, c), } _sql_constraints = [ ('name_uniq', 'unique(name, company_id)', 'Order Reference must be unique per Company!'), @@ -406,7 +404,7 @@ class sale_order(osv.osv): 'date_invoice': context.get('date_invoice', False), 'company_id': order.company_id.id, 'user_id': order.user_id and order.user_id.id or False, - 'section_id' : order.section_id.id + 'team_id' : order.team_id.id } # Care for deprecated _inv_get() hook - FIXME: to be removed after 6.1 @@ -1172,34 +1170,32 @@ class mail_compose_message(osv.Model): class account_invoice(osv.Model): _inherit = 'account.invoice' - def _get_default_section_id(self, cr, uid, context=None): - """ Gives default section by checking if present in the context """ - section_id = self._resolve_section_id_from_context(cr, uid, context=context) or False - if not section_id: - section_id = self.pool.get('res.users').browse(cr, uid, uid, context).default_section_id.id or False - return section_id + def _get_default_team_id(self, cr, uid, context=None): + """ Gives default team by checking if present in the context """ + team_id = self._resolve_team_id_from_context(cr, uid, context=context) or False + return team_id - def _resolve_section_id_from_context(self, cr, uid, context=None): - """ Returns ID of section based on the value of 'section_id' + def _resolve_team_id_from_context(self, cr, uid, context=None): + """ Returns ID of team based on the value of 'team_id' context key, or None if it cannot be resolved to a single Sales Team. """ if context is None: context = {} - if type(context.get('default_section_id')) in (int, long): - return context.get('default_section_id') - if isinstance(context.get('default_section_id'), basestring): - section_ids = self.pool.get('crm.case.section').name_search(cr, uid, name=context['default_section_id'], context=context) - if len(section_ids) == 1: - return int(section_ids[0][0]) + if type(context.get('default_team_id')) in (int, long): + return context.get('default_team_id') + if isinstance(context.get('default_team_id'), basestring): + team_ids = self.pool.get('crm.team').name_search(cr, uid, name=context['default_team_id'], context=context) + if len(team_ids) == 1: + return int(team_ids[0][0]) return None _columns = { - 'section_id': fields.many2one('crm.case.section', 'Sales Team'), + 'team_id': fields.many2one('crm.team', 'Sales Team', oldname='section_id'), } _defaults = { - 'section_id': lambda self, cr, uid, c=None: self._get_default_section_id(cr, uid, context=c) + 'team_id': lambda self, cr, uid, c=None: self._get_default_team_id(cr, uid, context=c) } def confirm_paid(self, cr, uid, ids, context=None): diff --git a/addons/sale/sale_data.xml b/addons/sale/sale_data.xml index e51be69e2f1..a44bb1ba2d5 100644 --- a/addons/sale/sale_data.xml +++ b/addons/sale/sale_data.xml @@ -48,16 +48,16 @@ Quotation Send 20 - crm.case.section + crm.team - section_id + team_id Sales Order Confirmed 21 - crm.case.section + crm.team - section_id + team_id diff --git a/addons/sale/sale_demo.xml b/addons/sale/sale_demo.xml index ddd205f2d59..eb4156a0efc 100644 --- a/addons/sale/sale_demo.xml +++ b/addons/sale/sale_demo.xml @@ -2,12 +2,12 @@ - + 52700 60000 - + 36000 40000 @@ -18,7 +18,7 @@ - + @@ -59,7 +59,7 @@ manual - + @@ -90,7 +90,7 @@ manual - + @@ -119,7 +119,7 @@ - + @@ -168,7 +168,7 @@ - + @@ -208,7 +208,7 @@ - + @@ -228,7 +228,7 @@ manual - + @@ -280,7 +280,7 @@ manual - + @@ -363,7 +363,7 @@ Thanks! - + draft out_invoice @@ -411,7 +411,7 @@ Thanks! - + draft out_invoice diff --git a/addons/sale/sale_view.xml b/addons/sale/sale_view.xml index d8ed80237a0..45d13bc00a8 100644 --- a/addons/sale/sale_view.xml +++ b/addons/sale/sale_view.xml @@ -209,7 +209,7 @@ - + @@ -256,7 +256,7 @@ - + @@ -551,7 +551,7 @@ - + @@ -564,10 +564,10 @@ - + - + @@ -580,7 +580,7 @@ - + @@ -596,8 +596,8 @@ [('state','not in',('draft','sent','cancel'))] { - 'search_default_section_id': [active_id], - 'default_section_id': active_id, + 'search_default_team_id': [active_id], + 'default_team_id': active_id, } @@ -619,8 +619,8 @@ tree,form,calendar,graph { - 'search_default_section_id': [active_id], - 'default_section_id': active_id, + 'search_default_team_id': [active_id], + 'default_team_id': active_id, 'show_address': 1, } @@ -650,8 +650,8 @@ ('state', 'not in', ['draft', 'cancel']), ('type', '=', 'out_invoice')] { - 'search_default_section_id': [active_id], - 'default_section_id': active_id, + 'search_default_team_id': [active_id], + 'default_team_id': active_id, 'default_type':'out_invoice', 'type':'out_invoice', 'journal_type': 'sale', @@ -677,7 +677,7 @@ Quotations Analysis sale.report graph - [('state','=','draft'),('section_id', '=', active_id)] + [('state','=','draft'),('team_id', '=', active_id)] {'search_default_order_month':1} This report performs analysis on your quotations. Analysis check your sales revenues and sort it by different group criteria (salesman, partner, product, etc.) Use this report to perform analysis on sales not having invoiced yet. If you want to analyse your turnover, you should use the Invoice Analysis report in the Accounting application. @@ -686,7 +686,7 @@ Sales Analysis sale.report graph - [('state','not in',('draft','sent','cancel')),('section_id', '=', active_id)] + [('state','not in',('draft','sent','cancel')),('team_id', '=', active_id)] {'search_default_order_month':1} This report performs analysis on your sales orders. Analysis check your sales revenues and sort it by different group criteria (salesman, partner, product, etc.) Use this report to perform analysis on sales not having invoiced yet. If you want to analyse your turnover, you should use the Invoice Analysis report in the Accounting application. @@ -695,7 +695,7 @@ Invoices Analysis account.invoice.report graph - [('section_id', '=', active_id),('state', 'not in', ['draft', 'cancel'])] + [('team_id', '=', active_id),('state', 'not in', ['draft', 'cancel'])] {'search_default_month':1} From this report, you can have an overview of the amount invoiced to your customer. The tool search can also be used to personalise your Invoices reports and so, match this analysis to your needs. diff --git a/addons/sale/sales_team.py b/addons/sale/sales_team.py index b6013838791..0f4b300073e 100644 --- a/addons/sale/sales_team.py +++ b/addons/sale/sales_team.py @@ -9,8 +9,8 @@ from openerp import tools from openerp.osv import fields, osv -class crm_case_section(osv.osv): - _inherit = 'crm.case.section' +class crm_team(osv.Model): + _inherit = 'crm.team' def _get_sale_orders_data(self, cr, uid, ids, field_name, arg, context=None): obj = self.pool['sale.order'] @@ -21,8 +21,8 @@ class crm_case_section(osv.osv): res = {} for id in ids: res[id] = {} - created_domain = [('section_id', '=', id), ('state', '=', 'draft'), ('date_order', '>=', date_begin), ('date_order', '<=', date_end)] - validated_domain = [('section_id', '=', id), ('state', 'not in', ['draft', 'sent', 'cancel']), ('date_order', '>=', date_begin), ('date_order', '<=', date_end)] + created_domain = [('team_id', '=', id), ('state', '=', 'draft'), ('date_order', '>=', date_begin), ('date_order', '<=', date_end)] + validated_domain = [('team_id', '=', id), ('state', 'not in', ['draft', 'sent', 'cancel']), ('date_order', '>=', date_begin), ('date_order', '<=', date_end)] res[id]['monthly_quoted'] = json.dumps(self.__get_bar_values(cr, uid, obj, created_domain, ['amount_total', 'date_order'], 'amount_total', 'date_order', context=context)) res[id]['monthly_confirmed'] = json.dumps(self.__get_bar_values(cr, uid, obj, validated_domain, ['amount_total', 'date_order'], 'amount_total', 'date_order', context=context)) @@ -36,7 +36,7 @@ class crm_case_section(osv.osv): res = {} for id in ids: - created_domain = [('section_id', '=', id), ('state', 'not in', ['draft', 'cancel']), ('date', '>=', date_begin), ('date', '<=', date_end)] + created_domain = [('team_id', '=', id), ('state', 'not in', ['draft', 'cancel']), ('date', '>=', date_begin), ('date', '<=', date_end)] res[id] = json.dumps(self.__get_bar_values(cr, uid, obj, created_domain, ['price_total', 'date'], 'price_total', 'date', context=context)) return res diff --git a/addons/sale/sales_team_view.xml b/addons/sale/sales_team_view.xml index 922caa9f033..0134ed9ffab 100644 --- a/addons/sale/sales_team_view.xml +++ b/addons/sale/sales_team_view.xml @@ -1,10 +1,10 @@ - - crm.case.section.form - crm.case.section - + + crm.team.form + crm.team + @@ -18,10 +18,10 @@ - - crm.case.section.kanban - crm.case.section - + + crm.team.kanban + crm.team + diff --git a/addons/sale_crm/sale_crm.py b/addons/sale_crm/sale_crm.py index cb260a62e04..ef31fd87a5b 100644 --- a/addons/sale_crm/sale_crm.py +++ b/addons/sale_crm/sale_crm.py @@ -25,7 +25,6 @@ class sale_order(osv.osv): _name = "sale.order" _inherit = ['sale.order', 'crm.tracking.mixin'] _columns = { - 'categ_ids': fields.many2many('crm.case.categ', 'sale_order_category_rel', 'order_id', 'category_id', 'Tags', \ - domain="['|', ('section_id', '=', section_id), ('section_id', '=', False), ('object_id.model', '=', 'crm.lead')]", context="{'object_name': 'crm.lead'}"), + 'tag_ids': fields.many2many('crm.lead.tag', 'sale_order_tag_rel', 'order_id', 'tag_id', 'Tags'), 'opportunity_id': fields.many2one('crm.lead', 'Opportunity', domain="[('type', '=', 'opportunity')]") } diff --git a/addons/sale_crm/sale_crm_view.xml b/addons/sale_crm/sale_crm_view.xml index d5bac4d8b15..f17a5f7d22f 100644 --- a/addons/sale_crm/sale_crm_view.xml +++ b/addons/sale_crm/sale_crm_view.xml @@ -29,7 +29,7 @@ - + {'stage_type': 'opportunity', 'default_type': 'opportunity', 'default_user_id': uid, 'needaction_menu_ref': 'sale.menu_sale_quotations'} @@ -39,7 +39,7 @@ - + diff --git a/addons/sale_crm/wizard/crm_make_sale.py b/addons/sale_crm/wizard/crm_make_sale.py index 9712daec949..4e8a54ebd52 100644 --- a/addons/sale_crm/wizard/crm_make_sale.py +++ b/addons/sale_crm/wizard/crm_make_sale.py @@ -92,8 +92,8 @@ class crm_make_sale(osv.osv_memory): vals = { 'origin': _('Opportunity: %s') % str(case.id), - 'section_id': case.section_id and case.section_id.id or False, - 'categ_ids': [(6, 0, [categ_id.id for categ_id in case.categ_ids])], + 'team_id': case.team_id and case.team_id.id or False, + 'tag_ids': [(6, 0, [categ_id.id for categ_id in case.tag_ids])], 'partner_id': partner.id, 'pricelist_id': pricelist, 'partner_invoice_id': partner_addr['invoice'], diff --git a/addons/sales_team/sales_team.py b/addons/sales_team/sales_team.py index def12c2468d..e489f5a0bcf 100644 --- a/addons/sales_team/sales_team.py +++ b/addons/sales_team/sales_team.py @@ -24,8 +24,8 @@ from openerp import tools from openerp.osv import fields, osv -class crm_case_section(osv.osv): - _name = "crm.case.section" +class crm_team(osv.Model): + _name = "crm.team" _inherit = ['mail.thread', 'ir.needaction_mixin'] _description = "Sales Teams" _order = "complete_name" @@ -44,14 +44,14 @@ class crm_case_section(osv.osv): :param str value_field: the field used to compute the value of the bar slice :param str groupby_field: the fields used to group - :return list section_result: a list of dicts: [ + :return list team_result: a list of dicts: [ { 'value': (int) bar_column_value, 'tootip': (str) bar_column_tooltip, } ] """ month_begin = date.today().replace(day=1) - section_result = [{ + team_result = [{ 'value': 0, 'tooltip': (month_begin + relativedelta.relativedelta(months=-i)).strftime('%B %Y'), } for i in range(self._period_number - 1, -1, -1)] @@ -60,8 +60,8 @@ class crm_case_section(osv.osv): for group in group_obj: group_begin_date = datetime.strptime(group['__domain'][0][2], pattern) month_delta = relativedelta.relativedelta(month_begin, group_begin_date) - section_result[self._period_number - (month_delta.months + 1)] = {'value': group.get(value_field, 0), 'tooltip': group.get(groupby_field, 0)} - return section_result + team_result[self._period_number - (month_delta.months + 1)] = {'value': group.get(value_field, 0), 'tooltip': group.get(groupby_field, 0)} + return team_result _columns = { 'name': fields.char('Sales Team', size=64, required=True, translate=True), @@ -71,10 +71,10 @@ class crm_case_section(osv.osv): "true, it will allow you to hide the sales team without removing it."), 'change_responsible': fields.boolean('Reassign Escalated', help="When escalating to this team override the salesman with the team leader."), 'user_id': fields.many2one('res.users', 'Team Leader'), - 'member_ids': fields.many2many('res.users', 'sale_member_rel', 'section_id', 'member_id', 'Team Members'), + 'member_ids': fields.many2many('res.users', 'sale_member_rel', 'team_id', 'member_id', 'Team Members'), 'reply_to': fields.char('Reply-To', size=64, help="The email address put in the 'Reply-To' of all emails sent by Odoo about cases in this sales team"), - 'parent_id': fields.many2one('crm.case.section', 'Parent Team'), - 'child_ids': fields.one2many('crm.case.section', 'parent_id', 'Child Teams'), + 'parent_id': fields.many2one('crm.team', 'Parent Team'), + 'child_ids': fields.one2many('crm.team', 'parent_id', 'Child Teams'), 'note': fields.text('Description'), 'working_hours': fields.float('Working Hours', digits=(16, 2)), 'color': fields.integer('Color Index'), @@ -112,19 +112,5 @@ class crm_case_section(osv.osv): class res_partner(osv.Model): _inherit = 'res.partner' _columns = { - 'section_id': fields.many2one('crm.case.section', 'Sales Team'), + 'team_id': fields.many2one('crm.team', 'Sales Team', oldname='section_id'), } - - -class res_users(osv.Model): - _inherit = 'res.users' - _columns = { - 'default_section_id': fields.many2one('crm.case.section', 'Default Sales Team'), - } - - def __init__(self, pool, cr): - init_res = super(res_users, self).__init__(pool, cr) - # duplicate list to avoid modifying the original reference - self.SELF_WRITEABLE_FIELDS = list(self.SELF_WRITEABLE_FIELDS) - self.SELF_WRITEABLE_FIELDS.extend(['default_section_id']) - return init_res diff --git a/addons/sales_team/sales_team.xml b/addons/sales_team/sales_team.xml index 2f74f485a1c..5763f20f0e4 100644 --- a/addons/sales_team/sales_team.xml +++ b/addons/sales_team/sales_team.xml @@ -4,39 +4,12 @@ - - - Users Preferences - res.users - - - - - - - - - - - - res.users.preferences.form - res.users - - - - - - - - - + - - - - crm.case.section.kanban - crm.case.section + + crm.team.kanban + crm.team @@ -71,10 +44,10 @@ - - - Case Sections - Search - crm.case.section + + + Case Teams - Search + crm.team @@ -91,14 +64,14 @@ - - + + Sales Teams - crm.case.section + crm.team form kanban,tree,form {} - +

Click here to define a new sales team. @@ -110,11 +83,11 @@ - + - - crm.case.section.form - crm.case.section + + crm.team.form + crm.team

@@ -155,10 +128,10 @@ - - - crm.case.section.tree - crm.case.section + + + crm.team.tree + crm.team child_ids @@ -169,11 +142,11 @@ - + Sales Teams - crm.case.section + crm.team form - +

Click here to define a new sales team. @@ -185,7 +158,7 @@ - +