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 @@