Skip to content

Commit

Permalink
[MERGE] forward port branch saas-12.1 up to b119300
Browse files Browse the repository at this point in the history
  • Loading branch information
beledouxdenis committed May 2, 2019
2 parents 27eb8ba + b119300 commit fd0a100
Show file tree
Hide file tree
Showing 117 changed files with 3,007 additions and 338 deletions.
2 changes: 2 additions & 0 deletions addons/account/__init__.py
Expand Up @@ -45,6 +45,8 @@ def _auto_install_l10n(cr, registry):
'PL', 'PT', 'RO', 'SI', 'TR', 'UK', 'VE', 'VN'
]:
module_list.append('base_vat')
if country_code == 'MX':
module_list.append('l10n_mx_edi')

# European countries will be using SEPA
europe = env.ref('base.europe', raise_if_not_found=False)
Expand Down
2 changes: 1 addition & 1 deletion addons/account/models/account_invoice.py
Expand Up @@ -743,7 +743,7 @@ def message_new(self, msg_dict, custom_values=None):
# Subscribe internal users on the newly created bill
partners = self.env['res.partner'].browse(seen_partner_ids)
is_internal = lambda p: (p.user_ids and
all(p.user_ids.mapped(lambda u: u.user_has_groups('base.group_user'))))
all(p.user_ids.mapped(lambda u: u.has_group('base.group_user'))))
partners_to_subscribe = partners.filtered(is_internal)
if partners_to_subscribe:
invoice.message_subscribe([p.id for p in partners_to_subscribe])
Expand Down
10 changes: 10 additions & 0 deletions addons/account/models/account_payment.py
Expand Up @@ -87,6 +87,16 @@ def default_get(self, fields):
# Check all invoices have the same currency
if any(inv.currency_id != invoices[0].currency_id for inv in invoices):
raise UserError(_("In order to pay multiple invoices at once, they must use the same currency."))
# Check if, in batch payments, there are not negative invoices and positive invoices
dtype = invoices[0].type
for inv in invoices[1:]:
if inv.type != dtype:
if ((dtype == 'in_refund' and inv.type == 'in_invoice') or
(dtype == 'in_invoice' and inv.type == 'in_refund')):
raise UserError(_("You cannot register payments for vendor bills and supplier refunds at the same time."))
if ((dtype == 'out_refund' and inv.type == 'out_invoice') or
(dtype == 'out_invoice' and inv.type == 'out_refund')):
raise UserError(_("You cannot register payments for customer invoices and credit notes at the same time."))

# Look if we are mixin multiple commercial_partner or customer invoices with vendor bills
multi = any(inv.commercial_partner_id != invoices[0].commercial_partner_id
Expand Down
4 changes: 2 additions & 2 deletions addons/account/models/res_users.py
Expand Up @@ -14,8 +14,8 @@ def _check_one_user_type(self):
super(Users, self)._check_one_user_type()

users_with_both_groups = self.filtered(lambda user:
user.user_has_groups('account.group_show_line_subtotals_tax_included') and
user.user_has_groups('account.group_show_line_subtotals_tax_excluded')
user.has_group('account.group_show_line_subtotals_tax_included') and
user.has_group('account.group_show_line_subtotals_tax_excluded')
)
if users_with_both_groups:
names = ", ".join(users_with_both_groups.mapped('name'))
Expand Down
11 changes: 11 additions & 0 deletions addons/account/security/account_security.xml
Expand Up @@ -59,6 +59,17 @@
<field name="category_id" ref="base.module_category_hidden"/>
</record>

<record id="account_analytic_line_rule_billing_user" model="ir.rule">
<field name="name">account.analytic.line.billing.user</field>
<field name="model_id" ref="analytic.model_account_analytic_line"/>
<field name="domain_force">[(1, '=', 1)]</field>
<field name="groups" eval="[(4, ref('account.group_account_invoice'))]"/>
<field name="perm_create" eval="1"/>
<field name="perm_write" eval="1"/>
<field name="perm_unlink" eval="1"/>
<field name="perm_read" eval="0"/>
</record>

</data>


Expand Down
9 changes: 9 additions & 0 deletions addons/account/static/src/scss/account_journal_dashboard.scss
Expand Up @@ -36,6 +36,15 @@
width: 450px;
}
}
.o_kanban_group {
&:not(.o_column_folded) {
width: 450px + 2*$o-kanban-group-padding;

@include media-breakpoint-down(sm) {
width: 100%;
}
}
}
}

// Style for the widget "dashboard_graph"
Expand Down
2 changes: 1 addition & 1 deletion addons/account/views/account_portal_templates.xml
Expand Up @@ -83,7 +83,7 @@
<div class="row mt16 o_portal_invoice_sidebar">
<!-- Sidebar -->
<t t-call="portal.portal_record_sidebar">
<t t-set="classes" t-value="'col-12 col-lg flex-lg-grow-0 d-print-none'"/>
<t t-set="classes" t-value="'col-lg-auto d-print-none'"/>
<t t-set="title">
<h2 class="mb-0">
<b t-if="invoice.residual > 0" t-field="invoice.residual"/>
Expand Down
4 changes: 2 additions & 2 deletions addons/auth_signup/controllers/main.py
Expand Up @@ -44,7 +44,7 @@ def web_auth_signup(self, *args, **kw):
lang=user_sudo.lang,
auth_login=werkzeug.url_encode({'auth_login': user_sudo.email}),
).send_mail(user_sudo.id, force_send=True)
return super(AuthSignupHome, self).web_login(*args, **kw)
return self.web_login(*args, **kw)
except UserError as e:
qcontext['error'] = e.name or e.value
except (SignupError, AssertionError) as e:
Expand All @@ -69,7 +69,7 @@ def web_auth_reset_password(self, *args, **kw):
try:
if qcontext.get('token'):
self.do_signup(qcontext)
return super(AuthSignupHome, self).web_login(*args, **kw)
return self.web_login(*args, **kw)
else:
login = qcontext.get('login')
assert login, _("No login provided.")
Expand Down
6 changes: 4 additions & 2 deletions addons/base_import_module/models/ir_module.py
Expand Up @@ -38,6 +38,8 @@ def _import_module(self, module, path, force=False):
installed_mods = [m.name for m in known_mods if m.state == 'installed']

terp = load_information_from_description_file(module, mod_path=path)
if not terp:
return False
values = self.get_values_from_terp(terp)
if 'version' in terp:
values['latest_version'] = terp['version']
Expand Down Expand Up @@ -133,8 +135,8 @@ def import_zipfile(self, module_file, force=False):
try:
# assert mod_name.startswith('theme_')
path = opj(module_dir, mod_name)
self._import_module(mod_name, path, force=force)
success.append(mod_name)
if self._import_module(mod_name, path, force=force):
success.append(mod_name)
except Exception as e:
_logger.exception('Error while importing module')
errors[mod_name] = exception_to_unicode(e)
Expand Down
2 changes: 1 addition & 1 deletion addons/base_setup/data/base_setup_data.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data noupdate="1">
<record model="ir.config_parameter" id="show_effect">
<record model="ir.config_parameter" id="show_effect" forcecreate="False">
<field name="key">base_setup.show_effect</field>
<field name="value">True</field>
</record>
Expand Down
12 changes: 9 additions & 3 deletions addons/board/static/src/js/add_to_board_menu.js
Expand Up @@ -86,12 +86,18 @@ var AddToBoardMenu = Widget.extend({
var context = new Context(this.action.context);
context.add(searchQuery.context);
context.add({
group_by: pyUtils.eval('groupbys', searchQuery.groupBys || [])
group_by: searchQuery.groupBy,
orderedBy: searchQuery.orderedBy,
});

this.trigger_up('get_controller_query_params', {
callback: function (controllerContext) {
context.add(controllerContext);
callback: function (controllerQueryParams) {
var queryContext = controllerQueryParams.context;
var allContext = _.extend(
_.omit(controllerQueryParams, ['context']),
queryContext
);
context.add(allContext);
}
});

Expand Down
3 changes: 2 additions & 1 deletion addons/board/static/src/js/board_view.js
Expand Up @@ -272,7 +272,8 @@ var BoardRenderer = FormRenderer.extend({
searchQuery: {
context: context,
domain: domain,
groupBy: context.group_by || [],
groupBy: typeof context.group_by === 'string' && context.group_by ? [context.group_by] : context.group_by || [],
orderedBy: context.orderedBy || [],
},
withControlPanel: false,
});
Expand Down
82 changes: 79 additions & 3 deletions addons/board/static/tests/dashboard_tests.js
Expand Up @@ -109,7 +109,7 @@ QUnit.test('display the no content helper', function (assert) {
});

QUnit.test('basic functionality, with one sub action', function (assert) {
assert.expect(25);
assert.expect(26);

var form = createView({
View: BoardView,
Expand All @@ -118,7 +118,7 @@ QUnit.test('basic functionality, with one sub action', function (assert) {
arch: '<form string="My Dashboard">' +
'<board style="2-1">' +
'<column>' +
'<action context="{}" view_mode="list" string="ABC" name="51" domain="[[\'foo\', \'!=\', \'False\']]"></action>' +
'<action context="{&quot;orderedBy&quot;: [{&quot;name&quot;: &quot;foo&quot;, &quot;asc&quot;: True}]}" view_mode="list" string="ABC" name="51" domain="[[\'foo\', \'!=\', \'False\']]"></action>' +
'</column>' +
'</board>' +
'</form>',
Expand All @@ -132,6 +132,12 @@ QUnit.test('basic functionality, with one sub action', function (assert) {
}
if (route === '/web/dataset/search_read') {
assert.deepEqual(args.domain, [['foo', '!=', 'False']], "the domain should be passed");
assert.deepEqual(args.context.orderedBy, [{
'name': 'foo',
'asc': true,
}],
'orderedBy is present in the search read when specified on the custom action'
);
}
if (route === '/web/view/edit_custom') {
assert.step('edit custom');
Expand Down Expand Up @@ -686,7 +692,19 @@ QUnit.test('dashboard intercepts custom events triggered by sub controllers', fu
});

QUnit.test('save actions to dashboard', function (assert) {
assert.expect(3);
assert.expect(6);

testUtils.patch(ListController, {
getOwnedQueryParams: function () {
var result = this._super.apply(this, arguments);
result.context = {
'fire': 'on the bayou',
}
return result;
}
});

this.data['partner'].fields.foo.sortable = true;

var actionManager = createActionManager({
data: this.data,
Expand All @@ -696,6 +714,16 @@ QUnit.test('save actions to dashboard', function (assert) {
},
mockRPC: function (route, args) {
if (route === '/board/add_to_dashboard') {
assert.deepEqual(args.context_to_save.group_by, ['foo'],
'The group_by should have been saved');
assert.deepEqual(args.context_to_save.orderedBy,
[{
name: 'foo',
asc: true,
}],
'The orderedBy should have been saved');
assert.strictEqual(args.context_to_save.fire, 'on the bayou',
'The context of a controller should be passed and flattened');
assert.strictEqual(args.action_id, 1,
"should save the correct action");
assert.strictEqual(args.view_mode, 'list',
Expand All @@ -716,12 +744,22 @@ QUnit.test('save actions to dashboard', function (assert) {
assert.containsOnce(actionManager, '.o_list_view',
"should display the list view");

// Sort the list
testUtils.dom.click($('.o_column_sortable'));

// Group It
testUtils.dom.click($('.o_search_options .o_dropdown button:contains(Group By)'));
testUtils.dom.click($('.o_search_options .o_group_by_menu button'));
testUtils.dom.click($('.o_search_options .o_group_by_menu button.o_apply_group'));

// add this action to dashboard
testUtils.dom.click($('.o_search_options .o_dropdown button:contains(Favorites)'));
testUtils.dom.click($('.o_add_to_board.o_menu_header'));
testUtils.fields.editInput($('input.o_add_to_board_input'), 'a name');
testUtils.dom.click($('.o_add_to_board_confirm_button'));

testUtils.unpatch(ListController);

actionManager.destroy();
});

Expand Down Expand Up @@ -911,6 +949,44 @@ QUnit.test("Dashboard should use correct groupby", function (assert) {
form.destroy();
});

QUnit.test("Dashboard should use correct groupby when defined as a string of one field", function (assert) {
assert.expect(1);
var form = createView({
View: BoardView,
model: 'board',
data: this.data,
arch: '<form string="My Dashboard">' +
'<board style="2-1">' +
'<column>' +
'<action context="{\'group_by\': \'bar\'}" string="ABC" name="51"></action>' +
'</column>' +
'</board>' +
'</form>',
mockRPC: function (route, args) {
if (args.method === 'read_group') {
assert.deepEqual(args.kwargs.groupby, ['bar'],
'user defined groupby should have precedence on action groupby');
}
if (route === '/web/action/load') {
return $.when({
res_model: 'partner',
context: {
group_by: 'some_field',
},
views: [[4, 'list']],
});
}
return this._super.apply(this, arguments);
},
archs: {
'partner,4,list':
'<list string="Partner"><field name="foo"/></list>',
},
});

form.destroy();
});

QUnit.test('click on a cell of pivot view inside dashboard', function (assert) {
assert.expect(3);

Expand Down
3 changes: 3 additions & 0 deletions addons/calendar/data/mail_data.xml
Expand Up @@ -8,6 +8,7 @@
<field name="email_from">${object.event_id.user_id.email or ''}</field>
<field name="email_to" >${('' if object.partner_id and object.partner_id.email and object.partner_id.email==object.email else object.email|safe)}</field>
<field name="partner_to">${object.partner_id and object.partner_id.email and object.partner_id.email==object.email and object.partner_id.id or False }</field>
<field name="lang">${object.partner_id.lang}</field>
<field name="body_html" type="html">
<div>
% set colors = {'needsAction': 'grey', 'accepted': 'green', 'tentative': '#FFFF00', 'declined': 'red'}
Expand Down Expand Up @@ -91,6 +92,7 @@
<field name="email_from">${object.event_id.user_id.email or ''}</field>
<field name="email_to" >${('' if object.partner_id and object.partner_id.email and object.partner_id.email==object.email else object.email|safe)}</field>
<field name="partner_to">${object.partner_id and object.partner_id.email and object.partner_id.email==object.email and object.partner_id.id or False }</field>
<field name="lang">${object.partner_id.lang}</field>
<field name="body_html" type="html">
<div>
% set colors = {'needsAction': 'grey', 'accepted': 'green', 'tentative': '#FFFF00', 'declined': 'red'}
Expand Down Expand Up @@ -174,6 +176,7 @@
<field name="email_from">${object.event_id.user_id.email or ''}</field>
<field name="email_to" >${('' if object.partner_id and object.partner_id.email and object.partner_id.email==object.email else object.email|safe)}</field>
<field name="partner_to">${object.partner_id and object.partner_id.email and object.partner_id.email==object.email and object.partner_id.id or False }</field>
<field name="lang">${object.partner_id.lang}</field>
<field name="body_html" type="html">
<div>
% set colors = {'needsAction': 'grey', 'accepted': 'green', 'tentative': '#FFFF00', 'declined': 'red'}
Expand Down
3 changes: 2 additions & 1 deletion addons/calendar/models/mail_message.py
Expand Up @@ -26,6 +26,7 @@ def _search(self, args, offset=0, limit=None, order=None, count=False, access_ri
def _find_allowed_model_wise(self, doc_model, doc_dict):
if doc_model == 'calendar.event':
order = self._context.get('order', self.env[doc_model]._order)
for virtual_id in self.env[doc_model].browse(doc_dict).get_recurrent_ids([], order=order):
records = self.env[doc_model].search([('id', 'in', list(doc_dict))])
for virtual_id in records.get_recurrent_ids([], order=order):
doc_dict.setdefault(virtual_id, doc_dict[get_real_ids(virtual_id)])
return super(Message, self)._find_allowed_model_wise(doc_model, doc_dict)
6 changes: 3 additions & 3 deletions addons/crm/data/crm_data.xml
@@ -1,15 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data noupdate="1">
<record id="sales_team.salesteam_website_sales" model="crm.team">
<record id="sales_team.salesteam_website_sales" model="crm.team" forcecreate="False">
<field name="use_opportunities" eval="False"/>
</record>

<record id="sales_team.pos_sales_team" model="crm.team">
<record id="sales_team.pos_sales_team" model="crm.team" forcecreate="False">
<field name="use_opportunities" eval="False"/>
</record>

<record id="sales_team.ebay_sales_team" model="crm.team">
<record id="sales_team.ebay_sales_team" model="crm.team" forcecreate="False">
<field name="use_opportunities" eval="False"/>
</record>

Expand Down
2 changes: 1 addition & 1 deletion addons/crm/data/crm_demo.xml
Expand Up @@ -5,7 +5,7 @@
<field name="groups_id" eval="[(4,ref('sales_team.group_sale_salesman'))]"/>
</record>

<record id="sales_team.team_sales_department" model="crm.team">
<record id="sales_team.team_sales_department" model="crm.team" forcecreate="False">
<field name="alias_name">sales</field>
<field name="alias_user_id" ref="base.user_admin"/>
<field name="company_id" eval="False"/>
Expand Down
8 changes: 7 additions & 1 deletion addons/delivery/models/sale_order.py
Expand Up @@ -102,9 +102,15 @@ def _create_delivery_line(self, carrier, price_unit, price_unit_in_description=F
taxes_ids = self.fiscal_position_id.map_tax(taxes, carrier.product_id, self.partner_id).ids

# Create the sales order line
carrier_with_partner_lang = carrier.with_context(lang=self.partner_id.lang)
if carrier_with_partner_lang.product_id.description_sale:
so_description = '%s: %s' % (carrier_with_partner_lang.name,
carrier_with_partner_lang.product_id.description_sale)
else:
so_description = carrier_with_partner_lang.name
values = {
'order_id': self.id,
'name': carrier.with_context(lang=self.partner_id.lang).name,
'name': so_description,
'product_uom_qty': 1,
'product_uom': carrier.product_id.uom_id.id,
'product_id': carrier.product_id.id,
Expand Down
2 changes: 1 addition & 1 deletion addons/delivery/views/delivery_view.xml
Expand Up @@ -94,7 +94,7 @@
<label for="free_over"/>
</div>
<field nolabel="1" name="amount" attrs="{'required':[('free_over','!=', False)], 'invisible':[('free_over','=', False)]}"/>
<field name="product_id" context="{'default_type': 'service', 'sale_ok': False, 'purchase_ok': False}" />
<field name="product_id" context="{'default_type': 'service', 'default_sale_ok': False, 'default_purchase_ok': False}" />
<field name="company_id" groups="base.group_multi_company"/>
</group>
</group>
Expand Down

0 comments on commit fd0a100

Please sign in to comment.