diff --git a/addons/account_followup/wizard/account_followup_print.py b/addons/account_followup/wizard/account_followup_print.py
index 550ca753059..e72ebdc448f 100644
--- a/addons/account_followup/wizard/account_followup_print.py
+++ b/addons/account_followup/wizard/account_followup_print.py
@@ -168,7 +168,7 @@ class account_followup_print(osv.osv_memory):
if partner.max_followup_id.send_letter:
partner_ids_to_print.append(partner.id)
nbprints += 1
- message = _("Follow-up letter of ") + " " + partner.partner_id.latest_followup_level_id_without_lit.name + "" + _(" will be sent")
+ message = "%s %s %s" % (_("Follow-up letter of "), partner.partner_id.latest_followup_level_id_without_lit.name, _(" will be sent"))
partner_obj.message_post(cr, uid, [partner.partner_id.id], body=message, context=context)
if nbunknownmails == 0:
resulttext += str(nbmails) + _(" email(s) sent")
diff --git a/addons/product/_common.py b/addons/product/_common.py
index c05dcee66a2..f44f6b11a4c 100644
--- a/addons/product/_common.py
+++ b/addons/product/_common.py
@@ -20,9 +20,6 @@
##############################################################################
from openerp import tools
-import math
-
-
def rounding(f, r):
# TODO for trunk: log deprecation warning
# _logger.warning("Deprecated rounding method, please use tools.float_round to round floats.")
@@ -32,4 +29,4 @@ def rounding(f, r):
def ceiling(f, r):
if not r:
return f
- return math.ceil(f / r) * r
+ return tools.float_round(f, precision_rounding=r, rounding_method='UP')
diff --git a/addons/product/product.py b/addons/product/product.py
index d284a6242fb..9f014ecca46 100644
--- a/addons/product/product.py
+++ b/addons/product/product.py
@@ -134,10 +134,10 @@ class product_uom(osv.osv):
'name': fields.char('Unit of Measure', required=True, translate=True),
'category_id': fields.many2one('product.uom.categ', 'Product Category', required=True, ondelete='cascade',
help="Conversion between Units of Measure can only occur if they belong to the same category. The conversion will be made based on the ratios."),
- 'factor': fields.float('Ratio', required=True,digits=(12, 12),
+ 'factor': fields.float('Ratio', required=True, digits=0, # force NUMERIC with unlimited precision
help='How much bigger or smaller this unit is compared to the reference Unit of Measure for this category:\n'\
'1 * (reference unit) = ratio * (this unit)'),
- 'factor_inv': fields.function(_factor_inv, digits=(12,12),
+ 'factor_inv': fields.function(_factor_inv, digits=0, # force NUMERIC with unlimited precision
fnct_inv=_factor_inv_write,
string='Bigger Ratio',
help='How many times this Unit of Measure is bigger than the reference Unit of Measure in this category:\n'\
diff --git a/addons/product/product_view.xml b/addons/product/product_view.xml
index 88aa0d93c21..4eb42e38d3b 100644
--- a/addons/product/product_view.xml
+++ b/addons/product/product_view.xml
@@ -592,8 +592,14 @@
e.g: 1 * (reference unit) = ratio * (this unit)
diff --git a/addons/project/security/ir.model.access.csv b/addons/project/security/ir.model.access.csv index 0435e51fd2e..28ac60f87bd 100644 --- a/addons/project/security/ir.model.access.csv +++ b/addons/project/security/ir.model.access.csv @@ -1,26 +1,27 @@ -id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink -access_project_project,project.project,model_project_project,project.group_project_user,1,0,0,0 -access_project_project_manager,project.project,model_project_project,project.group_project_manager,1,1,1,1 -access_account_analytic_account_user,account.analytic.account,analytic.model_account_analytic_account,project.group_project_user,1,0,0,0 -access_account_analytic_account,account.analytic.account,analytic.model_account_analytic_account,project.group_project_manager,1,1,1,1 -access_project_task_type_user,project.task.type user,model_project_task_type,project.group_project_user,1,0,0,0 -access_project_task_type_manager,project.task.type manager,model_project_task_type,project.group_project_manager,1,1,1,1 -access_project_task,project.task,model_project_task,project.group_project_user,1,1,1,1 -access_project_task_work,project.task.work,model_project_task_work,project.group_project_user,1,1,1,1 -access_report_project_task_user,report.project.task.user,model_report_project_task_user,project.group_project_manager,1,1,1,1 -access_partner_task user,base.res.partner user,base.model_res_partner,project.group_project_user,1,0,0,0 -access_task_on_partner,project.task on partners,model_project_task,base.group_user,1,0,0,0 -access_project_on_partner,project.project on partners,model_project_project,base.group_user,1,0,0,0 -access_project_task_sale_user,project.task salesman,model_project_task,base.group_sale_salesman,1,1,1,1 -access_project_task_type_sale_user,project.task.type salesman,project.model_project_task_type,base.group_sale_salesman,1,0,0,0 -access_project_task_history_sale_user,project.task.history salesman,project.model_project_task_history,base.group_sale_salesman,1,1,1,1 -access_project_project_sale_user,project.project salesman,model_project_project,base.group_sale_salesman,1,0,0,0 -access_account_analytic_line_project,account.analytic.line project,analytic.model_account_analytic_line,project.group_project_manager,1,1,1,1 -access_project_task_history,project.task.history project,project.model_project_task_history,project.group_project_user,1,1,1,0 -access_project_task_history_cumulative,project.task.history project,project.model_project_task_history_cumulative,project.group_project_manager,1,0,0,0 -access_project_task_history_cumulative,project.task.history project,project.model_project_task_history_cumulative,project.group_project_user,1,0,0,0 -access_resource_calendar,project.resource_calendar manager,resource.model_resource_calendar,project.group_project_user,1,0,0,0 -access_resource_calendar_leaves_user,resource.calendar.leaves user,resource.model_resource_calendar_leaves,project.group_project_user,1,1,1,1 -access_project_category,project.project_category,model_project_category,,1,0,0,0 -access_project_category_manager,project.project_category,model_project_category,project.group_project_manager,1,1,1,1 -access_mail_alias,mail.alias,mail.model_mail_alias,project.group_project_manager,1,1,1,1 +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_project_project,project.project,model_project_project,project.group_project_user,1,0,0,0 +access_project_project_manager,project.project,model_project_project,project.group_project_manager,1,1,1,1 +access_account_analytic_account_user,account.analytic.account,analytic.model_account_analytic_account,project.group_project_user,1,0,0,0 +access_account_analytic_account,account.analytic.account,analytic.model_account_analytic_account,project.group_project_manager,1,1,1,1 +access_project_task_type_user,project.task.type user,model_project_task_type,project.group_project_user,1,0,0,0 +access_project_task_type_manager,project.task.type manager,model_project_task_type,project.group_project_manager,1,1,1,1 +access_project_task,project.task,model_project_task,project.group_project_user,1,1,1,1 +access_project_task_work,project.task.work,model_project_task_work,project.group_project_user,1,1,1,1 +access_report_project_task_user,report.project.task.user,model_report_project_task_user,project.group_project_manager,1,1,1,1 +access_partner_task user,base.res.partner user,base.model_res_partner,project.group_project_user,1,0,0,0 +access_task_on_partner,project.task on partners,model_project_task,base.group_user,1,0,0,0 +access_project_on_partner,project.project on partners,model_project_project,base.group_user,1,0,0,0 +access_project_task_sale_user,project.task salesman,model_project_task,base.group_sale_salesman,1,1,1,1 +access_project_task_type_sale_user,project.task.type salesman,project.model_project_task_type,base.group_sale_salesman,1,0,0,0 +access_project_task_history_sale_user,project.task.history salesman,project.model_project_task_history,base.group_sale_salesman,1,1,1,1 +access_project_project_sale_user,project.project salesman,model_project_project,base.group_sale_salesman,1,0,0,0 +access_account_analytic_line_project,account.analytic.line project,analytic.model_account_analytic_line,project.group_project_manager,1,1,1,1 +access_project_task_history,project.task.history project,project.model_project_task_history,project.group_project_user,1,1,1,0 +access_project_task_history_cumulative,project.task.history project,project.model_project_task_history_cumulative,project.group_project_manager,1,0,0,0 +access_project_task_history_cumulative,project.task.history project,project.model_project_task_history_cumulative,project.group_project_user,1,0,0,0 +access_resource_calendar,project.resource_calendar user,resource.model_resource_calendar,project.group_project_user,1,0,0,0 +access_resource_calendar_attendance,project.resource_calendar_attendance user,resource.model_resource_calendar_attendance,project.group_project_user,1,0,0,0 +access_resource_calendar_leaves_user,resource.calendar.leaves user,resource.model_resource_calendar_leaves,project.group_project_user,1,1,1,1 +access_project_category,project.project_category,model_project_category,,1,0,0,0 +access_project_category_manager,project.project_category,model_project_category,project.group_project_manager,1,1,1,1 +access_mail_alias,mail.alias,mail.model_mail_alias,project.group_project_manager,1,1,1,1 diff --git a/addons/web_graph/static/src/js/graph_widget.js b/addons/web_graph/static/src/js/graph_widget.js index 97a5ad66d4e..a08ee529a67 100644 --- a/addons/web_graph/static/src/js/graph_widget.js +++ b/addons/web_graph/static/src/js/graph_widget.js @@ -56,13 +56,13 @@ openerp.web_graph.Graph = openerp.web.Widget.extend({ return this.model.call('fields_get', []).then(function (f) { self.fields = f; - self.fields.__count = {field:'__count', type: 'integer', string:_t('Quantity')}; + self.fields.__count = {field:'__count', type: 'integer', string:_t('Count')}; self.groupby_fields = self.get_groupby_fields(); self.measure_list = self.get_measures(); self.add_measures_to_options(); self.pivot_options.row_groupby = self.create_field_values(self.pivot_options.row_groupby || []); self.pivot_options.col_groupby = self.create_field_values(self.pivot_options.col_groupby || []); - self.pivot_options.measures = self.create_field_values(self.pivot_options.measures || [{field:'__count', type: 'integer', string:'Quantity'}]); + self.pivot_options.measures = self.create_field_values(self.pivot_options.measures || [{field:'__count', type: 'integer', string:'Count'}]); self.pivot = new openerp.web_graph.PivotTable(self.model, self.domain, self.fields, self.pivot_options); self.pivot.update_data().then(function () { self.display_data(); diff --git a/addons/web_graph/static/src/js/pivot_table.js b/addons/web_graph/static/src/js/pivot_table.js index a46203faff5..a99bae1756f 100644 --- a/addons/web_graph/static/src/js/pivot_table.js +++ b/addons/web_graph/static/src/js/pivot_table.js @@ -18,7 +18,7 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({ this.updating = false; this.model = model; this.fields = fields; - this.fields.__count = {type: 'integer', string:_t('Quantity')}; + this.fields.__count = {type: 'integer', string:_t('Count')}; this.measures = options.measures || []; this.rows = { groupby: options.row_groupby, headers: null }; this.cols = { groupby: options.col_groupby, headers: null }; diff --git a/openerp/addons/base/ir/ir_actions.py b/openerp/addons/base/ir/ir_actions.py index e19abdbe8f2..518d3718d2e 100644 --- a/openerp/addons/base/ir/ir_actions.py +++ b/openerp/addons/base/ir/ir_actions.py @@ -1183,6 +1183,8 @@ class ir_actions_act_client(osv.osv): def _get_params(self, cr, uid, ids, field_name, arg, context): result = {} + # Need to remove bin_size from context, to obtains the binary and not the length. + context = dict(context, bin_size_params_store=False) for record in self.browse(cr, uid, ids, context=context): result[record.id] = record.params_store and eval(record.params_store, {'uid': uid}) or False return result diff --git a/openerp/addons/base/tests/base_test.yml b/openerp/addons/base/tests/base_test.yml index 5590e735135..a6f32a7c9d0 100644 --- a/openerp/addons/base/tests/base_test.yml +++ b/openerp/addons/base/tests/base_test.yml @@ -203,8 +203,8 @@ - !python {model: res.currency}: | from openerp.tools import float_compare, float_is_zero, float_round, float_repr - def try_round(amount, expected, precision_digits=3, float_round=float_round, float_repr=float_repr): - result = float_repr(float_round(amount, precision_digits=precision_digits), + def try_round(amount, expected, precision_digits=3, float_round=float_round, float_repr=float_repr, rounding_method='HALF-UP'): + result = float_repr(float_round(amount, precision_digits=precision_digits, rounding_method=rounding_method), precision_digits=precision_digits) assert result == expected, 'Rounding error: got %s, expected %s' % (result, expected) try_round(2.6745, '2.675') @@ -218,6 +218,18 @@ try_round(457.4554, '457.455') try_round(-457.4554, '-457.455') + # Try some rounding value with rounding method UP instead of HALF-UP + # We use 8.175 because when normalizing 8.175 with precision_digits=3 it gives + # us 8175,0000000001234 as value, and if not handle correctly the rounding UP + # value will be incorrect (should be 8,175 and not 8,176) + try_round(8.175, '8.175', rounding_method='UP') + try_round(8.1751, '8.176', rounding_method='UP') + try_round(-8.175, '-8.175', rounding_method='UP') + try_round(-8.1751, '-8.176', rounding_method='UP') + try_round(-6.000, '-6.000', rounding_method='UP') + try_round(1.8, '2', 0, rounding_method='UP') + try_round(-1.8, '-2', 0, rounding_method='UP') + # Extended float range test, inspired by Cloves Almeida's test on bug #882036. fractions = [.0, .015, .01499, .675, .67499, .4555, .4555, .45555] expecteds = ['.00', '.02', '.01', '.68', '.67', '.46', '.456', '.4556'] diff --git a/openerp/models.py b/openerp/models.py index dfc41bf2475..7c87d153069 100644 --- a/openerp/models.py +++ b/openerp/models.py @@ -178,7 +178,12 @@ def get_pg_type(f, type_override=None): if field_type in FIELDS_TO_PGTYPES: pg_type = (FIELDS_TO_PGTYPES[field_type], FIELDS_TO_PGTYPES[field_type]) elif issubclass(field_type, fields.float): - if f.digits: + # Explicit support for "falsy" digits (0, False) to indicate a + # NUMERIC field with no fixed precision. The values will be saved + # in the database with all significant digits. + # FLOAT8 type is still the default when there is no precision because + # it is faster for most operations (sums, etc.) + if f.digits is not None: pg_type = ('numeric', 'NUMERIC') else: pg_type = ('float8', 'DOUBLE PRECISION') diff --git a/openerp/report/render/rml2pdf/trml2pdf.py b/openerp/report/render/rml2pdf/trml2pdf.py index dde2315aa24..48031b1ccf4 100644 --- a/openerp/report/render/rml2pdf/trml2pdf.py +++ b/openerp/report/render/rml2pdf/trml2pdf.py @@ -91,7 +91,6 @@ class NumberedCanvas(canvas.Canvas): self._saved_page_states = [] def showPage(self): - self._saved_page_states.append(dict(self.__dict__)) self._startPage() def save(self): @@ -126,6 +125,8 @@ class PageCount(platypus.Flowable): class PageReset(platypus.Flowable): def draw(self): + """Flag to close current story page numbering and prepare for the next + should be executed after the rendering of the full story""" self.canv._doPageReset = True class _rml_styles(object,): @@ -936,6 +937,9 @@ class TinyDocTemplate(platypus.BaseDocTemplate): self.handle_frameBegin() def afterPage(self): + if isinstance(self.canv, NumberedCanvas): + # save current page states before eventual reset + self.canv._saved_page_states.append(dict(self.canv.__dict__)) if self.canv._doPageReset: # Following a