diff --git a/addons/base_report_designer/plugin/openerp_report_designer.zip b/addons/base_report_designer/plugin/openerp_report_designer.zip
index 22c0b7768f2..3ee0260060f 100644
Binary files a/addons/base_report_designer/plugin/openerp_report_designer.zip and b/addons/base_report_designer/plugin/openerp_report_designer.zip differ
diff --git a/addons/base_report_designer/plugin/openerp_report_designer/bin/script/Change.py b/addons/base_report_designer/plugin/openerp_report_designer/bin/script/Change.py
index 730ce8efefb..d4359a466ca 100644
--- a/addons/base_report_designer/plugin/openerp_report_designer/bin/script/Change.py
+++ b/addons/base_report_designer/plugin/openerp_report_designer/bin/script/Change.py
@@ -54,11 +54,11 @@ class Change:
def __init__(self, aVal= None, sURL=""):
self.win=DBModalDialog(60, 50, 120, 90, "Connect to Open ERP Server")
- self.win.addFixedText("lblVariable", 38, 12, 60, 15, "Server")
+ self.win.addFixedText("lblVariable", 38, 12, 25, 15, "Server ")
self.win.addEdit("txtHost",-2,9,60,15,sURL[sURL.find("/")+2:sURL.rfind(":")])
- self.win.addFixedText("lblReportName",45 , 31, 60, 15, "Port")
+ self.win.addFixedText("lblReportName",45 , 31, 15, 15, "Port ")
self.win.addEdit("txtPort",-2,28,60,15,sURL[sURL.rfind(":")+1:])
self.win.addFixedText("lblLoginName", 2, 51, 60, 15, "Protocol Connection")
@@ -92,6 +92,8 @@ class Change:
global url
url = self.protocol[self.win.getListBoxSelectedItem("lstProtocol")]+self.win.getEditText("txtHost")+":"+self.win.getEditText("txtPort")
self.sock=RPCSession(url)
+ desktop=getDesktop()
+ doc = desktop.getCurrentComponent()
docinfo=doc.getDocumentInfo()
docinfo.setUserFieldValue(0,url)
res=self.sock.listdb()
diff --git a/addons/base_report_designer/plugin/openerp_report_designer/bin/script/ServerParameter.py b/addons/base_report_designer/plugin/openerp_report_designer/bin/script/ServerParameter.py
index de67ea0abda..123be9b9bc2 100644
--- a/addons/base_report_designer/plugin/openerp_report_designer/bin/script/ServerParameter.py
+++ b/addons/base_report_designer/plugin/openerp_report_designer/bin/script/ServerParameter.py
@@ -192,6 +192,10 @@ class ServerParameter( unohelper.Base, XJobExecutor ):
Change(aVal,url)
if aVal[1]== -1:
self.win.getEditText("lstDatabase")
+ self.win.removeListBoxItems("lstDatabase", 0, self.win.getListBoxItemCount("lstDatabase"))
+ self.win.setEditText("txtHost",aVal[0])
+ for i in range(len(aVal[1])):
+ self.lstDatabase.addItem(aVal[1][i],i)
elif aVal[1]==0:
ErrorDialog(aVal[0],"")
else:
diff --git a/addons/crm/crm.py b/addons/crm/crm.py
index 9798fd09a4e..5336bdd23fb 100644
--- a/addons/crm/crm.py
+++ b/addons/crm/crm.py
@@ -22,6 +22,7 @@
import time
import base64
import tools
+
from osv import fields
from osv import osv
from tools.translate import _
@@ -135,6 +136,52 @@ class crm_case(object):
user = self.pool.get('res.users').browse(cr, uid, uid, context=context)
return user.context_section_id.id or False
+ def _find_next_stage(self, cr, uid, stage_list, index, current_seq, stage_pool, context=None):
+ if index + 1 == len(stage_list):
+ return False
+ next_stage_id = stage_list[index + 1]
+ next_stage = stage_pool.browse(cr, uid, next_stage_id, context=context)
+ if not next_stage:
+ return False
+
+ next_seq = next_stage.sequence
+ if (abs(next_seq - current_seq)) >= 1:
+ return next_stage
+ else :
+ return self._find_next_stage(cr, uid, stage_list, index + 1, current_seq, stage_pool)
+
+ def stage_change(self, cr, uid, ids, context=None, order='sequence'):
+ if not context:
+ context = {}
+ stage_pool = self.pool.get('crm.case.stage')
+ stage_type = context and context.get('stage_type','')
+ current_seq = False
+ next_stage_id = False
+ for case in self.browse(cr, uid, ids, context):
+ next_stage = False
+ data = {}
+
+ domain = [('type', '=', stage_type),('section_ids', '=', case.section_id.id)]
+ if case.section_id and case.section_id.stage_ids:
+ domain.append(('id', 'in', map(lambda x: x.id, case.section_id.stage_ids)))
+
+ stages = stage_pool.search(cr, uid, domain, order=order)
+ current_seq = case.stage_id.sequence
+ index = -1
+ if case.stage_id and case.stage_id.id in stages:
+ index = stages.index(case.stage_id.id)
+
+ next_stage = self._find_next_stage(cr, uid, stages, index, current_seq, stage_pool, context=context)
+ if next_stage:
+ next_stage_id = next_stage.id
+ data = {'stage_id': next_stage.id}
+ if next_stage.on_change:
+ data.update({'probability': next_stage.probability})
+ self.write(cr, uid, [case.id], data, context=context)
+
+ return next_stage_id
+
+
def stage_next(self, cr, uid, ids, context=None):
"""This function computes next stage for case from its current stage
using available stage for that case type
@@ -143,32 +190,10 @@ class crm_case(object):
@param uid: the current user’s ID for security checks,
@param ids: List of case IDs
@param context: A standard dictionary for contextual values"""
- if not context:
- context = {}
- stage_pool = self.pool.get('crm.case.stage')
- model = self._name
- for case in self.browse(cr, uid, ids, context):
- next_stage = False
- data = {}
- domain = [('object_id.model', '=', model),('section_ids', '=', case.section_id.id)]
- if case.section_id and case.section_id.stage_ids:
- domain.append(('id', 'in', map(lambda x: x.id, case.section_id.stage_ids)))
- stages = stage_pool.search(cr, uid, domain, order='sequence')
- index = -1
- if case.stage_id and case.stage_id.id in stages:
- index = stages.index(case.stage_id.id)
- if index + 1 == len(stages):
- return False
- else:
- next_stage = stages[index + 1]
- if next_stage:
- data = {'stage_id': next_stage}
- stage = stage_pool.browse(cr, uid, next_stage, context=context)
- if stage.on_change:
- data.update({'probability': stage.probability})
- self.write(cr, uid, [case.id], data, context=context)
- return next_stage
-
+
+
+ return self.stage_change(cr, uid, ids, context=context, order='sequence')
+
def stage_previous(self, cr, uid, ids, context=None):
"""This function computes previous stage for case from its current stage
using available stage for that case type
@@ -177,31 +202,7 @@ class crm_case(object):
@param uid: the current user’s ID for security checks,
@param ids: List of case IDs
@param context: A standard dictionary for contextual values"""
- if not context:
- context = {}
- stage_pool = self.pool.get('crm.case.stage')
- model = self._name
- for case in self.browse(cr, uid, ids, context):
- prev_stage = False
- data = {}
- domain = [('object_id.model', '=', model),('section_ids', '=', case.section_id.id)]
- if case.section_id and case.section_id.stage_ids:
- domain.append(('id', 'in', map(lambda x: x.id, case.section_id.stage_ids)))
- stages = stage_pool.search(cr, uid, domain, order='sequence')
- index = 0
- if case.stage_id and case.stage_id.id in stages:
- index = stages.index(case.stage_id.id)
- if index == 0:
- return False
- else:
- prev_stage = stages[index - 1]
- if prev_stage:
- data = {'stage_id': prev_stage}
- stage = stage_pool.browse(cr, uid, prev_stage, context=context)
- if stage.on_change:
- data.update({'probability': stage.probability})
- self.write(cr, uid, [case.id], data, context=context)
- return prev_stage
+ return self.stage_change(cr, uid, ids, context=context, order='sequence desc')
def onchange_partner_id(self, cr, uid, ids, part, email=False):
"""This function returns value of partner address based on partner
@@ -482,27 +483,27 @@ class crm_case_stage(osv.osv):
_columns = {
'name': fields.char('Stage Name', size=64, required=True, translate=True),
'sequence': fields.integer('Sequence', help="Gives the sequence order when displaying a list of case stages."),
- 'object_id': fields.many2one('ir.model', 'Object Name'),
'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="Change Probability on next and previous stages."),
- 'requirements': fields.text('Requirements')
+ 'requirements': fields.text('Requirements'),
+ 'type': fields.selection([('lead','Lead'),('opportunity','Opportunity'),('claim','Claim'), ('fundraising','Fundraising')], 'Type'),
}
- def _find_object_id(self, cr, uid, context=None):
- """Finds id for case object
+
+ def _find_stage_type(self, cr, uid, context=None):
+ """Finds type of stage according to object.
@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 context: A standard dictionary for contextual values
"""
- object_id = context and context.get('object_id', False) or False
- ids = self.pool.get('ir.model').search(cr, uid, [('model', '=', object_id)])
- return ids and ids[0]
+ type = context and context.get('type', '') or ''
+ return type
_defaults = {
'sequence': lambda *args: 1,
'probability': lambda *args: 0.0,
- 'object_id' : _find_object_id
+ 'type': _find_stage_type,
}
crm_case_stage()
@@ -629,6 +630,7 @@ class crm_case_stage(osv.osv):
_columns = {
'section_ids':fields.many2many('crm.case.section', 'section_stage_rel', 'stage_id', 'section_id', 'Sections'),
}
+
crm_case_stage()
diff --git a/addons/crm/crm_lead.py b/addons/crm/crm_lead.py
index e0bed8934f2..8cc45c75e57 100644
--- a/addons/crm/crm_lead.py
+++ b/addons/crm/crm_lead.py
@@ -135,7 +135,7 @@ class crm_lead(crm_case, osv.osv):
],'Type', help="Type is used to separate Leads and Opportunities"),
'priority': fields.selection(crm.AVAILABLE_PRIORITIES, 'Priority'),
'date_closed': fields.datetime('Closed', readonly=True),
- 'stage_id': fields.many2one('crm.case.stage', 'Stage'),
+ 'stage_id': fields.many2one('crm.case.stage', 'Stage', domain="[('type','=','lead')]"),
'user_id': fields.many2one('res.users', 'Salesman',help='By Default Salesman is Administrator when create New User'),
'referred': fields.char('Referred By', size=64),
'date_open': fields.datetime('Opened', readonly=True),
@@ -150,6 +150,19 @@ class crm_lead(crm_case, osv.osv):
\nIf the case needs to be reviewed then the state is set to \'Pending\'.'),
'message_ids': fields.one2many('mailgate.message', 'res_id', 'Messages', domain=[('model','=',_name)]),
}
+
+ def _get_stage_id(self, cr, uid, context=None):
+ """Finds type of stage according to object.
+ @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 context: A standard dictionary for contextual values
+ """
+ if context is None:
+ context = {}
+ type = context and context.get('stage_type', '')
+ stage_ids = self.pool.get('crm.case.stage').search(cr, uid, [('type','=',type),('sequence','>=',1)])
+ return stage_ids and stage_ids[0] or False
_defaults = {
'active': lambda *a: 1,
@@ -160,6 +173,7 @@ class crm_lead(crm_case, osv.osv):
'section_id': crm_case._get_section,
'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[2][0],
+ 'stage_id': _get_stage_id,
}
def onchange_partner_address_id(self, cr, uid, ids, add, email=False):
@@ -297,7 +311,7 @@ class crm_lead(crm_case, osv.osv):
return super(crm_lead,self).write(cr, uid, ids, vals, context)
def stage_next(self, cr, uid, ids, context=None):
- stage = super(crm_lead, self).stage_next(cr, uid, ids, context)
+ stage = super(crm_lead, self).stage_next(cr, uid, ids, context=context)
if stage:
stage_obj = self.pool.get('crm.case.stage').browse(cr, uid, stage, context=context)
if stage_obj.on_change:
diff --git a/addons/crm/crm_lead_data.xml b/addons/crm/crm_lead_data.xml
index 2a49e43e683..3cb34c49299 100644
--- a/addons/crm/crm_lead_data.xml
+++ b/addons/crm/crm_lead_data.xml
@@ -2,34 +2,39 @@
-
+
+ Lost
+
+
+ lead
+ New
-
+ leadQualification
-
+ leadProposition
-
+ leadNegotiation
-
+ lead
@@ -37,15 +42,10 @@
-
+ lead
-
- Lost
-
-
-
-
+
Sales Department
diff --git a/addons/crm/crm_lead_menu.xml b/addons/crm/crm_lead_menu.xml
index 6c74dccac15..2fff1b57d3c 100644
--- a/addons/crm/crm_lead_menu.xml
+++ b/addons/crm/crm_lead_menu.xml
@@ -9,7 +9,7 @@
['|', ('type','=','lead'), ('type','=',False)]
- {'search_default_current':1, 'default_type': 'lead', 'search_default_section_id': section_id}
+ {'search_default_current':1, 'default_type': 'lead', 'search_default_section_id': section_id, 'stage_type': 'lead'}'Leads' allows you to manage and keep track of all first potential interests of a partner in one of your products or services. A lead is a first, unqualified, contact with a prospect or customer. After being qualified, a lead can be converted into a business opportunity with the creation of the related partner for further detailed tracking of any linked activities. You can use leads when you import a database of prospects or to integrate your website's contact form with OpenERP.
diff --git a/addons/crm/crm_lead_view.xml b/addons/crm/crm_lead_view.xml
index cda3c4fcc1f..979ab26cfd1 100644
--- a/addons/crm/crm_lead_view.xml
+++ b/addons/crm/crm_lead_view.xml
@@ -9,8 +9,8 @@
crm.case.stageform
- [('object_id.model', '=', 'crm.lead')]
- {'object_id':'crm.lead'}
+ [('type', '=', 'lead')]
+ {'type':'lead'}Create specific stages that will help your sales better organise their sales pipeline by maintaining them to their leads and sales opportunities. It will allow them to easily track how is positioned a specific lead or opportunity in the sales cycle.
@@ -57,14 +57,14 @@
-
+
+ icon="gtk-go-back" context="{'stage_type': 'lead'}" />
+ icon="gtk-go-forward" context="{'stage_type': 'lead'}" />
@@ -329,7 +329,7 @@
-
+
diff --git a/addons/crm/crm_meeting_view.xml b/addons/crm/crm_meeting_view.xml
index 2f215488c99..2de562a23ce 100644
--- a/addons/crm/crm_meeting_view.xml
+++ b/addons/crm/crm_meeting_view.xml
@@ -47,7 +47,7 @@
diff --git a/addons/crm/crm_opportunity.py b/addons/crm/crm_opportunity.py
index 53f24dc69b0..44f2b1b85a4 100644
--- a/addons/crm/crm_opportunity.py
+++ b/addons/crm/crm_opportunity.py
@@ -50,7 +50,9 @@ class crm_opportunity(osv.osv):
'date_deadline': fields.date('Expected Closing'),
'date_action': fields.date('Next Action Date'),
'title_action': fields.char('Next Action', size=64),
+ 'stage_id': fields.many2one('crm.case.stage', 'Stage', domain="[('type','=','opportunity')]"),
}
+
def case_close(self, cr, uid, ids, *args):
"""Overrides close for crm_case for setting probability and close date
@param self: The object pointer
@@ -60,7 +62,13 @@ class crm_opportunity(osv.osv):
@param *args: Tuple Value for additional Params
"""
res = super(crm_opportunity, self).case_close(cr, uid, ids, args)
- value = {'date_closed': time.strftime('%Y-%m-%d %H:%M:%S')}
+ data_obj = self.pool.get('ir.model.data')
+ data_id = data_obj._get_id(cr, uid, 'crm', 'stage_lead5')
+ stage_id = data_obj.browse(cr, uid, data_id).res_id
+ stage_obj = self.pool.get('crm.case.stage').browse(cr, uid, stage_id)
+ value = {'date_closed': time.strftime('%Y-%m-%d %H:%M:%S'), 'stage_id': stage_id}
+ if stage_obj.on_change:
+ value.update({'probability': stage_obj.probability})
self.write(cr, uid, ids, value)
for (id, name) in self.name_get(cr, uid, ids):
@@ -79,16 +87,22 @@ class crm_opportunity(osv.osv):
@param *args: Tuple Value for additional Params
"""
res = super(crm_opportunity, self).case_close(cr, uid, ids, args)
- value = {'date_closed': time.strftime('%Y-%m-%d %H:%M:%S')}
+ data_obj = self.pool.get('ir.model.data')
+ data_id = data_obj._get_id(cr, uid, 'crm', 'stage_lead6')
+ stage_id = data_obj.browse(cr, uid, data_id).res_id
+ stage_obj = self.pool.get('crm.case.stage').browse(cr, uid, stage_id)
+ value = {'date_closed': time.strftime('%Y-%m-%d %H:%M:%S'), 'stage_id': stage_id}
+ if stage_obj.on_change:
+ value.update({'probability': stage_obj.probability})
- res = self.write(cr, uid, ids, value)
+ self.write(cr, uid, ids, value)
for (id, name) in self.name_get(cr, uid, ids):
opp = self.browse(cr, uid, id)
if opp.type == 'opportunity':
message = _("The opportunity '%s' has been marked as lost.") % name
self.log(cr, uid, id, message)
return res
-
+
def case_cancel(self, cr, uid, ids, *args):
"""Overrides cancel for crm_case for setting probability
@param self: The object pointer
@@ -110,7 +124,7 @@ class crm_opportunity(osv.osv):
@param *args: Tuple Value for additional Params
"""
res = super(crm_opportunity, self).case_reset(cr, uid, ids, *args)
- self.write(cr, uid, ids, {'stage_id': False})
+ self.write(cr, uid, ids, {'stage_id': False, 'probability': 0.0})
return res
diff --git a/addons/crm/crm_opportunity_data.xml b/addons/crm/crm_opportunity_data.xml
index c2f750c29d1..a20cbc5e344 100644
--- a/addons/crm/crm_opportunity_data.xml
+++ b/addons/crm/crm_opportunity_data.xml
@@ -1,56 +1,109 @@
-
- Interest in Computer
-
-
-
-
- Interest in Accessories
-
-
-
-
- Need Services
-
-
-
-
- Need Information
-
-
-
-
- Need a Website Design
-
-
-
-
- Potential Reseller
-
-
-
-
- Need Consulting
-
-
-
-
- Other
-
-
-
+
+
+
+
+ Lost
+
+
+ opportunity
+
+
+
+ New
+
+
+ opportunity
+
+
+
+ Qualification
+
+
+ opportunity
+
+
+
+ Proposition
+
+
+ opportunity
+
+
+
+ Negotiation
+
+
+ opportunity
+
+
+
+ Won
+
+
+
+ opportunity
+
+
+
+ Sales Department
+ Sales
+
+
+
+
+
+ Interest in Computer
+
+
+
+
+ Interest in Accessories
+
+
+
+
+ Need Services
+
+
+
+
+ Need Information
+
+
+
+
+ Need a Website Design
+
+
+
+
+ Potential Reseller
+
+
+
+
+ Need Consulting
+
+
+
+
+ Other
+
+
+
-
- Campaign 2
-
-
-
- Campaign 1
-
-
+
+ Campaign 2
+
+
+
+ Campaign 1
+
+
diff --git a/addons/crm/crm_opportunity_demo.xml b/addons/crm/crm_opportunity_demo.xml
index 48812b17cf0..8dda7436b64 100644
--- a/addons/crm/crm_opportunity_demo.xml
+++ b/addons/crm/crm_opportunity_demo.xml
@@ -20,7 +20,7 @@
-
+
@@ -36,7 +36,7 @@
-
+
@@ -53,7 +53,7 @@
-
+
@@ -70,7 +70,7 @@
-
+
@@ -86,7 +86,7 @@
-
+
diff --git a/addons/crm/crm_opportunity_menu.xml b/addons/crm/crm_opportunity_menu.xml
index 6b2e2d0fc39..cd57c2026af 100644
--- a/addons/crm/crm_opportunity_menu.xml
+++ b/addons/crm/crm_opportunity_menu.xml
@@ -28,7 +28,7 @@
crm.leadtree,form,graph,calendar[('type','=','opportunity')]
- {'search_default_user_id':uid,'search_default_current':1, 'search_default_section_id':section_id,'default_type': 'opportunity'}
+ {'search_default_user_id':uid,'search_default_current':1, 'search_default_section_id':section_id, 'stage_type': 'opportunity'}Opportunities allows you to manage and keep track of your sales pipeline by creating specific customer or prospect related sales documents in order to follow up potential sales. Information such as the expected revenue, opportunity stage, expected closing date, communication history and so on can be maintained in them. Opportunities can be connected with the email gateway: new emails create opportunities, each of them automatically gets the history of the conversation with the customer.
diff --git a/addons/crm/crm_opportunity_view.xml b/addons/crm/crm_opportunity_view.xml
index 5ca69c22790..c928b120579 100644
--- a/addons/crm/crm_opportunity_view.xml
+++ b/addons/crm/crm_opportunity_view.xml
@@ -1,6 +1,21 @@
+
+
+ Stages
+ crm.case.stage
+ form
+
+ [('type', '=', 'opportunity')]
+ {'type':'opportunity'}
+ Create specific stages that will help your sales better organise their sales pipeline by maintaining them to their sales opportunities. It will allow them to easily track how is positioned a specific opportunity in the sales cycle.
+
+
+
+
Opportunities
@@ -15,12 +30,12 @@
+ domain="[('type','=','opportunity'),('section_ids', '=', section_id)]"/>
+ type="object" icon="gtk-go-forward" string="" context="{'stage_type': 'opportunity'}"/>
@@ -303,7 +318,7 @@
-
+
diff --git a/addons/crm/crm_view.xml b/addons/crm/crm_view.xml
index fa576bca24f..f0c2d55a642 100644
--- a/addons/crm/crm_view.xml
+++ b/addons/crm/crm_view.xml
@@ -3,10 +3,13 @@
+ groups="base.group_sale_manager,base.group_sale_salesman,base.group_partner_manager"/>
+
+
@@ -119,7 +122,8 @@
-
diff --git a/addons/crm_claim/crm_claim.py b/addons/crm_claim/crm_claim.py
index f90a2d01b56..cc6a1ac6868 100644
--- a/addons/crm_claim/crm_claim.py
+++ b/addons/crm_claim/crm_claim.py
@@ -63,7 +63,7 @@ class crm_claim(crm.crm_case, osv.osv):
'email_cc': fields.text('Watchers Emails', size=252, 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"),
'email_from': fields.char('Email', size=128, help="These people will receive email."),
'partner_phone': fields.char('Phone', size=32),
- 'stage_id': fields.many2one ('crm.case.stage', 'Stage', domain="('object_id.model', '=', 'crm.claim')]"),
+ 'stage_id': fields.many2one ('crm.case.stage', 'Stage', domain="[('type','=','claim')]"),
'cause': fields.text('Root Cause'),
'state': fields.selection(crm.AVAILABLE_STATES, 'State', size=16, readonly=True,
help='The state is set to \'Draft\', when a case is created.\
@@ -72,6 +72,19 @@ class crm_claim(crm.crm_case, osv.osv):
\nIf the case needs to be reviewed then the state is set to \'Pending\'.'),
'message_ids': fields.one2many('mailgate.message', 'res_id', 'Messages', domain=[('model','=',_name)]),
}
+
+ def _get_stage_id(self, cr, uid, context=None):
+ """Finds type of stage according to object.
+ @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 context: A standard dictionary for contextual values
+ """
+ if context is None:
+ context = {}
+ type = context and context.get('stage_type', '')
+ stage_ids = self.pool.get('crm.case.stage').search(cr, uid, [('type','=',type),('sequence','>=',1)])
+ return stage_ids and stage_ids[0] or False
_defaults = {
'user_id': crm.crm_case._get_default_user,
@@ -82,7 +95,8 @@ class crm_claim(crm.crm_case, osv.osv):
'section_id':crm.crm_case. _get_section,
'date': lambda *a: time.strftime('%Y-%m-%d %H:%M:%S'),
'company_id': lambda s, cr, uid, c: s.pool.get('res.company')._company_default_get(cr, uid, 'crm.case', context=c),
- 'priority': lambda *a: crm.AVAILABLE_PRIORITIES[2][0],
+ 'priority': lambda *a: crm.AVAILABLE_PRIORITIES[2][0],
+ 'stage_id': _get_stage_id,
}
def onchange_partner_id(self, cr, uid, ids, part, email=False):
@@ -119,7 +133,6 @@ class crm_claim(crm.crm_case, osv.osv):
address = self.pool.get('res.partner.address').browse(cr, uid, add)
return {'value': {'email_from': address.email, 'partner_phone': address.phone, 'partner_mobile': address.mobile}}
-
crm_claim()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/crm_claim/crm_claim_data.xml b/addons/crm_claim/crm_claim_data.xml
index 13292d16c3b..e917ba5bea6 100644
--- a/addons/crm_claim/crm_claim_data.xml
+++ b/addons/crm_claim/crm_claim_data.xml
@@ -45,22 +45,22 @@
Accepted as Claim1
-
+ claimActions Defined2
-
+ claimActions Done10
-
+ claimWon't fix
- 11
-
+ 0
+ claim
diff --git a/addons/crm_claim/crm_claim_menu.xml b/addons/crm_claim/crm_claim_menu.xml
index 18642f18282..1989917ba6b 100644
--- a/addons/crm_claim/crm_claim_menu.xml
+++ b/addons/crm_claim/crm_claim_menu.xml
@@ -14,7 +14,7 @@
formtree,calendar,form,graph
- {'search_default_section_id': section_id, "search_default_current":1,"search_default_user_id":uid}
+ {'search_default_section_id': section_id, "search_default_current":1,"search_default_user_id":uid, "stage_type":'claim'}Record and track your customers' claims. Claims can be linked to a sales order or a lot. You can send emails with attachments and get the history of everything that happened on a specific claim (emails sent, interventions type and so on..). Claims can be automatically linked to an email address using the mail gateway module.
diff --git a/addons/crm_claim/crm_claim_view.xml b/addons/crm_claim/crm_claim_view.xml
index 6e7cc710dc2..a6f81885714 100644
--- a/addons/crm_claim/crm_claim_view.xml
+++ b/addons/crm_claim/crm_claim_view.xml
@@ -29,8 +29,8 @@
crm.case.stageform
- [('object_id.model', '=', 'crm.claim')]
- {'object_id':'crm.claim'}
+ [('type', '=', 'claim')]
+ {'type':'claim'}You can create claim stages to categorize the status of every claim entered in the system. The stages define all the steps required for the resolution of a claim.
@@ -78,8 +78,7 @@
-
+
diff --git a/addons/crm_claim/report/crm_claim_report.py b/addons/crm_claim/report/crm_claim_report.py
index f03a5f75d12..ffb56340aac 100644
--- a/addons/crm_claim/report/crm_claim_report.py
+++ b/addons/crm_claim/report/crm_claim_report.py
@@ -62,7 +62,7 @@ class crm_claim_report(osv.osv):
'create_date': fields.datetime('Create Date', readonly=True),
'day': fields.char('Day', size=128, readonly=True),
'delay_close': fields.float('Delay to close', digits=(16,2),readonly=True, group_operator="avg",help="Number of Days to close the case"),
- 'stage_id': fields.many2one ('crm.case.stage', 'Stage', readonly=True),
+ 'stage_id': fields.many2one ('crm.case.stage', 'Stage', readonly=True, domain="[('type','=','claim')]"),
'categ_id': fields.many2one('crm.case.categ', 'Category',\
domain="[('section_id','=',section_id),\
('object_id.model', '=', 'crm.claim')]", readonly=True),
diff --git a/addons/crm_claim/report/crm_claim_report_view.xml b/addons/crm_claim/report/crm_claim_report_view.xml
index 1fa47c09a9f..ca1c03a58ae 100644
--- a/addons/crm_claim/report/crm_claim_report_view.xml
+++ b/addons/crm_claim/report/crm_claim_report_view.xml
@@ -86,7 +86,7 @@
help="My Sales Team(s)" />
-
+
-
+
diff --git a/addons/crm_fundraising/crm_fundraising.py b/addons/crm_fundraising/crm_fundraising.py
index 21d5e9081bd..f4950842800 100644
--- a/addons/crm_fundraising/crm_fundraising.py
+++ b/addons/crm_fundraising/crm_fundraising.py
@@ -61,7 +61,7 @@ class crm_fundraising(crm.crm_case, osv.osv):
'partner_name2': fields.char('Employee Email', size=64),
'partner_phone': fields.char('Phone', size=32),
'partner_mobile': fields.char('Mobile', size=32),
- 'stage_id': fields.many2one ('crm.case.stage', 'Stage', domain="('object_id.model', '=', 'crm.fundraising')]"),
+ 'stage_id': fields.many2one ('crm.case.stage', 'Stage', domain="[('type', '=', 'fundraising')]"),
'type_id': fields.many2one('crm.case.resource.type', 'Campaign', \
domain="[('section_id','=',section_id)]"),
'duration': fields.float('Duration'),
diff --git a/addons/crm_fundraising/crm_fundraising_view.xml b/addons/crm_fundraising/crm_fundraising_view.xml
index eea653a4d48..51a2a2fa6b4 100644
--- a/addons/crm_fundraising/crm_fundraising_view.xml
+++ b/addons/crm_fundraising/crm_fundraising_view.xml
@@ -29,8 +29,8 @@
crm.case.stageform
- [('object_id.model', '=', 'crm.fundraising')]
- {'object_id':'crm.fundraising'}
+ [('type', '=', 'fundraising')]
+ {'type':'fundraising'}Create and manage fund raising activity categories you want to be maintained in the system.
diff --git a/addons/crm_fundraising/report/crm_fundraising_report_view.xml b/addons/crm_fundraising/report/crm_fundraising_report_view.xml
index 50ca70c5576..73514b677b2 100644
--- a/addons/crm_fundraising/report/crm_fundraising_report_view.xml
+++ b/addons/crm_fundraising/report/crm_fundraising_report_view.xml
@@ -105,7 +105,7 @@
domain="[('section_id.user_id','=',uid)]"
help="My Sales Team(s)" />
-
+
-
+
diff --git a/addons/crm_helpdesk/report/crm_helpdesk_report_view.xml b/addons/crm_helpdesk/report/crm_helpdesk_report_view.xml
index 1fea2a0f2d4..d54b719fe2b 100644
--- a/addons/crm_helpdesk/report/crm_helpdesk_report_view.xml
+++ b/addons/crm_helpdesk/report/crm_helpdesk_report_view.xml
@@ -78,7 +78,7 @@
domain="[('section_id.user_id','=',uid)]"
help="My Sales Team(s)" />
-
+
-
+
-
+
diff --git a/addons/fetchmail/fetchmail.py b/addons/fetchmail/fetchmail.py
index 77748adf017..7592061ec36 100644
--- a/addons/fetchmail/fetchmail.py
+++ b/addons/fetchmail/fetchmail.py
@@ -57,9 +57,8 @@ class email_server(osv.osv):
'user' : fields.char('User Name', size=256, required=True, readonly=True, states={'draft':[('readonly', False)]}),
'password' : fields.char('Password', size=1024, invisible=True, required=True, readonly=True, states={'draft':[('readonly', False)]}),
'note': fields.text('Description'),
- 'action_id':fields.many2one('ir.actions.server', 'Reply Email', required=False, domain="[('state','=','email')]",
- help="An Email Server Action. It will be run whenever an e-mail is fetched from server."),
- 'object_id': fields.many2one('ir.model', "Model", required=True, help="OpenObject Model. Generates a record of this model."),
+ 'action_id':fields.many2one('ir.actions.server', 'Email Server Action', required=False, domain="[('state','=','email')]", help="An Email Server Action. It will be run whenever an e-mail is fetched from server."),
+ 'object_id': fields.many2one('ir.model', "Model", required=True, help="OpenObject Model. Generates a record of this model.\nSelect Object with message_new attrbutes."),
'priority': fields.integer('Server Priority', readonly=True, states={'draft':[('readonly', False)]}, help="Priority between 0 to 10, select define the order of Processing"),
'user_id':fields.many2one('res.users', 'User', required=False),
'message_ids': fields.one2many('mailgate.message', 'server_id', 'Messages', readonly=True),
@@ -73,7 +72,7 @@ class email_server(osv.osv):
}
def check_duplicate(self, cr, uid, ids):
- # RFC *-* Why this limitation? why not in SQL constraint?
+ # RFC *-* Why this limitation? why not in SQL constraint?
vals = self.read(cr, uid, ids, ['user', 'password'])[0]
cr.execute("select count(id) from email_server where user=%s and password=%s", (vals['user'], vals['password']))
res = cr.fetchone()
@@ -82,8 +81,19 @@ class email_server(osv.osv):
return False
return True
+ def check_model(self, cr, uid, ids, context = None):
+ if context is None:
+ context = {}
+ current_rec = self.read(cr, uid, ids, context)[0]
+ if current_rec:
+ model = self.pool.get(current_rec.get('object_id')[1])
+ if hasattr(model, 'message_new'):
+ return True
+ return False
+
_constraints = [
- (check_duplicate, 'Warning! Can\'t have duplicate server configuration!', ['user', 'password'])
+ (check_duplicate, 'Warning! Can\'t have duplicate server configuration!', ['user', 'password']),
+ (check_model, 'Warning! Record for selected Model can not be created\nPlease choose valid Model', ['object_id'])
]
def onchange_server_type(self, cr, uid, ids, server_type=False, ssl=False):
@@ -103,7 +113,6 @@ class email_server(osv.osv):
for server in self.browse(cr, uid, ids, context):
logger.notifyChannel('imap', netsvc.LOG_INFO, 'fetchmail start checking for new emails on %s' % (server.name))
context.update({'server_id': server.id, 'server_type': server.type})
- count = 0
try:
if server.type == 'imap':
imap_server = None
@@ -150,6 +159,7 @@ class email_server(osv.osv):
context.update({'get_server': True})
for server in self.browse(cr, uid, ids, context):
count = 0
+ user = server.user_id.id or uid
try:
if server.type == 'imap':
imap_server = self.button_confirm_login(cr, uid, [server.id], context=context)
@@ -157,9 +167,9 @@ class email_server(osv.osv):
result, data = imap_server.search(None, '(UNSEEN)')
for num in data[0].split():
result, data = imap_server.fetch(num, '(RFC822)')
- res_id = email_tool.process_email(cr, uid, server.object_id.model, data[0][1], attach=server.attach, context=context)
+ res_id = email_tool.process_email(cr, user, server.object_id.model, data[0][1], attach=server.attach, context=context)
if res_id and server.action_id:
- action_pool.run(cr, uid, [server.action_id.id], {'active_id': res_id, 'active_ids':[res_id]})
+ action_pool.run(cr, user, [server.action_id.id], {'active_id': res_id, 'active_ids':[res_id]})
imap_server.store(num, '+FLAGS', '\\Seen')
count += 1
@@ -174,9 +184,9 @@ class email_server(osv.osv):
for num in range(1, numMsgs + 1):
(header, msges, octets) = pop_server.retr(num)
msg = '\n'.join(msges)
- res_id = email_tool.process_email(cr, uid, server.object_id.model, msg, attach=server.attach, context=context)
+ res_id = email_tool.process_email(cr, user, server.object_id.model, msg, attach=server.attach, context=context)
if res_id and server.action_id:
- action_pool.run(cr, uid, [server.action_id.id], {'active_id': res_id, 'active_ids':[res_id]})
+ action_pool.run(cr, user, [server.action_id.id], {'active_id': res_id, 'active_ids':[res_id]})
pop_server.dele(num)
diff --git a/addons/fetchmail/fetchmail_view.xml b/addons/fetchmail/fetchmail_view.xml
index ecdb4acfb3b..7d55f9f5a7a 100644
--- a/addons/fetchmail/fetchmail_view.xml
+++ b/addons/fetchmail/fetchmail_view.xml
@@ -7,7 +7,7 @@
email.servertree
-
+
@@ -48,6 +48,7 @@
+
diff --git a/addons/hr_timesheet_invoice/hr_timesheet_invoice_view.xml b/addons/hr_timesheet_invoice/hr_timesheet_invoice_view.xml
index 70b227136e9..cc5f8da627c 100644
--- a/addons/hr_timesheet_invoice/hr_timesheet_invoice_view.xml
+++ b/addons/hr_timesheet_invoice/hr_timesheet_invoice_view.xml
@@ -118,6 +118,7 @@
tree,form[]{'search_default_to_invoice': 1}
+ This lists show you every task work you can invoice to the customer. Select the lines in order to generate the invoices automatically.
-
-
-
+
diff --git a/addons/project/i18n/project.pot b/addons/project/i18n/project.pot
index ffc28ddf2db..42cae0e9680 100644
--- a/addons/project/i18n/project.pot
+++ b/addons/project/i18n/project.pot
@@ -1430,7 +1430,7 @@ msgstr ""
#. module: project
#: model:ir.actions.act_window,help:project.open_view_project_all
-msgid "A project contains a set of tasks or issues that will be performed by your resources assigned on it. A project can be put into a hierarchy, as a child of a Parent Project. This allows you to design large project structure with different phases spread over the project duration cycle. Each user can set his default project in his own preferences, in order to filter automatically the tasks or issues he usually works on."
+msgid "A project contains a set of tasks or issues that will be performed by your assigned personnel. A project can be put into a hierarchy, as a child of a Parent Project. This allows you to design large project structure with different phases spread over the project's duration cycle. Each user can set his default project in his own preferences, in order to filter automatically the tasks or issues he usually works on. If you have personalized your Project application in order to invoice the time spent on a task, you can choose to invoice or not one project in the billing section."
msgstr ""
#. module: project
diff --git a/addons/project/project_view.xml b/addons/project/project_view.xml
index a06397341bb..7a65129af2c 100644
--- a/addons/project/project_view.xml
+++ b/addons/project/project_view.xml
@@ -160,7 +160,7 @@
{'search_default_Current':1}
- A project contains a set of tasks or issues that will be performed by your resources assigned on it. A project can be put into a hierarchy, as a child of a Parent Project. This allows you to design large project structure with different phases spread over the project duration cycle. Each user can set his default project in his own preferences, in order to filter automatically the tasks or issues he usually works on.
+ A project contains a set of tasks or issues that will be performed by your assigned personnel. A project can be put into a hierarchy, as a child of a Parent Project. This allows you to design large project structure with different phases spread over the project's duration cycle. Each user can set his default project in his own preferences, in order to filter automatically the tasks or issues he usually works on. If you have personalized your Project application in order to invoice the time spent on a task, you can choose to invoice or not one project in the billing section.
@@ -225,6 +225,9 @@
widget="float_time"
attrs="{'readonly':[('state','!=','draft')]}"
on_change="onchange_planned(planned_hours, effective_hours)"/>
+
diff --git a/addons/project_gtd/project_gtd.py b/addons/project_gtd/project_gtd.py
index 90bef42b452..a3c9d48476b 100644
--- a/addons/project_gtd/project_gtd.py
+++ b/addons/project_gtd/project_gtd.py
@@ -106,7 +106,7 @@ class project_task(osv.osv):
timebox_obj = self.pool.get('project.gtd.timebox')
access_pool = self.pool.get('ir.model.access')
if (res['type'] == 'search') and access_pool.check_groups(cr, uid, "project_gtd.group_project_getting"):
- tt = timebox_obj.browse(cr, uid, timebox_obj.search(cr,uid,[]))
+ tt = timebox_obj.browse(cr, uid, timebox_obj.search(cr,uid,[]), context=context)
search_extended ='''''' % (len(tt)+7,1,_('Getting Things Done'))
search_extended += '''''' % (_('Inbox'),)
search_extended += '''''' % (_('GTD'),)
@@ -125,7 +125,7 @@ class project_task(osv.osv):
if search_extended:
res['arch'] = unicode(res['arch'], 'utf8').replace('', search_extended)
attrs_sel = self.pool.get('project.gtd.context').name_search(cr, uid, '', [], context=context)
- context_id_info = self.pool.get('project.task').fields_get(cr, uid, ['context_id'])
+ context_id_info = self.pool.get('project.task').fields_get(cr, uid, ['context_id'], context=context)
context_id_info['context_id']['selection'] = attrs_sel
res['fields'].update(context_id_info)
return res
diff --git a/addons/project_long_term/i18n/project_long_term.pot b/addons/project_long_term/i18n/project_long_term.pot
index b3a2358809d..2e28070c646 100644
--- a/addons/project_long_term/i18n/project_long_term.pot
+++ b/addons/project_long_term/i18n/project_long_term.pot
@@ -500,7 +500,7 @@ msgstr ""
#. module: project_long_term
#: model:ir.ui.menu,name:project_long_term.menu_view_resource_calendar
-msgid "Working Period"
+msgid "Working Time"
msgstr ""
#. module: project_long_term
diff --git a/addons/project_long_term/project_long_term_view.xml b/addons/project_long_term/project_long_term_view.xml
index 39d9d1cfa8b..0cdb7af5ad7 100644
--- a/addons/project_long_term/project_long_term_view.xml
+++ b/addons/project_long_term/project_long_term_view.xml
@@ -377,7 +377,7 @@
src_model="project.phase"
view_mode="tree,form"
context="{'search_default_phase_id': [active_id]}"
- domain="[('phase_id', '=', active_id)]"
+ domain="[('phase_id', '=', active_id),('project_id','=',project_id)]"
/>
+ view_type="form"
+ />
+
+
# ------------------------------------------------------
# Menu Items
diff --git a/addons/project_long_term/security/ir.model.access.csv b/addons/project_long_term/security/ir.model.access.csv
index 3aaebb64294..6d4961f2cfe 100644
--- a/addons/project_long_term/security/ir.model.access.csv
+++ b/addons/project_long_term/security/ir.model.access.csv
@@ -1,8 +1,8 @@
"id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink"
"access_project_phase","project.phase","model_project_phase","project.group_project_user",1,1,1,0
"access_project_resource_allocation","project.resource.allocation","model_project_resource_allocation","project.group_project_user",1,0,0,0
-"access_project_phase_manager","project.phase manager","model_project_phase","project.group_project_manager",1,0,0,0
-"access_project_resource_allocation_manager","project.resource.allocation manager","model_project_resource_allocation","project.group_project_manager",1,0,0,0
+"access_project_phase_manager","project.phase manager","model_project_phase","project.group_project_manager",1,1,1,1
+"access_project_resource_allocation_manager","project.resource.allocation manager","model_project_resource_allocation","project.group_project_manager",1,1,1,1
"access_resource_resource_user","resource.resource user","resource.model_resource_resource","project.group_project_user",1,0,0,0
"access_resource_calendar_leaves_user","resource.calendar.leaves user","resource.model_resource_calendar_leaves","project.group_project_user",1,1,1,1
"access_resource_resource_manager","resource.resource manager","resource.model_resource_resource","project.group_project_manager",1,1,1,1
diff --git a/addons/project_timesheet/project_timesheet_view.xml b/addons/project_timesheet/project_timesheet_view.xml
index dd9967cb0e0..d349292b997 100644
--- a/addons/project_timesheet/project_timesheet_view.xml
+++ b/addons/project_timesheet/project_timesheet_view.xml
@@ -19,6 +19,18 @@
+
+ Inherit project form : Customer
+ project.project
+ form
+
+
+
+
+
+
+
+
Inherit project search view : Invoicing Dataproject.project
@@ -64,10 +76,58 @@
+
+ account.analytic.line.inherit.select
+ account.analytic.line
+ search
+ 10
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Bill Tasks Works
+ account.analytic.line
+ form
+ tree,form
+ []
+ {'search_default_to_invoice': 1}
+
+
+ This lists show you every task work you can invoice to the customer. Select the lines in order to generate the invoices automatically.
+
+
+ parent="menu_project_billing" action="action_project_timesheet_bill_task"/>
diff --git a/addons/resource/i18n/resource.pot b/addons/resource/i18n/resource.pot
index 8e704e446f0..8e2da3bcf83 100644
--- a/addons/resource/i18n/resource.pot
+++ b/addons/resource/i18n/resource.pot
@@ -88,7 +88,7 @@ msgstr ""
#. module: resource
#: view:resource.calendar:0
-msgid "Search Working Period"
+msgid "Search Working Time"
msgstr ""
#. module: resource
@@ -187,7 +187,7 @@ msgstr ""
#. module: resource
#: model:ir.actions.act_window,name:resource.action_resource_calendar_form
#: view:resource.calendar:0
-msgid "Working Period"
+msgid "Working Time"
msgstr ""
#. module: resource
diff --git a/addons/resource/resource.py b/addons/resource/resource.py
index 9012dfa7e38..5c3ec8bacb8 100644
--- a/addons/resource/resource.py
+++ b/addons/resource/resource.py
@@ -203,8 +203,8 @@ class resource_calendar_attendance(osv.osv):
'name' : fields.char("Name", size=64, required=True),
'dayofweek': fields.selection([('0','Monday'),('1','Tuesday'),('2','Wednesday'),('3','Thursday'),('4','Friday'),('5','Saturday'),('6','Sunday')], 'Day of week'),
'date_from' : fields.date('Starting date'),
- 'hour_from' : fields.float('Work from', size=8, required=True),
- 'hour_to' : fields.float("Work to", size=8, required=True),
+ 'hour_from' : fields.float('Work from', size=8, required=True, help="Working time will start from"),
+ 'hour_to' : fields.float("Work to", size=8, required=True, help="Working time will end at"),
'calendar_id' : fields.many2one("resource.calendar", "Resource's Calendar", required=True),
}
_order = 'dayofweek, hour_from'
diff --git a/addons/resource/resource_view.xml b/addons/resource/resource_view.xml
index 2a20f101b0f..1840c2a5f27 100644
--- a/addons/resource/resource_view.xml
+++ b/addons/resource/resource_view.xml
@@ -37,7 +37,7 @@
resource.calendarsearch
-
+
@@ -76,7 +76,7 @@
resource.calendarform
-