From c077cd7448edd17bb047819a2ea2d42b064e5694 Mon Sep 17 00:00:00 2001 From: Olivier Dony Date: Tue, 13 Dec 2016 23:01:55 +0100 Subject: [PATCH 01/21] [FIX] point_of_sale: scroll to bottom after weighing product When switching back from the scale screen to the product screen, the order summary was re-drawn and always scrolled at the top. This happens because the redraw takes place in the background while the scale screen is still displayed, so the new area does not know its size yet and cannot be scrolled properly. Swapping these operations around fixes the issue and it happens fast enough to be invisible to the user. --- addons/point_of_sale/static/src/js/screens.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/addons/point_of_sale/static/src/js/screens.js b/addons/point_of_sale/static/src/js/screens.js index 51ed423bbaa..ebdf2ec5762 100644 --- a/addons/point_of_sale/static/src/js/screens.js +++ b/addons/point_of_sale/static/src/js/screens.js @@ -272,8 +272,9 @@ var ScaleScreenWidget = ScreenWidget.extend({ }); this.$('.next,.buy-product').click(function(){ - self.order_product(); self.gui.show_screen(self.next_screen); + // add product *after* switching screen to scroll properly + self.order_product(); }); queue.schedule(function(){ From 9f5839c35a378a69ca47ec234c6cced247bbe8ac Mon Sep 17 00:00:00 2001 From: Olivier Dony Date: Tue, 13 Dec 2016 11:20:59 +0100 Subject: [PATCH 02/21] [FIX] point_of_sale: do not reset selected category every time There seems to be no need to reset to the root category on the product list every time we switch back to the list from another screen. Unless a full refresh was requested (e.g after closing an order). This avoids losing the currently selected category after each screen switch. It can be quite convenient to stay in the same category while the cashier is processing items that need to be weighed, for example. This commit allows POS screen widgets to distinguish when the user is expecting a full reset of the target screen, vs. simply re-displaying it. --- addons/point_of_sale/static/src/js/gui.js | 2 +- addons/point_of_sale/static/src/js/screens.js | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/addons/point_of_sale/static/src/js/gui.js b/addons/point_of_sale/static/src/js/gui.js index 11da0b4441f..360414c9b06 100644 --- a/addons/point_of_sale/static/src/js/gui.js +++ b/addons/point_of_sale/static/src/js/gui.js @@ -114,7 +114,7 @@ var Gui = core.Class.extend({ this.current_screen.hide(); } this.current_screen = screen; - this.current_screen.show(); + this.current_screen.show(refresh); } }, diff --git a/addons/point_of_sale/static/src/js/screens.js b/addons/point_of_sale/static/src/js/screens.js index ebdf2ec5762..a559ea7e7cc 100644 --- a/addons/point_of_sale/static/src/js/screens.js +++ b/addons/point_of_sale/static/src/js/screens.js @@ -938,10 +938,12 @@ var ProductScreenWidget = ScreenWidget.extend({ } }, - show: function(){ + show: function(reset){ this._super(); - this.product_categories_widget.reset_category(); - this.numpad.state.reset(); + if (reset) { + this.product_categories_widget.reset_category(); + this.numpad.state.reset(); + } }, close: function(){ From 43a0decb3aa9571643d3d206796937f13a11f059 Mon Sep 17 00:00:00 2001 From: Olivier Dony Date: Wed, 14 Dec 2016 13:32:14 +0100 Subject: [PATCH 03/21] [FIX] point_of_sale: correct typo in order pricelist selection Typo introduced in 44f9e923c29bb96b28db6df12f0ff5b3d42d9558 prevented the selection of the correct non-default pricelist. --- addons/point_of_sale/point_of_sale.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/point_of_sale/point_of_sale.py b/addons/point_of_sale/point_of_sale.py index 668e6a03e63..7ae4d7141f9 100644 --- a/addons/point_of_sale/point_of_sale.py +++ b/addons/point_of_sale/point_of_sale.py @@ -932,7 +932,7 @@ class pos_order(osv.osv): # set name based on the sequence specified on the config session = self.pool['pos.session'].browse(cr, uid, values['session_id'], context=context) values['name'] = session.config_id.sequence_id._next() - values.setdefault('session_id', session.config_id.pricelist_id.id) + values.setdefault('pricelist_id', session.config_id.pricelist_id.id) else: # fallback on any pos.order sequence values['name'] = self.pool.get('ir.sequence').next_by_code(cr, uid, 'pos.order', context=context) From e892c574825c19598fe3c243fcb651f8b6d50d0f Mon Sep 17 00:00:00 2001 From: Olivier Dony Date: Fri, 2 Dec 2016 10:22:40 +0100 Subject: [PATCH 04/21] [FIX] point_of_sale: repair rescue session system Rev 87a3fe92de43dd7fce7e3364a5ca8dbb417ca7f8 revamped the rescue session system in an attempt to simplify it, but created new problems. The rescue system is designed for accepting POS orders that belong to a POS session that is already closed. After 87a3fe92de43dd7fce7e3364a5ca8dbb417ca7f8: - The system tried to automatically reuse an existing session that matches the properties of the closed one. This will often come as a surprise to the POS users, with orders appearing from nowhere in a live session, possibly invalidating the cash control steps, etc. Using a separate new session with an obvious "RESCUE" name is much better for users. They will be able to review the rescued order separately as well. - When no open session was available, the system tried to create a new one (without the rescue flag). This could often fail because existing sessions could conflict with the new one, completely breaking the recovery. (E.g. a session from the same POS but with a different user) The rescue flag was designed to avoid this pitfall, allowing multiple extra rescue sessions to coexist with live ones. This patch restores the use of the RESCUE flag for recovery sessions, and forces the creation of a new session for every recovered session. Recovery sessions will also be labelled as "RESCUE" now, making it things more obvious for end users. --- addons/point_of_sale/point_of_sale.py | 45 +++++++++++---------------- 1 file changed, 19 insertions(+), 26 deletions(-) diff --git a/addons/point_of_sale/point_of_sale.py b/addons/point_of_sale/point_of_sale.py index 7ae4d7141f9..02869ce33e8 100644 --- a/addons/point_of_sale/point_of_sale.py +++ b/addons/point_of_sale/point_of_sale.py @@ -536,8 +536,12 @@ class pos_session(osv.osv): } statements.append(create_statement(st_values, context=context)) + unique_name = self.pool['ir.sequence'].next_by_code(cr, uid, 'pos.session', context=context) + if values.get('name'): + unique_name += ' ' + values['name'] + values.update({ - 'name': self.pool['ir.sequence'].next_by_code(cr, uid, 'pos.session', context=context), + 'name': unique_name, 'statement_ids': [(6, 0, statements)], 'config_id': config_id }) @@ -681,41 +685,30 @@ class pos_order(osv.osv): } # This deals with orders that belong to a closed session. In order - # to recover from this we: - # - assign the order to another compatible open session - # - if that doesn't exist, create a new one + # to recover from this situation we create a new rescue session, + # making it obvious that something went wrong. + # A new, separate, rescue session is preferred for every such recovery, + # to avoid adding unrelated orders to live sessions. def _get_valid_session(self, cr, uid, order, context=None): session = self.pool.get('pos.session') closed_session = session.browse(cr, uid, order['pos_session_id'], context=context) - open_sessions = session.search(cr, uid, [('state', '=', 'opened'), - ('config_id', '=', closed_session.config_id.id), - ('user_id', '=', closed_session.user_id.id)], - limit=1, order="start_at DESC", context=context) - _logger.warning('session %s (ID: %s) was closed but received order %s (total: %s) belonging to it', closed_session.name, closed_session.id, order['name'], order['amount_total']) + _logger.warning('attempting to create recovery session for saving order %s', order['name']) + new_session_id = session.create(cr, uid, { + 'config_id': closed_session.config_id.id, + 'name': _('(RESCUE FOR %(session)s)') % {'session': closed_session.name}, + 'rescue': True, # avoid conflict with live sessions + }, context=context) + new_session = session.browse(cr, uid, new_session_id, context=context) - if open_sessions: - open_session = session.browse(cr, uid, open_sessions[0], context=context) - _logger.warning('using session %s (ID: %s) for order %s instead', - open_session.name, - open_session.id, - order['name']) - return open_session.id - else: - _logger.warning('attempting to create new session for order %s', order['name']) - new_session_id = session.create(cr, uid, { - 'config_id': closed_session.config_id.id, - }, context=context) - new_session = session.browse(cr, uid, new_session_id, context=context) + # bypass opening_control (necessary when using cash control) + new_session.signal_workflow('open') - # bypass opening_control (necessary when using cash control) - new_session.signal_workflow('open') - - return new_session_id + return new_session_id def _match_payment_to_invoice(self, cr, uid, order, context=None): account_precision = self.pool.get('decimal.precision').precision_get(cr, uid, 'Account') From 110140993764db76124555ff4afb285b673e8c32 Mon Sep 17 00:00:00 2001 From: Olivier Dony Date: Wed, 14 Dec 2016 13:30:34 +0100 Subject: [PATCH 05/21] [FIX] point_of_sale: reuse cashbox instead of always creating one Version 9.0 comes with a revamped accounting system, and the cashbox system for cash control on bank statements was changed in the process. The POS App was updated to use the new system, but failed to reuse the existing cashbox control if one already existed. This worked as expected on bank statements directly, but not on POS sessions where a new cash control had to be input every time. This fix requires an update of the views, but works in a backwards compatible manner. Users who do not sync their view definitions will still be able to work (but will still experience the bug). --- addons/point_of_sale/point_of_sale.py | 29 +++++++++++++++++++++ addons/point_of_sale/point_of_sale_view.xml | 8 +++--- 2 files changed, 33 insertions(+), 4 deletions(-) diff --git a/addons/point_of_sale/point_of_sale.py b/addons/point_of_sale/point_of_sale.py index 02869ce33e8..86a2764a005 100644 --- a/addons/point_of_sale/point_of_sale.py +++ b/addons/point_of_sale/point_of_sale.py @@ -645,6 +645,35 @@ class pos_session(osv.osv): 'url': '/pos/web/', } + @api.multi + def open_cashbox(self): + self.ensure_one() + context = dict(self._context) + balance_type = context.get('balance') or 'start' + context['bank_statement_id'] = self.cash_register_id.id + context['balance'] = balance_type + + action = { + 'name': _('Cash Control'), + 'view_type': 'form', + 'view_mode': 'form', + 'res_model': 'account.bank.statement.cashbox', + 'view_id': self.env.ref('account.view_account_bnk_stmt_cashbox').id, + 'type': 'ir.actions.act_window', + 'context': context, + 'target': 'new' + } + + cashbox_id = None + if balance_type == 'start': + cashbox_id = self.cash_register_id.cashbox_start_id.id + else: + cashbox_id = self.cash_register_id.cashbox_end_id.id + if cashbox_id: + action['res_id'] = cashbox_id + + return action + class pos_order(osv.osv): _name = "pos.order" _description = "Point of Sale" diff --git a/addons/point_of_sale/point_of_sale_view.xml b/addons/point_of_sale/point_of_sale_view.xml index dd8234f298d..33850ed8404 100644 --- a/addons/point_of_sale/point_of_sale_view.xml +++ b/addons/point_of_sale/point_of_sale_view.xml @@ -814,18 +814,18 @@ Money Out - - From 57788ddb6714f8bd42d3a2399352fe261a47cb61 Mon Sep 17 00:00:00 2001 From: Stefan Rijnhart Date: Wed, 20 Jul 2016 14:03:31 +0200 Subject: [PATCH 06/21] [FIX] stock: add missing context when creating procurement order Closes #12858 --- addons/stock/wizard/make_procurement_product.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/stock/wizard/make_procurement_product.py b/addons/stock/wizard/make_procurement_product.py index bef04a3db68..7fd7f44c740 100644 --- a/addons/stock/wizard/make_procurement_product.py +++ b/addons/stock/wizard/make_procurement_product.py @@ -77,7 +77,7 @@ class make_procurement(osv.osv_memory): 'warehouse_id': proc.warehouse_id.id, 'location_id': wh.lot_stock_id.id, 'company_id': wh.company_id.id, - }) + }, context=context) procurement_obj.signal_workflow(cr, uid, [procure_id], 'button_confirm') id2 = data_obj._get_id(cr, uid, 'procurement', 'procurement_tree_view') From 4f6e4bb28e113e47038a1a1ff1947a94c178b39d Mon Sep 17 00:00:00 2001 From: Stefan Rijnhart Date: Tue, 8 Mar 2016 18:37:58 +0100 Subject: [PATCH 07/21] [FIX] account: use code from defaults dict if present Do not force a ugly '... (copy)' code if provides one. Closes #11260 --- addons/account/account.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/account/account.py b/addons/account/account.py index 2bae5c5c7e4..e1d41fe919e 100644 --- a/addons/account/account.py +++ b/addons/account/account.py @@ -642,7 +642,7 @@ class account_account(osv.osv): done_list = [] account = self.browse(cr, uid, id, context=context) new_child_ids = [] - default.update(code=_("%s (copy)") % (account['code'] or '')) + default.setdefault('code', _("%s (copy)") % (account['code'] or '')) if not local: done_list = [] if account.id in done_list: From 3ac2904b46628fead1479f65aa2c81c6dc266888 Mon Sep 17 00:00:00 2001 From: Cyril Gaudin Date: Tue, 23 Aug 2016 15:00:43 +0200 Subject: [PATCH 08/21] [FIX] report: missing context v7 signature The v8 call uses `context=self._context` Private method so should be ok to modify the signature. Closes #13263 --- addons/report/models/report.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/addons/report/models/report.py b/addons/report/models/report.py index 3e14f1dffca..0bd99c26ed8 100644 --- a/addons/report/models/report.py +++ b/addons/report/models/report.py @@ -192,7 +192,7 @@ class Report(osv.Model): # Get the ir.actions.report.xml record we are working on. report = self._get_report_from_name(cr, uid, report_name) # Check if we have to save the report or if we have to get one from the db. - save_in_attachment = self._check_attachment_use(cr, uid, ids, report) + save_in_attachment = self._check_attachment_use(cr, uid, ids, report, context=context) # Get the paperformat associated to the report, otherwise fallback on the company one. if not report.paperformat_id: user = self.pool['res.users'].browse(cr, uid, uid) @@ -311,7 +311,7 @@ class Report(osv.Model): # Report generation helpers #-------------------------------------------------------------------------- @api.v7 - def _check_attachment_use(self, cr, uid, ids, report): + def _check_attachment_use(self, cr, uid, ids, report, context=None): """ Check attachment_use field. If set to true and an existing pdf is already saved, load this one now. Else, mark save it. """ @@ -320,7 +320,7 @@ class Report(osv.Model): save_in_attachment['loaded_documents'] = {} if report.attachment: - records = self.pool[report.model].browse(cr, uid, ids) + records = self.pool[report.model].browse(cr, uid, ids, context=context) filenames = self._attachment_filename(cr, uid, records, report) attachments = None if report.attachment_use: From f6692139da96bf25ed0699157e53254373607415 Mon Sep 17 00:00:00 2001 From: Jairo Llopis Date: Wed, 3 Aug 2016 10:48:53 +0200 Subject: [PATCH 09/21] [FIX] event: add missing name attribute This breaks nothing, but allows to enable this filter by default. Closes #12997 --- addons/event/event_view.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/event/event_view.xml b/addons/event/event_view.xml index 3ee33e011b6..bf713b49fe4 100644 --- a/addons/event/event_view.xml +++ b/addons/event/event_view.xml @@ -273,7 +273,7 @@ - + @@ -424,7 +424,7 @@ - + From 13ed92c6d80e7e4ef45e368a5cd35c71f099c572 Mon Sep 17 00:00:00 2001 From: Martin Trigaux Date: Wed, 14 Dec 2016 15:53:03 +0100 Subject: [PATCH 10/21] [FIX] payment_transfer: untranslated string Replaces and closes #12787 --- .../payment_transfer/i18n/payment_transfer.pot | 17 +++++++++++++++-- .../payment_transfer/models/payment_acquirer.py | 4 ++-- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/addons/payment_transfer/i18n/payment_transfer.pot b/addons/payment_transfer/i18n/payment_transfer.pot index c7576b07d9b..21284df9640 100644 --- a/addons/payment_transfer/i18n/payment_transfer.pot +++ b/addons/payment_transfer/i18n/payment_transfer.pot @@ -6,8 +6,8 @@ msgid "" msgstr "" "Project-Id-Version: Odoo Server 8.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2015-09-05 12:00+0000\n" -"PO-Revision-Date: 2015-09-05 12:00+0000\n" +"POT-Creation-Date: 2016-12-14 14:52+0000\n" +"PO-Revision-Date: 2016-12-14 14:52+0000\n" "Last-Translator: <>\n" "Language-Team: \n" "MIME-Version: 1.0\n" @@ -15,6 +15,18 @@ msgstr "" "Content-Transfer-Encoding: \n" "Plural-Forms: \n" +#. module: payment_transfer +#: code:addons/payment_transfer/models/payment_acquirer.py:32 +#, python-format +msgid "
\n" +"

Please use the following transfer details

\n" +"

%(bank_title)s

\n" +"%(bank_accounts)s\n" +"

Communication

\n" +"

Please use the order name as communication reference.

\n" +"
" +msgstr "" + #. module: payment_transfer #: model:payment.acquirer,pre_msg:payment_transfer.payment_acquirer_transfer msgid "

Transfer information will be provided after choosing the payment mode.

\n" @@ -45,6 +57,7 @@ msgstr "" #. module: payment_transfer #: code:addons/payment_transfer/models/payment_acquirer.py:19 +#: model:payment.acquirer,name:payment_transfer.payment_acquirer_transfer #, python-format msgid "Wire Transfer" msgstr "" diff --git a/addons/payment_transfer/models/payment_acquirer.py b/addons/payment_transfer/models/payment_acquirer.py index 2abdb541f1e..e2d9e0cefc6 100644 --- a/addons/payment_transfer/models/payment_acquirer.py +++ b/addons/payment_transfer/models/payment_acquirer.py @@ -29,13 +29,13 @@ class TransferPaymentAcquirer(osv.Model): accounts = self.pool['res.partner.bank'].name_get(cr, uid, bank_ids, context=context) bank_title = _('Bank Accounts') if len(accounts) > 1 else _('Bank Account') bank_accounts = ''.join(['
    '] + ['
  • %s
  • ' % name for id, name in accounts] + ['
']) - post_msg = '''
+ post_msg = _('''

Please use the following transfer details

%(bank_title)s

%(bank_accounts)s

Communication

Please use the order name as communication reference.

-
''' % { +
''') % { 'bank_title': bank_title, 'bank_accounts': bank_accounts, } From 8d43fc46f29c343bf3d1f8c6c5a09ff1a0de58e9 Mon Sep 17 00:00:00 2001 From: "Laurent Mignon (ACSONE)" Date: Wed, 12 Oct 2016 13:37:52 +0200 Subject: [PATCH 11/21] [FIX] report: add missing context This PR allow to use the context to specify contextual informations used in the create method of ir.attachement. Closes #13790 --- addons/report/models/report.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/addons/report/models/report.py b/addons/report/models/report.py index 0bd99c26ed8..0cc0b81ad81 100644 --- a/addons/report/models/report.py +++ b/addons/report/models/report.py @@ -265,7 +265,8 @@ class Report(osv.Model): return self._run_wkhtmltopdf( cr, uid, headerhtml, footerhtml, contenthtml, context.get('landscape'), paperformat, specific_paperformat_args, save_in_attachment, - context.get('set_viewport_size') + context.get('set_viewport_size'), + context ) @api.v8 @@ -372,7 +373,7 @@ class Report(osv.Model): def _check_wkhtmltopdf(self): return wkhtmltopdf_state - def _run_wkhtmltopdf(self, cr, uid, headers, footers, bodies, landscape, paperformat, spec_paperformat_args=None, save_in_attachment=None, set_viewport_size=False): + def _run_wkhtmltopdf(self, cr, uid, headers, footers, bodies, landscape, paperformat, spec_paperformat_args=None, save_in_attachment=None, set_viewport_size=False, context=None): """Execute wkhtmltopdf as a subprocess in order to convert html given in input into a pdf document. @@ -475,7 +476,7 @@ class Report(osv.Model): 'res_id': reporthtml[0], } try: - self.pool['ir.attachment'].create(cr, uid, attachment) + self.pool['ir.attachment'].create(cr, uid, attachment, context) except AccessError: _logger.info("Cannot save PDF report %r as attachment", attachment['name']) else: From 450f7df00d49d3a9a7dc810e6744292600ea8091 Mon Sep 17 00:00:00 2001 From: Jordan Vrtanoski Date: Sat, 7 May 2016 15:54:32 +0400 Subject: [PATCH 12/21] [FIX] web: transfer context to underlying many2one in reference field Fixes #11955 (loss of context in many2one subwidget) Closes #11957 --- addons/web/static/src/js/view_form.js | 1 + 1 file changed, 1 insertion(+) diff --git a/addons/web/static/src/js/view_form.js b/addons/web/static/src/js/view_form.js index 1555caf454e..3d84cd44c9a 100644 --- a/addons/web/static/src/js/view_form.js +++ b/addons/web/static/src/js/view_form.js @@ -5570,6 +5570,7 @@ instance.web.form.FieldReference = instance.web.form.AbstractField.extend(instan this.m2o = new instance.web.form.FieldMany2One(fm, { attrs: { name: 'Referenced Document', modifiers: JSON.stringify({readonly: this.get('effective_readonly')}), + context: this.build_context().eval(), }}); this.m2o.on("change:value", this, this.data_changed); this.m2o.appendTo(this.$(".oe_form_view_reference_m2o")); From 8e3e7874ad140c0e8676d6998aa8f3cb306979c2 Mon Sep 17 00:00:00 2001 From: Raphael Collet Date: Thu, 15 Dec 2016 09:52:21 +0100 Subject: [PATCH 13/21] [FIX] models: allow constraint methods triggered by function fields --- openerp/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openerp/models.py b/openerp/models.py index 3b1b46dedb8..f20eae7ecf5 100644 --- a/openerp/models.py +++ b/openerp/models.py @@ -749,7 +749,7 @@ class BaseModel(object): for name in func._constrains: if name not in cls._fields: _logger.warning("method %s.%s: @constrains parameter %r is not a field name", cls._name, attr, name) - if not cls._fields[name].store: + if not cls._fields[name].column: _logger.warning("method %s.%s: @constrains parameter %r is not stored", cls._name, attr, name) methods.append(func) From 64249936e82926353350a0db8490eb6b17fe5941 Mon Sep 17 00:00:00 2001 From: Raphael Collet Date: Thu, 15 Dec 2016 11:08:13 +0100 Subject: [PATCH 14/21] [FIX] models: allow constraint methods triggered by function fields --- openerp/models.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/openerp/models.py b/openerp/models.py index f20eae7ecf5..b13139de47f 100644 --- a/openerp/models.py +++ b/openerp/models.py @@ -747,10 +747,11 @@ class BaseModel(object): methods = [] for attr, func in getmembers(cls, is_constraint): for name in func._constrains: - if name not in cls._fields: + field = cls._fields.get(name) + if not field: _logger.warning("method %s.%s: @constrains parameter %r is not a field name", cls._name, attr, name) - if not cls._fields[name].column: - _logger.warning("method %s.%s: @constrains parameter %r is not stored", cls._name, attr, name) + if not (field.store or field.column and field.column._fnct_inv): + _logger.warning("method %s.%s: @constrains parameter %r is not writeable", cls._name, attr, name) methods.append(func) # optimization: memoize result on cls, it will not be recomputed From c7fc8e172240f72cdd6f89a246fd9122323257f6 Mon Sep 17 00:00:00 2001 From: Hans Henrik Gabelgaard Date: Fri, 6 May 2016 14:39:53 +0200 Subject: [PATCH 15/21] [CLA] signature for hhgabelgaard cf #11947 --- doc/cla/individual/hhgabelgaard.md | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 doc/cla/individual/hhgabelgaard.md diff --git a/doc/cla/individual/hhgabelgaard.md b/doc/cla/individual/hhgabelgaard.md new file mode 100644 index 00000000000..e873ef3f5e4 --- /dev/null +++ b/doc/cla/individual/hhgabelgaard.md @@ -0,0 +1,11 @@ +Denmark, 2016-05-06 + +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, + +Hans Henrik Gabelgaard hhg@gabelgaard.org https://github.com/hhgabelgaard \ No newline at end of file From 638989b84e1119e10e6b2f2d33aab683ceef4aa5 Mon Sep 17 00:00:00 2001 From: Hans Henrik Gabelgaard Date: Fri, 6 May 2016 09:32:19 +0200 Subject: [PATCH 16/21] [FIX] mail: keep recipients after saving a template When sending an email via the mail.compose wizard, the selected partners are stored in the context (`active_ids`). If the composed message is saved (button "save template"), the context is lost in the _reopen action. The active_ids content of the new context is the id of the newly created mail template and is used as the id of a res.partner (sending the email to a different contact). Keep the context during the reopen to avoid losing active_ids. Closes #11947 --- .../email_template/wizard/mail_compose_message.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/addons/email_template/wizard/mail_compose_message.py b/addons/email_template/wizard/mail_compose_message.py index 60b3b0d3af0..fcc4441abf1 100644 --- a/addons/email_template/wizard/mail_compose_message.py +++ b/addons/email_template/wizard/mail_compose_message.py @@ -23,18 +23,17 @@ from openerp import tools from openerp.osv import osv, fields -def _reopen(self, res_id, model): +def _reopen(self, res_id, model, context=None): + # save original model in context, because selecting the list of available + # templates requires a model in context + context = dict(context or {}, default_model=model) return {'type': 'ir.actions.act_window', 'view_mode': 'form', 'view_type': 'form', 'res_id': res_id, 'res_model': self._name, 'target': 'new', - # save original model in context, because selecting the list of available - # templates requires a model in context - 'context': { - 'default_model': model, - }, + 'context': context, } @@ -148,7 +147,7 @@ class mail_compose_message(osv.TransientModel): template_values = record.onchange_template_id(template_id, record.composition_mode, record.model, record.res_id)['value'] template_values['template_id'] = template_id record.write(template_values) - return _reopen(self, record.id, record.model) + return _reopen(self, record.id, record.model, context=context) #------------------------------------------------------ # Wizard validation and send From e0c9b9c2cd4f0a2d965d27b4f241d941e5bcd8a7 Mon Sep 17 00:00:00 2001 From: Martin Trigaux Date: Thu, 15 Dec 2016 14:41:37 +0100 Subject: [PATCH 17/21] [IMP] point_of_sale: more informative error The pos loading crashes in the following scenario. 1. start selling a product (order line the localstorage) 2. archive or delete the product in backend 3. reload the pos session The POS is interrupted with not much information. Give an error a bit more meaningful. --- addons/point_of_sale/static/src/js/models.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/addons/point_of_sale/static/src/js/models.js b/addons/point_of_sale/static/src/js/models.js index 219f6c75cfa..3880049e6d3 100644 --- a/addons/point_of_sale/static/src/js/models.js +++ b/addons/point_of_sale/static/src/js/models.js @@ -1081,7 +1081,8 @@ exports.Orderline = Backbone.Model.extend({ init_from_JSON: function(json) { this.product = this.pos.db.get_product_by_id(json.product_id); if (!this.product) { - console.error('ERROR: attempting to recover product not available in the point of sale'); + console.error('ERROR: attempting to recover product ID', json.product_id, + 'not available in the point of sale. Correct the product or clean the browser cache.'); } this.price = json.price_unit; this.set_discount(json.discount); From 9fd715e1f5d2f62c940c8d9d5f184110be493a97 Mon Sep 17 00:00:00 2001 From: Denis Ledoux Date: Fri, 16 Dec 2016 11:19:49 +0100 Subject: [PATCH 18/21] [FIX] account_analytic_default: invoice, avoid account overwrite Due to the following revision: bdf630f9b89a3d47c3826dac6fe9a04e6aa701d5 When creating an invoice from a purchase order with an analytic account set, the analytic account was no longer copied on the invoice, as the analytic account that was added thanks to https://github.com/odoo/odoo/blob/9.0/addons/purchase/invoice.py#L53 was overwritten with `False` as `rec` was False or if `rec` was True, it was overwritten with the analytic account of `rec`. opw-697702 --- .../account_analytic_default/account_analytic_default.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/addons/account_analytic_default/account_analytic_default.py b/addons/account_analytic_default/account_analytic_default.py index d6b94b446ed..8a1f09d2f37 100644 --- a/addons/account_analytic_default/account_analytic_default.py +++ b/addons/account_analytic_default/account_analytic_default.py @@ -71,12 +71,11 @@ class account_invoice_line(osv.osv): return res def _set_additional_fields(self, invoice): - rec = self.env['account.analytic.default'].account_get(self.product_id.id, self.invoice_id.partner_id.id, self._uid, + if not self.account_analytic_id: + rec = self.env['account.analytic.default'].account_get(self.product_id.id, self.invoice_id.partner_id.id, self._uid, time.strftime('%Y-%m-%d'), company_id=self.company_id.id, context=self._context) - if rec: - self.account_analytic_id = rec.analytic_id.id - else: - self.account_analytic_id = False + if rec: + self.account_analytic_id = rec.analytic_id.id super(account_invoice_line, self)._set_additional_fields(invoice) class stock_picking(osv.osv): From 20935462a0cabeb45480ce70114ff2f4e91eaf79 Mon Sep 17 00:00:00 2001 From: Denis Ledoux Date: Fri, 16 Dec 2016 14:21:38 +0100 Subject: [PATCH 19/21] [FIX] account: register payment with change gain with currency rate > 100 On an invoice, when registering a payment in a foreign currency for which the payment pays entirely the invoice, and even more thanks to the change gain(write off), but for which the foreign currency rate to the company currency is higher than 100, (higher than the currency decimal precision of 2 digts), e.g. Invoice in CDF, Payment in USD (1 USD = 948 CDF), and choosing the option "Mark invoice as fully paid" for the difference handling, the invoice could not be marked as paid, according to the result of the currency rate rounding. This is because the debit or credit of the writeoff was computed from the payment difference, in the foreign currency, to the company currency, which lead to two currency rate computation, one in each way, company currency to foreign currency, then foreign currency to company currency, and some precision was lost in the process. Instead of computing the debit or credit of the writeoff from the payment difference, we now compute it from the payment amount in the company currency minus the invoice residual amount in the company currency, to avoid the double currency computation rate, so the precision is not lost in the process, and the invoice move is finally fully reconciled e.g.: Invoice of 247590.40 FC Payment of 267 USD (1 USD = 948 FC) Payment difference: (247590,40 / 948) - 267 = -5.83 (Gain of 5.83 USD) Before the revision, the credit of the writeoff was computed as: `((247590,40 FC / 948) - 267 USD) * 948 = 5526,84` After the revision, the credit of the writeoff is computed: `247590.40 - (267 * 948) = 5525.6` Notice in the first formula that the rate computation is performed two times, once in each way (`/948` then `*948`), while only once in the second, and this avoid the loss of 1.24 FC in the process. Without this precise debit/credit of the writeoff, the invoice could not be marked as fully paid, as the move was not fully reconciled. opw-687201 --- addons/account/models/account_payment.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/addons/account/models/account_payment.py b/addons/account/models/account_payment.py index 7320c2c795b..454cb4ad5f9 100644 --- a/addons/account/models/account_payment.py +++ b/addons/account/models/account_payment.py @@ -384,7 +384,12 @@ class account_payment(models.Model): #Reconcile with the invoices if self.payment_difference_handling == 'reconcile' and self.payment_difference: writeoff_line = self._get_shared_move_line_vals(0, 0, 0, move.id, False) - debit_wo, credit_wo, amount_currency_wo, currency_id = aml_obj.with_context(date=self.payment_date).compute_amount_fields(self.payment_difference, self.currency_id, self.company_id.currency_id, invoice_currency) + amount_currency_wo, currency_id = aml_obj.with_context(date=self.payment_date).compute_amount_fields(self.payment_difference, self.currency_id, self.company_id.currency_id, invoice_currency)[2:] + total_residual_company_signed = sum(invoice.residual_company_signed for invoice in self.invoice_ids) + total_payment_company_signed = self.currency_id.with_context(date=self.payment_date).compute(self.amount, self.company_id.currency_id) + amount_wo = total_residual_company_signed - total_payment_company_signed + debit_wo = amount_wo > 0 and amount_wo or 0.0 + credit_wo = amount_wo < 0 and -amount_wo or 0.0 writeoff_line['name'] = _('Counterpart') writeoff_line['account_id'] = self.writeoff_account_id.id writeoff_line['debit'] = debit_wo From cee2e62b6f2732a4f4560951218d0672ff67bdb5 Mon Sep 17 00:00:00 2001 From: Denis Ledoux Date: Fri, 16 Dec 2016 14:59:02 +0100 Subject: [PATCH 20/21] [FIX] account: add comment for the previous revision It has been done outside of the previous commit to give the possibility to point the comment to the according revision, as this is a really tricky case. opw-687201 --- addons/account/models/account_payment.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/addons/account/models/account_payment.py b/addons/account/models/account_payment.py index 454cb4ad5f9..486c7eba0ab 100644 --- a/addons/account/models/account_payment.py +++ b/addons/account/models/account_payment.py @@ -385,6 +385,9 @@ class account_payment(models.Model): if self.payment_difference_handling == 'reconcile' and self.payment_difference: writeoff_line = self._get_shared_move_line_vals(0, 0, 0, move.id, False) amount_currency_wo, currency_id = aml_obj.with_context(date=self.payment_date).compute_amount_fields(self.payment_difference, self.currency_id, self.company_id.currency_id, invoice_currency)[2:] + # the writeoff debit and credit must be computed from the invoice residual in company currency + # minus the payment amount in company currency, and not from the payment difference in the payment currency + # to avoid loss of precision during the currency rate computations. See revision 20935462a0cabeb45480ce70114ff2f4e91eaf79 for a detailed example. total_residual_company_signed = sum(invoice.residual_company_signed for invoice in self.invoice_ids) total_payment_company_signed = self.currency_id.with_context(date=self.payment_date).compute(self.amount, self.company_id.currency_id) amount_wo = total_residual_company_signed - total_payment_company_signed From 1246a470df5b8dee2845ebe8639076d2a715c341 Mon Sep 17 00:00:00 2001 From: Christophe Simonis Date: Fri, 16 Dec 2016 15:16:56 +0100 Subject: [PATCH 21/21] [FIX] mail: correct MailComposer wizard Oversight of previous forward-port. --- addons/mail/wizard/mail_compose_message.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/mail/wizard/mail_compose_message.py b/addons/mail/wizard/mail_compose_message.py index 50ac534dc18..79ab171c483 100644 --- a/addons/mail/wizard/mail_compose_message.py +++ b/addons/mail/wizard/mail_compose_message.py @@ -396,7 +396,7 @@ class MailComposer(models.TransientModel): # generate the saved template record.write({'template_id': template.id}) record.onchange_template_id_wrapper() - return _reopen(self, record.id, record.model, context=context) + return _reopen(self, record.id, record.model, context=self._context) #------------------------------------------------------ # Template rendering