diff --git a/addons/account/account_invoice_view.xml b/addons/account/account_invoice_view.xml
index c70ef41c0f2..6c9834a0cb1 100644
--- a/addons/account/account_invoice_view.xml
+++ b/addons/account/account_invoice_view.xml
@@ -145,6 +145,7 @@
+
@@ -504,6 +505,17 @@
+
+ Invoices
+ account.invoice
+ form
+ tree,form,calendar,graph
+
+ [('type','in', ['out_invoice', 'out_refund']), ('state', 'not in', ['draft', 'cancel'])]
+ {'type':False}
+
+
+
Pending Invoice
account.invoice
diff --git a/addons/account/account_move_line.py b/addons/account/account_move_line.py
index 348d0ced3bc..dcdbd9da785 100644
--- a/addons/account/account_move_line.py
+++ b/addons/account/account_move_line.py
@@ -306,7 +306,8 @@ class account_move_line(osv.osv):
if not id:
return []
ml = self.browse(cr, uid, id, context=context)
- return map(lambda x: x.id, ml.move_id.line_id)
+ domain = (context or {}).get('on_write_domain', [])
+ return self.pool.get('account.move.line').search(cr, uid, domain + [['id', 'in', [l.id for l in ml.move_id.line_id]]], context=context)
def _balance(self, cr, uid, ids, name, arg, context=None):
if context is None:
diff --git a/addons/account/partner.py b/addons/account/partner.py
index 2b9cb47bb63..4ca4abde46e 100644
--- a/addons/account/partner.py
+++ b/addons/account/partner.py
@@ -242,7 +242,7 @@ class res_partner(osv.osv):
result = {}
account_invoice_report = self.pool.get('account.invoice.report')
for partner in self.browse(cr, uid, ids, context=context):
- domain = [('partner_id', 'child_of', partner.id)]
+ domain = [('partner_id', 'child_of', partner.id), ('state', 'not in', ['draft', 'cancel'])]
invoice_ids = account_invoice_report.search(cr, uid, domain, context=context)
invoices = account_invoice_report.browse(cr, uid, invoice_ids, context=context)
result[partner.id] = sum(inv.user_currency_price_total for inv in invoices)
diff --git a/addons/account/partner_view.xml b/addons/account/partner_view.xml
index 9c85d091a71..dd99a854135 100644
--- a/addons/account/partner_view.xml
+++ b/addons/account/partner_view.xml
@@ -77,7 +77,7 @@
class="oe_stat_button"
id="invoice_button"
icon="fa-pencil-square-o"
- name="%(account.action_invoice_tree)d"
+ name="%(account.action_invoice_refund_out_tree)d"
attrs="{'invisible': [('customer', '=', False)]}"
context="{'search_default_partner_id': active_id,'default_partner_id': active_id}">
Invoiced
diff --git a/addons/account/static/src/xml/account_bank_statement_reconciliation.xml b/addons/account/static/src/xml/account_bank_statement_reconciliation.xml
index 6140b492699..dd1a5f8a0bf 100644
--- a/addons/account/static/src/xml/account_bank_statement_reconciliation.xml
+++ b/addons/account/static/src/xml/account_bank_statement_reconciliation.xml
@@ -152,6 +152,7 @@
| Description | |
| Amount | () |
| Account | |
+ | Note | |
diff --git a/addons/account_payment/account_payment_view.xml b/addons/account_payment/account_payment_view.xml
index c4088a62ee6..8d2eaadfa31 100644
--- a/addons/account_payment/account_payment_view.xml
+++ b/addons/account_payment/account_payment_view.xml
@@ -132,8 +132,8 @@
-
-
+
+
diff --git a/addons/base_import/models.py b/addons/base_import/models.py
index ab2ec8b72ce..9157b9b5920 100644
--- a/addons/base_import/models.py
+++ b/addons/base_import/models.py
@@ -157,7 +157,7 @@ class ir_import(orm.TransientModel):
for field in fields:
# FIXME: should match all translations & original
# TODO: use string distance (levenshtein? hamming?)
- if header == field['name'] \
+ if header.lower() == field['name'].lower() \
or header.lower() == field['string'].lower():
return [field]
diff --git a/addons/google_account/__init__.py b/addons/google_account/__init__.py
index 47544bfd347..c16913ab79c 100644
--- a/addons/google_account/__init__.py
+++ b/addons/google_account/__init__.py
@@ -20,3 +20,5 @@
##############################################################################
import google_account
import controllers
+
+from .google_account import TIMEOUT # noqa
\ No newline at end of file
diff --git a/addons/google_account/google_account.py b/addons/google_account/google_account.py
index db137b087e6..2cc56d0cba4 100644
--- a/addons/google_account/google_account.py
+++ b/addons/google_account/google_account.py
@@ -15,6 +15,7 @@ import simplejson
import logging
_logger = logging.getLogger(__name__)
+TIMEOUT = 20
class google_service(osv.osv_memory):
_name = 'google.service'
@@ -31,7 +32,7 @@ class google_service(osv.osv_memory):
data = werkzeug.url_encode(data)
try:
req = urllib2.Request("https://accounts.google.com/o/oauth2/token", data, headers)
- content = urllib2.urlopen(req).read()
+ content = urllib2.urlopen(req, timeout=TIMEOUT).read()
except urllib2.HTTPError:
error_msg = "Something went wrong during your token generation. Maybe your Authorization Code is invalid or already expired"
raise self.pool.get('res.config.settings').get_config_warning(cr, _(error_msg), context=context)
@@ -148,7 +149,7 @@ class google_service(osv.osv_memory):
raise ('Method not supported [%s] not in [GET, POST, PUT, PATCH or DELETE]!' % (type))
req.get_method = lambda: type.upper()
- request = urllib2.urlopen(req)
+ request = urllib2.urlopen(req, timeout=TIMEOUT)
status = request.getcode()
if int(status) in (204, 404): # Page not found, no response
diff --git a/addons/google_drive/google_drive.py b/addons/google_drive/google_drive.py
index 019ea745ce6..8bfc6fd7697 100644
--- a/addons/google_drive/google_drive.py
+++ b/addons/google_drive/google_drive.py
@@ -20,6 +20,7 @@
import logging
from openerp import SUPERUSER_ID
+from openerp.addons.google_account import TIMEOUT
from openerp.osv import fields, osv
from openerp.tools.translate import _
from openerp.exceptions import UserError
@@ -82,7 +83,7 @@ class config(osv.Model):
headers = {"Content-type": "application/x-www-form-urlencoded", "Accept-Encoding": "gzip, deflate"}
try:
req = urllib2.Request('https://accounts.google.com/o/oauth2/token', data, headers)
- content = urllib2.urlopen(req).read()
+ content = urllib2.urlopen(req, timeout=TIMEOUT).read()
except urllib2.HTTPError:
if user_is_admin:
model, action_id = self.pool['ir.model.data'].get_object_reference(cr, uid, 'base_setup', 'action_general_configuration')
@@ -102,7 +103,7 @@ class config(osv.Model):
headers = {"Content-type": "application/x-www-form-urlencoded", "Accept-Encoding": "gzip, deflate"}
try:
req = urllib2.Request(request_url, None, headers)
- parents = urllib2.urlopen(req).read()
+ parents = urllib2.urlopen(req, timeout=TIMEOUT).read()
except urllib2.HTTPError:
raise UserError(_("The Google Template cannot be found. Maybe it has been deleted."))
parents_dict = json.loads(parents)
@@ -114,7 +115,7 @@ class config(osv.Model):
data_json = json.dumps(data)
# resp, content = Http().request(request_url, "POST", data_json, headers)
req = urllib2.Request(request_url, data_json, headers)
- content = urllib2.urlopen(req).read()
+ content = urllib2.urlopen(req, timeout=TIMEOUT).read()
content = json.loads(content)
res = {}
if content.get('alternateLink'):
@@ -129,7 +130,7 @@ class config(osv.Model):
data = {'role': 'writer', 'type': 'anyone', 'value': '', 'withLink': True}
try:
req = urllib2.Request(request_url, json.dumps(data), headers)
- urllib2.urlopen(req)
+ urllib2.urlopen(req, timeout=TIMEOUT)
except urllib2.HTTPError:
raise self.pool.get('res.config.settings').get_config_warning(cr, _("The permission 'reader' for 'anyone with the link' has not been written on the document"), context=context)
user = self.pool['res.users'].browse(cr, uid, uid, context=context)
@@ -137,10 +138,10 @@ class config(osv.Model):
data = {'role': 'writer', 'type': 'user', 'value': user.email}
try:
req = urllib2.Request(request_url, json.dumps(data), headers)
- urllib2.urlopen(req)
+ urllib2.urlopen(req, timeout=TIMEOUT)
except urllib2.HTTPError:
pass
- return res
+ return res
def get_google_drive_config(self, cr, uid, res_model, res_id, context=None):
'''
diff --git a/addons/google_spreadsheet/google_spreadsheet.py b/addons/google_spreadsheet/google_spreadsheet.py
index df63ac5f632..2d062c9a9d2 100644
--- a/addons/google_spreadsheet/google_spreadsheet.py
+++ b/addons/google_spreadsheet/google_spreadsheet.py
@@ -27,7 +27,7 @@ import werkzeug.urls
import urllib2
from openerp.osv import osv
-from openerp import SUPERUSER_ID
+from openerp.addons.google_account import TIMEOUT
_logger = logging.getLogger(__name__)
@@ -92,7 +92,7 @@ class config(osv.osv):
'https://spreadsheets.google.com/feeds/cells/%s/od6/private/full/batch?%s' % (spreadsheet_key, werkzeug.url_encode({'v': 3, 'access_token': access_token})),
data=request,
headers={'content-type': 'application/atom+xml', 'If-Match': '*'})
- urllib2.urlopen(req)
+ urllib2.urlopen(req, timeout=TIMEOUT)
except (urllib2.HTTPError, urllib2.URLError):
_logger.warning("An error occured while writting the formula on the Google Spreadsheet.")
diff --git a/addons/mrp/mrp.py b/addons/mrp/mrp.py
index 2fb1e73f560..4f76185a3d5 100644
--- a/addons/mrp/mrp.py
+++ b/addons/mrp/mrp.py
@@ -369,6 +369,7 @@ class mrp_bom(osv.osv):
class mrp_bom_line(osv.osv):
_name = 'mrp.bom.line'
_order = "sequence"
+ _rec_name = "product_id"
def _get_child_bom_lines(self, cr, uid, ids, field_name, arg, context=None):
"""If the BOM line refers to a BOM, return the ids of the child BOM lines"""
diff --git a/addons/point_of_sale/point_of_sale.py b/addons/point_of_sale/point_of_sale.py
index bd05695fbe6..a5c343fc9a9 100644
--- a/addons/point_of_sale/point_of_sale.py
+++ b/addons/point_of_sale/point_of_sale.py
@@ -1008,8 +1008,8 @@ class pos_order(osv.osv):
inv_line['price_unit'] = line.price_unit
inv_line['discount'] = line.discount
inv_line['name'] = inv_name
- if line.tax_ids:
- inv_line['invoice_line_tax_id'] = [(6, 0, [x.id for x in line.tax_ids])]
+ if inv_line['invoice_line_tax_id']:
+ inv_line['invoice_line_tax_id'] = [(6, 0, inv_line['invoice_line_tax_id'])]
inv_line_ref.create(cr, uid, inv_line, context=context)
inv_ref.button_reset_taxes(cr, uid, [inv_id], context=context)
self.signal_workflow(cr, uid, [order.id], 'invoice')
diff --git a/addons/web/static/src/js/view_list_editable.js b/addons/web/static/src/js/view_list_editable.js
index f5bda4bce11..5b6d4015655 100644
--- a/addons/web/static/src/js/view_list_editable.js
+++ b/addons/web/static/src/js/view_list_editable.js
@@ -433,7 +433,8 @@
var self = this;
var on_write_callback = self.fields_view.arch.attrs.on_write;
if (!on_write_callback) { return $.when(); }
- return this.dataset.call(on_write_callback, [source_record.get('id')])
+ var context = new instance.web.CompoundContext(self.dataset.get_context(), {'on_write_domain': self.dataset.domain}).eval();
+ return this.dataset.call(on_write_callback, [source_record.get('id'), context])
.then(function (ids) {
return $.when.apply(
null, _(ids).map(
diff --git a/addons/web_kanban/static/src/js/kanban.js b/addons/web_kanban/static/src/js/kanban.js
index 3bc5684486a..b04f8d7a6f1 100644
--- a/addons/web_kanban/static/src/js/kanban.js
+++ b/addons/web_kanban/static/src/js/kanban.js
@@ -766,12 +766,12 @@ instance.web_kanban.KanbanGroup = instance.web.Widget.extend({
},
do_show_more: function(evt) {
var self = this;
- var ids = self.view.dataset.ids.splice(0);
+ var ids = self.view.dataset.ids.slice(0);
return this.dataset.read_slice(this.view.fields_keys.concat(['__last_update']), {
'limit': self.view.limit,
'offset': self.dataset_offset += self.view.limit
}).then(function(records) {
- self.view.dataset.ids = ids.concat(self.dataset.ids);
+ self.view.dataset.ids = ids.concat(_.difference(self.dataset.ids, ids));
self.do_add_records(records);
self.compute_cards_auto_height();
self.view.postprocess_m2m_tags();
diff --git a/addons/website/models/ir_http.py b/addons/website/models/ir_http.py
index 9dd1347d4f3..b109bdbecd8 100644
--- a/addons/website/models/ir_http.py
+++ b/addons/website/models/ir_http.py
@@ -1,6 +1,4 @@
# -*- coding: utf-8 -*-
-import datetime
-import hashlib
import logging
import os
import re
@@ -170,7 +168,6 @@ class ir_http(orm.AbstractModel):
path += '?' + request.httprequest.query_string
return werkzeug.utils.redirect(path, code=301)
-
def _handle_exception(self, exception, code=500):
is_website_request = bool(getattr(request, 'website_enabled', False) and request.website)
if not is_website_request:
diff --git a/addons/website/models/website.py b/addons/website/models/website.py
index 4abed17d91b..2784b55fef4 100644
--- a/addons/website/models/website.py
+++ b/addons/website/models/website.py
@@ -309,7 +309,7 @@ class website(osv.osv):
return False
@openerp.tools.ormcache(skiparg=3)
- def _get_languages(self, cr, uid, id, context=None):
+ def _get_languages(self, cr, uid, id):
website = self.browse(cr, uid, id)
return [(lg.code, lg.name) for lg in website.language_ids]
@@ -324,7 +324,7 @@ class website(osv.osv):
return uri
def get_languages(self, cr, uid, ids, context=None):
- return self._get_languages(cr, uid, ids[0], context=context)
+ return self._get_languages(cr, uid, ids[0])
def get_alternate_languages(self, cr, uid, ids, req=None, context=None):
langs = []
diff --git a/addons/website_quote/views/website_quotation.xml b/addons/website_quote/views/website_quotation.xml
index 6a05067766a..c1fe283d9ea 100644
--- a/addons/website_quote/views/website_quotation.xml
+++ b/addons/website_quote/views/website_quotation.xml
@@ -157,7 +157,8 @@