diff --git a/addons/account/models/account_invoice.py b/addons/account/models/account_invoice.py
index 4cddc629a26..4f1413f7ba3 100644
--- a/addons/account/models/account_invoice.py
+++ b/addons/account/models/account_invoice.py
@@ -608,7 +608,7 @@ class AccountInvoice(models.Model):
credit_aml = self.pool.get('account.move.line').browse(cr, uid, credit_aml_id, context=context)
inv = self.browse(cr, uid, id, context=context)
if not credit_aml.currency_id and inv.currency_id != inv.company_id.currency_id:
- credit_aml.with_context(allow_amount_currency=True).write({
+ credit_aml.with_context(allow_amount_currency=True, check_move_validity=False).write({
'amount_currency': inv.company_id.currency_id.with_context(date=credit_aml.date).compute(credit_aml.balance, inv.currency_id),
'currency_id': inv.currency_id.id})
if credit_aml.payment_id:
diff --git a/addons/account/models/res_config.py b/addons/account/models/res_config.py
index 778d5cd1460..3b2ff3ecb67 100644
--- a/addons/account/models/res_config.py
+++ b/addons/account/models/res_config.py
@@ -232,10 +232,8 @@ class AccountConfigSettings(models.TransientModel):
def set_product_taxes(self):
""" Set the product taxes if they have changed """
ir_values_obj = self.env['ir.values']
- if self.default_sale_tax_id:
- ir_values_obj.sudo().set_default('product.template', "taxes_id", [self.default_sale_tax_id.id], for_all_users=True, company_id=self.company_id.id)
- if self.default_purchase_tax_id:
- ir_values_obj.sudo().set_default('product.template', "supplier_taxes_id", [self.default_purchase_tax_id.id], for_all_users=True, company_id=self.company_id.id)
+ ir_values_obj.sudo().set_default('product.template', "taxes_id", [self.default_sale_tax_id.id] if self.default_sale_tax_id else False, for_all_users=True, company_id=self.company_id.id)
+ ir_values_obj.sudo().set_default('product.template', "supplier_taxes_id", [self.default_purchase_tax_id.id] if self.default_purchase_tax_id else False, for_all_users=True, company_id=self.company_id.id)
@api.multi
def set_chart_of_accounts(self):
diff --git a/addons/account/wizard/account_invoice_refund.py b/addons/account/wizard/account_invoice_refund.py
index b45e4a5970c..56608722806 100644
--- a/addons/account/wizard/account_invoice_refund.py
+++ b/addons/account/wizard/account_invoice_refund.py
@@ -74,7 +74,7 @@ class AccountInvoiceRefund(models.TransientModel):
for tmpline in refund.move_id.line_ids:
if tmpline.account_id.id == inv.account_id.id:
to_reconcile_lines += tmpline
- to_reconcile_lines.filtered(lambda l: l.reconciled == False).reconcile()
+ to_reconcile_lines.filtered(lambda l: l.reconciled == False).reconcile()
if mode == 'modify':
invoice = inv.read(
['name', 'type', 'number', 'reference',
diff --git a/addons/account_budget/report/analytic_account_budget_report.py b/addons/account_budget/report/analytic_account_budget_report.py
index 265a76e6b3e..ffc5c0ad0e2 100644
--- a/addons/account_budget/report/analytic_account_budget_report.py
+++ b/addons/account_budget/report/analytic_account_budget_report.py
@@ -60,11 +60,16 @@ class analytic_account_budget_report(report_sxw.rml_parse):
'theo':0.00,
'pln':0.00,
'prac':0.00,
- 'perc':0.00
+ 'perc':0.00,
+ 'date_from': budget_name[0].date_from,
+ 'date_to': budget_name[0].date_to,
}
result.append(res)
-
- line_ids = c_b_lines_obj.search(self.cr, self.uid, [('id', 'in', b_line_ids), ('crossovered_budget_id','=',budget_ids[i][0])])
+ domain_lines = [('id', 'in', b_line_ids),
+ ('crossovered_budget_id', '=', budget_ids[i][0]),
+ ('date_from', '<=', d_to),
+ ('date_to', '>=', d_from)]
+ line_ids = c_b_lines_obj.search(self.cr, self.uid, domain_lines)
line_id = c_b_lines_obj.browse(self.cr, self.uid, line_ids)
tot_theo = tot_pln = tot_prac = tot_perc = 0
diff --git a/addons/account_budget/report/budget_report.py b/addons/account_budget/report/budget_report.py
index cc2274c2eea..3ff1f7d0927 100644
--- a/addons/account_budget/report/budget_report.py
+++ b/addons/account_budget/report/budget_report.py
@@ -66,8 +66,11 @@ class budget_report(report_sxw.rml_parse):
'perc': 0.00
}
result.append(res)
-
- line_ids = c_b_lines_obj.search(self.cr, self.uid, [('id', 'in', budget_ids), ('analytic_account_id','=',an_ids[i][0])])
+ domain_lines = [('id', 'in', budget_ids),
+ ('analytic_account_id','=',an_ids[i][0]),
+ ('date_from', '<=', d_to),
+ ('date_to', '>=', d_from)]
+ line_ids = c_b_lines_obj.search(self.cr, self.uid, domain_lines)
line_id = c_b_lines_obj.browse(self.cr, self.uid, line_ids)
tot_theo = tot_pln = tot_prac = tot_perc = 0.00
diff --git a/addons/account_budget/views/report_analyticaccountbudget.xml b/addons/account_budget/views/report_analyticaccountbudget.xml
index dab987d6099..9f6e31aa258 100644
--- a/addons/account_budget/views/report_analyticaccountbudget.xml
+++ b/addons/account_budget/views/report_analyticaccountbudget.xml
@@ -32,6 +32,8 @@
Planned Amt |
Practical Amt |
Perc(%) |
+ Start date |
+ End Date |
@@ -42,6 +44,8 @@
|
|
% |
+ |
+ |
|
diff --git a/addons/account_voucher/account_voucher.py b/addons/account_voucher/account_voucher.py
index 97fecf300f8..01bc7c3dd8c 100644
--- a/addons/account_voucher/account_voucher.py
+++ b/addons/account_voucher/account_voucher.py
@@ -365,7 +365,7 @@ class account_voucher_line(models.Model):
if product.description_purchase:
values['name'] += '\n' + product.description_purchase
else:
- values['price_unit'] = product.lst_price
+ values['price_unit'] = price_unit or product.lst_price
taxes = product.taxes_id or account.tax_ids
if product.description_sale:
values['name'] += '\n' + product.description_sale
@@ -375,7 +375,7 @@ class account_voucher_line(models.Model):
if company and currency:
if company.currency_id != currency:
if type == 'purchase':
- values['price_unit'] = product.standard_price
+ values['price_unit'] = price_unit or product.standard_price
values['price_unit'] = values['price_unit'] * currency.rate
return {'value': values, 'domain': {}}
diff --git a/addons/google_account/models/google_service.py b/addons/google_account/models/google_service.py
index d707ee8d188..15ad409fe42 100644
--- a/addons/google_account/models/google_service.py
+++ b/addons/google_account/models/google_service.py
@@ -8,6 +8,7 @@ import urllib2
import werkzeug.urls
from odoo import api, fields, models, registry, _
+from odoo.exceptions import UserError
from odoo.http import request
@@ -124,6 +125,9 @@ class GoogleService(models.TransientModel):
client_id = Parameters.get_param('google_%s_client_id' % (service,), default=False)
client_secret = Parameters.get_param('google_%s_client_secret' % (service,), default=False)
+ if not client_id or not client_secret:
+ raise UserError(_("The account for the Google service '%s' is not configured") % service)
+
headers = {"content-type": "application/x-www-form-urlencoded"}
data = werkzeug.url_encode({
'refresh_token': refresh_token,
diff --git a/addons/sale_stock/sale_stock.py b/addons/sale_stock/sale_stock.py
index 862ac1c7854..8d0be728b2c 100644
--- a/addons/sale_stock/sale_stock.py
+++ b/addons/sale_stock/sale_stock.py
@@ -73,7 +73,7 @@ class SaleOrder(models.Model):
@api.multi
def action_cancel(self):
- self.order_line.mapped('procurement_ids').cancel()
+ self.mapped('order_line').mapped('procurement_ids').cancel()
super(SaleOrder, self).action_cancel()
@api.multi
diff --git a/addons/stock/models/stock_move.py b/addons/stock/models/stock_move.py
index c35c73a9ba4..49c22a63a93 100644
--- a/addons/stock/models/stock_move.py
+++ b/addons/stock/models/stock_move.py
@@ -157,7 +157,8 @@ class StockMove(models.Model):
@api.depends('product_id', 'product_uom', 'product_uom_qty')
def _compute_product_qty(self):
if self.product_uom:
- self.product_qty = self.env['product.uom']._compute_qty_obj(self.product_uom, self.product_uom_qty, self.product_id.uom_id)
+ rounding_method = self._context.get('rounding_method', 'UP')
+ self.product_qty = self.env['product.uom']._compute_qty_obj(self.product_uom, self.product_uom_qty, self.product_id.uom_id, rounding_method=rounding_method)
def _set_product_qty(self):
""" The meaning of product_qty field changed lately and is now a functional field computing the quantity
@@ -980,12 +981,12 @@ class StockMove(models.Model):
# TDE CLEANME: remove context key + add as parameter
if self.env.context.get('source_location_id'):
defaults['location_id'] = self.env.context['source_location_id']
- new_move = self.copy(defaults)
+ new_move = self.with_context(rounding_method='HALF-UP').copy(defaults)
# ctx = context.copy()
# TDE CLEANME: used only in write in this file, to clean
# ctx['do_not_propagate'] = True
- self.with_context(do_not_propagate=True).write({'product_uom_qty': self.product_uom_qty - uom_qty})
+ self.with_context(do_not_propagate=True, rounding_method='HALF-UP').write({'product_uom_qty': self.product_uom_qty - uom_qty})
if self.move_dest_id and self.propagate and self.move_dest_id.state not in ('done', 'cancel'):
new_move_prop = self.move_dest_id.split(qty)
diff --git a/doc/cla/individual/NothingCtrl.md b/doc/cla/individual/NothingCtrl.md
new file mode 100644
index 00000000000..bf58b0034d3
--- /dev/null
+++ b/doc/cla/individual/NothingCtrl.md
@@ -0,0 +1,9 @@
+Vietnam, 2017-08-15
+
+I hereby agree to the terms of the Odoo Individual Contributor License Agreement v1.0.
+
+I declare that I am authorized and able to make this agreement and sign this declaration.
+
+Signed,
+
+Duong Bao Thang nothingctrl@gmail.com https://github.com/NothingCtrl
diff --git a/doc/reference/views.rst b/doc/reference/views.rst
index 9449fe15fd9..45d58f62ec8 100644
--- a/doc/reference/views.rst
+++ b/doc/reference/views.rst
@@ -838,17 +838,13 @@ attributes:
Possible children of the view element are:
``field``
- declares fields to aggregate or to use in kanban *logic*. If the field is
- simply displayed in the kanban view, it does not need to be pre-declared.
+ declares fields to use in kanban *logic*. If the field is simply displayed in
+ the kanban view, it does not need to be pre-declared.
Possible attributes are:
``name`` (required)
the name of the field to fetch
- ``sum``, ``avg``, ``min``, ``max``, ``count``
- displays the corresponding aggregation at the top of a kanban column, the
- field's value is the label of the aggregation (a string). Only one
- aggregate operation per field is supported.
``templates``
defines a list of :ref:`reference/qweb` templates. Cards definition may be
diff --git a/openerp/addons/base/ir/ir_model.py b/openerp/addons/base/ir/ir_model.py
index 68ad0509011..2008084df62 100644
--- a/openerp/addons/base/ir/ir_model.py
+++ b/openerp/addons/base/ir/ir_model.py
@@ -384,7 +384,8 @@ class IrModelFields(models.Model):
if field.state == 'manual' and field.ttype == 'many2many':
rel_name = field.relation_table or model._fields[field.name].relation
tables_to_drop.add(rel_name)
- model._pop_field(field.name)
+ if field.state == 'manual':
+ model._pop_field(field.name)
if tables_to_drop:
# drop the relation tables that are not used by other fields
diff --git a/openerp/models.py b/openerp/models.py
index 1205c84e24c..bdd0e13c2c1 100644
--- a/openerp/models.py
+++ b/openerp/models.py
@@ -6034,13 +6034,16 @@ class BaseModel(object):
return RecordCache(self)
@api.model
- def _in_cache_without(self, field):
- """ Make sure ``self`` is present in cache (for prefetching), and return
- the records of model ``self`` in cache that have no value for ``field``
- (:class:`Field` instance).
+ def _in_cache_without(self, field, limit=PREFETCH_MAX):
+ """ Return records to prefetch that have no value in cache for ``field``
+ (:class:`Field` instance), including ``self``.
+ Return at most ``limit`` records.
"""
ids = filter(None, self._prefetch[self._name] - set(self.env.cache[field]))
- return self.browse(ids)
+ recs = self.browse(ids)
+ if limit and len(recs) > limit:
+ recs = self + (recs - self)[:(limit - len(self))]
+ return recs
@api.model
def refresh(self):