[MERGE] forward port branch saas-14 up to 8c692aac88
This commit is contained in:
@@ -181,6 +181,12 @@ msgid "<br><br>\n"
|
||||
" You can insert canned responses in your message by typing <b>:shortcut</b>.<br>"
|
||||
msgstr ""
|
||||
|
||||
#. module: mail
|
||||
#: code:addons/mail/models/mail_channel.py:475
|
||||
#, python-format
|
||||
msgid "<div class=\"o_mail_notification\">%(author)s invited %(new_partner)s to <a href=\"#\" class=\"o_channel_redirect\" data-oe-id=\"%(channel_id)s\">#%(channel_name)s</a></div>"
|
||||
msgstr ""
|
||||
|
||||
#. module: mail
|
||||
#: code:addons/mail/models/mail_channel.py:552
|
||||
#, python-format
|
||||
|
||||
@@ -472,7 +472,15 @@ class Channel(models.Model):
|
||||
partners_to_add = partners - channel.channel_partner_ids
|
||||
channel.write({'channel_last_seen_partner_ids': [(0, 0, {'partner_id': partner_id}) for partner_id in partners_to_add.ids]})
|
||||
for partner in partners_to_add:
|
||||
notification = _('<div class="o_mail_notification">joined <a href="#" class="o_channel_redirect" data-oe-id="%s">#%s</a></div>') % (self.id, self.name,)
|
||||
if partner.id != self.env.user.partner_id.id:
|
||||
notification = _('<div class="o_mail_notification">%(author)s invited %(new_partner)s to <a href="#" class="o_channel_redirect" data-oe-id="%(channel_id)s">#%(channel_name)s</a></div>') % {
|
||||
'author': self.env.user.display_name,
|
||||
'new_partner': partner.display_name,
|
||||
'channel_id': channel.id,
|
||||
'channel_name': channel.name,
|
||||
}
|
||||
else:
|
||||
notification = _('<div class="o_mail_notification">joined <a href="#" class="o_channel_redirect" data-oe-id="%s">#%s</a></div>') % (channel.id, channel.name,)
|
||||
self.message_post(body=notification, message_type="notification", subtype="mail.mt_comment", author_id=partner.id)
|
||||
|
||||
# broadcast the channel header to the added partner
|
||||
|
||||
@@ -199,6 +199,10 @@ var Thread = Widget.extend({
|
||||
});
|
||||
},
|
||||
on_click_redirect: function (event) {
|
||||
// ignore inherited branding
|
||||
if ($(event.target).data('oe-field') !== undefined) {
|
||||
return;
|
||||
}
|
||||
var id = $(event.target).data('oe-id');
|
||||
if (id) {
|
||||
event.preventDefault();
|
||||
|
||||
@@ -82,6 +82,11 @@ class MrpBom(models.Model):
|
||||
if self.product_tmpl_id:
|
||||
self.product_uom_id = self.product_tmpl_id.uom_id.id
|
||||
|
||||
@api.onchange('routing_id')
|
||||
def onchange_routing_id(self):
|
||||
for line in self.bom_line_ids:
|
||||
line.operation_id = False
|
||||
|
||||
@api.multi
|
||||
def name_get(self):
|
||||
return [(bom.id, '%s%s' % (bom.code and '%s: ' % bom.code or '', bom.product_tmpl_id.display_name)) for bom in self]
|
||||
|
||||
@@ -409,13 +409,11 @@ class Task(models.Model):
|
||||
|
||||
@api.onchange('project_id')
|
||||
def _onchange_project(self):
|
||||
default_partner_id = self.env.context.get('default_partner_id')
|
||||
default_partner = self.env['res.partner'].browse(default_partner_id) if default_partner_id else self.env['res.partner']
|
||||
if self.project_id:
|
||||
self.partner_id = self.project_id.partner_id or default_partner
|
||||
if self.project_id.partner_id:
|
||||
self.partner_id = self.project_id.partner_id
|
||||
self.stage_id = self.stage_find(self.project_id.id, [('fold', '=', False)])
|
||||
else:
|
||||
self.partner_id = default_partner
|
||||
self.stage_id = False
|
||||
|
||||
@api.onchange('user_id')
|
||||
|
||||
@@ -116,7 +116,7 @@ class SaleOrder(models.Model):
|
||||
validity_date = fields.Date(string='Expiration Date', readonly=True, copy=False, states={'draft': [('readonly', False)], 'sent': [('readonly', False)]},
|
||||
help="Manually set the expiration date of your quotation (offer), or it will set the date automatically based on the template if online quotation is installed.")
|
||||
create_date = fields.Datetime(string='Creation Date', readonly=True, index=True, help="Date on which sales order is created.")
|
||||
confirmation_date = fields.Datetime(string='Confirmation Date', readonly=True, index=True, help="Date on which the sales order is confirmed.", oldname="date_confirm")
|
||||
confirmation_date = fields.Datetime(string='Confirmation Date', readonly=True, index=True, help="Date on which the sales order is confirmed.", oldname="date_confirm", copy=False)
|
||||
user_id = fields.Many2one('res.users', string='Salesperson', index=True, track_visibility='onchange', default=lambda self: self.env.user)
|
||||
partner_id = fields.Many2one('res.partner', string='Customer', readonly=True, states={'draft': [('readonly', False)], 'sent': [('readonly', False)]}, required=True, change_default=True, index=True, track_visibility='always')
|
||||
partner_invoice_id = fields.Many2one('res.partner', string='Invoice Address', readonly=True, required=True, states={'draft': [('readonly', False)], 'sent': [('readonly', False)]}, help="Invoice address for current sales order.")
|
||||
|
||||
@@ -30,7 +30,7 @@ class StockHistory(models.Model):
|
||||
# on the individual lines.
|
||||
res = super(StockHistory, self).read_group(domain, fields, groupby, offset=offset, limit=limit, orderby=orderby, lazy=lazy)
|
||||
if 'inventory_value' in fields:
|
||||
groupby_list = groupby if not lazy else groupby[:-1]
|
||||
groupby_list = groupby[:1] if lazy else groupby
|
||||
date = self._context.get('history_date', fieldsDatetime.now())
|
||||
|
||||
# Step 2: retrieve the stock history lines. The result contains the 'expanded'
|
||||
@@ -39,7 +39,9 @@ class StockHistory(models.Model):
|
||||
fields_2 = set(
|
||||
['id', 'product_id', 'price_unit_on_quant', 'company_id', 'quantity'] + groupby_list
|
||||
)
|
||||
tables, where_clause, where_clause_params = self._where_calc(domain).get_sql()
|
||||
query = self._where_calc(domain)
|
||||
self._apply_ir_rules(query, 'read')
|
||||
tables, where_clause, where_clause_params = query.get_sql()
|
||||
select = "SELECT %s FROM %s WHERE %s "
|
||||
query = select % (','.join(fields_2), tables, where_clause)
|
||||
self._cr.execute(query, where_clause_params)
|
||||
|
||||
@@ -504,6 +504,17 @@ function swap(array, elem1, elem2) {
|
||||
array[i1] = elem2;
|
||||
}
|
||||
|
||||
function is_email(value, allow_mailto) {
|
||||
// http://stackoverflow.com/questions/46155/validate-email-address-in-javascript
|
||||
var re;
|
||||
if (allow_mailto) {
|
||||
re = /^(mailto:)?(([^<>()\[\]\.,;:\s@\"]+(\.[^<>()\[\]\.,;:\s@\"]+)*)|(\".+\"))@(([^<>()[\]\.,;:\s@\"]+\.)+[^<>()[\]\.,;:\s@\"]{2,})$/i;
|
||||
} else {
|
||||
re = /^(([^<>()\[\]\.,;:\s@\"]+(\.[^<>()\[\]\.,;:\s@\"]+)*)|(\".+\"))@(([^<>()[\]\.,;:\s@\"]+\.)+[^<>()[\]\.,;:\s@\"]{2,})$/i;
|
||||
}
|
||||
return re.test(value);
|
||||
}
|
||||
|
||||
function toBoolElse (str, elseValues, trueValues, falseValues) {
|
||||
var ret = _.str.toBool(str, trueValues, falseValues);
|
||||
if (_.isUndefined(ret)) {
|
||||
@@ -569,6 +580,7 @@ return {
|
||||
reject_after: reject_after,
|
||||
delay: delay,
|
||||
swap: swap,
|
||||
is_email: is_email,
|
||||
toBoolElse: toBoolElse,
|
||||
async_when: async_when,
|
||||
};
|
||||
|
||||
@@ -5,6 +5,7 @@ var core = require('web.core');
|
||||
var ajax = require('web.ajax');
|
||||
var Dialog = require('web.Dialog');
|
||||
var Widget = require('web.Widget');
|
||||
var utils = require('web.utils');
|
||||
var base = require('web_editor.base');
|
||||
var rte = require('web_editor.rte');
|
||||
|
||||
@@ -1048,6 +1049,7 @@ var LinkDialog = Dialog.extend({
|
||||
if (!$e.length) {
|
||||
$e = this.$('input.url-source:first');
|
||||
}
|
||||
$e.closest('.form-group').removeClass('has-error');
|
||||
var val = $e.val();
|
||||
var label = this.$('#o_link_dialog_label_input').val() || val;
|
||||
|
||||
@@ -1068,8 +1070,7 @@ var LinkDialog = Dialog.extend({
|
||||
var size = this.$("select.link-style").val() || '';
|
||||
var classes = (this.data.className || "") + (style && style.length ? " btn " : "") + style + " " + size;
|
||||
var isNewWindow = this.$('input.window-new').prop('checked');
|
||||
|
||||
if ($e.hasClass('email-address') && $e.val().indexOf("@") !== -1) {
|
||||
if ($e.hasClass('email-address') && (_.str.startsWith(val, 'mailto:') || (val.indexOf("@") !== -1 && !_.str.startsWith(val, 'http') && !_.str.startsWith(val, 'www')))) {
|
||||
self.get_data_buy_mail(def, $e, isNewWindow, label, classes, test);
|
||||
} else {
|
||||
self.get_data_buy_url(def, $e, isNewWindow, label, classes, test);
|
||||
@@ -1078,7 +1079,13 @@ var LinkDialog = Dialog.extend({
|
||||
},
|
||||
get_data_buy_mail: function (def, $e, isNewWindow, label, classes, test) {
|
||||
var val = $e.val();
|
||||
def.resolve(val.indexOf("mailto:") === 0 ? val : 'mailto:' + val, isNewWindow, label, classes);
|
||||
if (utils.is_email(val, true)) {
|
||||
def.resolve(val.indexOf("mailto:") === 0 ? val : 'mailto:' + val, isNewWindow, label, classes);
|
||||
} else {
|
||||
$e.closest('.form-group').addClass('has-error');
|
||||
$e.focus();
|
||||
def.reject();
|
||||
}
|
||||
},
|
||||
get_data_buy_url: function (def, $e, isNewWindow, label, classes, test) {
|
||||
def.resolve($e.val(), isNewWindow, label, classes);
|
||||
|
||||
@@ -74,7 +74,14 @@ class SaleOrder(models.Model):
|
||||
(0, 'Not mandatory on website quote validation'),
|
||||
(1, 'Immediate after website order validation'),
|
||||
(2, 'Immediate after website order validation and save a token'),
|
||||
], 'Payment', help="Require immediate payment by the customer when validating the order from the website quote")
|
||||
], 'Payment', help="Require immediate payment by the customer when validating the order from the website quote", compute='_compute_require_payment', store=True)
|
||||
|
||||
@api.one
|
||||
@api.depends('template_id')
|
||||
def _compute_require_payment(self):
|
||||
# Do not overwrite if the field is already set
|
||||
if self.template_id and (self.require_payment is None or self.require_payment is False):
|
||||
self.require_payment = self.template_id.require_payment
|
||||
|
||||
@api.multi
|
||||
def copy(self, default=None):
|
||||
|
||||
@@ -617,14 +617,11 @@
|
||||
<input type="hidden" t-if="len(product.product_variant_ids) == 1" class="product_id" name="product_id" t-att-value="product.product_variant_id.id"/>
|
||||
<t t-if="len(product.product_variant_ids) > 1">
|
||||
<label label-default="label-default" class="radio" t-foreach="product.product_variant_ids" t-as="variant_id">
|
||||
<input type="radio" name="product_id" class="js_product_change" t-att-checked="'checked' if variant_id_index == 0 else None" t-att-value="variant_id.id" t-att-data-lst_price="variant_id.lst_price" t-att-data-price="variant_id.price"/>
|
||||
<input type="radio" name="product_id" class="js_product_change" t-att-checked="'checked' if variant_id_index == 0 else ''" t-att-value="variant_id.id" t-att-data-lst_price="compute_currency(variant_id.lst_price)" t-att-data-price="variant_id.price"/>
|
||||
<span t-esc="variant_id.name_get()[0][1]"/>
|
||||
<span class="badge" t-if="variant_id.price_extra">
|
||||
<t t-esc="variant_id.price_extra > 0 and '+' or ''"/><span t-field="variant_id.price_extra" style="white-space: nowrap;" t-options='{
|
||||
"widget": "monetary",
|
||||
"from_currency": product.currency_id,
|
||||
"display_currency": website.currency_id
|
||||
}'/>
|
||||
<t t-set="diff_price" t-value="variant_id.price - variant_id.product_tmpl_id.price"/>
|
||||
<span class="badge" t-if="diff_price != 0">
|
||||
<t t-esc="diff_price > 0 and '+' or '-'"/><span t-esc="abs(diff_price)" t-esc-options='{"widget": "monetary", "display_currency": "website.currency_id"}'/>
|
||||
</span>
|
||||
</label>
|
||||
</t>
|
||||
|
||||
Reference in New Issue
Block a user