From ce11312dba5f796b2c5769d66433aad103f30766 Mon Sep 17 00:00:00 2001 From: Martin Trigaux Date: Wed, 12 Jul 2017 09:36:57 +0200 Subject: [PATCH 01/16] [FIX] doc: remove nonexistant reference business removed at 411f8208 --- doc/index.rst | 1 - 1 file changed, 1 deletion(-) diff --git a/doc/index.rst b/doc/index.rst index dcdd6ab752b..21231b7ce3f 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -17,7 +17,6 @@ Index api_integration setup reference - business .. ifconfig:: todo_include_todos From a6f2dc07e5abded193a5f0808408314043e940f9 Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Wed, 12 Jul 2017 09:28:02 +0200 Subject: [PATCH 02/16] [FIX] sale: traceback when choosing a product with warning as order.line If a user chooses a product that has a blocking error message, the product is set to False. This is good, but we do not want the following to happen: The other onchange triggers are called and "product_uom_change" generates an error because there is no product. (In fact it is "_compute_price_rule" on "product.pricelist" who raise) The onchange update the values of the other fields related to the product (eg for the "name" field where the name of the product that is canceled by the warning is assigned). --- addons/sale/models/sale.py | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/addons/sale/models/sale.py b/addons/sale/models/sale.py index f73235bc361..d512037e445 100644 --- a/addons/sale/models/sale.py +++ b/addons/sale/models/sale.py @@ -878,6 +878,21 @@ class SaleOrderLine(models.Model): uom=self.product_uom.id ) + result = {'domain': domain} + + title = False + message = False + warning = {} + if product.sale_line_warn != 'no-message': + title = _("Warning for %s") % product.name + message = product.sale_line_warn_msg + warning['title'] = title + warning['message'] = message + result = {'warning': warning} + if product.sale_line_warn == 'block': + self.product_id = False + return result + name = product.name_get()[0][1] if product.description_sale: name += '\n' + product.description_sale @@ -889,22 +904,11 @@ class SaleOrderLine(models.Model): vals['price_unit'] = self.env['account.tax']._fix_tax_included_price(self._get_display_price(product), product.taxes_id, self.tax_id) self.update(vals) - title = False - message = False - warning = {} - if product.sale_line_warn != 'no-message': - title = _("Warning for %s") % product.name - message = product.sale_line_warn_msg - warning['title'] = title - warning['message'] = message - if product.sale_line_warn == 'block': - self.product_id = False - return {'warning': warning} - return {'domain': domain} + return result @api.onchange('product_uom', 'product_uom_qty') def product_uom_change(self): - if not self.product_uom: + if not self.product_uom or not self.product_id: self.price_unit = 0.0 return if self.order_id.pricelist_id and self.order_id.partner_id: From 4001aaf2c47d3e7e6334aaa453f58054b98ee864 Mon Sep 17 00:00:00 2001 From: Sylvain LE GAL Date: Wed, 12 Jul 2017 09:58:34 +0200 Subject: [PATCH 03/16] [FIX] l10n_fr_certification : fix string_to_hash computation - use datas of all lines, and not only the last lines. - removed useless 'move_id' field from account.move.line Was PR #18175. Courtesy of Sylvain Legal --- addons/l10n_fr_certification/models/account.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/addons/l10n_fr_certification/models/account.py b/addons/l10n_fr_certification/models/account.py index bef0880d7ca..07d5fc04e41 100644 --- a/addons/l10n_fr_certification/models/account.py +++ b/addons/l10n_fr_certification/models/account.py @@ -10,7 +10,7 @@ ERR_MSG = _("According to the french law, you cannot modify a %s in order for it #forbidden fields MOVE_FIELDS = ['date', 'journal_id', 'company_id'] -LINE_FIELDS = ['debit', 'credit', 'account_id', 'move_id', 'partner_id'] +LINE_FIELDS = ['debit', 'credit', 'account_id', 'partner_id'] class AccountMove(models.Model): @@ -55,7 +55,8 @@ class AccountMove(models.Model): for line in move.line_ids: for field in LINE_FIELDS: - values[field] = _getattrstring(line, field) + k = 'line_%d_%s' % (line.id, field) + values[k] = _getattrstring(line, field) #make the json serialization canonical # (https://tools.ietf.org/html/draft-staykov-hu-json-canonical-form-00) move.l10n_fr_string_to_hash = dumps(values, sort_keys=True, encoding="utf-8", From 566968bf99312ed4439d4274d9a7e1211d180b2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mois=C3=A9s=20L=C3=B3pez?= Date: Mon, 10 Jul 2017 22:23:09 -0500 Subject: [PATCH 04/16] [FIX] doc: use new URI wkhtmltopdf releases The old release of wkhtmltopdf are no longer published on the download page. The developer explicitely asks to use the github link cf: wkhtmltopdf/wkhtmltopdf#3524 wkhtmltopdf/wkhtmltopdf#3521 wkhtmltopdf/wkhtmltopdf#3518 wkhtmltopdf/wkhtmltopdf#3508 Closes #18146 --- doc/setup/install.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/setup/install.rst b/doc/setup/install.rst index de21d6c53ab..aae7d03b8ba 100644 --- a/doc/setup/install.rst +++ b/doc/setup/install.rst @@ -546,7 +546,7 @@ default db to serve on localhost:8069 http://www.enterprisedb.com/products-services-training/pgdownload .. _Quilt: http://en.wikipedia.org/wiki/Quilt_(software) .. _saas: https://www.odoo.com/page/start -.. _the wkhtmltopdf download page: http://wkhtmltopdf.org/downloads.html +.. _the wkhtmltopdf download page: https://github.com/wkhtmltopdf/wkhtmltopdf/releases/tag/0.12.1 .. _UAC: http://en.wikipedia.org/wiki/User_Account_Control .. _wkhtmltopdf: http://wkhtmltopdf.org .. _pip: https://pip.pypa.io From 058cc22d2c680f73501ce1a49762eda1a4c9ce9d Mon Sep 17 00:00:00 2001 From: Nicolas Martinelli Date: Thu, 29 Jun 2017 14:07:01 +0200 Subject: [PATCH 05/16] [FIX] website_form: send email with subject - Use the form builder to send an email - Customize the snippet to include the subject and the body - Send a mail => The subject is not included in the email This is because the subject is filtered out and considered as a blacklisted field. It happens because `mail.mail` inherits from `mail.message`. The field property `website_form_blacklisted` is set to: - `True` for `mail.mail` - `False` for `mail.message` Since we go through all inherited models, the property on `mail.mail` is overriden by the property on `mail.message`. It is actually not necessary to go through all inherited models, since in the case of `inherits`, we copy the fields of the inherited model to the target model. The check is simplified by only checking the fields of the current model. Based on work of @nla-odoo opw-748926 --- addons/website_form/models/models.py | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/addons/website_form/models/models.py b/addons/website_form/models/models.py index c3e8be8d36d..65fed9e526c 100644 --- a/addons/website_form/models/models.py +++ b/addons/website_form/models/models.py @@ -18,12 +18,6 @@ class website_form_model(models.Model): website_form_default_field_id = fields.Many2one('ir.model.fields', 'Field for custom form data', domain="[('model', '=', model), ('ttype', '=', 'text')]", help="Specify the field which will contain meta and custom form fields datas.") website_form_label = fields.Char("Label for form action", help="Form action label. Ex: crm.lead could be 'Send an e-mail' and project.issue could be 'Create an Issue'.") - def _all_inherited_model_ids(self): - return list(itertools.chain( - [self.id], - *(m._all_inherited_model_ids() for m in self.inherited_model_ids) - )) - def _get_form_writable_fields(self): """ Restriction of "authorized fields" (fields which can be used in the @@ -31,16 +25,16 @@ class website_form_model(models.Model): builders and are writable. By default no field is writable by the form builder. """ - excluded = { + included = { field.name for field in self.env['ir.model.fields'].sudo().search([ - ('model_id', 'in', self._all_inherited_model_ids()), - ('website_form_blacklisted', '=', True) + ('model_id', '=', self.id), + ('website_form_blacklisted', '=', False) ]) } return { k: v for k, v in self.get_authorized_fields().iteritems() - if k not in excluded + if k in included } @api.multi From e6e17cc5d6483afbdd898248858933b85ac422d4 Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Wed, 12 Jul 2017 12:38:52 +0200 Subject: [PATCH 06/16] [FIX] product: Error message when adding an item to a quote When a user tries to add a product on an opportunity, the date_order of the order is added into the context. This value can be False. When "_compute_price_rule" is called without "date" arguments (some onchange, compute...) the method method use the context date (in this case the value is False) or the today date. The date value is used in an sql request and raise a value exception. opw-751700 --- addons/product/models/product_pricelist.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/product/models/product_pricelist.py b/addons/product/models/product_pricelist.py index abe09f05fd6..e6c402bc95a 100644 --- a/addons/product/models/product_pricelist.py +++ b/addons/product/models/product_pricelist.py @@ -106,7 +106,7 @@ class Pricelist(models.Model): """ self.ensure_one() if not date: - date = self._context.get('date', fields.Date.today()) + date = self._context.get('date') or fields.Date.today() if not uom_id and self._context.get('uom'): uom_id = self._context['uom'] if uom_id: From 999dc80e7c5561dd866f3d0a0551a65795a9f87c Mon Sep 17 00:00:00 2001 From: Cedric Snauwaert Date: Wed, 12 Jul 2017 11:28:28 +0200 Subject: [PATCH 07/16] [FIX] base_import: when parsing date field, strip extra spaces --- addons/base_import/models/base_import.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/base_import/models/base_import.py b/addons/base_import/models/base_import.py index ad69cb01402..b9e22ad9925 100644 --- a/addons/base_import/models/base_import.py +++ b/addons/base_import/models/base_import.py @@ -615,7 +615,7 @@ class Import(models.TransientModel): for num, line in enumerate(data): if line[index]: try: - line[index] = dt.strftime(dt.strptime(ustr(line[index]).encode('utf-8'), user_format), server_format) + line[index] = dt.strftime(dt.strptime(ustr(line[index].strip()).encode('utf-8'), user_format), server_format) except ValueError, e: raise ValueError(_("Column %s contains incorrect values. Error in line %d: %s") % (name, num + 1, ustr(e.message))) except Exception, e: From 68934c6b87c8b8ee7906c577dcc970baa88864c4 Mon Sep 17 00:00:00 2001 From: Nicolas Martinelli Date: Wed, 12 Jul 2017 12:26:23 +0200 Subject: [PATCH 08/16] [FIX] mass_mailing: access error when 'Retry' A user without 'Administration/Settings' access rights cannot use the 'Retry' button on a mass-mailing. This is because only this level of power is allowed to unlink `mail.mail` records. However, this button is supposed to be used by regular mass mailing users. opw-744616 --- addons/mass_mailing/models/mass_mailing.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/mass_mailing/models/mass_mailing.py b/addons/mass_mailing/models/mass_mailing.py index 7aa8ddeec56..db828aa1b75 100644 --- a/addons/mass_mailing/models/mass_mailing.py +++ b/addons/mass_mailing/models/mass_mailing.py @@ -517,7 +517,7 @@ class MassMailing(models.Model): def retry_failed_mail(self): failed_mails = self.env['mail.mail'].search([('mailing_id', 'in', self.ids), ('state', '=', 'exception')]) failed_mails.mapped('statistics_ids').unlink() - failed_mails.unlink() + failed_mails.sudo().unlink() self.write({'state': 'in_queue'}) #------------------------------------------------------ From b1b83925913136f82e1af710643aeeebaca086cc Mon Sep 17 00:00:00 2001 From: Nicolas Martinelli Date: Thu, 2 Feb 2017 09:59:29 +0100 Subject: [PATCH 09/16] [FIX] sales_team, crm: expected closing On the CRM dashboard, the shortcut 'exp. closing' is the same than the 'overdue' shortcut. However, the number of opportunities in these categories is computed differently (see method `retrieve_sales_dashboard`). We introduce a new filter "Overdue Opportunities" which reflects this difference. Backport of 9d2f48dc7fa9d5de3e850ff7ac82d9b31cf188cd opw-704173 opw-751165 --- addons/crm/crm_lead_view.xml | 3 +++ addons/sales_team/static/src/js/sales_team_dashboard.js | 2 ++ addons/sales_team/static/src/xml/sales_team_dashboard.xml | 2 +- 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/addons/crm/crm_lead_view.xml b/addons/crm/crm_lead_view.xml index f5deb670046..12dddbe0e62 100644 --- a/addons/crm/crm_lead_view.xml +++ b/addons/crm/crm_lead_view.xml @@ -633,6 +633,9 @@ ]"/> + - + exp. closing From 3e8ba4905ccd32ea4324b8baa46e6554ce84c7ac Mon Sep 17 00:00:00 2001 From: Nicolas Martinelli Date: Thu, 13 Jul 2017 08:32:45 +0200 Subject: [PATCH 10/16] [FIX] crm: expected closing The "exp. closing" dashboard button takes into account the won opportunities. It shouldn't. Backport of 9d2f48dc7fa9d5de3e850ff7ac82d9b31cf188cd opw-751165 opw-744940 --- addons/crm/crm_lead.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/crm/crm_lead.py b/addons/crm/crm_lead.py index 6fedd54890b..b8902cb736d 100644 --- a/addons/crm/crm_lead.py +++ b/addons/crm/crm_lead.py @@ -1147,7 +1147,7 @@ Update your business card, phone book, social media,... Send an email right now res['closing']['today'] += 1 if date_deadline >= date.today() and date_deadline <= date.today() + timedelta(days=7): res['closing']['next_7_days'] += 1 - if date_deadline < date.today(): + if date_deadline < date.today() and not opp['date_closed']: res['closing']['overdue'] += 1 # Next activities From 37ff69d45e3a595824c79ecde1923b0c4a5f33f8 Mon Sep 17 00:00:00 2001 From: Goffin Simon Date: Mon, 26 Jun 2017 11:54:46 +0200 Subject: [PATCH 11/16] [FIX] mrp: Post inventory button without finished product" This fix 2332df6bc7380e742e7d3dfb945124e21078087d has been done in stable and some customers wants to keep the button "Post Inventory" available all the time. Now the button is just visible in developper mode. opw:748347 --- addons/mrp/models/mrp_production.py | 7 ++----- addons/mrp/views/mrp_production_views.xml | 2 +- addons/stock/models/product.py | 3 --- addons/stock_account/models/product.py | 3 --- 4 files changed, 3 insertions(+), 12 deletions(-) diff --git a/addons/mrp/models/mrp_production.py b/addons/mrp/models/mrp_production.py index 613e3f64a9f..739a62a1add 100644 --- a/addons/mrp/models/mrp_production.py +++ b/addons/mrp/models/mrp_production.py @@ -208,11 +208,8 @@ class MrpProduction(models.Model): @api.depends('move_raw_ids.quantity_done', 'move_finished_ids.quantity_done') def _compute_post_visible(self): for order in self: - if order.product_tmpl_id._is_cost_method_standard(): - order.post_visible = any((x.quantity_done > 0 and x.state not in ['done', 'cancel']) for x in order.move_raw_ids) or \ - any((x.quantity_done > 0 and x.state not in ['done' 'cancel']) for x in order.move_finished_ids) - else: - order.post_visible = any((x.quantity_done > 0 and x.state not in ['done' 'cancel']) for x in order.move_finished_ids) + order.post_visible = any(order.move_raw_ids.filtered(lambda x: (x.quantity_done) > 0 and (x.state not in ['done', 'cancel']))) or \ + any(order.move_finished_ids.filtered(lambda x: (x.quantity_done) > 0 and (x.state not in ['done', 'cancel']))) @api.multi @api.depends('workorder_ids.state', 'move_finished_ids') diff --git a/addons/mrp/views/mrp_production_views.xml b/addons/mrp/views/mrp_production_views.xml index 7865afdd1f2..46546c4e5e0 100644 --- a/addons/mrp/views/mrp_production_views.xml +++ b/addons/mrp/views/mrp_production_views.xml @@ -48,7 +48,7 @@