diff --git a/addons/web/views/webclient_templates.xml b/addons/web/views/webclient_templates.xml
index 9cb88403ac9..9c679393f34 100644
--- a/addons/web/views/webclient_templates.xml
+++ b/addons/web/views/webclient_templates.xml
@@ -268,7 +268,7 @@
-
+
diff --git a/addons/web_editor/static/src/js/translator.js b/addons/web_editor/static/src/js/translator.js
index 4fd9825567f..bc431f3ba55 100644
--- a/addons/web_editor/static/src/js/translator.js
+++ b/addons/web_editor/static/src/js/translator.js
@@ -177,6 +177,10 @@ var Translate = Widget.extend({
},
rte_changed: function (node) {
var $node = $(node);
+ $node.find("p").each(function () { // remove
element which might have been inserted because of copy-paste
+ var $p = $(this);
+ $p.after($p.html()).remove();
+ });
var trans = this.getTranlationObject($node[0]);
$node.toggleClass('o_dirty', trans.value !== $node.html().replace(/[ \t\n\r]+/, ' '));
},
diff --git a/addons/website/models/ir_http.py b/addons/website/models/ir_http.py
index ef81fa10f83..ca519654ad1 100644
--- a/addons/website/models/ir_http.py
+++ b/addons/website/models/ir_http.py
@@ -24,6 +24,10 @@ from odoo.addons.website.models.website import slug, url_for, _UNSLUG_RE
logger = logging.getLogger(__name__)
+# global resolver (GeoIP API is thread-safe, for multithreaded workers)
+# This avoids blowing up open files limit
+odoo._geoip_resolver = None
+
class RequestUID(object):
def __init__(self, **kw):
@@ -34,7 +38,7 @@ class Http(models.AbstractModel):
_inherit = 'ir.http'
rerouting_limit = 10
- _geoip_resolver = None
+ _geoip_resolver = None # backwards-compatibility
@classmethod
def _get_converters(cls):
@@ -90,26 +94,31 @@ class Http(models.AbstractModel):
@classmethod
def _geoip_setup_resolver(cls):
- if cls._geoip_resolver is None:
- try:
- import GeoIP
- # updated database can be downloaded on MaxMind website
- # http://dev.maxmind.com/geoip/legacy/install/city/
- geofile = config.get('geoip_database')
- if os.path.exists(geofile):
- cls._geoip_resolver = GeoIP.open(geofile, GeoIP.GEOIP_STANDARD)
- else:
- cls._geoip_resolver = False
- logger.warning('GeoIP database file %r does not exists, apt-get install geoip-database-contrib or download it from http://dev.maxmind.com/geoip/legacy/install/city/', geofile)
- except ImportError:
- cls._geoip_resolver = False
+ # Lazy init of GeoIP resolver
+ if cls._geoip_resolver is not None:
+ return
+ if odoo._geoip_resolver is not None:
+ cls._geoip_resolver = odoo._geoip_resolver
+ return
+ try:
+ import GeoIP
+ # updated database can be downloaded on MaxMind website
+ # http://dev.maxmind.com/geoip/legacy/install/city/
+ geofile = config.get('geoip_database')
+ if os.path.exists(geofile):
+ odoo._geoip_resolver = GeoIP.open(geofile, GeoIP.GEOIP_STANDARD)
+ else:
+ odoo._geoip_resolver = False
+ logger.warning('GeoIP database file %r does not exists, apt-get install geoip-database-contrib or download it from http://dev.maxmind.com/geoip/legacy/install/city/', geofile)
+ except ImportError:
+ odoo._geoip_resolver = False
@classmethod
def _geoip_resolve(cls):
if 'geoip' not in request.session:
record = {}
- if cls._geoip_resolver and request.httprequest.remote_addr:
- record = cls._geoip_resolver.record_by_addr(request.httprequest.remote_addr) or {}
+ if odoo._geoip_resolver and request.httprequest.remote_addr:
+ record = odoo._geoip_resolver.record_by_addr(request.httprequest.remote_addr) or {}
request.session['geoip'] = record
@classmethod
diff --git a/addons/website_crm_partner_assign/controllers/main.py b/addons/website_crm_partner_assign/controllers/main.py
index 46267ee55c4..9edc425e69a 100644
--- a/addons/website_crm_partner_assign/controllers/main.py
+++ b/addons/website_crm_partner_assign/controllers/main.py
@@ -5,6 +5,7 @@ import datetime
import werkzeug
from collections import OrderedDict
+from werkzeug.exceptions import NotFound
from odoo import fields
from odoo import http
@@ -93,13 +94,13 @@ class WebsiteAccount(website_account):
this_week_end_date = fields.Date.to_string(fields.Date.from_string(today) + datetime.timedelta(days=7))
searchbar_filters = {
- 'all': {'label': _('All'), 'domain': []},
+ 'all': {'label': _('Active'), 'domain': []},
'today': {'label': _('Today Activities'), 'domain': [('activity_date_deadline', '=', today)]},
'week': {'label': _('This Week Activities'),
'domain': [('activity_date_deadline', '>=', today), ('activity_date_deadline', '<=', this_week_end_date)]},
'overdue': {'label': _('Overdue Activities'), 'domain': [('activity_date_deadline', '<', today)]},
- 'won': {'label': _('Won'), 'domain': [('stage_id.probability', '=', 100), ('stage_id.fold', '=', True)]},
- 'lost': {'label': _('Lost'), 'domain': [('active', '=', False)]},
+ 'won': {'label': _('Won'), 'domain': [('stage_id.probability', '=', 100), ('stage_id.on_change', '=', True)]},
+ 'lost': {'label': _('Lost'), 'domain': [('active', '=', False), ('probability', '=', 0)]},
}
searchbar_sortings = {
'date': {'label': _('Newest'), 'order': 'create_date desc'},
@@ -118,6 +119,8 @@ class WebsiteAccount(website_account):
if not filterby:
filterby = 'all'
domain += searchbar_filters[filterby]['domain']
+ if filterby == 'lost':
+ CrmLead = CrmLead.with_context(active_test=False)
# archive groups - Default Group By 'create_date'
archive_groups = self._get_archive_groups('crm.lead', domain)
@@ -149,16 +152,21 @@ class WebsiteAccount(website_account):
})
return request.render("website_crm_partner_assign.portal_my_opportunities", values)
- @http.route(['/my/lead/
'], type='http', auth="user", website=True)
- def portal_my_lead(self, lead=None, **kw):
+ @http.route(['''/my/lead/'''], type='http', auth="user", website=True)
+ def portal_my_lead(self, lead, **kw):
+ if lead.type != 'lead':
+ raise NotFound()
return request.render("website_crm_partner_assign.portal_my_lead", {'lead': lead})
- @http.route(['/my/opportunity/'], type='http', auth="user", website=True)
- def portal_my_opportunity(self, lead=None, **kw):
+ @http.route(['''/my/opportunity/'''], type='http', auth="user", website=True)
+ def portal_my_opportunity(self, opp, **kw):
+ if opp.type != 'opportunity':
+ raise NotFound()
+
return request.render(
"website_crm_partner_assign.portal_my_opportunity", {
- 'opportunity': lead,
- 'user_activity': lead.activity_ids.filtered(lambda activity: activity.user_id == request.env.user)[:1],
+ 'opportunity': opp,
+ 'user_activity': opp.activity_ids.filtered(lambda activity: activity.user_id == request.env.user)[:1],
'stages': request.env['crm.stage'].search([('probability', '!=', '100')], order='sequence desc'),
'activity_types': request.env['mail.activity.type'].sudo().search([]),
'states': request.env['res.country.state'].sudo().search([]),
diff --git a/addons/website_crm_partner_assign/models/crm_lead.py b/addons/website_crm_partner_assign/models/crm_lead.py
index 95cf731c869..6556deeec70 100644
--- a/addons/website_crm_partner_assign/models/crm_lead.py
+++ b/addons/website_crm_partner_assign/models/crm_lead.py
@@ -232,26 +232,29 @@ class CrmLead(models.Model):
'planned_revenue': values['planned_revenue'],
'probability': values['probability'],
'priority': values['priority'],
+ 'date_deadline': values['date_deadline'] or False,
}
# As activities may belong to several users, only the current portal user activity
# will be modified by the portal form. If no activity exist we create a new one instead
# that we assign to the portal user.
+
user_activity = lead.activity_ids.filtered(lambda activity: activity.user_id == self.env.user)[:1]
- if user_activity:
- user_activity.sudo().write({
- 'activity_type_id': values['activity_type_id'],
- 'summary': values['activity_summary'],
- 'date_deadline': values['activity_date_deadline'],
- })
- else:
- self.env['mail.activity'].sudo().create({
- 'res_model_id': self.env.ref('crm.model_crm_lead').id,
- 'res_id': lead.id,
- 'user_id': self.env.user.id,
- 'activity_type_id': values['activity_type_id'],
- 'summary': values['activity_summary'],
- 'date_deadline': values['activity_date_deadline'],
- })
+ if values['activity_date_deadline']:
+ if user_activity:
+ user_activity.sudo().write({
+ 'activity_type_id': values['activity_type_id'],
+ 'summary': values['activity_summary'],
+ 'date_deadline': values['activity_date_deadline'],
+ })
+ else:
+ self.env['mail.activity'].sudo().create({
+ 'res_model_id': self.env.ref('crm.model_crm_lead').id,
+ 'res_id': lead.id,
+ 'user_id': self.env.user.id,
+ 'activity_type_id': values['activity_type_id'],
+ 'summary': values['activity_summary'],
+ 'date_deadline': values['activity_date_deadline'],
+ })
lead.write(lead_values)
@api.model
diff --git a/addons/website_crm_partner_assign/static/src/js/crm_partner_assign.js b/addons/website_crm_partner_assign/static/src/js/crm_partner_assign.js
index 3357c9d9384..b5920cb31ee 100644
--- a/addons/website_crm_partner_assign/static/src/js/crm_partner_assign.js
+++ b/addons/website_crm_partner_assign/static/src/js/crm_partner_assign.js
@@ -101,6 +101,8 @@ $('.edit_contact_confirm').on('click',function(){
});
$('.new_opp_confirm').on('click',function(e){
+ var $btn = $(this);
+ $btn.prop('disabled', true);
new Model('crm.lead')
.call("create_opp_portal", [{
contact_name: $('.new_opp_form .contact_name').val(),
@@ -111,10 +113,15 @@ $('.new_opp_confirm').on('click',function(e){
if (response.errors) {
$('#new-opp-dialog .alert').remove();
$('#new-opp-dialog div:first').prepend("" + response.errors + "
");
+ $btn.prop('disabled', false);
+
}
else {
window.location = '/my/opportunity/' + response.id;
}
+ })
+ .fail(function() {
+ $btn.prop('disabled', false);
});
return false;
});
@@ -124,6 +131,7 @@ $('.edit_opp_confirm').on('click',function(){
$btn.prop('disabled', true);
new Model('crm.lead')
.call("update_lead_portal", [[parseInt($('.edit_opp_form .opportunity_id').val())],{
+ date_deadline: $('.edit_opp_form .date_deadline').val(),
planned_revenue: parseFloat($('.edit_opp_form .planned_revenue').val()),
probability: parseFloat($('.edit_opp_form .probability').val()),
activity_type_id: parseInt($('.edit_opp_form .next_activity').find(":selected").attr('data')),
diff --git a/addons/website_crm_partner_assign/views/website_crm_partner_assign_templates.xml b/addons/website_crm_partner_assign/views/website_crm_partner_assign_templates.xml
index df60fa3eac8..668848908ab 100644
--- a/addons/website_crm_partner_assign/views/website_crm_partner_assign_templates.xml
+++ b/addons/website_crm_partner_assign/views/website_crm_partner_assign_templates.xml
@@ -215,7 +215,7 @@
- There are currently no leads for your account.
+ There are currently no leads.
@@ -227,7 +227,7 @@
- There are currently no opportunities for your account.
+ There are currently no opportunities.
@@ -307,13 +307,13 @@