uco (OpenERP)
2010-12-14 11:45:50 +05:30
16 changed files with 327 additions and 83 deletions
+53 -58
View File
@@ -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,36 +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')
stage_type = context and context.get('stage_type','')
current_seq = 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='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]
current_seq = case.stage_id.sequence
if next_stage:
stage = stage_pool.browse(cr, uid, next_stage, context=context)
next_seq = stage.sequence
if current_seq and (next_seq - current_seq) >= 1:
data = {'stage_id': next_stage}
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
@@ -181,34 +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')
stage_type = context and context.get('stage_type','')
for case in self.browse(cr, uid, ids, context):
prev_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='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]
current_seq = case.stage_id.sequence
if prev_stage:
stage = stage_pool.browse(cr, uid, prev_stage, context=context)
prev_seq = stage.sequence
if current_seq and (prev_seq - current_seq) <= 1:
data = {'stage_id': prev_stage}
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
@@ -636,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()
+7 -7
View File
@@ -2,7 +2,12 @@
<openerp>
<data noupdate="1">
<record model="crm.case.stage" id="stage_lead6">
<field name="name">Lost</field>
<field eval="'0'" name="probability"/>
<field eval="'0'" name="sequence"/>
<field name="type">lead</field>
</record>
<!-- CASE STATUS(stage_id) -->
<record model="crm.case.stage" id="stage_lead1">
<field name="name">New</field>
@@ -40,12 +45,7 @@
<field name="type">lead</field>
</record>
<record model="crm.case.stage" id="stage_lead6">
<field name="name">Lost</field>
<field eval="'0'" name="probability"/>
<field eval="'6'" name="sequence"/>
<field name="type">lead</field>
</record>
<record model="crm.case.section" id="section_sales_department">
<field name="name">Sales Department</field>
+3 -3
View File
@@ -57,14 +57,14 @@
<newline />
<field name="section_id" widget="selection" />
<field name="user_id" />
<field name="stage_id" domain="[('type','=','lead'),('section_ids', '=', section_id)]"/>
<field name="stage_id" domain="[('type','=','lead'),('section_ids', '=', section_id)]" />
<group col="2" colspan="1">
<button name="stage_previous" string=""
states="open,pending,draft" type="object"
icon="gtk-go-back" context="{'stage_type': 'lead'}"/>
icon="gtk-go-back" context="{'stage_type': 'lead'}" />
<button name="stage_next" string=""
states="open,pending,draft" type="object"
icon="gtk-go-forward" />
icon="gtk-go-forward" context="{'stage_type': 'lead'}" />
</group>
<field name="type" invisible="1"/>
</group>
+5 -4
View File
@@ -39,14 +39,15 @@
</group>
<field name="user_id"/>
<button name="action_makeMeeting" type="object"
string="Schedule Meeting" icon="gtk-redo" />
<button string="Schedule/Log Call"
name="%(opportunity2phonecall_act)d" icon="terp-call-start" type="action" groups="base.group_extended"/>
<field name="planned_revenue"/>
<field name="probability"/>
<field name="date_deadline"/>
<button string="Schedule/Log Call"
name="%(opportunity2phonecall_act)d" icon="terp-call-start" type="action" groups="base.group_extended"/>
<button name="action_makeMeeting" type="object"
string="Schedule Meeting" icon="gtk-redo" />
<newline/>
<field name="date_action"/>
<field name="title_action"/>
+1
View File
@@ -123,6 +123,7 @@
<separator string="Stage Definition" colspan="4"/>
<field name="name" select="1"/>
<field name="type" invisible="1" />
<field name="section_ids" invisible="1" />
<field name="sequence"/>
<field name="probability"/>
<field name="on_change"/>
+1 -1
View File
@@ -59,7 +59,7 @@
</record>
<record model="crm.case.stage" id="stage_claim3">
<field name="name">Won't fix</field>
<field name="sequence">11</field>
<field name="sequence">0</field>
<field name="type">claim</field>
</record>
+1 -2
View File
@@ -72,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()
@@ -113,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
@@ -175,6 +175,12 @@ class OutlookAddin:
toolbar = bars.Item("Standard")
openerp_bar = bars.Item('Open ERP')
item = openerp_bar.Controls.Add(Type = constants.msoControlButton, Temporary = True)
item = self.toolbarButtonConfig = DispatchWithEvents(item, Configuration)
item.Caption = "Configuration"
item.TooltipText = "Click to configure OpenERP."
item.Enabled = True
item = openerp_bar.Controls.Add(Type=constants.msoControlButton, Temporary=True)
# Hook events for the item
item = self.toolbarButton = DispatchWithEvents(item, ArchiveEvent)
@@ -198,6 +204,8 @@ class OutlookAddin:
item.TooltipText = "Click to Open Document that has been pushed to server."
item.Enabled = True
# Hook events for the item
# item = toolbarweb.Controls.Add(Type = constants.msoControlButton, Temporary = True)
# item = self.toolbarButtonPartner = DispatchWithEvents(item, ViewPartners)
@@ -1406,14 +1406,11 @@ def OpenPartnerForm(txtProcessor,*args):
txtProcessor.init_done=True
return
try:
linktopartner = "http://"+web_server+":"+str(web_server_port)+"/openerp/form/view?model=res.partner&id="+str(vals)
import urllib
next = urllib.urlencode({'next' : '/openerp/form/view?model=res.partner&id=' +str(vals) })
weburl = 'http://'+web_server+':'+str(web_server_port)+'/'
linktopartner = weburl + '?' + next
win32gui.SendMessage(partner_link, win32con.WM_SETTEXT, 0, str(linktopartner))
# import urllib
# encode = urllib.urlencode('/openerp/form/view?model=res.partner&id='+str(vals))
# weburl = 'http://'+web_server+':'+str(web_server_port)
# linktopartner = weburl + "?next=" + encode
# win32gui.SendMessage(partner_link, win32con.WM_SETTEXT, 0, linktopartner)
except Exception,e:
win32ui.MessageBox("Error While Opening Partner.\n"+str(e),"Open Partner", flag_error)
webbrowser.open_new(linktopartner)
@@ -1469,7 +1466,10 @@ def SerachOpenDocuemnt(txtProcessor,*args):
txtProcessor.init_done=True
return
try:
linktodoc = "http:\\\\" +web_server+ ":"+str(web_server_port)+"\\openerp\\form\\view?model="+vals[0][1]+"&id="+str(vals[1][1])
import urllib
next = urllib.urlencode({'next' : '/openerp/form/view?model='+vals[0][1]+'&id='+str(vals[1][1])})
weburl = 'http://'+web_server+':'+str(web_server_port)+'/'
linktodoc = weburl + '?' + next
win32gui.SendMessage(link_box, win32con.WM_SETTEXT, 0, str(linktodoc))
except Exception,e:
win32ui.MessageBox("Error While Opening Document.\n"+str(e),"Open Document", flag_error)
+15
View File
@@ -0,0 +1,15 @@
OpenERP, Open Source Management Solution
Copyright © 2010 OpenERP SA (<http://openerp.com>).
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 Lice
along with this program. If not, see <http://www.gnu.org/licenses/>.
+19
View File
@@ -0,0 +1,19 @@
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2010 OpenERP s.a. (<http://openerp.com>).
#
# 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 <http://www.gnu.org/licenses/>.
#
##############################################################################
+34
View File
@@ -0,0 +1,34 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2010 OpenERP s.a. (<http://openerp.com>).
#
# 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 <http://www.gnu.org/licenses/>.
#
##############################################################################
{
'name': 'Add uservoice button in header',
'version': '1.0',
'category': 'Generic Modules/Others',
'description': "",
'author': 'OpenERP s.a.',
'website': 'http://openerp.com',
'depends': ['base'],
'data': [],
'installable': True,
'active': False,
'web': True,
'certificate': '0040452504963885',
}
+22
View File
@@ -0,0 +1,22 @@
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2010 OpenERP s.a. (<http://openerp.com>).
#
# 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 <http://www.gnu.org/licenses/>.
#
##############################################################################
import editors
import controllers
+68
View File
@@ -0,0 +1,68 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2010 OpenERP s.a. (<http://openerp.com>).
#
# 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 <http://www.gnu.org/licenses/>.
#
##############################################################################
from openerp.controllers import SecuredController
from openerp.utils import rpc
from openobject.tools import expose
import cherrypy
class Root(SecuredController):
_cp_path = "/openerp"
@expose(mark_only=True)
def menu(self, active=None, next=None):
try:
menu_id = int(active)
except (TypeError, ValueError):
menu_id = False
menus = rpc.RPCProxy("ir.ui.menu")
ids = menus.search([('parent_id', '=', False)])
if next or active:
if not menu_id and ids:
menu_id = ids[0]
menu = ''
if menu_id:
ctx = dict(lang='NO_LANG') # force loading original string even if the english have been translated...
menu = menus.read([menu_id], ['name'], ctx)[0]['name'] or ''
general_forum = 77459
forum = {
'accounting': 87921,
'administration': 87935,
'human resources': 87923,
'knowledge': 87927,
'manufacturing': 87915,
'marketing': 87925,
'point of sale': 87929,
'project': 87919,
'purchases': 87911,
'sales': 87907,
'tools': 87933,
'warehouse': 87913,
}.get(menu.lower().strip(), general_forum)
cherrypy.request.uservoice_forum = forum
return super(Root, self).menu(active, next)
+75
View File
@@ -0,0 +1,75 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2010 OpenERP s.a. (<http://openerp.com>).
#
# 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 <http://www.gnu.org/licenses/>.
#
##############################################################################
import openobject.templating
class BaseTemplateEditor(openobject.templating.TemplateEditor):
templates = ['/openobject/controllers/templates/base.mako']
def edit(self, template, template_text):
output = super(BaseTemplateEditor, self).edit(template, template_text)
end_head = output.index('</head>')
output = output[:end_head] + """
<link rel="stylesheet" type="text/css" href="/web_uservoice/static/css/uservoice.css"/>
""" + output[end_head:]
end_body = output.index('</body>')
# testing forum: 84397
output = output[:end_body] + """
<script type="text/javascript">
var uservoiceOptions = {
key: 'openerpsa',
host: 'feedback.openerp.com',
forum: '${getattr(cp.request, 'uservoice_forum', 77459)}',
lang: 'en',
showTab: false
};
function _loadUserVoice() {
var s = document.createElement('script');
s.src = ("https:" == document.location.protocol ? "https://" : "http://") + "cdn.uservoice.com/javascripts/widgets/tab.js";
document.getElementsByTagName('head')[0].appendChild(s);
}
_loadSuper = window.onload;
window.onload = (typeof window.onload != 'function') ? _loadUserVoice : function() { _loadSuper(); _loadUserVoice(); };
</script>
""" + output[end_body:]
return output
class HeaderTemplateEditor(openobject.templating.TemplateEditor):
templates = ['/openerp/controllers/templates/header.mako']
def edit(self, template, template_text):
output = super(HeaderTemplateEditor, self).edit(template, template_text)
PAT = '<ul class="tools">'
ul = output.index(PAT)
output = output[:ul] + """
<p class="logout feedback"><a href="#" onclick="UserVoice.Popin.show(uservoiceOptions); return false;"><img src="/web_uservoice/static/images/uv_favicon.png" />feedback</a></p>
""" + output[ul:]
return output
@@ -0,0 +1,7 @@
#corner p.feedback a {
/*color: #9a0404;*/
}
#corner p.feedback img {
vertical-align: middle;
margin-right: 0.5em;
}