From b0acb42f0ba18b8cf50377baf5509880d480a499 Mon Sep 17 00:00:00 2001 From: Josse Colpaert Date: Tue, 12 Dec 2017 10:55:18 +0100 Subject: [PATCH 1/8] [FIX] stock: avoid infinite or longer than necessary loops In some cases the MRP scheduler can remain blocked on an infinite loop consuming a lot of CPU. The reason comes from the loop 'Check done procurements' If a new procument is created from another process (such like MTO orders) during this loop, the process never ends. The only way to reproduce is in debug mode: 1. Put a breakpoint on line 'Check done procurements' 2. Launch the MRP scheduler manually and stay paused on the breakpoint 3. In parrallel, create and confirm a sale order with a MTO route, this will trigger the creation of a new procurement order in state 'Running' 4. Continue debugging step by step the scheduler and you will notice that the loop never ends. Closes #21565 opw-787651 --- addons/procurement/models/procurement.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/addons/procurement/models/procurement.py b/addons/procurement/models/procurement.py index dd8d1fdeece..b00ace616df 100644 --- a/addons/procurement/models/procurement.py +++ b/addons/procurement/models/procurement.py @@ -282,19 +282,19 @@ class ProcurementOrder(models.Model): ProcurementSudo = self.env['procurement.order'].sudo() # Run confirmed procurements procurements = ProcurementSudo.search([('state', '=', 'confirmed')] + (company_id and [('company_id', '=', company_id)] or [])) + run_procurements = [] while procurements: procurements.run(autocommit=use_new_cursor) + run_procurements.extend(procurements.ids) if use_new_cursor: self.env.cr.commit() - procurements = ProcurementSudo.search([('id', 'not in', procurements.ids), ('state', '=', 'confirmed')] + (company_id and [('company_id', '=', company_id)] or [])) + procurements = ProcurementSudo.search([('id', 'not in', run_procurements), ('state', '=', 'confirmed')] + (company_id and [('company_id', '=', company_id)] or [])) # Check done procurements procurements = ProcurementSudo.search([('state', '=', 'running')] + (company_id and [('company_id', '=', company_id)] or [])) - while procurements: - procurements.check(autocommit=use_new_cursor) - if use_new_cursor: - self.env.cr.commit() - procurements = ProcurementSudo.search([('id', 'not in', procurements.ids), ('state', '=', 'running')] + (company_id and [('company_id', '=', company_id)] or [])) + procurements.check(autocommit=use_new_cursor) + if use_new_cursor: + self.env.cr.commit() finally: if use_new_cursor: From 2a9e6e6a3b4b9593af96cf0495c8feaa970aaeb3 Mon Sep 17 00:00:00 2001 From: "Adrien Peiffer (ACSONE)" Date: Tue, 28 Nov 2017 15:37:56 +0100 Subject: [PATCH 2/8] [FIX] res_partner: bad sudo. Using sudo on super call can turn into infinite call in odoo. opw:785415 --- odoo/addons/base/res/res_partner.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/odoo/addons/base/res/res_partner.py b/odoo/addons/base/res/res_partner.py index 8e91a0b3ebd..9184a9ec68a 100644 --- a/odoo/addons/base/res/res_partner.py +++ b/odoo/addons/base/res/res_partner.py @@ -509,7 +509,7 @@ class Partner(models.Model, FormatAddress): result = True # To write in SUPERUSER on field is_company and avoid access rights problems. if 'is_company' in vals and self.user_has_groups('base.group_partner_manager') and not self.env.uid == SUPERUSER_ID: - result = super(Partner, self).sudo().write({'is_company': vals.get('is_company')}) + result = super(Partner, self.sudo()).write({'is_company': vals.get('is_company')}) del vals['is_company'] result = result and super(Partner, self).write(vals) for partner in self: From 30d0861f0a9c9079c3c2222ca6d1b2a2e33469c2 Mon Sep 17 00:00:00 2001 From: Wolfgang Taferner Date: Tue, 5 Dec 2017 09:35:42 +0100 Subject: [PATCH 3/8] [FIX] base: ir.sequence better fallback Zero is an non-acceptable value for sequences, so the fallback should be one instead. Fixes #21267 --- openerp/addons/base/ir/ir_sequence.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openerp/addons/base/ir/ir_sequence.py b/openerp/addons/base/ir/ir_sequence.py index 25728399b19..61997e23348 100644 --- a/openerp/addons/base/ir/ir_sequence.py +++ b/openerp/addons/base/ir/ir_sequence.py @@ -105,7 +105,7 @@ class ir_sequence(models.Model): def _set_number_next_actual(self): for record in self: - record.write({'number_next': record.number_next_actual or 0}) + record.write({'number_next': record.number_next_actual or 1}) name = fields.Char(required=True) code = fields.Char('Sequence Code') From b3be0b75764d6a0c45097f72cf9d38a459969646 Mon Sep 17 00:00:00 2001 From: Josse Colpaert Date: Thu, 7 Dec 2017 17:13:05 +0100 Subject: [PATCH 4/8] [FIX] stock: don't propagate cancel when chained move is done When you have e.g. an SO with a product MTO generating a manufacturing order, and you put the delivery order to done, before the MO is done, you can not cancel the MO anymore, because the cancel method checks if the move is not done. As the user stays blocked in this case, it is better to just not try to cancel the destination move by not propagating the cancel when the destination move is done. opw-786571 --- addons/stock/models/stock_move.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/addons/stock/models/stock_move.py b/addons/stock/models/stock_move.py index b9c52991a84..719bf08ea1a 100644 --- a/addons/stock/models/stock_move.py +++ b/addons/stock/models/stock_move.py @@ -669,7 +669,8 @@ class StockMove(models.Model): self.ensure_one() if self.move_dest_id: if self.propagate: - self.move_dest_id.action_cancel() + if self.move_dest_id.state not in ('done', 'cancel'): + self.move_dest_id.action_cancel() elif self.move_dest_id.state == 'waiting': # If waiting, the chain will be broken and we are not sure if we can still wait for it (=> could take from stock instead) self.move_dest_id.write({'state': 'confirmed'}) From 22f8660e2211fd84f84f530cfed29a594a228a02 Mon Sep 17 00:00:00 2001 From: Josse Colpaert Date: Mon, 11 Dec 2017 16:47:53 +0100 Subject: [PATCH 5/8] [FIX] stock: don't propagate cancel when chained move is done When you have e.g. an SO with a product MTO generating a manufacturing order, and you put the delivery order to done, before the MO is done, you can not cancel the MO anymore, because the cancel method checks if the move is not done (and raises an error). As the user stays blocked in this case, it is better to just not try to cancel the destination move by not propagating the cancel when the destination move is done. opw-786571 --- addons/stock/stock.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/addons/stock/stock.py b/addons/stock/stock.py index d95e34eca3b..45fe1e380d9 100644 --- a/addons/stock/stock.py +++ b/addons/stock/stock.py @@ -2532,7 +2532,8 @@ class stock_move(osv.osv): else: if move.move_dest_id: if move.propagate: - self.action_cancel(cr, uid, [move.move_dest_id.id], context=context) + if move.move_dest_id.state not in ('done', 'cancel'): + self.action_cancel(cr, uid, [move.move_dest_id.id], context=context) elif move.move_dest_id.state == 'waiting': #If waiting, the chain will be broken and we are not sure if we can still wait for it (=> could take from stock instead) self.write(cr, uid, [move.move_dest_id.id], {'state': 'confirmed'}, context=context) From d847a664157738fe896dc5636977489f2da2a7ff Mon Sep 17 00:00:00 2001 From: auyeung112002 Date: Tue, 28 Nov 2017 12:05:29 +0800 Subject: [PATCH 6/8] [FIX] web: Make search view dropdown menu scrollable --- addons/web/static/src/less/search_view.less | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/addons/web/static/src/less/search_view.less b/addons/web/static/src/less/search_view.less index a34905cb929..c50cd58be83 100644 --- a/addons/web/static/src/less/search_view.less +++ b/addons/web/static/src/less/search_view.less @@ -139,6 +139,9 @@ // Filters .o_filters_menu { .o-selected-li; + + max-height: ~"calc(100vh - 125px)"; + overflow: auto; .o_filter_condition { .o-search-options-dropdown-custom-li; @@ -175,6 +178,9 @@ // Group By .o_group_by_menu { .o-selected-li; + + max-height: ~"calc(100vh - 125px)"; + overflow: auto; .divider {display: none;} // hide the divider by default (no group) .o_add_group { // add button @@ -186,6 +192,9 @@ // Favorites .o_favorites_menu { .o-selected-li; + + max-height: ~"calc(100vh - 125px)"; + overflow: auto; .divider {display: none;} // hide the divider by default (no favorite) .o-searchview-custom-private, .o-searchview-custom-public { From b92aaf1e660d67c6b02974c9f059ca9026168e73 Mon Sep 17 00:00:00 2001 From: Martin Trigaux Date: Tue, 12 Dec 2017 16:20:02 +0100 Subject: [PATCH 7/8] [FIX] mail: display email of partner in the tags --- addons/mail/static/src/js/many2many_tags_email.js | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/addons/mail/static/src/js/many2many_tags_email.js b/addons/mail/static/src/js/many2many_tags_email.js index 4b273b456e1..dc1a405444c 100644 --- a/addons/mail/static/src/js/many2many_tags_email.js +++ b/addons/mail/static/src/js/many2many_tags_email.js @@ -82,6 +82,21 @@ var FieldMany2ManyTagsEmail = form_relational.FieldMany2ManyTags.extend({ }); }); }, + + /** + * Override for res.partner + * name_get is dynamic (based on context) while display_name is static + * (stored) + */ + get_render_data: function(ids){ + this.dataset.cancel_read(); + return this.dataset.name_get(ids).then(function (names) { + return _.map(names, function(name) { + return {id: name[0], display_name: name[1]}; + }); + }); + }, + }); From 1022e4fb25c71c7b653f81912d2afb2214a4f279 Mon Sep 17 00:00:00 2001 From: Christophe Simonis Date: Wed, 13 Dec 2017 15:17:22 +0100 Subject: [PATCH 8/8] [MERGE] forward port branch 9.0 up to 22f8660e221 Works better when you add files... --- odoo/addons/base/ir/ir_sequence.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/odoo/addons/base/ir/ir_sequence.py b/odoo/addons/base/ir/ir_sequence.py index 5431a33eac2..140ff7e01bd 100644 --- a/odoo/addons/base/ir/ir_sequence.py +++ b/odoo/addons/base/ir/ir_sequence.py @@ -96,7 +96,7 @@ class IrSequence(models.Model): def _set_number_next_actual(self): for seq in self: - seq.write({'number_next': seq.number_next_actual or 0}) + seq.write({'number_next': seq.number_next_actual or 1}) name = fields.Char(required=True) code = fields.Char(string='Sequence Code') @@ -309,7 +309,7 @@ class IrSequenceDateRange(models.Model): def _set_number_next_actual(self): for seq in self: - seq.write({'number_next': seq.number_next_actual or 0}) + seq.write({'number_next': seq.number_next_actual or 1}) date_from = fields.Date(string='From', required=True) date_to = fields.Date(string='To', required=True)