[MERGE] forward port of branch 8.0 up to d780014
This commit is contained in:
@@ -145,6 +145,7 @@
|
||||
<field name="amount_untaxed" sum="Untaxed Amount"/>
|
||||
<field name="amount_total" sum="Total Amount"/>
|
||||
<field name="state"/>
|
||||
<field name="type" invisible="context.get('type',True)"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
@@ -504,6 +505,17 @@
|
||||
<field name="search_view_id" ref="view_account_invoice_filter"/>
|
||||
</record>
|
||||
|
||||
<record id="action_invoice_refund_out_tree" model="ir.actions.act_window">
|
||||
<field name="name">Invoices</field>
|
||||
<field name="res_model">account.invoice</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form,calendar,graph</field>
|
||||
<field name="view_id" ref="invoice_tree"/>
|
||||
<field name="domain">[('type','in', ['out_invoice', 'out_refund']), ('state', 'not in', ['draft', 'cancel'])]</field>
|
||||
<field name="context">{'type':False}</field>
|
||||
<field name="search_view_id" ref="view_account_invoice_filter"/>
|
||||
</record>
|
||||
|
||||
<record id="action_invoice_tree_pending_invoice" model="ir.actions.act_window">
|
||||
<field name="name">Pending Invoice</field>
|
||||
<field name="res_model">account.invoice</field>
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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}">
|
||||
<div><strong><field name="total_invoiced" widget="monetary"/></strong><br/>Invoiced</div>
|
||||
|
||||
@@ -152,6 +152,7 @@
|
||||
<tr><td>Description</td><td><t t-esc="line.name"/></td></tr>
|
||||
<tr><td>Amount</td><td><t t-esc="line.amount_str"/><t t-if="line.amount_currency_str"> (<t t-esc="line.amount_currency_str"/>)</t></td></tr>
|
||||
<tr><td>Account</td><td><t t-esc="line.account_code"/> <t t-esc="line.account_name"/></td></tr>
|
||||
<tr t-if="line.note"><td>Note</td><td><t t-esc="line.note"/></td></tr>
|
||||
</table>
|
||||
</t>
|
||||
|
||||
|
||||
@@ -132,8 +132,8 @@
|
||||
<field name="bank_id" domain="[('partner_id', '=', partner_id)]"/>
|
||||
<field name="ml_maturity_date"/>
|
||||
<field name="date"/>
|
||||
<field name="amount_currency" string="Amount" groups="base.group_multi_currency"/>
|
||||
<field name="currency" groups="base.group_multi_currency"/>
|
||||
<field name="amount_currency" string="Amount"/>
|
||||
<field name="currency"/>
|
||||
<field name="name"/>
|
||||
<field name="amount" sum="Total in Company Currency" invisible="1"/>
|
||||
</tree>
|
||||
|
||||
@@ -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]
|
||||
|
||||
|
||||
@@ -20,3 +20,5 @@
|
||||
##############################################################################
|
||||
import google_account
|
||||
import controllers
|
||||
|
||||
from .google_account import TIMEOUT # noqa
|
||||
@@ -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
|
||||
|
||||
@@ -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):
|
||||
'''
|
||||
|
||||
@@ -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.")
|
||||
|
||||
|
||||
@@ -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"""
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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 = []
|
||||
|
||||
@@ -157,7 +157,8 @@
|
||||
|
||||
<template id="quotation_toolbar">
|
||||
<div class="text-center hidden-print" t-if="quotation.state in ('draft', 'sent', 'waiting_date')">
|
||||
<a class="btn btn-success fa fa-check" data-toggle="modal" data-target="#modalaccept">
|
||||
<a class="btn btn-success fa fa-check" data-toggle="modal" data-target="#modalaccept"
|
||||
t-if="days_valid">
|
||||
Accept
|
||||
</a>
|
||||
<a class="btn btn-info fa fa-comment" type="submit" href="#discussion">
|
||||
|
||||
@@ -851,7 +851,9 @@ Possible children of the view element are:
|
||||
an object with all the requested fields as its attributes. Each field has
|
||||
two attributes ``value`` and ``raw_value``, the former is formatted
|
||||
according to current user parameters, the latter is the direct value from
|
||||
a :meth:`~openerp.models.Model.read`
|
||||
a :meth:`~openerp.models.Model.read` (except for date and datetime fields
|
||||
that are `formatted according to user's locale
|
||||
<https://github.com/odoo/odoo/blob/8.0/addons/web_kanban/static/src/js/kanban.js#L900>`_)
|
||||
``read_only_mode``
|
||||
self-explanatory
|
||||
|
||||
|
||||
@@ -118,7 +118,7 @@ class ir_attachment(osv.osv):
|
||||
return self.pool['ir.config_parameter'].get_param(cr, SUPERUSER_ID, 'ir_attachment.location', 'file')
|
||||
|
||||
@tools.ormcache(skiparg=3)
|
||||
def _filestore(self, cr, uid, context=None):
|
||||
def _filestore(self, cr, uid):
|
||||
return tools.config.filestore(cr.dbname)
|
||||
|
||||
def force_storage(self, cr, uid, context=None):
|
||||
|
||||
@@ -58,6 +58,7 @@ class ir_filters(osv.osv):
|
||||
"""
|
||||
# available filters: private filters (user_id=uid) and public filters (uid=NULL),
|
||||
# and filters for the action (action_id=action_id) or global (action_id=NULL)
|
||||
context = self.pool['res.users'].context_get(cr, uid)
|
||||
action_domain = self._get_action_domain(cr, uid, action_id)
|
||||
filter_ids = self.search(cr, uid, action_domain +
|
||||
[('model_id','=',model),('user_id','in',[uid, False])])
|
||||
|
||||
@@ -5,9 +5,11 @@
|
||||
import datetime
|
||||
import hashlib
|
||||
import logging
|
||||
import mimetypes
|
||||
import re
|
||||
import sys
|
||||
|
||||
import werkzeug
|
||||
import werkzeug.exceptions
|
||||
import werkzeug.routing
|
||||
import werkzeug.urls
|
||||
|
||||
@@ -729,7 +729,11 @@ class ir_model_access(osv.osv):
|
||||
a.perm_''' + access_mode, (model_name,))
|
||||
return [('%s/%s' % x) if x[0] else x[1] for x in cr.fetchall()]
|
||||
|
||||
@tools.ormcache()
|
||||
# The context parameter is useful when the method translates error messages.
|
||||
# But as the method raises an exception in that case, the key 'lang' might
|
||||
# not be really necessary as a cache key, unless the `ormcache_context`
|
||||
# decorator catches the exception (it does not at the moment.)
|
||||
@tools.ormcache_context(accepted_keys=('lang',))
|
||||
def check(self, cr, uid, model, mode='read', raise_exception=True, context=None):
|
||||
if uid==1:
|
||||
# User root have all accesses
|
||||
|
||||
@@ -338,7 +338,7 @@ class res_users(osv.osv):
|
||||
for id in ids:
|
||||
if id in self._uid_cache[db]:
|
||||
del self._uid_cache[db][id]
|
||||
self.context_get.clear_cache(self)
|
||||
self._context_get.clear_cache(self)
|
||||
self.has_group.clear_cache(self)
|
||||
return res
|
||||
|
||||
@@ -374,8 +374,8 @@ class res_users(osv.osv):
|
||||
return super(res_users, self).copy(cr, uid, id, default, context)
|
||||
|
||||
@tools.ormcache(skiparg=2)
|
||||
def context_get(self, cr, uid, context=None):
|
||||
user = self.browse(cr, SUPERUSER_ID, uid, context)
|
||||
def _context_get(self, cr, uid):
|
||||
user = self.browse(cr, SUPERUSER_ID, uid)
|
||||
result = {}
|
||||
for k in self._fields:
|
||||
if k.startswith('context_'):
|
||||
@@ -391,6 +391,9 @@ class res_users(osv.osv):
|
||||
result[context_key] = res or False
|
||||
return result
|
||||
|
||||
def context_get(self, cr, uid, context=None):
|
||||
return self._context_get(cr, uid)
|
||||
|
||||
def action_get(self, cr, uid, context=None):
|
||||
dataobj = self.pool['ir.model.data']
|
||||
data_id = dataobj._get_id(cr, SUPERUSER_ID, 'base', 'action_res_users_my')
|
||||
|
||||
@@ -105,7 +105,7 @@ class ormcache_context(ormcache):
|
||||
# arguments, and pass them positionally to lookup(). This is why context
|
||||
# is not passed through kwargs!
|
||||
if self.context_pos < len(args):
|
||||
context = args[self.context_pos]
|
||||
context = args[self.context_pos] or {}
|
||||
else:
|
||||
context = kwargs.get('context') or {}
|
||||
ckey = [(k, context[k]) for k in self.accepted_keys if k in context]
|
||||
|
||||
Reference in New Issue
Block a user