diff --git a/addons/account/account_bank_statement.py b/addons/account/account_bank_statement.py index 0f6701806a4..998d74b0e8b 100644 --- a/addons/account/account_bank_statement.py +++ b/addons/account/account_bank_statement.py @@ -860,6 +860,16 @@ class account_bank_statement_line(osv.osv): mv_line_dict['credit'] = credit_at_old_rate to_create.append(mv_line_dict) + # If the reconciliation is performed in another currency than the company currency, the amounts are converted to get the right debit/credit. + # If there is more than 1 debit and 1 credit, this can induce a rounding error, which we put in the foreign exchane gain/loss account. + if st_line_currency.id != company_currency.id: + diff_amount = bank_st_move_vals['debit'] - bank_st_move_vals['credit'] \ + + sum(aml['debit'] for aml in to_create) - sum(aml['credit'] for aml in to_create) + if not company_currency.is_zero(diff_amount): + diff_aml = self.get_currency_rate_line(cr, uid, st_line, diff_amount, move_id, context=context) + diff_aml['name'] = _('Rounding error from currency conversion') + to_create.append(diff_aml) + # Create move lines move_line_pairs_to_reconcile = [] for mv_line_dict in to_create: diff --git a/addons/account/account_invoice.py b/addons/account/account_invoice.py index 4553ec7ed8d..469acc2e317 100644 --- a/addons/account/account_invoice.py +++ b/addons/account/account_invoice.py @@ -1096,6 +1096,7 @@ class account_invoice(models.Model): values['date_invoice'] = date or fields.Date.context_today(invoice) values['state'] = 'draft' values['number'] = False + values['origin'] = invoice.number if period_id: values['period_id'] = period_id diff --git a/addons/account/partner_view.xml b/addons/account/partner_view.xml index b50d259ac7f..ae488f3eb08 100644 --- a/addons/account/partner_view.xml +++ b/addons/account/partner_view.xml @@ -70,6 +70,7 @@ res.partner + - + + + + + + partner.view.button.contracts_count + res.partner + + + + + diff --git a/addons/calendar/calendar.py b/addons/calendar/calendar.py index 19aa9ed7d0b..90f81e8d884 100644 --- a/addons/calendar/calendar.py +++ b/addons/calendar/calendar.py @@ -1417,6 +1417,12 @@ class calendar_event(osv.Model): del context['default_date'] return super(calendar_event, self).message_post(cr, uid, thread_id, body=body, subject=subject, type=type, subtype=subtype, parent_id=parent_id, attachments=attachments, context=context, **kwargs) + def message_subscribe(self, cr, uid, ids, partner_ids, subtype_ids=None, context=None): + return super(calendar_event, self).message_subscribe(cr, uid, get_real_ids(ids), partner_ids, subtype_ids=subtype_ids, context=context) + + def message_unsubscribe(self, cr, uid, ids, partner_ids, context=None): + return super(calendar_event, self).message_unsubscribe(cr, uid, get_real_ids(ids), partner_ids, context=context) + def do_sendmail(self, cr, uid, ids, context=None): for event in self.browse(cr, uid, ids, context): current_user = self.pool['res.users'].browse(cr, uid, uid, context=context) @@ -1748,7 +1754,6 @@ class calendar_event(osv.Model): return res - class mail_message(osv.Model): _inherit = "mail.message" diff --git a/addons/point_of_sale/point_of_sale.py b/addons/point_of_sale/point_of_sale.py index 0fa216b0c5e..ca4ea6f3c0e 100644 --- a/addons/point_of_sale/point_of_sale.py +++ b/addons/point_of_sale/point_of_sale.py @@ -26,6 +26,7 @@ import sets from openerp import tools, models from openerp.osv import fields, osv +from openerp.tools import float_is_zero from openerp.tools.translate import _ from openerp.exceptions import UserError @@ -602,7 +603,7 @@ class pos_order(osv.osv): session.write({'sequence_number': order['sequence_number'] + 1}) session.refresh() - if order['amount_return']: + if not float_is_zero(order['amount_return'], self.pool.get('decimal.precision').precision_get(cr, uid, 'Account')): cash_journal = session.cash_journal_id if not cash_journal: cash_journal_ids = filter(lambda st: st.journal_id.type=='cash', session.statement_ids) diff --git a/addons/project/project.py b/addons/project/project.py index 820c3a752e3..16ff6fc67e8 100644 --- a/addons/project/project.py +++ b/addons/project/project.py @@ -206,7 +206,7 @@ class project(osv.osv): return res def _task_count(self, cr, uid, ids, field_name, arg, context=None): res={} - for tasks in self.browse(cr, uid, ids, context): + for tasks in self.browse(cr, uid, ids, dict(context, active_test=False)): res[tasks.id] = len(tasks.task_ids) return res def _get_alias_models(self, cr, uid, context=None): diff --git a/addons/project/project_view.xml b/addons/project/project_view.xml index b7eac8f0673..01aaf42e378 100644 --- a/addons/project/project_view.xml +++ b/addons/project/project_view.xml @@ -281,7 +281,7 @@
diff --git a/addons/project_issue/project_issue_view.xml b/addons/project_issue/project_issue_view.xml index 96577bb104a..05da0efa5ae 100644 --- a/addons/project_issue/project_issue_view.xml +++ b/addons/project_issue/project_issue_view.xml @@ -399,12 +399,13 @@ res.partner + diff --git a/openerp/fields.py b/openerp/fields.py index 0c1f058ca91..94eb790ef73 100644 --- a/openerp/fields.py +++ b/openerp/fields.py @@ -658,7 +658,7 @@ class Field(object): self.column = fields.property(**args) elif self.column: # let the column provide a valid column for the given parameters - self.column = self.column.new(**args) + self.column = self.column.new(_computed_field=bool(self.compute), **args) else: # create a fresh new column of the right type self.column = getattr(fields, self.type)(**args) @@ -677,7 +677,6 @@ class Field(object): _column_groups = property(attrgetter('groups')) _column_change_default = property(attrgetter('change_default')) _column_deprecated = property(attrgetter('deprecated')) - _column_compute = property(lambda self: bool(self.compute)) ############################################################################ # diff --git a/openerp/models.py b/openerp/models.py index cff7e390251..8d2aff9df3a 100644 --- a/openerp/models.py +++ b/openerp/models.py @@ -64,7 +64,7 @@ from .api import Environment from .exceptions import AccessError, MissingError, ValidationError, UserError from .osv import fields from .osv.query import Query -from .tools import lazy_property, ormcache +from .tools import frozendict, lazy_property, ormcache from .tools.config import config from .tools.misc import CountingStream, DEFAULT_SERVER_DATETIME_FORMAT, DEFAULT_SERVER_DATE_FORMAT from .tools.safe_eval import safe_eval as eval @@ -633,6 +633,7 @@ class BaseModel(object): '_register': False, '_columns': None, # recomputed in _setup_fields() '_defaults': None, # recomputed in _setup_base() + '_fields': frozendict(), # idem '_inherits': dict(cls._inherits), '_depends': dict(cls._depends), '_constraints': list(cls._constraints), diff --git a/openerp/osv/fields.py b/openerp/osv/fields.py index c8a961c68f5..2924f0f4db4 100644 --- a/openerp/osv/fields.py +++ b/openerp/osv/fields.py @@ -115,6 +115,7 @@ class _column(object): """ args0 = { 'string': string, + 'help': args.pop('help', None), 'required': required, 'readonly': readonly, '_domain': domain, @@ -127,6 +128,9 @@ class _column(object): 'translate': translate, 'select': select, 'manual': manual, + 'group_operator': args.pop('group_operator', None), + 'groups': args.pop('groups', None), + 'deprecated': args.pop('deprecated', None), } for key, val in args0.iteritems(): if val: @@ -140,30 +144,23 @@ class _column(object): if not self._classic_write or self.deprecated or self.manual: self._prefetch = False - def new(self, **args): - """ return a column like `self` with the given parameters """ + def new(self, _computed_field=False, **args): + """ Return a column like `self` with the given parameters; the parameter + `_computed_field` tells whether the corresponding field is computed. + """ # memory optimization: reuse self whenever possible; you can reduce the # average memory usage per registry by 10 megabytes! - return self if self.same_parameters(args) else type(self)(**args) - - def same_parameters(self, args): - dummy = object() - return all( - # either both are falsy, or they are equal - (not val1 and not val) or (val1 == val) - for key, val in args.iteritems() - for val1 in [getattr(self, key, getattr(self, '_' + key, dummy))] - ) + column = type(self)(**args) + return self if self.to_field_args() == column.to_field_args() else column def to_field(self): """ convert column `self` to a new-style field """ from openerp.fields import Field - return Field.by_type[self._type](**self.to_field_args()) + return Field.by_type[self._type](column=self, **self.to_field_args()) def to_field_args(self): """ return a dictionary with all the arguments to pass to the field """ base_items = [ - ('column', self), # field interfaces self ('copy', self.copy), ] truthy_items = filter(itemgetter(1), [ @@ -349,7 +346,7 @@ class float(_column): # synopsis: digits_compute(cr) -> (precision, scale) self.digits_compute = digits_compute - def new(self, **args): + def new(self, _computed_field=False, **args): # float columns are database-dependent, so always recreate them return type(self)(**args) @@ -1292,9 +1289,9 @@ class function(_column): self._symbol_f = type_class._symbol_f self._symbol_set = type_class._symbol_set - def new(self, **args): - if args.get('compute'): - # field is computed, we need an instance of the given type + def new(self, _computed_field=False, **args): + if _computed_field: + # field is computed, we need an instance of a non-function column type_class = globals()[self._type] return type_class(**args) else: