[MERGE] Foward-port saas-5 up to ee4df1e
This commit is contained in:
@@ -74,13 +74,19 @@ class account_analytic_line(osv.osv):
|
|||||||
product_obj = self.pool.get('product.product')
|
product_obj = self.pool.get('product.product')
|
||||||
analytic_journal_obj =self.pool.get('account.analytic.journal')
|
analytic_journal_obj =self.pool.get('account.analytic.journal')
|
||||||
product_price_type_obj = self.pool.get('product.price.type')
|
product_price_type_obj = self.pool.get('product.price.type')
|
||||||
|
product_uom_obj = self.pool.get('product.uom')
|
||||||
j_id = analytic_journal_obj.browse(cr, uid, journal_id, context=context)
|
j_id = analytic_journal_obj.browse(cr, uid, journal_id, context=context)
|
||||||
prod = product_obj.browse(cr, uid, prod_id, context=context)
|
prod = product_obj.browse(cr, uid, prod_id, context=context)
|
||||||
result = 0.0
|
result = 0.0
|
||||||
if prod_id:
|
if prod_id:
|
||||||
unit = prod.uom_id.id
|
unit_obj = False
|
||||||
|
if unit:
|
||||||
|
unit_obj = product_uom_obj.browse(cr, uid, unit, context=context)
|
||||||
|
if not unit_obj or prod.uom_id.category_id.id != unit_obj.category_id.id:
|
||||||
|
unit = prod.uom_id.id
|
||||||
if j_id.type == 'purchase':
|
if j_id.type == 'purchase':
|
||||||
unit = prod.uom_po_id.id
|
if not unit_obj or prod.uom_po_id.category_id.id != unit_obj.category_id.id:
|
||||||
|
unit = prod.uom_po_id.id
|
||||||
if j_id.type <> 'sale':
|
if j_id.type <> 'sale':
|
||||||
a = prod.property_account_expense.id
|
a = prod.property_account_expense.id
|
||||||
if not a:
|
if not a:
|
||||||
|
|||||||
@@ -379,7 +379,7 @@ class account_invoice(models.Model):
|
|||||||
assert len(self) == 1, 'This option should only be used for a single id at a time.'
|
assert len(self) == 1, 'This option should only be used for a single id at a time.'
|
||||||
template = self.env.ref('account.email_template_edi_invoice', False)
|
template = self.env.ref('account.email_template_edi_invoice', False)
|
||||||
compose_form = self.env.ref('mail.email_compose_message_wizard_form', False)
|
compose_form = self.env.ref('mail.email_compose_message_wizard_form', False)
|
||||||
ctx = dict(self._context,
|
ctx = dict(
|
||||||
default_model='account.invoice',
|
default_model='account.invoice',
|
||||||
default_res_id=self.id,
|
default_res_id=self.id,
|
||||||
default_use_template=bool(template),
|
default_use_template=bool(template),
|
||||||
|
|||||||
@@ -377,11 +377,20 @@ class MergePartnerAutomatic(osv.TransientModel):
|
|||||||
return {'type': 'ir.actions.act_window_close'}
|
return {'type': 'ir.actions.act_window_close'}
|
||||||
|
|
||||||
def _generate_query(self, fields, maximum_group=100):
|
def _generate_query(self, fields, maximum_group=100):
|
||||||
group_fields = ', '.join(fields)
|
sql_fields = []
|
||||||
|
for field in fields:
|
||||||
|
if field in ['email', 'name']:
|
||||||
|
sql_fields.append('lower(%s)' % field)
|
||||||
|
elif field in ['vat']:
|
||||||
|
sql_fields.append("replace(%s, ' ', '')" % field)
|
||||||
|
else:
|
||||||
|
sql_fields.append(field)
|
||||||
|
|
||||||
|
group_fields = ', '.join(sql_fields)
|
||||||
|
|
||||||
filters = []
|
filters = []
|
||||||
for field in fields:
|
for field in fields:
|
||||||
if field in ['email', 'name']:
|
if field in ['email', 'name', 'vat']:
|
||||||
filters.append((field, 'IS NOT', 'NULL'))
|
filters.append((field, 'IS NOT', 'NULL'))
|
||||||
|
|
||||||
criteria = ' AND '.join('%s %s %s' % (field, operator, value)
|
criteria = ' AND '.join('%s %s %s' % (field, operator, value)
|
||||||
|
|||||||
@@ -935,7 +935,7 @@ class mail_thread(osv.AbstractModel):
|
|||||||
|
|
||||||
# 1. message is a reply to an existing message (exact match of message_id)
|
# 1. message is a reply to an existing message (exact match of message_id)
|
||||||
ref_match = thread_references and tools.reference_re.search(thread_references)
|
ref_match = thread_references and tools.reference_re.search(thread_references)
|
||||||
msg_references = thread_references.split()
|
msg_references = mail_header_msgid_re.findall(thread_references)
|
||||||
mail_message_ids = mail_msg_obj.search(cr, uid, [('message_id', 'in', msg_references)], context=context)
|
mail_message_ids = mail_msg_obj.search(cr, uid, [('message_id', 'in', msg_references)], context=context)
|
||||||
if ref_match and mail_message_ids:
|
if ref_match and mail_message_ids:
|
||||||
original_msg = mail_msg_obj.browse(cr, SUPERUSER_ID, mail_message_ids[0], context=context)
|
original_msg = mail_msg_obj.browse(cr, SUPERUSER_ID, mail_message_ids[0], context=context)
|
||||||
@@ -978,7 +978,7 @@ class mail_thread(osv.AbstractModel):
|
|||||||
email_from, email_to, message_id, model, thread_id, custom_values, uid)
|
email_from, email_to, message_id, model, thread_id, custom_values, uid)
|
||||||
return [route]
|
return [route]
|
||||||
|
|
||||||
# 2. Reply to a private message
|
# 3. Reply to a private message
|
||||||
if in_reply_to:
|
if in_reply_to:
|
||||||
mail_message_ids = mail_msg_obj.search(cr, uid, [
|
mail_message_ids = mail_msg_obj.search(cr, uid, [
|
||||||
('message_id', '=', in_reply_to),
|
('message_id', '=', in_reply_to),
|
||||||
@@ -995,7 +995,7 @@ class mail_thread(osv.AbstractModel):
|
|||||||
email_from, email_to, message_id, mail_message.id, custom_values, uid)
|
email_from, email_to, message_id, mail_message.id, custom_values, uid)
|
||||||
return [route]
|
return [route]
|
||||||
|
|
||||||
# 3. Look for a matching mail.alias entry
|
# 4. Look for a matching mail.alias entry
|
||||||
# Delivered-To is a safe bet in most modern MTAs, but we have to fallback on To + Cc values
|
# Delivered-To is a safe bet in most modern MTAs, but we have to fallback on To + Cc values
|
||||||
# for all the odd MTAs out there, as there is no standard header for the envelope's `rcpt_to` value.
|
# for all the odd MTAs out there, as there is no standard header for the envelope's `rcpt_to` value.
|
||||||
rcpt_tos = \
|
rcpt_tos = \
|
||||||
@@ -1030,7 +1030,7 @@ class mail_thread(osv.AbstractModel):
|
|||||||
routes.append(route)
|
routes.append(route)
|
||||||
return routes
|
return routes
|
||||||
|
|
||||||
# 4. Fallback to the provided parameters, if they work
|
# 5. Fallback to the provided parameters, if they work
|
||||||
if not thread_id:
|
if not thread_id:
|
||||||
# Legacy: fallback to matching [ID] in the Subject
|
# Legacy: fallback to matching [ID] in the Subject
|
||||||
match = tools.res_re.search(decode_header(message, 'Subject'))
|
match = tools.res_re.search(decode_header(message, 'Subject'))
|
||||||
|
|||||||
@@ -67,8 +67,7 @@ class MassMailController(http.Controller):
|
|||||||
|
|
||||||
contact_ids = Contacts.search(cr, SUPERUSER_ID, [('list_id', '=', int(list_id)), ('email', '=', email)], context=context)
|
contact_ids = Contacts.search(cr, SUPERUSER_ID, [('list_id', '=', int(list_id)), ('email', '=', email)], context=context)
|
||||||
if not contact_ids:
|
if not contact_ids:
|
||||||
contact_ng = Contacts.name_create(cr, SUPERUSER_ID, email, context=context)
|
Contacts.add_to_list(cr, SUPERUSER_ID, email, int(list_id), context=context)
|
||||||
Contacts.write(cr, SUPERUSER_ID, [contact_ng[0]], {'list_id': int(list_id)}, context=context)
|
|
||||||
# add email to session
|
# add email to session
|
||||||
request.session['mass_mailing_email'] = email
|
request.session['mass_mailing_email'] = email
|
||||||
return True
|
return True
|
||||||
|
|||||||
@@ -52,15 +52,24 @@ class MassMailingContact(osv.Model):
|
|||||||
'list_id': _get_latest_list
|
'list_id': _get_latest_list
|
||||||
}
|
}
|
||||||
|
|
||||||
def name_create(self, cr, uid, name, context=None):
|
def get_name_email(self, name, context):
|
||||||
name, email = self.pool['res.partner']._parse_partner_name(name, context=context)
|
name, email = self.pool['res.partner']._parse_partner_name(name, context=context)
|
||||||
if name and not email:
|
if name and not email:
|
||||||
email = name
|
email = name
|
||||||
if email and not name:
|
if email and not name:
|
||||||
name = email
|
name = email
|
||||||
|
return name, email
|
||||||
|
|
||||||
|
def name_create(self, cr, uid, name, context=None):
|
||||||
|
name, email = self.get_name_email(name, context=context)
|
||||||
rec_id = self.create(cr, uid, {'name': name, 'email': email}, context=context)
|
rec_id = self.create(cr, uid, {'name': name, 'email': email}, context=context)
|
||||||
return self.name_get(cr, uid, [rec_id], context)[0]
|
return self.name_get(cr, uid, [rec_id], context)[0]
|
||||||
|
|
||||||
|
def add_to_list(self, cr, uid, name, list_id, context=None):
|
||||||
|
name, email = self.get_name_email(name, context=context)
|
||||||
|
rec_id = self.create(cr, uid, {'name': name, 'email': email, 'list_id': list_id}, context=context)
|
||||||
|
return self.name_get(cr, uid, [rec_id], context)[0]
|
||||||
|
|
||||||
def message_get_default_recipients(self, cr, uid, ids, context=None):
|
def message_get_default_recipients(self, cr, uid, ids, context=None):
|
||||||
res = {}
|
res = {}
|
||||||
for record in self.browse(cr, uid, ids, context=context):
|
for record in self.browse(cr, uid, ids, context=context):
|
||||||
|
|||||||
@@ -115,6 +115,7 @@ instance.web.Dialog = instance.web.Widget.extend({
|
|||||||
this.init_dialog();
|
this.init_dialog();
|
||||||
}
|
}
|
||||||
this.$buttons.insertAfter(this.$dialog_box.find(".modal-body"));
|
this.$buttons.insertAfter(this.$dialog_box.find(".modal-body"));
|
||||||
|
$('.tooltip').remove(); //remove open tooltip if any to prevent them staying when modal is opened
|
||||||
//add to list of currently opened modal
|
//add to list of currently opened modal
|
||||||
opened_modal.push(this.$dialog_box);
|
opened_modal.push(this.$dialog_box);
|
||||||
return this;
|
return this;
|
||||||
@@ -1156,7 +1157,7 @@ instance.web.Client = instance.web.Widget.extend({
|
|||||||
}, 0);
|
}, 0);
|
||||||
});
|
});
|
||||||
instance.web.bus.on('click', this, function(ev) {
|
instance.web.bus.on('click', this, function(ev) {
|
||||||
$.fn.tooltip('destroy');
|
$('.tooltip').remove();
|
||||||
if (!$(ev.target).is('input[type=file]')) {
|
if (!$(ev.target).is('input[type=file]')) {
|
||||||
self.$el.find('.oe_dropdown_menu.oe_opened, .oe_dropdown_toggle.oe_opened').removeClass('oe_opened');
|
self.$el.find('.oe_dropdown_menu.oe_opened, .oe_dropdown_toggle.oe_opened').removeClass('oe_opened');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -772,7 +772,7 @@ instance.web.unblockUI = function() {
|
|||||||
/* Bootstrap defaults overwrite */
|
/* Bootstrap defaults overwrite */
|
||||||
$.fn.tooltip.Constructor.DEFAULTS.placement = 'auto top';
|
$.fn.tooltip.Constructor.DEFAULTS.placement = 'auto top';
|
||||||
$.fn.tooltip.Constructor.DEFAULTS.html = true;
|
$.fn.tooltip.Constructor.DEFAULTS.html = true;
|
||||||
$.fn.tooltip.Constructor.DEFAULTS.container = 'body';
|
$.fn.tooltip.Constructor.DEFAULTS.trigger = 'hover focus click';
|
||||||
//overwrite bootstrap tooltip method to prevent showing 2 tooltip at the same time
|
//overwrite bootstrap tooltip method to prevent showing 2 tooltip at the same time
|
||||||
var bootstrap_show_function = $.fn.tooltip.Constructor.prototype.show;
|
var bootstrap_show_function = $.fn.tooltip.Constructor.prototype.show;
|
||||||
$.fn.tooltip.Constructor.prototype.show = function () {
|
$.fn.tooltip.Constructor.prototype.show = function () {
|
||||||
@@ -786,6 +786,18 @@ $.fn.tooltip.Constructor.prototype.show = function () {
|
|||||||
if (e.isDefaultPrevented() || !inDom) return;
|
if (e.isDefaultPrevented() || !inDom) return;
|
||||||
return bootstrap_show_function.call(this);
|
return bootstrap_show_function.call(this);
|
||||||
};
|
};
|
||||||
|
//overwrite bootstrap tooltip init method in order to check if tooltip is in a modal or not and
|
||||||
|
//if so it needs to have a container body in order to be visible
|
||||||
|
var bootstrap_init_tooltip_fnct = $.fn.tooltip.Constructor.prototype.init;
|
||||||
|
$.fn.tooltip.Constructor.prototype.init = function (type, element, options) {
|
||||||
|
options = options || {}
|
||||||
|
if ($('.modal[aria-hidden="false"]').length !== 0){
|
||||||
|
if (options && !options.container){
|
||||||
|
options = _.extend({container: 'body'},options);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return bootstrap_init_tooltip_fnct.call(this, type, element, options);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registry for all the client actions key: tag value: widget
|
* Registry for all the client actions key: tag value: widget
|
||||||
|
|||||||
@@ -1835,7 +1835,6 @@ instance.web.form.FormWidget = instance.web.Widget.extend(instance.web.form.Invi
|
|||||||
trigger = trigger || this.$el;
|
trigger = trigger || this.$el;
|
||||||
options = _.extend({
|
options = _.extend({
|
||||||
delay: { show: 500, hide: 0 },
|
delay: { show: 500, hide: 0 },
|
||||||
trigger: 'hover',
|
|
||||||
title: function() {
|
title: function() {
|
||||||
var template = widget.template + '.tooltip';
|
var template = widget.template + '.tooltip';
|
||||||
if (!QWeb.has_template(template)) {
|
if (!QWeb.has_template(template)) {
|
||||||
|
|||||||
@@ -40,7 +40,7 @@
|
|||||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||||
<h3 class="modal-title"><t t-raw="title"/></h3>
|
<h3 class="modal-title"><t t-raw="title"/></h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body" style="overflow-y: auto;">
|
<div class="modal-body">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -42,11 +42,12 @@ class WebsiteCustomer(http.Controller):
|
|||||||
if country_id:
|
if country_id:
|
||||||
domain += [('country_id', '=', country_id)]
|
domain += [('country_id', '=', country_id)]
|
||||||
if not any(x['country_id'][0] == country_id for x in countries):
|
if not any(x['country_id'][0] == country_id for x in countries):
|
||||||
country = country_obj.browse(cr, uid, country_id, context)
|
country = country_obj.read(cr, uid, country_id, ['name'], context)
|
||||||
countries.append({
|
if country:
|
||||||
'country_id_count': 0,
|
countries.append({
|
||||||
'country_id': (country_id, country.name)
|
'country_id_count': 0,
|
||||||
})
|
'country_id': (country_id, country['name'])
|
||||||
|
})
|
||||||
countries.sort(key=lambda d: d['country_id'][1])
|
countries.sort(key=lambda d: d['country_id'][1])
|
||||||
|
|
||||||
countries.insert(0, {
|
countries.insert(0, {
|
||||||
|
|||||||
+7
-6
@@ -4447,18 +4447,19 @@ class BaseModel(object):
|
|||||||
order_by = self._generate_order_by(order, query)
|
order_by = self._generate_order_by(order, query)
|
||||||
from_clause, where_clause, where_clause_params = query.get_sql()
|
from_clause, where_clause, where_clause_params = query.get_sql()
|
||||||
|
|
||||||
limit_str = limit and ' limit %d' % limit or ''
|
|
||||||
offset_str = offset and ' offset %d' % offset or ''
|
|
||||||
where_str = where_clause and (" WHERE %s" % where_clause) or ''
|
where_str = where_clause and (" WHERE %s" % where_clause) or ''
|
||||||
query_str = 'SELECT "%s".id FROM ' % self._table + from_clause + where_str + order_by + limit_str + offset_str
|
|
||||||
|
|
||||||
if count:
|
if count:
|
||||||
# /!\ the main query must be executed as a subquery, otherwise
|
# Ignore order, limit and offset when just counting, they don't make sense and could
|
||||||
# offset and limit apply to the result of count()!
|
# hurt performance
|
||||||
cr.execute('SELECT count(*) FROM (%s) AS count' % query_str, where_clause_params)
|
query_str = 'SELECT count(1) FROM ' + from_clause + where_str
|
||||||
|
cr.execute(query_str, where_clause_params)
|
||||||
res = cr.fetchone()
|
res = cr.fetchone()
|
||||||
return res[0]
|
return res[0]
|
||||||
|
|
||||||
|
limit_str = limit and ' limit %d' % limit or ''
|
||||||
|
offset_str = offset and ' offset %d' % offset or ''
|
||||||
|
query_str = 'SELECT "%s".id FROM ' % self._table + from_clause + where_str + order_by + limit_str + offset_str
|
||||||
cr.execute(query_str, where_clause_params)
|
cr.execute(query_str, where_clause_params)
|
||||||
res = cr.fetchall()
|
res = cr.fetchall()
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user