[MERGE] forward port branch saas-12 up to 54ebe31
This commit is contained in:
@@ -903,8 +903,8 @@ class AccountMoveLine(models.Model):
|
|||||||
# Writeoff line in the account of self
|
# Writeoff line in the account of self
|
||||||
first_line_dict = vals.copy()
|
first_line_dict = vals.copy()
|
||||||
first_line_dict['account_id'] = self[0].account_id.id
|
first_line_dict['account_id'] = self[0].account_id.id
|
||||||
if 'analytic_account_id' in vals:
|
if 'analytic_account_id' in first_line_dict:
|
||||||
del vals['analytic_account_id']
|
del first_line_dict['analytic_account_id']
|
||||||
|
|
||||||
# Writeoff line in specified writeoff account
|
# Writeoff line in specified writeoff account
|
||||||
second_line_dict = vals.copy()
|
second_line_dict = vals.copy()
|
||||||
|
|||||||
@@ -39,12 +39,12 @@
|
|||||||
<field name="tax_ids" widget="one2many_list" nolabel="1">
|
<field name="tax_ids" widget="one2many_list" nolabel="1">
|
||||||
<tree name="tax_map_tree" string="Tax Mapping" editable="bottom">
|
<tree name="tax_map_tree" string="Tax Mapping" editable="bottom">
|
||||||
<field name="tax_src_id" domain="[('type_tax_use', '!=', None)]"/>
|
<field name="tax_src_id" domain="[('type_tax_use', '!=', None)]"/>
|
||||||
<field name="tax_dest_id" domain="[('type_tax_use', '!=', None), ('price_include', '=', False)]"/>
|
<field name="tax_dest_id" domain="[('type_tax_use', '!=', None)]"/>
|
||||||
</tree>
|
</tree>
|
||||||
<form name="tax_map_form" string="Tax Mapping">
|
<form name="tax_map_form" string="Tax Mapping">
|
||||||
<group>
|
<group>
|
||||||
<field name="tax_src_id" domain="[('type_tax_use', '!=', None)]"/>
|
<field name="tax_src_id" domain="[('type_tax_use', '!=', None)]"/>
|
||||||
<field name="tax_dest_id" domain="[('type_tax_use', '!=', None), ('price_include', '=', False)]"/>
|
<field name="tax_dest_id" domain="[('type_tax_use', '!=', None)]"/>
|
||||||
</group>
|
</group>
|
||||||
</form>
|
</form>
|
||||||
</field>
|
</field>
|
||||||
|
|||||||
@@ -124,7 +124,7 @@ class BaseActionRule(models.Model):
|
|||||||
|
|
||||||
def _update_registry(self):
|
def _update_registry(self):
|
||||||
""" Update the registry after a modification on action rules. """
|
""" Update the registry after a modification on action rules. """
|
||||||
if self.env.registry.ready:
|
if self.env.registry.ready and not self.env.context.get('import_file'):
|
||||||
# for the sake of simplicity, simply force the registry to reload
|
# for the sake of simplicity, simply force the registry to reload
|
||||||
self._cr.commit()
|
self._cr.commit()
|
||||||
self.env.reset()
|
self.env.reset()
|
||||||
|
|||||||
@@ -649,7 +649,7 @@ class Import(models.TransientModel):
|
|||||||
}]
|
}]
|
||||||
|
|
||||||
_logger.info('importing %d rows...', len(data))
|
_logger.info('importing %d rows...', len(data))
|
||||||
import_result = self.env[self.res_model].load(import_fields, data)
|
import_result = self.env[self.res_model].with_context(import_file=True).load(import_fields, data)
|
||||||
_logger.info('done')
|
_logger.info('done')
|
||||||
|
|
||||||
# If transaction aborted, RELEASE SAVEPOINT is going to raise
|
# If transaction aborted, RELEASE SAVEPOINT is going to raise
|
||||||
|
|||||||
@@ -525,7 +525,7 @@
|
|||||||
<field name="source_id" invisible="1"/>
|
<field name="source_id" invisible="1"/>
|
||||||
<field name="stage_id"/>
|
<field name="stage_id"/>
|
||||||
<field name="planned_revenue" sum="Expected Revenues"/>
|
<field name="planned_revenue" sum="Expected Revenues"/>
|
||||||
<field name="probability" avg="Avg. of Probability"/>
|
<field name="probability" />
|
||||||
<field name="team_id"/>
|
<field name="team_id"/>
|
||||||
<field name="user_id"/>
|
<field name="user_id"/>
|
||||||
<field name="referred" invisible="1"/>
|
<field name="referred" invisible="1"/>
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ def format_tz(env, dt, tz=False, format=False):
|
|||||||
format_time = langs.time_format or '%I-%M %p'
|
format_time = langs.time_format or '%I-%M %p'
|
||||||
|
|
||||||
fdate = ts.strftime(format_date).decode('utf-8')
|
fdate = ts.strftime(format_date).decode('utf-8')
|
||||||
ftime = ts.strftime(format_time)
|
ftime = ts.strftime(format_time).decode('utf-8')
|
||||||
return "%s %s%s" % (fdate, ftime, (' (%s)' % tz) if tz else '')
|
return "%s %s%s" % (fdate, ftime, (' (%s)' % tz) if tz else '')
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|||||||
@@ -36,12 +36,6 @@
|
|||||||
<field name="groups" eval="[(4, ref('account.group_account_user'))]"/>
|
<field name="groups" eval="[(4, ref('account.group_account_user'))]"/>
|
||||||
<field name="domain_force">[(1, '=', 1)]</field>
|
<field name="domain_force">[(1, '=', 1)]</field>
|
||||||
</record>
|
</record>
|
||||||
<record id="rule_pos_cashbox_line_user" model="ir.rule">
|
|
||||||
<field name="name">Point Of Sale Cashbox Line POS User</field>
|
|
||||||
<field name="model_id" ref="account.model_account_cashbox_line" />
|
|
||||||
<field name="groups" eval="[(4, ref('group_pos_user'))]"/>
|
|
||||||
<field name="domain_force">[('bank_statement_id.pos_session_id', '!=', False)]</field>
|
|
||||||
</record>
|
|
||||||
<record id="rule_pos_cashbox_line_accountant" model="ir.rule">
|
<record id="rule_pos_cashbox_line_accountant" model="ir.rule">
|
||||||
<field name="name">Point Of Sale Cashbox Line Accountant</field>
|
<field name="name">Point Of Sale Cashbox Line Accountant</field>
|
||||||
<field name="model_id" ref="account.model_account_cashbox_line" />
|
<field name="model_id" ref="account.model_account_cashbox_line" />
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ var quotation_button_step_index = _.findIndex(tour.tours.sale_tour.steps, functi
|
|||||||
tour.tours.sale_tour.steps.splice(quotation_button_step_index, 1, {
|
tour.tours.sale_tour.steps.splice(quotation_button_step_index, 1, {
|
||||||
trigger: ".o_kanban_manage_button_section > a",
|
trigger: ".o_kanban_manage_button_section > a",
|
||||||
content: _t("Click here to see more options."),
|
content: _t("Click here to see more options."),
|
||||||
position: "bottom"
|
position: "right"
|
||||||
}, {
|
}, {
|
||||||
trigger: ".o_quotation_view_button",
|
trigger: ".o_quotation_view_button",
|
||||||
content: _t("Let's have a look at the quotations of this sales team."),
|
content: _t("Let's have a look at the quotations of this sales team."),
|
||||||
|
|||||||
@@ -1705,7 +1705,6 @@ var Column = Class.extend({
|
|||||||
id: id,
|
id: id,
|
||||||
tag: tag
|
tag: tag
|
||||||
});
|
});
|
||||||
|
|
||||||
this.modifiers = attrs.modifiers ? JSON.parse(attrs.modifiers) : {};
|
this.modifiers = attrs.modifiers ? JSON.parse(attrs.modifiers) : {};
|
||||||
delete attrs.modifiers;
|
delete attrs.modifiers;
|
||||||
_.extend(this, attrs);
|
_.extend(this, attrs);
|
||||||
@@ -1732,10 +1731,14 @@ var Column = Class.extend({
|
|||||||
if (this.type !== 'integer' && this.type !== 'float' && this.type !== 'monetary') {
|
if (this.type !== 'integer' && this.type !== 'float' && this.type !== 'monetary') {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
var aggregation_func = this['group_operator'] || 'sum';
|
|
||||||
if (!(aggregation_func in this)) {
|
var aggregation_func = (this.sum && 'sum') || (this.avg && 'avg') ||
|
||||||
|
(this.max && 'max') || (this.min && 'min') || this.group_operator;
|
||||||
|
|
||||||
|
if (!aggregation_func) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
var C = function (fn, label) {
|
var C = function (fn, label) {
|
||||||
this['function'] = fn;
|
this['function'] = fn;
|
||||||
this.label = label;
|
this.label = label;
|
||||||
|
|||||||
@@ -147,6 +147,20 @@ animation.registry.ul = animation.Class.extend({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a fix for apple device (<= IPhone 4, IPad 2)
|
||||||
|
* Standard bootstrap requires data-toggle='collapse' element to be <a/> tags. Unfortunatly one snippet uses a
|
||||||
|
* <div/> tag instead. The fix forces an empty click handler on these div, which allows standard bootstrap to work.
|
||||||
|
*
|
||||||
|
* This should be removed in a future odoo snippets refactoring.
|
||||||
|
*/
|
||||||
|
animation.registry._fix_apple_collapse = animation.Class.extend({
|
||||||
|
selector: ".s_faq_collapse [data-toggle='collapse']",
|
||||||
|
start: function () {
|
||||||
|
this.$target.off("click._fix_apple_collapse").on("click._fix_apple_collapse", function () {});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------
|
/* -------------------------------------------------------------------------
|
||||||
Gallery Animation
|
Gallery Animation
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ It also will include the feedback tool for the livechat, and web pages to displa
|
|||||||
""",
|
""",
|
||||||
'depends': ['website', 'im_livechat'],
|
'depends': ['website', 'im_livechat'],
|
||||||
'installable': True,
|
'installable': True,
|
||||||
|
'auto_install': True,
|
||||||
'data': [
|
'data': [
|
||||||
'views/website_livechat.xml',
|
'views/website_livechat.xml',
|
||||||
'views/res_config.xml',
|
'views/res_config.xml',
|
||||||
|
|||||||
@@ -213,7 +213,7 @@ class Partner(models.Model, FormatAddress):
|
|||||||
|
|
||||||
# technical field used for managing commercial fields
|
# technical field used for managing commercial fields
|
||||||
commercial_partner_id = fields.Many2one('res.partner', compute='_compute_commercial_partner',
|
commercial_partner_id = fields.Many2one('res.partner', compute='_compute_commercial_partner',
|
||||||
string='Commercial Entity', store=True)
|
string='Commercial Entity', store=True, index=True)
|
||||||
commercial_company_name = fields.Char('Company Name Entity', compute='_compute_commercial_company_name',
|
commercial_company_name = fields.Char('Company Name Entity', compute='_compute_commercial_company_name',
|
||||||
store=True)
|
store=True)
|
||||||
company_name = fields.Char('Company Name')
|
company_name = fields.Char('Company Name')
|
||||||
|
|||||||
@@ -71,10 +71,17 @@ class Discussion(models.Model):
|
|||||||
message_concat = fields.Text(string='Message concatenate')
|
message_concat = fields.Text(string='Message concatenate')
|
||||||
important_messages = fields.One2many('test_new_api.message', 'discussion',
|
important_messages = fields.One2many('test_new_api.message', 'discussion',
|
||||||
domain=[('important', '=', True)])
|
domain=[('important', '=', True)])
|
||||||
|
very_important_messages = fields.One2many(
|
||||||
|
'test_new_api.message', 'discussion',
|
||||||
|
domain=lambda self: self._domain_very_important())
|
||||||
emails = fields.One2many('test_new_api.emailmessage', 'discussion')
|
emails = fields.One2many('test_new_api.emailmessage', 'discussion')
|
||||||
important_emails = fields.One2many('test_new_api.emailmessage', 'discussion',
|
important_emails = fields.One2many('test_new_api.emailmessage', 'discussion',
|
||||||
domain=[('important', '=', True)])
|
domain=[('important', '=', True)])
|
||||||
|
|
||||||
|
def _domain_very_important(self):
|
||||||
|
"""Ensure computed O2M domains work as expected."""
|
||||||
|
return [("important", "=", True)]
|
||||||
|
|
||||||
@api.onchange('moderator')
|
@api.onchange('moderator')
|
||||||
def _onchange_moderator(self):
|
def _onchange_moderator(self):
|
||||||
self.participants |= self.moderator
|
self.participants |= self.moderator
|
||||||
|
|||||||
@@ -621,6 +621,12 @@ class TestFields(common.TransactionCase):
|
|||||||
message.important = True
|
message.important = True
|
||||||
self.assertIn(message, discussion.important_messages)
|
self.assertIn(message, discussion.important_messages)
|
||||||
|
|
||||||
|
# writing on very_important_messages should call its domain method
|
||||||
|
self.assertIn(message, discussion.very_important_messages)
|
||||||
|
discussion.write({'very_important_messages': [(5,)]})
|
||||||
|
self.assertFalse(discussion.very_important_messages)
|
||||||
|
self.assertFalse(message.exists())
|
||||||
|
|
||||||
|
|
||||||
class TestHtmlField(common.TransactionCase):
|
class TestHtmlField(common.TransactionCase):
|
||||||
|
|
||||||
|
|||||||
+5
-1
@@ -1099,6 +1099,8 @@ class Integer(Field):
|
|||||||
'group_operator': 'sum',
|
'group_operator': 'sum',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_description_group_operator = property(attrgetter('group_operator'))
|
||||||
|
|
||||||
def convert_to_column(self, value, record):
|
def convert_to_column(self, value, record):
|
||||||
return int(value or 0)
|
return int(value or 0)
|
||||||
|
|
||||||
@@ -1160,6 +1162,7 @@ class Float(Field):
|
|||||||
|
|
||||||
_related__digits = property(attrgetter('_digits'))
|
_related__digits = property(attrgetter('_digits'))
|
||||||
_description_digits = property(attrgetter('digits'))
|
_description_digits = property(attrgetter('digits'))
|
||||||
|
_description_group_operator = property(attrgetter('group_operator'))
|
||||||
|
|
||||||
def convert_to_column(self, value, record):
|
def convert_to_column(self, value, record):
|
||||||
result = float(value or 0.0)
|
result = float(value or 0.0)
|
||||||
@@ -1201,6 +1204,7 @@ class Monetary(Field):
|
|||||||
|
|
||||||
_related_currency_field = property(attrgetter('currency_field'))
|
_related_currency_field = property(attrgetter('currency_field'))
|
||||||
_description_currency_field = property(attrgetter('currency_field'))
|
_description_currency_field = property(attrgetter('currency_field'))
|
||||||
|
_description_group_operator = property(attrgetter('group_operator'))
|
||||||
|
|
||||||
def _setup_regular_base(self, model):
|
def _setup_regular_base(self, model):
|
||||||
super(Monetary, self)._setup_regular_base(model)
|
super(Monetary, self)._setup_regular_base(model)
|
||||||
@@ -1283,7 +1287,7 @@ class _String(Field):
|
|||||||
return self.translate(callback, value)
|
return self.translate(callback, value)
|
||||||
else:
|
else:
|
||||||
return value
|
return value
|
||||||
|
|
||||||
|
|
||||||
class Char(_String):
|
class Char(_String):
|
||||||
""" Basic string field, can be length-limited, usually displayed as a
|
""" Basic string field, can be length-limited, usually displayed as a
|
||||||
|
|||||||
@@ -443,7 +443,7 @@ class configmanager(object):
|
|||||||
for x in self.options['addons_path'].split(','))
|
for x in self.options['addons_path'].split(','))
|
||||||
|
|
||||||
self.options['init'] = opt.init and dict.fromkeys(opt.init.split(','), 1) or {}
|
self.options['init'] = opt.init and dict.fromkeys(opt.init.split(','), 1) or {}
|
||||||
self.options['demo'] = (self.options['init']
|
self.options['demo'] = (dict(self.options['init'])
|
||||||
if not self.options['without_demo'] else {})
|
if not self.options['without_demo'] else {})
|
||||||
self.options['update'] = opt.update and dict.fromkeys(opt.update.split(','), 1) or {}
|
self.options['update'] = opt.update and dict.fromkeys(opt.update.split(','), 1) or {}
|
||||||
self.options['translate_modules'] = opt.translate_modules and map(lambda m: m.strip(), opt.translate_modules.split(',')) or ['all']
|
self.options['translate_modules'] = opt.translate_modules and map(lambda m: m.strip(), opt.translate_modules.split(',')) or ['all']
|
||||||
|
|||||||
Reference in New Issue
Block a user