summaryrefslogtreecommitdiff
path: root/addons
diff options
context:
space:
mode:
authorChristophe Simonis <chs@odoo.com>2018-08-06 13:44:01 +0200
committerChristophe Simonis <chs@odoo.com>2018-08-06 13:44:01 +0200
commit427f717d1885aacdeebaa0ba5d8638829dfb88ff (patch)
treeab5a56cb306319a46011c532d6e8a7a4b74a7c04 /addons
parentfa618fcdd96885e8d1c95e4b00aa99840a58e140 (diff)
parent932b22994169fe6d00b1be23656949a94ac46ef0 (diff)
[MERGE] forward port branch saas-11.2 up to 932b2299416
Diffstat (limited to 'addons')
-rw-r--r--addons/account/models/account_payment.py15
-rw-r--r--addons/account_asset/models/account_asset.py4
-rw-r--r--addons/barcodes/README.rst2
-rw-r--r--addons/board/static/src/js/board_view.js2
-rw-r--r--addons/calendar/models/mail_activity.py2
-rw-r--r--addons/crm/models/crm_team.py24
-rw-r--r--addons/mass_mailing_event/models/__init__.py1
-rw-r--r--addons/mass_mailing_event/models/mass_mailing.py12
-rw-r--r--addons/product/views/product_views.xml10
-rw-r--r--addons/purchase/models/stock.py4
-rw-r--r--addons/sale_stock/tests/test_sale_stock.py4
-rw-r--r--addons/stock/models/procurement.py13
-rw-r--r--addons/stock/models/stock_move.py6
-rw-r--r--addons/web/static/src/js/views/kanban/kanban_column_progressbar.js6
-rw-r--r--addons/web/static/src/js/views/pivot/pivot_model.js4
-rw-r--r--addons/website_sale_digital/controllers/main.py2
16 files changed, 80 insertions, 31 deletions
diff --git a/addons/account/models/account_payment.py b/addons/account/models/account_payment.py
index ebfa4de4e5d..d782b91fee7 100644
--- a/addons/account/models/account_payment.py
+++ b/addons/account/models/account_payment.py
@@ -185,14 +185,15 @@ class account_abstract_payment(models.AbstractModel):
:param currency: If not specified, search a default currency on wizard/journal.
:return: The total amount to pay the invoices.
'''
- # Get the payment currency
- if not currency:
- currency = self.currency_id or self.journal_id.currency_id or self.journal_id.company_id.currency_id
# Get the payment invoices
if not invoices:
invoices = self.invoice_ids
+ # Get the payment currency
+ if not currency:
+ currency = self.currency_id or self.journal_id.currency_id or self.journal_id.company_id.currency_id or invoices and invoices[0].currency_id
+
# Avoid currency rounding issues by summing the amounts according to the company_currency_id before
total = 0.0
groups = groupby(invoices, lambda i: i.currency_id)
@@ -204,6 +205,14 @@ class account_abstract_payment(models.AbstractModel):
total += payment_currency.with_context(date=self.payment_date).compute(amount_total, currency)
return total
+ @api.onchange('journal_id')
+ def _onchange_journal(self):
+ res = super(account_register_payments, self)._onchange_journal()
+ active_ids = self._context.get('active_ids')
+ invoices = self.env['account.invoice'].browse(active_ids)
+ self.amount = abs(self._compute_payment_amount(invoices))
+ return res
+
class account_register_payments(models.TransientModel):
_name = "account.register.payments"
diff --git a/addons/account_asset/models/account_asset.py b/addons/account_asset/models/account_asset.py
index 440185d475f..85c2c659119 100644
--- a/addons/account_asset/models/account_asset.py
+++ b/addons/account_asset/models/account_asset.py
@@ -351,7 +351,9 @@ class AccountAssetAsset(models.Model):
def set_to_close(self):
move_ids = self._get_disposal_moves()
if move_ids:
- self._return_disposal_view(move_ids)
+ return self._return_disposal_view(move_ids)
+ # Fallback, as if we just clicked on the smartbutton
+ return self.open_entries()
@api.multi
def set_to_draft(self):
diff --git a/addons/barcodes/README.rst b/addons/barcodes/README.rst
index 696ab62fbc5..62739b10fe4 100644
--- a/addons/barcodes/README.rst
+++ b/addons/barcodes/README.rst
@@ -106,7 +106,7 @@ The purpose of this component is to listen to keypresses to detect barcodes, the
on core.bus inside a 'barcode_event'.
All keypress events are buffered until there is no more keypress during 50ms or a carriage return / tab is
inputted (because most barcode scanners use this as a suffix).
-If the buffered keys looks like a barcode (match the the regexp /.{3,}[\n\r\t]*), an event is triggered :
+If the buffered keys looks like a barcode, an event is triggered :
core.bus.trigger('barcode_scanned', barcode);
Otherwise, the keypresses are 'resent'. However, for security reasons, a keypress event programmatically
crafted doesn't trigger native browser behaviors. For this reason, BarcodeEvents doesn't intercept keypresses
diff --git a/addons/board/static/src/js/board_view.js b/addons/board/static/src/js/board_view.js
index aa0613e9785..b2d57903a3d 100644
--- a/addons/board/static/src/js/board_view.js
+++ b/addons/board/static/src/js/board_view.js
@@ -248,7 +248,7 @@ var BoardRenderer = FormRenderer.extend({
}
var view = _.find(action.views, function (descr) {
return descr[1] === params.viewType;
- });
+ }) || [false, params.viewType];
return self.loadViews(action.res_model, context, [view])
.then(function (viewsInfo) {
var viewInfo = viewsInfo[params.viewType];
diff --git a/addons/calendar/models/mail_activity.py b/addons/calendar/models/mail_activity.py
index 3efcea70a3b..0741658a087 100644
--- a/addons/calendar/models/mail_activity.py
+++ b/addons/calendar/models/mail_activity.py
@@ -24,7 +24,7 @@ class MailActivity(models.Model):
'default_res_id': self.env.context.get('default_res_id'),
'default_res_model': self.env.context.get('default_res_model'),
'default_name': self.summary,
- 'default_description': self.note and tools.html2plaintext(self.note) or '',
+ 'default_description': self.note and tools.html2plaintext(self.note).strip() or '',
'default_activity_ids': [(6, 0, self.ids)],
}
return action
diff --git a/addons/crm/models/crm_team.py b/addons/crm/models/crm_team.py
index e7ed3a61e08..f24f253d230 100644
--- a/addons/crm/models/crm_team.py
+++ b/addons/crm/models/crm_team.py
@@ -149,14 +149,22 @@ class Team(models.Model):
tree_view_id = self.env.ref('crm.crm_case_tree_view_oppor').id
form_view_id = self.env.ref('crm.crm_case_form_view_oppor').id
kanb_view_id = self.env.ref('crm.crm_case_kanban_view_leads').id
- action['views'] = [
- [kanb_view_id, 'kanban'],
- [tree_view_id, 'tree'],
- [form_view_id, 'form'],
- [False, 'graph'],
- [False, 'calendar'],
- [False, 'pivot']
- ]
+
+ mode_string = action.get('view_mode', '')
+ view_mode = mode_string.split(',') if mode_string else ['kanban', 'tree', 'form', 'graph', 'calendar', 'pivot']
+ dict_views = {
+ 'kanban': kanb_view_id,
+ 'tree': tree_view_id,
+ 'form': form_view_id,
+ 'graph': False,
+ 'calendar': False,
+ 'pivot': False,
+ }
+
+ # Sort the views according to the view mode of the action
+ # which can be modified via studio, or technical menu for that matter
+ action['views'] = [[dict_views.get(view_type, False), view_type] for view_type in view_mode]
+
action['context'] = action_context
return action
diff --git a/addons/mass_mailing_event/models/__init__.py b/addons/mass_mailing_event/models/__init__.py
index 80862024115..85b632eb8a3 100644
--- a/addons/mass_mailing_event/models/__init__.py
+++ b/addons/mass_mailing_event/models/__init__.py
@@ -2,3 +2,4 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from . import event
+from . import mass_mailing
diff --git a/addons/mass_mailing_event/models/mass_mailing.py b/addons/mass_mailing_event/models/mass_mailing.py
new file mode 100644
index 00000000000..a9849ad8deb
--- /dev/null
+++ b/addons/mass_mailing_event/models/mass_mailing.py
@@ -0,0 +1,12 @@
+from odoo import models, api
+
+
+class MassMailingCampaign(models.Model):
+ _inherit = "mail.mass_mailing"
+
+ @api.onchange('mailing_model_id', 'contact_list_ids')
+ def _onchange_model_and_list(self):
+ result = super(MassMailingCampaign, self)._onchange_model_and_list()
+ if self.mailing_model_name == 'event.registration' and self.mailing_domain == '[]':
+ self.mailing_domain = self.env.context.get('default_mailing_domain', '[]')
+ return result
diff --git a/addons/product/views/product_views.xml b/addons/product/views/product_views.xml
index c6c498927bd..246bd1d282c 100644
--- a/addons/product/views/product_views.xml
+++ b/addons/product/views/product_views.xml
@@ -73,6 +73,11 @@
</div>
</group>
</group>
+ <group name="description_internal">
+ <group string="Description for Internal" colspan="4">
+ <field name="description" nolabel="1" placeholder="This note is only for internal purposes."/>
+ </group>
+ </group>
</page>
<page string="Sales" attrs="{'invisible':[('sale_ok','=',False)]}" name="sales">
<div name="pricelist_item" groups="product.group_product_pricelist">
@@ -109,11 +114,6 @@
<field name="packaging_ids" nolabel="1" context="{'default_product_id': product_variant_id,'tree_view_ref':'product.product_packaging_tree_view', 'form_view_ref':'product.product_packaging_form_view'}"/>
</group>
</page>
- <group name="description_internal">
- <group string="Description for Internal">
- <field name="description" nolabel="1" placeholder="This note is only for internal purposes."/>
- </group>
- </group>
</notebook>
</sheet>
<div class="oe_chatter">
diff --git a/addons/purchase/models/stock.py b/addons/purchase/models/stock.py
index f1f98cdaa71..69b85c7b899 100644
--- a/addons/purchase/models/stock.py
+++ b/addons/purchase/models/stock.py
@@ -77,6 +77,10 @@ class StockMove(models.Model):
vals['purchase_line_id'] = self.purchase_line_id.id
return vals
+ def _clean_merged(self):
+ super(StockMove, self)._clean_merged()
+ self.write({'created_purchase_line_id': False})
+
def _action_done(self):
res = super(StockMove, self)._action_done()
self.mapped('purchase_line_id').sudo()._update_received_qty()
diff --git a/addons/sale_stock/tests/test_sale_stock.py b/addons/sale_stock/tests/test_sale_stock.py
index 399a6be021c..23cff0c7f8e 100644
--- a/addons/sale_stock/tests/test_sale_stock.py
+++ b/addons/sale_stock/tests/test_sale_stock.py
@@ -178,14 +178,14 @@ class TestSaleStock(TestSale):
# Check invoice
self.assertEqual(self.so.invoice_status, 'to invoice', 'Sale Stock: so invoice_status should be "to invoice" instead of "%s" after picking return' % self.so.invoice_status)
- self.assertAlmostEqual(self.so.order_line[0].qty_delivered, 3.0, 'Sale Stock: delivered quantity should be 3.0 instead of "%s" after picking return' % self.so.order_line[0].qty_delivered)
+ self.assertAlmostEqual(self.so.order_line[0].qty_delivered, 3.0, msg='Sale Stock: delivered quantity should be 3.0 instead of "%s" after picking return' % self.so.order_line[0].qty_delivered)
# let's do an invoice with refunds
adv_wiz = self.env['sale.advance.payment.inv'].with_context(active_ids=[self.so.id]).create({
'advance_payment_method': 'all',
})
adv_wiz.with_context(open_invoices=True).create_invoices()
self.inv_2 = self.so.invoice_ids.filtered(lambda r: r.state == 'draft')
- self.assertAlmostEqual(self.inv_2.invoice_line_ids[0].quantity, 2.0, 'Sale Stock: refund quantity on the invoice should be 2.0 instead of "%s".' % self.inv_2.invoice_line_ids[0].quantity)
+ self.assertAlmostEqual(self.inv_2.invoice_line_ids[0].quantity, 2.0, msg='Sale Stock: refund quantity on the invoice should be 2.0 instead of "%s".' % self.inv_2.invoice_line_ids[0].quantity)
self.assertEqual(self.so.invoice_status, 'no', 'Sale Stock: so invoice_status should be "no" instead of "%s" after invoicing the return' % self.so.invoice_status)
def test_03_sale_stock_delivery_partial(self):
diff --git a/addons/stock/models/procurement.py b/addons/stock/models/procurement.py
index fd08b362949..64929fa0084 100644
--- a/addons/stock/models/procurement.py
+++ b/addons/stock/models/procurement.py
@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
-from collections import defaultdict
+from collections import OrderedDict
from datetime import datetime
from dateutil.relativedelta import relativedelta
from odoo.tools.misc import split_every
@@ -318,9 +318,18 @@ class ProcurementGroup(models.Model):
orderpoints_noprefetch = orderpoints_noprefetch[1000:]
# Calculate groups that can be executed together
- location_data = defaultdict(lambda: dict(products=self.env['product.product'], orderpoints=self.env['stock.warehouse.orderpoint'], groups=list()))
+ location_data = OrderedDict()
+
+ def makedefault():
+ return {
+ 'products': self.env['product.product'],
+ 'orderpoints': self.env['stock.warehouse.orderpoint'],
+ 'groups': []
+ }
+
for orderpoint in orderpoints:
key = self._procurement_from_orderpoint_get_grouping_key([orderpoint.id])
+ location_data[key] = makedefault()
location_data[key]['products'] += orderpoint.product_id
location_data[key]['orderpoints'] += orderpoint
location_data[key]['groups'] = self._procurement_from_orderpoint_get_groups([orderpoint.id])
diff --git a/addons/stock/models/stock_move.py b/addons/stock/models/stock_move.py
index 48295f8b35e..88aede3ecf3 100644
--- a/addons/stock/models/stock_move.py
+++ b/addons/stock/models/stock_move.py
@@ -561,6 +561,10 @@ class StockMove(models.Model):
move.product_uom.id, move.restrict_partner_id.id, move.scrapped, move.origin_returned_move_id.id
]
+ def _clean_merged(self):
+ """Cleanup hook used when merging moves"""
+ self.write({'propagate': False})
+
def _merge_moves(self, merge_into=False):
""" This method will, for each move in `self`, go up in their linked picking and try to
find in their existing moves a candidate into which we can merge the move.
@@ -598,7 +602,7 @@ class StockMove(models.Model):
if moves_to_unlink:
# We are using propagate to False in order to not cancel destination moves merged in moves[0]
- moves_to_unlink.write({'propagate': False})
+ moves_to_unlink._clean_merged()
moves_to_unlink._action_cancel()
moves_to_unlink.sudo().unlink()
return (self | self.env['stock.move'].concat(*moves_to_merge)) - moves_to_unlink
diff --git a/addons/web/static/src/js/views/kanban/kanban_column_progressbar.js b/addons/web/static/src/js/views/kanban/kanban_column_progressbar.js
index b597ccf1c60..7e1f16c9fb0 100644
--- a/addons/web/static/src/js/views/kanban/kanban_column_progressbar.js
+++ b/addons/web/static/src/js/views/kanban/kanban_column_progressbar.js
@@ -142,6 +142,7 @@ var KanbanColumnProgressBar = Widget.extend({
// Display and animate the progress bars
var barNumber = 0;
+ var barMinWidth = 6; // In %
_.each(self.colors, function (val, key) {
var $bar = self.$bars[val];
var count = self.subgroupCounts && self.subgroupCounts[key] || 0;
@@ -168,16 +169,15 @@ var KanbanColumnProgressBar = Widget.extend({
$bar.addClass('o_bar_has_records');
// Make sure every bar that has records has some space
// and that everything adds up to 100%
- var minWidth = 6*barNumber;
- var maxWidth = 100 - minWidth;
+ var maxWidth = 100 - barMinWidth * barNumber;
self.$('.progress-bar.o_bar_has_records').css('max-width', maxWidth + '%');
- self.$('.progress-bar.o_bar_has_records').css('min-width', minWidth + '%');
$bar.css('width', (count * 100 / self.groupCount) + '%');
barNumber++;
} else {
$bar.css('width', '');
}
});
+ this.$('.progress-bar.o_bar_has_records').css('min-width', barMinWidth + '%');
// Display and animate the counter number
var start = this.prevTotalCounterValue;
diff --git a/addons/web/static/src/js/views/pivot/pivot_model.js b/addons/web/static/src/js/views/pivot/pivot_model.js
index b45f7a9ffdf..54f469bbc19 100644
--- a/addons/web/static/src/js/views/pivot/pivot_model.js
+++ b/addons/web/static/src/js/views/pivot/pivot_model.js
@@ -541,7 +541,7 @@ var PivotModel = AbstractModel.extend({
_loadData: function () {
var self = this;
var groupBys = [];
- var rowGroupBys = this.data.groupedBy.length ? this.data.groupedBy : this.initialRowGroupBys;
+ var rowGroupBys = !_.isEmpty(this.data.groupedBy) ? this.data.groupedBy : this.initialRowGroupBys;
var colGroupBys = this.data.colGroupBys;
var measures = _.map(this.data.measures, function(measure) {
if (self.fields[measure].type === 'many2one') {
@@ -624,7 +624,7 @@ var PivotModel = AbstractModel.extend({
});
var index = 0;
- var rowGroupBys = this.data.groupedBy.length ? this.data.groupedBy : this.initialRowGroupBys;
+ var rowGroupBys = !_.isEmpty(this.data.groupedBy) ? this.data.groupedBy : this.initialRowGroupBys;
var colGroupBys = this.data.colGroupBys;
var datapt, row, col, attrs, cell_value;
var main_row_header, main_col_header;
diff --git a/addons/website_sale_digital/controllers/main.py b/addons/website_sale_digital/controllers/main.py
index c53f27d7336..39d0492260a 100644
--- a/addons/website_sale_digital/controllers/main.py
+++ b/addons/website_sale_digital/controllers/main.py
@@ -44,7 +44,7 @@ class WebsiteSaleDigital(CustomerPortal):
product_id = product.id
template = product.product_tmpl_id
att = Attachment.search_read(
- domain=['|', '&', ('res_model', '=', product._name), ('res_id', '=', product_id), '&', ('res_model', '=', template._name), '&', ('res_id', '=', template.id), ('product_downloadable', '=', True)],
+ domain=['|', '&', ('res_model', '=', product._name), ('res_id', '=', product_id), '&', ('res_model', '=', template._name), ('res_id', '=', template.id), ('product_downloadable', '=', True)],
fields=['name', 'write_date'],
order='write_date desc',
)